aboutsummaryrefslogtreecommitdiff
path: root/src
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
downloadkermit-80-ebb2ff2af569d5822b70ee555a32d27cf7494816.tar.gz
kermit-80-ebb2ff2af569d5822b70ee555a32d27cf7494816.zip
Initial import of 4.11HEADmain
Diffstat (limited to 'src')
-rw-r--r--src/cpscmd.asm1140
-rw-r--r--src/cpscom.asm1371
-rw-r--r--src/cpscpm.asm932
-rw-r--r--src/cpsdat.asm648
-rw-r--r--src/cpsdef.asm287
-rw-r--r--src/cpsker.asm315
-rw-r--r--src/cpsmit.asm834
-rw-r--r--src/cpspk1.asm1904
-rw-r--r--src/cpspk2.asm1336
-rw-r--r--src/cpsrem.asm1149
-rw-r--r--src/cpsser.asm44
-rw-r--r--src/cpstt.asm862
-rw-r--r--src/cpsutl.asm1227
-rw-r--r--src/cpswld.asm222
-rw-r--r--src/cpxapp.asm749
-rw-r--r--src/cpxbbi.asm618
-rw-r--r--src/cpxbee.asm996
-rw-r--r--src/cpxcif.asm746
-rw-r--r--src/cpxcom.asm486
-rw-r--r--src/cpxgni.asm440
-rw-r--r--src/cpxhea.asm921
-rw-r--r--src/cpxlnk.asm206
-rw-r--r--src/cpxmrl.asm454
-rw-r--r--src/cpxnor.asm587
-rw-r--r--src/cpxpcw.asm912
-rw-r--r--src/cpxpro.asm561
-rw-r--r--src/cpxsb.asm696
-rw-r--r--src/cpxswt.asm294
-rw-r--r--src/cpxsy2.asm1364
-rw-r--r--src/cpxsyo.asm389
-rw-r--r--src/cpxsys.asm1386
-rw-r--r--src/cpxtm4.asm490
-rw-r--r--src/cpxtor.asm1229
-rw-r--r--src/cpxtyp.asm722
-rw-r--r--src/cpxvdu.asm462
-rw-r--r--src/cpxz80.asm350
36 files changed, 27329 insertions, 0 deletions
diff --git a/src/cpscmd.asm b/src/cpscmd.asm
new file mode 100644
index 0000000..6cff603
--- /dev/null
+++ b/src/cpscmd.asm
@@ -0,0 +1,1140 @@
+; CPSCMD.ASM
+; 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 provides a user oriented way of parsing commands.
+; It is similar to that of the COMND JSYS in TOPS-20.
+;
+; revision history (latest first):
+;
+;edit 13, 17-Jan-1991 by MF. Modified "cmifil" routine to zero the entire
+; fcb (not just the extent) to fix a bug in the COPY command which
+; prevented successive COPY commands from working properly.
+;edit 12, 16-Jan-1991 by MF. Modified routine "cmkeyw" to ignore leading
+; spaces/tabs before a keyword. This apparently was the intent in
+; "prompt" and "repars" (at least for command-lines) as the variable
+; "cmsflg "is set upon command parse and reparse. The intent was ,
+; subverted, however, as "cmkeyw" did not reset the flag to ignore
+; leading white space for each search thru the key tables (even though
+; the buffer pointer to the keyword entered was reset). The fix was
+; to reset the "spaces seen" flag (cmsflg) after "cmkey2" so that
+; it is reset each time a new table entry is compared to the text
+; the user has entered from the keyboard/TAKE-file etc. The upshot
+; of all this is that the kluge code in "cminbf" at "cminb0" designed
+; to force Kermit to ignore leading white space on command-lines in
+; TAKE-files and on the CP/M command-line is no longer needed and,
+; therefore, has been eliminated. Also modify "comnd" to expect leading
+; spaces for functions other than "get keyword".
+;edit 11, 26-Dec-1990 by MF. Modified routines to ignore leading white space
+; in lines from TAKE-files as well as during input from the CP/M
+; command-line (form-feeds are now considered white space under these
+; circumstances).
+;edit 10, 8-Sep-1990 by Mike Freeman. Modified routines to ignore leading
+; spaces/tabs when processing Kermit commands from the CP/M
+; command-line.
+; Added flag CMBFLG to allow initial word on a command-line
+; to be blank (useful for Remote commands such as Remote CWD etc).
+; Added flag cmqflg to prevent character-echoing while entering
+; commands so Remote CWD etc can have nonechoing password entry.
+; edit 9, 15 June, 1987 by OBSchou. Bug fixing to allow a second filename
+; (quiet) be entered as d:<blank>. Previous revision put the drive name
+; in first character of FCB, I put that character back to a space.
+;
+; edit 8, 12 June, 1987 by OBSchou. Addedin code in cmkeyw to print
+; 20 lines of help, then pause for a key from the user befor
+; proceeding with help.
+;
+; edit 7, 11 March, 1987 by OBSchou for Richard Russell, BBC. He writes:
+; Bug in cmtext which prevented use of octal characters (\nnn) fixed.
+;
+; edit 6, 18 June, 1986 by OBSchou, Loughborough University, Leics. UK
+; added code to parse a number from user input. Added check to make
+; sure the input command buffer does not overflow the limit.
+;
+; edit 5a: 7 March, 1986. OBSchou. Added stuff rom MJ Carter. He writes:
+; 7th May 85, MJ Carter [majoc], Nottingham University
+; Code in cmifil() put one too many spaces in the FCB; this caused
+; the BDOS of the British Micro Mimi to search for exteny 32,
+; rather than extent 0, so era() always said "can't find file"
+; Puttig a null at the point in question ought to fix 9 it.
+;
+; edit 5: 6-Feb-85 by Charles Carvalho
+; Make ffussy a runtime (rather than assembly-time) switch, to
+; eliminate conditional assembly in system-independent module.
+; Don't allow _%|()/\ in filenames if ffussy set; my CP/M manual
+; disallows those, too.
+;
+; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
+;
+;pcc006 2-jan-85 VJC modules:cp4cmd,cp4utl
+; Problems with "?" in filespecs. On reparse, may cause action
+; flag to be reset at wrong point, requiring multiple <CR>'s
+; to terminate the line or other weird stuff. Also need to
+; check flag and complain if wild-cards illegal.
+
+;pcc007 2-Jan-85 vjc modules:cp4def,cp4cmd
+; Cmifil is too fussy about what characters to accept in a
+; filespec. My CP/M manual says any printable character is ok
+; except <>.,;:?*[], and lower case. In practice, even those work
+; sometimes. Kermit itself uses '&' if file warning is on,
+; and then won't let you reference the file. Allow all
+; printable characters except those above. Add conditional
+; ffussy, so that if not ffussy, all special characters will be
+; allowed, just convert lower to upper-case.
+
+; edit 3: July 8, 1984 (CJC)
+; integrate Toad Hall changes for LASM compatibility: CP4CPM is linked
+; by CP4WLD, and links CP4UTL.
+;
+; edit 2: June 5, 1984 (CJC)
+; formatting and documentation; delete unnecessary code at cminb7; add
+; module version string.
+;
+; edit 1: May, 1984 (CJC)
+; extracted from CPMBASE.M80 version 3.9; modifications are described in
+; the accompanying .UPD file.
+
+cmdver: db 'CPSCMD.ASM (13) 17-Jan-1991$' ; name, edit number, date
+
+; This routine prints the prompt in DE and specifies the reparse
+; address.
+; called by: kermit
+
+prompt: pop h ;Get the return address.
+ push h ;Put it on the stack again.
+ shld cmrprs ;Save it as the address to go to on reparse.
+ lxi h,0 ;Clear out hl pair.
+ dad sp ;Get the present stack pointer.
+ shld cmostp ;Save for later restoral.
+ xchg ;Save the pointer to the prompt.
+ shld cmprmp
+ xchg
+ lxi h,cmdbuf
+ shld cmcptr ;Initialize the command pointer.
+ shld cmdptr
+ xra a
+ sta cmaflg ;Zero the flags.
+ sta cmccnt
+; mvi a,0FFH ;Try it this way (Daphne.)
+; sta cmsflg
+ call prcrlf ;Print a CR/LF [Toad Hall]
+ jmp prprmp ;Print the prompt. [Toad Hall]
+;
+; This address is jumped to on reparse.
+; here from: cmcfrm, cmkeyw, cmifil, cminbf
+
+repars: lhld cmostp ;Get the old stack pointer.
+ sphl ;Make it the present one.
+ lxi h,cmdbuf
+ shld cmdptr
+; mvi a,0FFH ;Try it this way (Daphne.)
+; sta cmsflg
+ lhld cmrprs ;Get the reparse address.
+ pchl ;Go there.
+
+; This address can be jumped to on a parsing error.
+; here from: cmkeyw, cminbf
+
+prserr: lhld cmostp ;Get the old stack pointer.
+ sphl ;Make it the present one.
+ lxi h,cmdbuf
+ shld cmcptr ;Initialize the command pointer.
+ shld cmdptr
+ xra a
+ sta cmaflg ;Zero the flags.
+ sta cmccnt
+; mvi a,0FFH ;Try it this way (Daphne.)
+; sta cmsflg
+ call prcrlf ;Print a CR/LF [Toad Hall]
+ call prprmp ;Print the prompt [Toad Hall]
+;* Instead return to before the prompt call.
+ lhld cmrprs
+ pchl
+;
+; This routine parses the specified function in A. Any additional
+; information is in DE and HL.
+; Returns +1 on success
+; +4 on failure (assumes a JMP follows the call)
+; called by: log, setcom, read, send, xmit, dir, era, keycmd, cfmcmd
+; and CPSREM
+
+comnd: sta cmstat ;Save what we are presently parsing.
+ call cminbf ;Get chars until an action or a erase char.
+ push psw ;[MF]Save function
+ mvi a,0ffh ;[MF]Expect leading spaces
+ sta cmsflg ;[MF]...
+ pop psw ;[MF]Restore function
+ cpi cmcfm ;Parse a confirm?
+ jz cmcfrm ;Go get one.
+ cpi cmkey ;Parse a keyword?
+ jz cmkeyw ;Try and get one.
+ cpi cmifi ;Parse an input file spec?
+ jz cmifil ;Go get one.
+ cpi cmifin ;Input file-spec silent?
+ jz cmifil ;do as he wishes
+ cpi cmofi ;Output file spec?
+ jz cmofil ;Go get one.
+ cpi cmtxt ;Parse arbitrary text?
+ jz cmtext ;Go do it.
+ cpi cmnum ;[7] Parse a number?
+ jz cmnumb ;[7] go do it
+ lxi d,cmer00 ;"?Unrecognized COMND call"
+ call prtstr
+ ret
+;
+; This routine parses arbitrary text up to a CR.
+; Accepts DE: address to put text
+; Returns in A: number of chars in text (may be 0)
+; DE: updated pointer
+; called by: comnd
+
+cmtext: xra a ; clear counters erc for slashes etc
+ sta slshsn ; if we are in a slash sequence
+ sta slashn ; the octal number being entered
+ sta slashc ; number of characters entered
+
+ xchg ;Put the pointer to the dest in HL.
+ shld cmptab ;Save the pointer.
+ mvi b,0 ;Init the char count
+cmtxt1: call cmgtch ;Get a char.
+ ora a ;Terminator?
+ jp cmtx3 ;No, put in user space. [rtr] was cmtx5
+ ani 7FH ;Turn off minus bit.
+ cpi esc ;An escape?
+ jnz cmtxt2 ;No.
+ mvi c,conout
+ mvi e,bell ;Get a bell.
+ call bdos
+ xra a
+ sta cmaflg ;Turn off the action flag.
+ lhld cmcptr ;Move the pointer to before the escape.
+ dcx h
+ shld cmcptr
+ shld cmdptr
+ lxi h,cmccnt ;Get the char count.
+ dcr m ;Decrement it by one.
+ jmp cmtxt1 ;Try again.
+
+cmtxt2: cpi '?' ;Is it a question mark?
+ jz cmtxt4 ;If so put it in the text. [rtr] was cmtx3
+ cpi ff ;Is it a formfeed?
+ cz clrtop ;If so blank the screen.
+ mov a,b ;Return the count.
+ lhld cmptab ;Return updated pointer in HL.
+ xchg
+ jmp rskp ;Return success.
+
+cmtx3: cpi '\' ; slash?
+ jnz cmtx3a ; nope, so try something else
+ lda slshsn ; a slash already entered?
+ ana a
+ cma ;[rtr]
+ jnz cmtx3a ; yes, so assume its a valid slash to enter
+ sta slshsn ; make sure the flag is set for next time routnd
+ jmp cmtxt1 ; get another character
+
+cmtx3a:
+; lxi h,cmaflg ;Point to the action flag.
+; mvi m,0 ;Set it to zero.
+ mov e,a ; save it in case we are interpreting a slash
+ lda slshsn ; slash already entered?
+ ana a ; test flag
+ mov a,e ; restore it in case...
+ jz cmtx5 ; not a slash seen, so enter as a normal character
+ cpi '\'
+ jnz cmtx3b ; \\ not detected
+ lda slashn ; else get number
+ jmp cmtx5b ; and enter it ( in the case of \n or \nn)
+ ; here if an octal number of 1 or 2 digits
+ ; entered instead of 3, followed by \ again
+
+cmtx3b:
+ sui 30h ; else it should be an octal number
+ jm cmtxt6 ; if not a digit complain
+ cpi 8 ; ditto
+ jp cmtxt6 ;[rtr] was cmtxt
+ mov e,a ; else add it to the number already entered
+ lda slashn
+ add a
+ add a
+ add a ; multiply by 8
+ add e
+ sta slashn
+ lda slashc ; get the count
+ inr a
+ sta slashc ; plus one. If three then a number entered
+ cpi 3
+ lda slashn ; get the number in case...
+ jz cmtx5
+ jmp cmtxt1 ; else loop
+
+cmtxt4: lhld cmdptr ;[rtr] Get a pointer into the buffer
+ inx h ;[rtr] Bump past '?'
+ shld cmdptr ;[rtr]
+cmtx5: call cmtx5c
+ jmp cmtxt1 ; put this into a subroutine
+
+cmtx5b:
+ call cmtx5c ; here if we see \n\ or \nn\ rather than \nnn\
+ mvi a,'\' ; so send slash number to buffer,
+ sta slshsn ; re-store a slash seen
+ jmp cmtxt1 ; try next one
+
+cmtx5c:
+ inr b ;Increment the count.
+ lhld cmptab ;Get the pointer.
+ mov m,a ;Put the char in the array.
+ inx h
+ shld cmptab ;Save the updated pointer.
+ xra a ; clear slash counters etc
+ sta slashc
+ sta slashn
+ sta slshsn
+ ret ; and exit
+
+cmtxt6: lxi d,cmer05 ; complain - not a valid \ parameter
+ call prtstr
+ jmp kermit ; and try another command
+ ds 20h ; for debugging
+;
+; This routine gets a number from user input.
+; Called by: comnd
+;
+cmnumb: lxi h,0 ; make sure the number is zero to start with
+ shld number
+cmnum0: call cmgtch ; get another character
+ ora a ; if negative then its an action
+ jp cmnum1 ; nope, so (possibly) valid input
+ ani 7fh ; else lets see what it is...
+ cpi esc ; do not know what to do with this one...
+ cpi ' ' ; if it is a space then either a return or more
+ jnz cmnum2 ; else
+ jmp rskp ; space is a deliminter
+ dw 0 ; set three bytes aside for a jump/call
+ dw 0 ; and then another three just in case...
+ dw 0 ; making 6 bytes
+cmnum2: cpi '?' ; user is curious
+ jz gnum2
+ cpi cr ; end of input?
+ jz cmnumx
+gnum1: jmp prserr ; did not under stand this, so error
+cmnumx: dw 0
+ dw 0
+ jmp rskp ; return ok
+
+gnum2: lhld number ; get the number.. if at all entered
+ mov a,l
+ ora h ; if hl = 0 then possibly no number entered
+ lxi d,cmin02 ; say confirm...or more on line
+ jnz gnum21 ; else say enter a return
+ lxi d,cmin01 ; say enter a number
+gnum21: call prtstr ; say it
+ call prcrlf ; do a lf
+ call prprmp ; another reprompt
+ lhld cmdptr ; get pointer of string already entered
+ mvi m,'$' ; dollar it to set end of line
+ lhld cmcptr
+ dcx h ; decrement and save the buffer pointer
+ shld cmcptr
+ lxi d,cmdbuf
+ call prtstr ; print what has already been entered
+ xra a
+ sta cmaflg ; turn the action flag off
+ jmp repars ; and try again
+
+ mvi a,cmcfm ; parse a confirm
+dw 0
+dw 0
+dw 0
+dw 0
+dw 0 ; some space to patch...
+dw 0
+
+cmnum1: ani 7fh ; here for a (potentially) valid number
+ sui '0' ; less ascii bias
+ jc gnum3
+ cpi 10 ; if 10 or more its still bad
+ jnc gnum3
+ cmc
+ lhld number ; now multiply number by ten and add the new value
+ push h
+ pop d
+ dad h ; hl = hl * 2
+ dad h ; * 4
+ dad d ; * 5
+ dad h ; * 10
+ mvi d,0
+ mov e,a ; add de to hl...
+ dad d
+ shld number
+ jmp cmnum0
+;
+gnum3: lxi d,cmer04 ; invalid number...
+ call prtstr
+ jmp rskp
+;
+
+;
+; This routine gets a confirm.
+; called by: comnd
+
+cmcfrm: call cmgtch ;Get a char.
+ ora a ;Is it negative (a terminator;a space or
+ ;a tab will not be returned here as they
+ ;will be seen as leading white space.)
+ rp ;If not, return failure.
+ ani 7FH ;Turn off the minus bit.
+ cpi esc ;Is it an escape?
+ jnz cmcfr2
+ mvi c,conout
+ mvi e,bell ;Get a bell.
+ call bdos
+ xra a
+ sta cmaflg ;Turn off the action flag.
+ lhld cmcptr ;Move the pointer to before the escape.
+ dcx h
+ shld cmcptr
+ shld cmdptr
+ lxi h,cmccnt ;Get the char count.
+ dcr m ;Decrement it by one.
+ jmp cmcfrm ;Try again.
+
+cmcfr2: cpi '?' ;Curious?
+ jnz cmcfr3
+ lxi d,cmin00 ;Print something useful.
+ call prtstr
+ call prcrlf ;Print a crlf. [Toad Hall]
+ call prprmp ;Reprint the prompt [Toad Hall]
+ lhld cmdptr ;Get the pointer into the buffer.
+ mvi a,'$' ;Put a $ there for printing.
+ mov m,a
+ lhld cmcptr
+ dcx h ;Decrement and save the buffer pointer.
+ shld cmcptr
+ lxi d,cmdbuf
+ call prtstr
+ xra a ;Turn off the action flag.
+ sta cmaflg
+ jmp repars ;Reparse everything.
+
+cmcfr3: cpi ff ;Is it a form feed?
+ cz clrtop ;If so blank the screen.
+ jmp rskp
+;
+; This routine parses a keyword from the table pointed
+; to in DE. The format of the table is as follows:
+;
+; addr: db n ;Where n is the # of entries in the table.
+; db m ;M is the size of the keyword.
+; db 'string$' ;Where string is the keyword.
+; db a,b ;Where a & b are pieces of data
+; ;to be returned. (Must be two of them.)
+;
+; The keywords must be in alphabetical order.
+;**** Note: The data value a is returned in registers A and E. The
+;**** data value b is returned in register D. This allows the two data
+; bytes to be stored as:
+; dw xxx
+; and result in a correctly formatted 16-bit value in register pair
+; DE.
+; called by: comnd
+
+cmkeyw: shld cmhlp ;Save the help.
+ xchg ;Get the address of the table.
+ shld cmptab ;Save the beginning of keyword tab for '?'.
+ mov b,m ;Get the number of entries in the table.
+ inx h
+ shld cmkptr
+ lhld cmdptr ;Save the command pointer.
+ shld cmsptr
+cmkey2: mov a,b ;Get the number of entries left.
+ ora a ;Any left?
+ rz ;If not we failed.
+ mvi a,0ffh ;[MF]Make sure we ignore leading spaces
+ sta cmsflg ;[MF]...
+ lhld cmkptr
+ mov e,m ;Get the length of the keyword.
+ inx h
+cmkey3: dcr e ;Decrement the number of chars left.
+ mov a,e
+ cpi 0FFH ;Have we passed the end?
+ jm cmkey5 ;If so go to the next.
+ call cmgtch ;Get a char.
+ ora a ;Is it a terminator?
+ jp cmkey4 ;If positive, it is not.
+ ani 7FH ;Turn off the minus bit.
+ cpi '?'
+ jnz cmky31
+ xra a
+ sta cmaflg ;Turn off the action flag.
+ lxi h,cmccnt ;Decrement the char count.
+ dcr m
+;* Must go through the keyword table and print them.
+ lhld cmhlp ;For now print the help text.
+ xchg
+ call p20ln ;[8] print at most 20 lines then pause
+; call prtstr
+ call prcrlf ;Print a crlf [Toad Hall]
+ call prprmp ;Reprint the prompt [Toad Hall]
+ lhld cmdptr ;Get the pointer into the buffer.
+ mvi a,'$' ;Put a $ there for printing.
+ mov m,a
+ lhld cmcptr
+ dcx h ;Decrement and save the buffer pointer.
+ shld cmcptr
+ lxi d,cmdbuf
+ call prtstr
+ jmp repars ;Reparse everything.
+
+cmky31: cpi esc ;Is it an escape?
+ jnz cmky35
+ xra a
+ sta cmaflg ;Turn off the action flag.
+ push d
+ push b
+ push h
+ call cmambg
+ jmp cmky32 ;Not ambiguous.
+ mvi c,conout
+ mvi e,bell
+ call bdos ;Ring the bell.
+ lhld cmcptr ;Move the pointer to before the escape.
+ dcx h
+ shld cmcptr
+ shld cmdptr
+ lxi h,cmccnt ;Get the char count.
+ dcr m ;Decrement it by one.
+ pop h
+ pop b
+ pop d
+ inr e ;Increment the left to parse char count.
+ jmp cmkey3
+
+cmky32: lhld cmcptr ;Pointer into buffer.
+ dcx h ;Backup to the escape.
+ xchg
+ pop h
+ push h
+cmky33: mov a,m ;Get the next char.
+ cpi '$' ;Finished?
+ jz cmky34
+ inx h
+ xchg
+ mov m,a ;Move it into the buffer.
+ inx h
+ xchg
+ lda cmccnt ;Increment the char count.
+ inr a
+ sta cmccnt
+ jmp cmky33
+
+cmky34: lda cmccnt ;Get the character count.
+ inr a ;Increment and save it.
+ sta cmccnt
+ xchg ;Put the command buffer pointer in HL.
+ mvi a,' ' ;Get a blank.
+ mov m,a ;Put it in the command buffer.
+ inx h ;Increment the pointer
+ shld cmcptr ;Save the updated pointer.
+ shld cmdptr
+ pop h
+ push h
+ xchg
+ call prtstr ;Print the rest of the keyword.
+ mvi c,conout
+ mvi e,' '
+ call bdos ;Print a blank.
+ pop h
+ pop b
+ pop d
+ jmp cmky37
+
+cmky35: push h
+ push d
+ call cmambg
+ jmp cmky36
+ lxi d,cmer01
+ call prtstr ;Say its ambiguous.
+ jmp prserr ;Give up.
+
+cmky36: pop d
+ pop h
+cmky37: inr e ;Add one incase it is negative.
+ mvi d,0
+ dad d ;Increment past the keyword.
+ inx h ;Past the $.
+ mov e,m ;Get the data.
+ inx h
+ mov d,m
+ mov a,e
+ jmp rskp
+
+cmkey4: cpi 'a' ;Is it less than a?
+ jm cmky41 ;If so don't capitalize it.
+ cpi 'z'+1 ;Is it more than z?
+ jp cmky41 ;If so don't capitalize it.
+ ani 137O ;Capitalize it.
+cmky41: mov d,m ;Get the next char of the keyword.
+ inx h
+ cmp d ;Match?
+ jz cmkey3 ;If so get the next letter.
+
+cmkey5: mvi d,0
+ mov a,e ;Get the number of chars left.
+ ora a ;Is it negative?
+ jp cmky51
+ mvi d,0FFH ;If so, sign extend.
+cmky51: dad d ;Increment past the keyword.
+ lxi d,0003H ;Plus the $ and data.
+ dad d
+ shld cmkptr
+ dcr b ;Decrement the number of entries left.
+ lhld cmsptr ;Get the old cmdptr.
+ shld cmdptr ;Restore it.
+;* check so we don't pass it.
+ jmp cmkey2 ;Go check the next keyword.
+;
+; Test keyword for ambiguity.
+; returns: nonskip if ambiguous, skip if OK.
+; called by: cmkeyw
+
+cmambg: dcr b ;Decrement the number of entries left.
+ rm ;If none left then it is not ambiguous.
+ inr e ;This is off by one;adjust.
+ mov c,e ;Save the char count.
+ mov a,e
+ ora a ;Any chars left?
+ rz ;No, it can't be ambiguous.
+ mvi d,0
+ dad d ;Increment past the keyword.
+ mvi e,3 ;Plus the $ and data.
+ dad d
+ mov b,m ;Get the length of the keyword.
+ inx h
+ xchg
+ lhld cmkptr ;Get pointer to keyword entry.
+ mov a,m ;Get the length of the keyword.
+ sub c ;Subtract how many left.
+ mov c,a ;Save the count.
+ cmp b
+ jz cmamb0
+ rp ;If larger than the new word then not amb.
+cmamb0: lhld cmsptr ;Get the pointer to what parsed.
+cmamb1: dcr c ;Decrement the count.
+ jm rskp ;If we are done then it is ambiguous.
+ xchg ;Exchange the pointers.
+ mov b,m ;Get the next char of the keyword
+ inx h
+ xchg ;Exchange the pointers.
+ mov a,m ;Get the next parsed char.
+ inx h
+ cpi 'a' ;Is it less than a?
+ jm cmamb2 ;If so don't capitalize it.
+ cpi 'z'+1 ;Is it more than z?
+ jp cmamb2 ;If so don't capitalize it.
+ ani 137O
+cmamb2: cmp b ;Are they equal?
+ rnz ;If not then its not ambiguous.
+ jmp cmamb1 ;Check the next char.
+;
+; cmofil - parse output filespec
+; cmifil - parse input filespec
+; here from: comnd
+
+cmofil: mvi a,0 ;Don't allow wildcards.
+; jmp cmifil ;For now, the same as CMIFI.
+cmifil: sta cmfwld ;Set wildcard flag
+ xchg ;Get the fcb address.
+ shld cmfcb ;Save it.
+ mvi e,0 ;Initialize char count.
+ mvi m,0 ;Set the drive to default to current.
+ inx h
+ shld cmfcb2
+ xra a ;Initialize counter.
+cmifi0: mvi m,' ' ;Blank the FCB.
+ inx h
+ inr a
+; cpi 0CH ;Twelve? [5a dont use this]
+ cpi 0Bh ; [majoc 850585] Eleven?
+ jm cmifi0
+cmif0a: ;[MF]Zero entire fcb, not just the extent
+ mvi m,0 ; [majoc 850507] Specify extent 0
+ inx h ;[MF]Increment fcb byte pointer
+ inr a ;[MF]Increment fcb byte count
+ cpi 32 ;[MF]Done with fcb?
+ jm cmif0a ;[MF]No, zero until done
+cmifi1: call cmgtch ;Get another char.
+ ora a ;Is it an action character?
+ jp cmifi2
+ ani 7FH ;Turn off the action bit.
+ cpi '?' ;A question mark?
+ jnz cmif12
+ lda cmfwld ;[pcc006] Wildcards allowed?
+ ora a ;[pcc006]
+ jz cmif11 ;[pcc006] complain if not
+ lhld cmdptr ;[jd] Increment buffer pointer
+ inx h ;[jd] that was decremented in cmgtch
+ shld cmdptr ;[jd] since we want this chr
+ lda cmcptr ;[pcc006] get lsb of real input pointer
+ cmp l ;[pcc006] is this the last chr input?
+ jnz cmif1a ;[pcc006] no, don't reset action flag
+ xra a ;[pcc006] yes, reset action flag
+ sta cmaflg ;[pcc006]
+cmif1a: mvi a,'?' ;[pcc006] get it back in A
+ jmp cmifi8 ;Treat like any other character
+
+cmif12: cpi esc ;An escape?
+ jnz cmif13
+;Try to recognize file-spec a'la TOPS-20
+ xra a
+ sta cmaflg ;Turn off the action flag.
+ lhld cmcptr ;Move the pointer to before the escape.
+ dcx h
+ shld cmcptr
+ shld cmdptr
+ lxi h,cmccnt ;Get the char count.
+ dcr m ;Decrement it by one.
+ mov a,e ;Save character count up to now.
+ sta temp1
+ cpi 9 ;Past '.'?
+ jm cmfrec ;No.
+ dcr a ;Yes, don't count point.
+cmfrec: lhld cmfcb2 ;Fill the rest with CP/M wildcards.
+cmfrc1: cpi 11 ;Done?
+ jp cmfrc2 ;Yes.
+ mvi m,'?'
+ inx h
+ inr a
+ jmp cmfrc1
+
+cmfrc2: mvi c,sfirst ;Find first matching file?
+ lhld cmfcb
+ xchg
+ call bdos
+ cpi 0FFH
+ jz cmfrc9 ;No, lose.
+ lxi h,fcbblk ;Copy first file spec.
+ call fspcop
+ lxi h,fcbblk+10H ;Get another copy (in case not ambiguous).
+ call fspcop
+ mvi c,snext ;More matching specs?
+ lhld cmfcb
+ xchg
+ call bdos
+ cpi 0FFH
+ jz cmfrc3 ;Only one.
+ lxi h,fcbblk+10H ;Copy second file spec.
+ call fspcop
+cmfrc3: lxi d,fcbblk ;Start comparing file names.
+ lxi h,fcbblk+10H
+ lda temp1 ;Bypass characters typed.
+ cpi 9 ;Past '.'?
+ jm cmfrc4 ;No.
+ dcr a ;Yes, don't count point.
+cmfrc4: mvi c,0
+cmfrl1: cmp c ;Bypassed?
+ jz cmfrl2 ;Yes.
+ inx d
+ inx h
+ inr c
+ jmp cmfrl1 ;Repeat.
+
+cmfrl2: mov a,c ;Get file name characters processed.
+ cpi 11 ;All done?
+ jz cmfrc5 ;Yes.
+ cpi 8 ;End of file name?
+ jnz cmfrl3 ;No.
+ lda temp1 ;Exactly at point?
+ cpi 9
+ jz cmfrl3 ;Yes, don't output a second point.
+ mvi a,'.' ;Output separator.
+ call cmfput
+cmfrl3: ldax d ;Get a character from first file spec.
+ inx d
+ mov b,m ;Get from second file spec.
+ inx h
+ cmp b ;Compare.
+ jnz cmfrc5 ;Ambiguous.
+ inr c ;Same, count.
+ cpi ' ' ;Blank?
+ jz cmfrl2 ;Yes, don't output.
+ call cmfput ;Put character into buffer.
+ jmp cmfrl2 ;Repeat.
+
+cmfrc5: mov a,c ;Get count of characters processed.
+ sta temp1 ;Save it.
+ mvi a,'$' ;Get terminator.
+ call cmfput ;Put it into buffer.
+ lhld cmdptr ;Output recognized characters.
+ xchg
+ mvi c,prstr
+ call bdos
+ lhld cmcptr ;Remove terminator from buffer.
+ dcx h
+ shld cmcptr
+ lxi h,cmccnt
+ dcr m
+ lda temp1 ;Characters processed.
+ cpi 11 ;Complete file name.
+ jz repars ;Yes, don't beep.
+
+cmfrc9: mvi c,conout
+ mvi e,bell
+ call bdos ;Ring the bell.
+ jmp repars
+;
+; Continue file spec parsing.
+
+cmif13: mov a,e ;It must be a terminator.
+ ora a ;Test the length of the file name.
+ jz cmifi9 ;If zero complain.
+ cpi 0DH
+ jp cmifi9 ;If too long complain.
+ jmp rskp ;Otherwise we have succeeded.
+
+cmifi2: cpi '.'
+ jnz cmifi3
+ inr e
+ mov a,e
+ cpi 1H ;Any chars yet?
+ jz cmifi9 ;No, give error.
+ cpi 0AH ;Tenth char?
+ jp cmifi9 ;Past it, give an error.
+ mvi c,9H
+ mvi b,0
+ lhld cmfcb
+ dad b ;Point to file type field.
+ shld cmfcb2
+ mvi e,9H ;Say we've gotten nine.
+ jmp cmifi1 ;Get the next char.
+
+cmifi3: cpi ':'
+ jnz cmifi4
+ inr e
+ mov a,e
+ cpi 2H ;Is it in the right place for a drive?
+ jnz cmifi9 ;If not, complain.
+ lhld cmfcb2
+ dcx h ;Point to previous character.
+ mov a,m ;Get the drive name.
+ sui '@' ;Get the drive number.
+ shld cmfcb2 ;Save pointer to beginning of name field.
+ mvi m,space ;[obs] restore a space in FCB
+ dcx h ;Point to drive number.
+ mov m,a ;Put it in the fcb.
+ mvi e,0 ;Start character count over.
+ jmp cmifi1
+
+cmifi4: cpi '*'
+ jnz cmifi7
+ lda cmfwld ;Wildcards allowed?
+ cpi 0
+ jz cmif11 ;No,complain
+ mov a,e
+ cpi 8H ;Is this in the name or type field?
+ jz cmifi9 ;If its where the dot should be give up.
+ jp cmifi5 ;Type.
+ mvi b,8H ;Eight chars.
+ jmp cmifi6
+
+cmifi5: mvi b,0CH ;Three chars.
+cmifi6: lhld cmfcb2 ;Get a pointer into the FCB.
+ mvi a,'?'
+ mov m,a ;Put a question mark in.
+ inx h
+ shld cmfcb2
+ inr e
+ mov a,e
+ cmp b
+ jm cmifi6 ;Go fill in another.
+ jmp cmifi1 ;Get the next char.
+
+cmifi7: cpi '!' ;[pcc007] control chr or space?
+ jm cmifi9 ;[pcc007] yes, illegal
+ mov h,a ;[5] stash input char for a bit
+ lda ffussy ;[5] while we check the fussy flag
+ ora a ;[5] set the flags accordingly
+ mov a,h ;[5] restore the input character
+ jz cmif7a ;[5] if ffussy=0, allow <>.,;:?*[]
+;[5] So far, we've eliminated "action characters" (including question),
+;[5] period, colon, asterisk, control characters, and space.
+;[5] That leaves us %(),/;<=>[\]_| to check for.
+ cpi '%' ;[5]
+ jz cmifi9 ;[5]
+ cpi '(' ;[5]
+ jz cmifi9 ;[5]
+ cpi ')' ;[5]
+ jz cmifi9 ;[5]
+ cpi ',' ;[pcc007] weed out comma
+ jz cmifi9 ;[pcc007]
+ cpi '/' ;[5]
+ jz cmifi9 ;[5]
+ cpi '9'+1 ;[pcc007] anything else 21H-39H is ok
+ jm cmifi8 ;[pcc007] except '*' never gets here
+ cpi '@' ;[pcc007] all of 3AH-3FH is illegal
+ jm cmifi9 ;[pcc007]
+ cpi '[' ;[pcc007] [\] also illegal
+ jm cmifi8 ;[pcc007]
+ cpi ']'+1 ;[pcc007]
+ jm cmifi9 ;[pcc007]
+ cpi '_' ;[5]
+ jz cmifi9 ;[5] (If I was doing CP/M, I would have
+ cpi '|' ;[5] just eliminated all them funny chars
+ jz cmifi9 ;[5] instead of a random selection)
+cmif7a: ;[5]
+ cpi 'a' ;[pcc007] if not lower case its ok
+ jm cmifi8 ;[pcc007] (DEL never gets here)
+ cpi 'z'+1 ;[pcc007] only convert letters
+ jp cmifi8 ;[pcc007]
+ ani 137O ;Capitalize.
+cmifi8: lhld cmfcb2 ;Get the pointer into the FCB.
+ mov m,a ;Put the char there.
+ inx h
+ shld cmfcb2
+ inr e
+ jmp cmifi1
+
+cmifi9: lda cmstat
+ cpi cmifin ;"silent"?
+ jz r ;Yes,let him go w/o check
+ lxi d,cmer02
+cmif10: mvi c,prstr
+ call bdos
+ ret
+
+cmif11: lxi d,cmer03 ;Complain about wildcards.
+ jmp cmif10
+
+;
+
+; copy filename from buffer
+; called with HL = destination, A = position (0-3) in buffer
+; called by: cmifil
+
+fspcop: push psw ;Save A.
+ lxi d,buff ;Get the right offset in the buffer.
+ rlc
+ rlc
+ rlc
+ rlc
+ rlc
+ add e
+ inr a ;Bypass drive spec.
+ mov e,a
+ mvi b,11 ;Copy file name.
+fspcp1: ldax d
+ inx d
+ mov m,a
+ inx h
+ dcr b
+ jnz fspcp1
+ pop psw ;Restore A.
+ ret
+
+; append character in A to command buffer
+; called by: cmifil
+
+cmfput: push h ;Save H.
+ lhld cmcptr ;Get buffer pointer.
+ mov m,a ;Store in buffer.
+ inx h
+ shld cmcptr
+ lxi h,cmccnt ;Count it.
+ inr m
+ pop h ;Restore H.
+ ret
+;
+; Read characters from the command buffer.
+; called by: cmtext, cmcfrm, cmkeyw, cmifil
+
+cmgtch: push h
+ push b
+cmgtc1: lda cmaflg
+ ora a ;Is it set.
+ cz cminbf ;If the action char flag is not set get more.
+ lhld cmdptr ;Get a pointer into the buffer.
+ mov a,m ;Get the next char.
+ inx h
+ shld cmdptr
+ cpi ' ' ;Is it a space?
+ jz cmgtc2
+ cpi tab ;Or a tab?
+ jnz cmgtc3
+cmgtc2: lda cmsflg ;Get the space flag.
+ ora a ;Was the last char a space?
+ jnz cmgtc1 ;Yes, get another char.
+ mvi a,0FFH ;Set the space flag.
+ sta cmsflg
+ mvi a,' '
+ pop b
+ pop h
+ jmp cmgtc5
+
+cmgtc3: push psw
+ xra a
+ sta cmsflg ;Zero the space flag.
+ pop psw
+ pop b
+ pop h
+ cpi esc
+ jz cmgtc5
+ cpi '?' ;Is the user curious?
+ jz cmgtc4
+ cpi cr
+ jz cmgtc4
+ cpi lf
+ jz cmgtc4
+ cpi ff
+ rnz ;Not an action char, just return.
+cmgtc4: push h
+ lhld cmdptr
+ dcx h
+ shld cmdptr
+ pop h
+cmgtc5: ori 80H ;Make the char negative to indicate it is
+ ret ;a terminator.
+;
+; Read characters from console into command buffer, processing
+; editing characters (^H, ^M, ^J, ^L, ^U, ^X, ?, del).
+; called by: comnd, cmgtch
+
+cminbf: push psw
+ push d
+ push h
+ lda cmaflg ;Is the action char flag set?
+ ora a
+ jnz cminb9 ;If so get no more chars.
+cminb1: lxi h,cmccnt ;Increment the char count.
+ inr m
+ mvi c,conin ;Get a char.
+ lda cmqflg ;[MF]but do we want it echoed?
+ ora a ;[MF]...
+ jz cmin1b ;[MF]Yup, proceed normally
+cmin1c: mvi e,0ffH ;[MF]Nope, do it with Direct
+ mvi c,dconio ;[MF]Console I/O
+ call bdos ;[MF]...
+ ora a ;[MF]Did the user type anything?
+ jz cmin1c ;[MF]No, don't go on until he/she does.
+ jmp cmin1a ;[MF]We got a character
+cmin1b: call bdos
+cmin1a: lhld cmcptr ;Get the pointer into the buffer.
+ mov m,a ;Put it in the buffer.
+ inx h
+ shld cmcptr
+ cpi 25O ;Is it a ^U?
+ jz cmnb12 ;Yes.
+ cpi 30O ;Is it a ^X?
+ jnz cminb2
+cmnb12: call clrlin ;Clear the line.
+ call prprmp ;Print the prompt [Toad Hall]
+ lxi h,cmdbuf
+ shld cmcptr ;Reset the point to the start.
+ lxi h,cmccnt ;Zero the count.
+ mvi m,0
+ jmp repars ;Go start over.
+
+cminb2: cpi 10O ;Backspace?
+ jz cminb3
+ cpi del ;or Delete?
+ jnz cminb4
+ lda cmqflg ;[MF]If we are echoing characters,
+ ora a ;[MF]...
+ cz delchr ;Print the delete string. [MF]
+cminb3: lda cmccnt ;Decrement the char count by two.
+ dcr a
+ dcr a
+ ora a ;Have we gone too far?
+ jp cmnb32 ;If not proceed.
+ mvi c,conout ;Ring the bell.
+ mvi e,bell
+ call bdos
+ jmp cmnb12 ;Go reprint prompt and reparse.
+
+cmnb32: sta cmccnt ;Save the new char count.
+ lda cmqflg ;[MF]Echoing characters?
+ ora a ;[MF]If we are, then
+ cz clrspc ;Erase the character. [MF]
+ lhld cmcptr ;Get the pointer into the buffer.
+ dcx h ;Back up in the buffer.
+ dcx h
+ shld cmcptr
+ jmp repars ;Go reparse everything.
+
+cminb4: cpi '?' ;Is it a question mark.
+ jz cminb6
+ cpi esc ;Is it an escape?
+ jz cminb6
+ cpi cr ;Is it a carriage return?
+ jz cminb5
+ cpi lf ;Is it a line feed?
+ jz cminb5
+ cpi ff ;Is it a formfeed?
+ jnz cminb8 ;no - just store it and
+ ;test if buffer overflowing, else get another character.
+ call clrtop
+cminb5: lda cmbflg ;[MF]Allowing initial blank word (<cr>)?
+ ora a ;[MF]...
+ jnz cminb6 ;[MF]Yes
+ lda cmccnt ;Have we parsed any chars yet?
+ cpi 1
+ jz prserr ;If not, just start over.
+cminb6: mvi a,0FFH ;Set the action flag.
+ sta cmaflg
+ jmp cminb9
+
+cminb8:
+ lda cmccnt ; get the command character count
+ cpi cmbufl ; check for comand buffer length
+ jm cminb1 ; if less, then all ok
+ mvi e,bell ; else beep at user
+ call outcon ; send it to the console
+ lda cmccnt ; back up one character
+ dcr a
+ sta cmccnt
+ lhld cmcptr ; ditto pointer
+ dcx h
+ shld cmcptr ; save it again
+ jmp cminb1 ; and try again
+
+cminb9: pop h
+ pop d
+ pop psw
+ ret
+;
+;Little utility to print the prompt. (We do a LOT of these.) [Toad Hall]
+;Enters with nothing.
+;Destroys HL (and I suppose B and DE and A).
+
+prprmp: mvi e,cr ; do a cr first
+ mvi c,dconio
+ call bdos
+ lhld cmprmp ;Get the prompt.
+ xchg
+ call prtstr
+ ret
+
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FOR RELEASE!
+
+; org ($+100h) AND 0FF00H
+
+
+IF lasm
+LINK CPSUTL
+ENDIF ;lasm [Toad Hall]
diff --git a/src/cpscom.asm b/src/cpscom.asm
new file mode 100644
index 0000000..7f2a57a
--- /dev/null
+++ b/src/cpscom.asm
@@ -0,0 +1,1371 @@
+; CPSCOM.ASM
+; 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 some of the main loop commands, all SET xxx and
+; status routines. File split from CPSMIT.ASM as that file
+; was getting too big.
+;
+; revision history:
+;
+;edit 13, 25-Mar-1991 by MF. Require confirmation if a STAY command
+; (code at "noexit") is given and a question-mark is entered.
+;edit 12, 21-Mar-1991 by MF. Change SET COLLISSION REPLACE to
+; SET COLLISION OVERWRITE to conform with C-Kermit. Modify SET COLLISION
+; help text slightly.
+
+;edit 11, 27-Feb-1991 by MF. Show Kermit version in VERSION command
+; ("shover").
+;edit 10, 12-Feb-1991 by MF. Modified OUTPUT command to get a "confirm"
+; after accepting the string to be output so that the OUTPUT command
+; doesn't immediately execute if a terminator other than <cr> is typed
+; (immediate execution confuses some users new to Kermit). This
+; situation should seldom, if ever, occur, as the OUTPUT command
+; is most likely to be executed in a TAKE-file but one should
+; protect oneself, shouldn't one?
+; Also commented out case-sensivity code as it is unlikely to be used.
+;edit 9, 4-Dec-1990 by MF. Add "stautr" routine to display Autoreceive
+; status in SHOW/STATUS/<ESC>S commands.
+;edit 8, 30-Nov-1990 by MF. Modify routine "statvt" (terminal status) to
+; display setting of "quiet" switch. Although I presume that Mr.
+; Schou thought the code would accommodate display of QUIET or
+; REGULAR, the code does not in fact allow this since the emulation
+; flag is not involved in the "quiet" setting.
+; Also fix SET TERMINAL's help text a bit.
+;edit 7, 8-Nov-1990 by MF. In SET {RECEIVE/SEND} PACKET-LENGTH routines,
+; call utility routine subbc from CPSUTL.ASM to do 16-bit subtraction
+; rather than doing it in-line to save a few bytes. Eliminate
+; commented-out instructions.
+;edit 6, 1-Nov-1990 by MF. Changed SET BAUD-RATE to SET SPEED in the quest
+; for uniformity of nomenclature (per request of FDC).
+;edit 5, 17-Oct-1990 by MF. Change SET {RECEIVE SEND} PACKET-SIZE to
+; SET {RECEIVE SEND} PACKET-LENGTH to conform with the nomenclature
+; suggested in Chapter 10 of the 6th edition of the Kermit Protocol
+; Manual.
+;edit 4, 14-Sep-1990 by MF. Implemented SET FILE-COLLISION (SET COLLISION)
+; command (except for SET COLLISION ASK and SET COLLISION APPEND).
+; How one APPENDs to a CP/M file depends upon whether it's ASCII or
+; BINARY -- something we may not know.
+; Also implemented SET INCOMPLETE-FILE command.
+; Let's also restore SET FILE-MODE DEFAULT: I never use it but if
+; we leave the DEFAULT code, as Version 4.09 does, the user is entitled
+; to be able to select it if he/she wishes (I'd favor getting rid
+; of it altogether but as soon as I did that, someone'd come out
+; of the woodwork and complain vehemently that he/she **likes**
+; SET FILE-MODE DEFAULT and would the so-and-so who took it out
+; please put it back in. Such is life. In any case, the user can
+; always set the file-mode from a take-file.
+;edit 3, 9-Sep-1990 by MF. Implemented setting of packet sizes for
+; packets up thru length 94 characters for SEND and RECEIVE. Even
+; for standard-length packets, variable sizes are useful.
+; Correct 16-bit subtraction in stspks/strpks to set carry if needed
+; Also corrected bug in routine getnp wherein a JMP KERMIT
+; instruction was left out after trying to parse a confirm, thus
+; skipping loading of number into HL.
+; Fixed bug in PRTSTR wherein BC/HL were not saved under certain
+; conditions, thus causing garbage to appear when PRTSTR was
+; called with QUIETD set.
+; edit 2, September 10, 1987, by OBSchou. Changed SET IBM to reset the
+; flow control flag. IBMs use 13h as a turnaround character (so they
+; say) so no flow control. Anybody willing to add comments etsc, as I
+; have NO IDEA what IBMs do or need.
+; Also removed the SET FILE-MODE DEFAULT option, as it always causes
+; so much trouble. Assume the default mode to be ASCII. Moved a test
+; for key pressed from the status routine to the CPSUTL file.
+;
+; edit 1, April 8th, 1987.
+; Hived off the SET command etc from CPSMIT.ASM to
+; make a more manageable file
+
+
+comver: db 'CPSCOM.ASM (13) 25-Mar-1991$' ;name, edit no. and date
+;
+;
+; This is the SET command.
+
+setcom: lxi d,settab ;Parse a keyword from the set table.
+ lxi h,sethlp
+ call keycmd
+ xchg ; Get result (dispatch address) into HL
+ pchl ; Dispatch.
+
+settab: db 26 ;[pcc013] 16 entries [Toad Hall] [9], now 17
+ ;[11] removed XMIT and added CASE and FLOW-CTL
+ ; Value is address of processing routine.
+ ;[14] removed SET CASE-SENSITIVE for now
+ ;[DRJ] Added SET USER. settab = 22
+ ;[OBS] Added SET AUTORECEIVE.
+ ; and SET NO-EXIT. settab = 24
+ ;[MF]Added SET COLLISION, settab=25
+ ;[MF]Added Set Incomplete settab=26
+ db 11, 'AUTORECEIVE$'
+ dw setaut
+ db 16, 'BLOCK-CHECK-TYPE$'
+ dw blkset
+ db 11, 'BUFFER-SIZE$'
+ dw setbuf
+; db 14, 'CASE-SENSITIVE$' ;[10]
+; dw setcase ;[10]
+ db 9,'COLLISION$' ;[MF]
+ dw setcol ;[MF]
+ db 5, 'DEBUG$'
+ dw setdbg
+ db 12, 'DEFAULT-DISK$'
+ dw setdisk
+ db 19, 'DIRECTORY-FILE-SIZE$'
+ dw hidef
+ db 6, 'ESCAPE$'
+ dw escape
+ db 9, 'FILE-MODE$'
+ dw setcpm
+ db 12, 'FLOW-CONTROL$' ;[10]
+ dw setflo ;[10]
+ db 3, 'IBM$'
+ dw ibmset
+ db 16,'INCOMPLETE-FILES$'
+ dw setinc ;[MF]Set Incomplete
+ db 10, 'LOCAL-ECHO$'
+ dw locall
+ db 7, 'LOGGING$' ;[pcc013]
+ dw setlog ;[pcc013]
+ db 7, 'NO-EXIT$'
+ dw noexit
+ db 6, 'PARITY$'
+ dw parset
+ db 4, 'PORT$'
+ dw prtset
+ db 7, 'PRINTER$'
+ dw setprn
+ db 7, 'RECEIVE$' ;[gnn]
+ dw setrec ;[gnn]
+ db 4, 'SEND$' ;[gnn]
+ dw setsnd ;[gnn]
+ db 5, 'SPEED$';[MF]
+ dw baud
+ db 7, 'TACTRAP$'
+ dw settac
+ db 8, 'TERMINAL$'
+ dw vt52em
+ db 5, 'TIMER$'
+ dw settim
+ db 4, 'USER$' ;[DJR]
+ dw user ;[DJR]
+ db 7, 'WARNING$'
+ dw filwar
+
+; help message for SET command. Caps indicate keywords
+
+sethlp: db cr,lf,'AUTORECEIVE to automatically re-receive files'
+ db cr,lf,'BLOCK-CHECK-TYPE for error detection'
+ db cr,lf,'BUFFER-SIZE for multi-sector buffering'
+; db cr,lf,'CASE-SENSITIVE to equate lower and upper case' ;[10]
+ db cr,lf,'COLLISION to specify action for filename conflicts'
+ db cr,lf,'DEBUG message control'
+ db cr,lf,'DEFAULT-DISK to receive data'
+ db cr,lf,'DIRECTORY-FILE-SIZE when displaying directories'
+ db cr,lf,'ESCAPE character during CONNECT'
+ db cr,lf,'FILE-MODE for outgoing files'
+ db cr,lf,'FLOW-CONTROL to set XON/XOFF flow control' ;[10]
+ db cr,lf,'IBM mode: parity and turn around handling'
+ db cr,lf,'INCOMPLETE-FILE disposition'
+ db cr,lf,'LOCAL-ECHO (half-duplex)'
+ db cr,lf,'LOGGING of terminal sessions' ;[pcc013]
+ db cr,lf,'NO-EXIT to prevent exit to CP/M after a command tail'
+ db cr,lf,'PARITY for communication line'
+ db cr,lf,'PORT to communicate on'
+ db cr,lf,'PRINTER copy control'
+ db cr,lf,'RECEIVE parameters' ;not all currently implemented
+ db cr,lf,'SEND parameters' ;Ditto
+ db cr,lf,'SPEED of communication line'
+ db cr,lf,'TAC interface support'
+ db cr,lf,'TERMINAL to set a terminal type'
+ db cr,lf,'TIMER control'
+ db cr,lf,'USER to set a user number' ;[DJR]
+ db cr,lf,'WARNING for filename conflicts'
+ db '$'
+
+;
+; SET AUTORECEIVE on/off command
+setaut: call onoff ; set it either on or off
+ sta autorc ; and save the flag
+ jmp kermit ; and do next command
+
+;SET BLOCK-CHECK-TYPE command.
+
+blkset: lxi d,blktab ;Get the address of the block-check table
+ lxi h,blkhlp ;And the address of the help text
+ call chkkey ;Go check input (val returns in A).
+ sta chktyp ;Save desired checksum type
+ jmp kermit ;Go get another command
+
+blktab: db 3 ;Three entries.
+ db 20, '1-CHARACTER-CHECKSUM$', '1','1'
+ db 20, '2-CHARACTER-CHECKSUM$', '2','2'
+ db 21, '3-CHARACTER-CRC-CCITT$', '3','3'
+
+blkhlp: db cr,lf,'1-CHARACTER-CHECKSUM'
+ db cr,lf,'2-CHARACTER-CHECKSUM'
+ db cr,lf,'3-CHARACTER-CRC-CCITT$'
+
+;
+; This is the SET BUFFER-SIZE command.
+; Sets to maximum number of sectors to use for multiple sector
+; buffering. Sorts a lot f problems on some slow disc-access machines..
+setbuf: mvi a,cmnum ; get a number from the user
+ call comnd
+ jmp kermit ; error if nothing
+ lhld number ; get the value
+ mov a,h
+ ana a
+ jnz setbu1 ; if number greater than 255 then error
+ lda maxbsc ; get maximum no sectors allowed by system
+ cmp l ; set flags from a-l
+ jm setbu1 ; if l > a then error
+ mov a,l ; only ls bits used
+ sta bufsec
+ jmp kermit
+
+setbu1: lxi d,erms25
+ call prtstr
+ jmp kermit
+
+
+;SET DEFAULT DISK command
+
+setdisk:lxi d,fcb
+ mvi a,cmifin ;get "file-spec" silently
+ call comnd
+ jmp setdi1
+setdi1: lda fcb
+ ora a ;Was a drive specified? (if zero, no)
+ jnz setdi2 ;he typed a drive-spec
+ lda curdsk ;he didn't - give him default
+setdi2: sta curdsk
+ mvi c,inbdos ;reset disks
+ call bdos
+ lda curdsk
+ dcr a ;LOGDSK is relative 0
+ mov e,a
+ mvi c,logdsk
+ call bdos ;and "LOG" it
+ jmp kermit ;all done
+;
+;SET SEND command. Sort of supported
+
+setsnd: lxi d,stsntb ;Parse a keyword from the set send table.
+ lxi h,stshlp
+ call keycmd
+ xchg ; Get dispatch address into HL
+ pchl ; Go for it.
+
+stsntb: db 4 ;Two entries. four entries
+ db 8, 'PAD-CHAR$'
+ dw stspac
+ db 7, 'PADDING$'
+ dw stspad
+ db 15, 'START-OF-PACKET$' ;[gnn]
+ dw stssop ;[gnn]
+ db 13,'PACKET-LENGTH$' ;
+ dw stspks ;
+; db 9,'CHECKTYPE$' ;
+; dw stsckt ;
+
+stshlp: db cr,lf,'PAD-CHAR to define the pad character to use'
+ db cr,lf,'PADDING to define the number of PAD-CHAR to use'
+ db cr,lf,'START-OF-PACKET to define the start of packet character' ;[gnn]
+ db cr,lf,'PACKET-LENGTH for the length of transmitted packet';
+; db cr,lf,'CHECKTYPE to define the check-type to use';[21]
+ db '$' ;[gnn]
+
+; SET SEND START-OF-PACKET [gnn]
+stssop: call cfmcmd
+ lxi d,sopmes
+ call prtstr
+ mvi c,conin
+ call bdos
+ sta sndsop
+ jmp kermit
+
+; SET SEND PADDING command. does nothing. get value to dspad
+stspad: call getnp ; get the number of padding characters
+ sta dspad ; save ad default send no. pad characters
+ jmp kermit
+
+; SET SEND PAD-CHAR command. does nothing. gets char to dspadc
+stspac: call getpad ; get the character to use
+ sta dspadc ; save as default send pad character
+ jmp kermit
+
+; SET SEND PACKET-LENGTH command. Max 95, but could be more for long pkts...
+stspks: call getnp ; get number into hl
+ lxi b,(maxpkt-1) ;[MF] One below upper limit of packet-size
+ push h ;[MF] Save number
+ call subbc ;[MF] Do 16-bit subtraction, even though
+ ;[MF] getnp puts low-order bits in a,
+ ;[MF] in case long packets are
+ ;[MF] implemented
+ pop h ;[MF] Restore number
+ lxi d,erms26 ; packet length to long error
+ jnc stspk1
+ mov a,l
+ sta spsiz ;[MF] Save as default send packet length
+ jmp kermit
+stspk1: call prtstr
+ jmp kermit ; error exit
+
+; SET SEND CHECKTYPE command. Accepts 1,2 or 3
+stsckt: call getnp ; get a number
+ cpi 4 ; if more than 3 then error
+ jnz stsck1
+stsck2: lxi d,erms27 ; checktype wrong
+ jmp kermit
+stsck1: cpi 0 ; error also for null
+ jz stsck2
+ adi 30h ; make it printable
+ sta sdckt ; save as default send checktype
+ jmp kermit
+
+
+;SET RECEIVE command. [gnn]
+setrec: lxi d,strctb ;Parse a keyword from the set rec table.
+ lxi h,stshlp ; use same help for send and receive
+ call keycmd
+ xchg ; Get dispatch address into HL
+ pchl ; Go for it.
+
+strctb: db 4 ; Three entries. four entries
+ db 8, 'PAD-CHAR$'
+ dw strpac ; use dummy entry of set send
+ db 7, 'PADDING$'
+ dw strpad ; use dummy entry of set send
+ db 15,'START-OF-PACKET$'
+ dw strsop
+ db 13,'PACKET-LENGTH$' ;
+ dw strpks ;
+; db 9,'CHECKTYPE$' ;
+; dw strckt ;
+
+; SET RECEIVE START-OF-PACKET
+strsop: call cfmcmd
+ lxi d,sopmes
+ call prtstr
+ mvi c,conin
+ call bdos
+ sta rcvsop
+ jmp kermit
+
+; SET RECEIVE PADDING
+strpad: mvi a,cmnum ; go parse a number
+ call comnd ; get it
+ jmp kermit ; duff entry, so die
+ mvi a,cmcfm ; ask to confirm
+ call comnd
+ lhld number ; get the number of padding charaters
+ mov a,l ; assume 255 or less
+ sta dspad ; save ad default send no. pad characters
+
+; SET SEND RECEIVE routines
+getpad: call cfmcmd
+ lxi d,padcms ; tell user we want the pad character
+ call prtstr
+ mvi c,conin ; get it verbatum
+ call bdos
+ ret
+
+; SET RECEIVE PAD-CHAR routine
+strpac: call getpad ; get the character to use
+ sta drpadc ; save it
+ jmp kermit
+
+; SET RECEIVE PACKET-LENGTH. Max 95, but could be more for long pkts...
+strpks: call getnp ; get number into hl
+ lxi b,(maxpkt-1) ;[MF] One below upper limit of packet-size
+ push h ;[MF] Save number
+ call subbc ;[MF] Do 16-bit subtraction, even though
+ ;[MF] getnp puts low-order bits in a,
+ ;[MF] in case long packets are
+ ;[MF] implemented
+ pop h ;[MF] Restore number
+ lxi d,erms26 ; packet length to long error
+ jnc strpk1
+ mov a,l
+ sta rpsiz ;[MF] Save as default receive packet-length
+ jmp kermit
+strpk1: call prtstr
+ jmp kermit ; error exit
+
+
+; SET RECEIVE CHECKTYPE
+strckt: call getnp ; get a number
+ cpi 4 ; if more than 3 then error
+ jnz strck1
+strck2: lxi d,erms27 ; checktype wrong
+ jmp kermit
+strck1: cpi 0 ; error also for null
+ jz strck2
+ adi 30h ; make it printable
+ sta rdckt ; save as default receive checktype
+ jmp kermit
+
+getnp: mvi a,cmnum ; go parse a number
+ call comnd ; get it
+ jmp kermit ; duff entry, so die
+ mvi a,cmcfm ; ask to confirm
+ call comnd
+ jmp kermit ;[MF] Die!
+ lhld number ; get the number of padding charaters
+ mov a,l ; assume 255 or less
+ ret ; return to caller
+
+
+; SET NO-EXIT on/off. Sets a flag to prevent automatically dropping
+; back to CPM after a command tail has been "done". No other use.
+noexit: call cfmcmd ;[MF]Get a "confirm" in case here via STAY
+ xra a
+ sta nexitf ; no exit to CP/M
+ jmp kermit
+
+;[pcc013]
+; This is the SET LOGGING ON/OFF subcommand
+
+setlog: call onoff ;[pcc013] Get on/off
+ sta logflg ;[pcc013] Store flag
+ jmp kermit
+;
+; This is the SET ESCAPE character subcommand.
+
+escape: call cfmcmd
+ lxi d,escmes ;Get the address of the escape message.
+ call prtstr
+ mvi c,conin ;Get the char.
+ call bdos
+ sta escchr ;Store the new escape character.
+ jmp kermit
+
+; This is the SET LOCAL-ECHO subcommand.
+
+locall: call onoff ;Get on/off setting [Toad Hall]
+ sta ecoflg ;Store local echo flag.
+ jmp kermit
+
+; This is the SET PRINTER ON/OFF subcommand
+
+setprn: call onoff ;Get on/off setting [Toad Hall]
+ sta prnflg ;Store printer flag
+ jmp kermit
+
+; This is the SET DEBUG ON/OFF subcommand
+
+setdbg: call onoff ;Get on/off setting [Toad Hall]
+ sta dbgflg ;Store debug flag
+ jmp kermit
+
+;[jd] this is the SET TIMER subcommand
+
+settim: call onoff ;Get on/off setting [Toad Hall]
+ sta timflg ;Store timer flag value
+ jmp kermit
+
+;This is the SET FILE-WARNING subcommand
+
+filwar: call onoff ;Get on/off setting [Toad Hall]
+ sta flwflg ;Store file-warning flag.
+ jmp kermit
+
+;[MF]This is the SET COLLISION subcommand
+;[MF]First, the requisite tables:
+;
+coltab: db 4 ;[MF]4 entries
+ db 6,'BACKUP$',02h,02h
+ db 7,'DISCARD$',03h,03h
+ db 9,'OVERWRITE$',00h,00h
+ db 6,'RENAME$',01h,01h
+;
+colhlp: db cr,lf,'BACKUP (rename) existing files'
+ db cr,lf,'DISCARD new versions of existing files'
+ db cr,lf,'OVERWRITE existing files'
+ db cr,lf,'RENAME new versions of existing files'
+ db '$'
+;
+;[MF]Now the routine proper
+;
+setcol: lxi d,coltab ;[MF]Table address
+ lxi h,colhlp ;[MF]Help address
+ call chkkey ;[MF]Get user's answer
+ sta flwflg ;[MF]and remember it
+ jmp kermit ;[MF]Back to main loop
+
+;[10] This is the SET FLOW-CONTROL subcommand.
+setflo: call onoff ;is it on or off
+ sta floctl ; store flow contol flag
+ jmp kermit
+
+;[10] SET CASE-SENSITIVE on or off
+;setcase:
+; call onoff ; set it on or off
+; sta casens ; save it
+; jmp kermit
+
+; SET FILE-SIZE on or off. If on, then show file size during DIR
+;
+hidef: call onoff ; see if on or off
+ sta hidefs
+ jmp kermit
+
+;
+; This is the SET IBM command.
+;
+; If SET IBM ON, we should do
+; 1) Flow Control = off
+; 2) Parity = mark
+; 3) Local echo = on
+; 4) Timer = on
+;
+; If SET IBM OF, we should assume (& do)
+; 1) Flow control = off (default)
+; 2) Parity = none
+; 3) Local Echo = off
+; 4) Timer = off
+
+
+ibmset: call onoff ;Get on/off setting [Toad Hall]
+ sta ibmflg ;Store IBM flag.
+ ora a ;Is it turned on?
+ jz ibmst1 ;If not, set parity to the default.
+;
+; SET IBM ON code
+ mvi a,ibmpar ;Get the IBM parity.
+ sta parity
+ mvi a,1 ;Set local echo on.
+ sta ecoflg
+ sta timflg ; also set timer on
+ xra a ; no flow control
+ sta floctl
+ jmp ibmst2 ; exit
+;
+; SET IBM OFF code
+
+ibmst1: mvi a,defpar ; set default parity (none)
+ sta parity
+ xra a ;Set local echo off.
+ sta ecoflg
+ sta timflg ;[jd] timer is same as local echo
+ sta floctl ;[obs] set flow control off
+ibmst2: jmp kermit ; exit from here
+
+;
+; SET FILE-MODE command.
+;[OBS] assume only ascii and binary, no default.
+
+setcpm: lxi d,typtab
+ lxi h,typhlp
+ call chkkey ;Get and confirm keyword, or die trying
+ sta cpmflg ;Set the CPM flag.
+ jmp kermit
+
+typtab: db 3 ;Three entries, now two entries
+ ;[MF]Now 3 again!
+ db 5, 'ASCII$', 01H,01H
+ db 6, 'BINARY$', 02H,02H
+ db 7, 'DEFAULT$', 00H,00H ; Default
+
+typhlp: db cr,lf,'ASCII BINARY DEFAULT'
+ db '$'
+;
+;setinc - Set Incomplete-file [MF]
+;
+setinc: lxi d,inctab ;[MF]Point to tables
+ lxi h,inchlp ;[MF]...
+ call chkkey ;[MF]Get user's answer or croak
+ sta incflg ;[MF]Remember the answer
+ jmp kermit ;[MF]We are done.
+;
+inctab: db 2 ;two entries
+ db 7,'DISCARD$'
+ db 00h,00h ;Discard incomplete files
+ db 4,'KEEP$'
+ db 01h,01h ;Keep incomplete files
+;
+inchlp: db cr,lf,'DISCARD KEEP'
+ db '$'
+
+; This is the SET PARITY subcommand.
+
+parset: lxi d,partab
+ lxi h,parhlp
+ call chkkey ;Get and confirm keyword, or die trying
+ sta parity ;Set the parity flag.
+ jmp kermit
+
+partab: db 5 ;Five entries.
+ db 4, 'EVEN$', parevn,parevn
+ db 4, 'MARK$', parmrk,parmrk
+ db 4, 'NONE$', parnon,parnon
+ db 3, 'ODD$', parodd,parodd
+ db 5, 'SPACE$', parspc,parspc
+
+parhlp: db cr,lf,'EVEN MARK NONE ODD SPACE$'
+
+; This is the SET TACTRAP subcommand.
+; options are ON, OFF, or CHARACTER. (for CHARACTER, we request the
+; new TAC Intercept character, and turn the TACtrap on)
+
+settac: lxi d,tactab
+ lxi h,tachlp
+ call chkkey ;Get and confirm keyword
+ ora a ;Was it "OFF" (zero)?
+ jz settc2 ;If so, go disable TACtrap.
+ cpi 1 ;Was it "ON"?
+ jz settc1 ;If so, go enable TACtrap.
+ lxi d,tacmes ;"CHARACTER". request new TAC Intercept char.
+ call prtstr
+ mvi c,conin ;Get the char.
+ call bdos
+ sta tacchr ;Store the new TAC Intercept character.
+settc1: lda tacchr ;Copy tacchr to tacflg to enable TACtrap.
+settc2: sta tacflg ;Enable/disable TACtrap
+ jmp kermit
+
+tactab: db 3 ;Three entries.
+ db 9, 'CHARACTER$', 02H,02H
+ db 3, 'OFF$', 00H,00H
+ db 2, 'ON$', 01H,01H
+
+tachlp: db cr,lf,'ON to enable TAC trap'
+ db cr,lf,'OFF to disable TAC trap'
+ db cr,lf,'CHARACTER to enable TAC trap and'
+ db ' specify intercept character$'
+
+; This is the SET VT52-EMULATION subcommand.
+; Now SET TERMINAL xxx
+;vt52em: lda vtflg ;get the flag value
+; cpi 0ffH ;0ffH means not allowed -
+; jz notimp ; say it's not implemented.
+; call onoff ;Get keyword (ON or OFF)
+; sta vtflg ;Set the VT52 emulation flag.
+; jmp kermit
+vt52em: lxi d,sttert ; set terminal type
+ lxi h,stterh ; help table
+ call chkkey ; get it
+ mov a,d ; value returned in DE
+ cpi vtdefe ; was it selecting an external terminal?
+ jnz vt52e1 ; no, so save new value
+ lhld extern+1 ; if external, lets see if one is in place
+ mov a,h
+ ora l
+ mvi a,vtdefe ; restore external flag
+ jnz vt52e1 ; we have one, so we can save value
+ call prcrlf
+ lxi d,inms11 ; load up sorry message
+ call prtstr
+ jmp kermit
+
+vt52e1: cpi 40h ; are we to have a quiet display?
+ jnz vt52e2
+ sta quietd ; store it
+ jmp kermit
+
+vt52e2: cpi 80h ; are we to be a noisy display?
+ jnz vt52e3
+ xra a
+ sta quietd
+ jmp kermit
+
+vt52e3: sta vtflg ; else save new set parameter..
+ jmp kermit ; and exit
+
+; tabe with string entry, and the returned value as two identical bytes.
+sttert: db 6 ; six types
+ db 4,'DUMB$',vtdefd,vtdefd ; assume our terminal is thick
+ db 8,'EXTERNAL$',vtdefe,vtdefe ; assume off, but terminal is in dep. code
+ db 5,'QUIET$',40h,40h ; display quiet
+ db 7,'REGULAR$',80h,80h ; display loud
+ db 3,'OFF$',vtdefo,vtdefo ; assume our terminal does everything
+ db 4,'VT52$',vtdefv,vtdefv ; VT52 as before
+
+stterh: db cr,lf,'DUMB - only printable characters passed to terminal'
+ db cr,lf,'EXTERNAL - with emulation code system specific'
+ db cr,lf,'OFF - all characters passed to terminal'
+ db cr,lf,'QUIET - display nothing during transfers'
+ db cr,lf,'REGULAR - normal display for transfers'
+ db cr,lf,'VT52 - assume Kermit can emulate a VT52'
+ db '$'
+
+;
+; Note: For the SET BAUD and SET PORT commands, which might not be
+; supported for the current system, the command tables are stored in
+; the overlay. We locate them through pointers in the linkage area:
+; spdtab for SET BAUD, prttab for SET PORT. The contents of spdtab
+; (or prttab) is the address of the beginning of the table (the table
+; does NOT begin at spdtab). If the address is zero, the command is
+; not supported. If the table address is nonzero, then there is a
+; corresponding help message pointed to by (NOT starting at) spdhlp
+; or prthlp.
+
+; This is the SET BAUD command
+
+baud: lhld spdtab ; get pointer to speed table
+ mov a,h
+ ora l ; test for NULL (zero)
+ jz notimp ; if so, say it's not implemented
+ xchg ; move speed table address to DE
+ lhld spdhlp ; get pointer to speed help text
+ call keycmd
+ push d ; save selected speed
+ call cfmcmd ; confirm...
+ pop h ; restore speed to HL
+ shld speed ; save all 16 bits of speed value
+ xchg ; move speed to DE
+ call sysspd ; do system-dependent speed setting.
+ jmp kermit ; return to command level
+
+; This is the SET PORT command
+
+prtset: lhld prttab ; get pointer to port table
+ mov a,h
+ ora l ; test for NULL
+ jz notimp ; not supported if pointer was null.
+ xchg ; move port table address to DE
+ lhld prthlp ; get pointer to port help text
+ call keycmd
+ push d ; save selected port entry
+ call cfmcmd ; confirm...
+ pop h ; restore table address to HL
+ shld port ;[hh] save all 16 bits of port value
+ call sysprt ; go do port stuff
+ jmp kermit
+;
+; Subroutines for SET subcommands
+
+; ontab - command table for onoff.
+; onhlp - help text for onoff.
+; onoff - accept "ON" or "OFF" keyword.
+; returns:
+; success: value in A (non-zero = ON)
+; error: no return to caller. print error message and return to
+; main loop.
+ontab: db 2 ;Two entries.
+ db 3, 'OFF$', 00H,00H
+ db 2, 'ON$', 01H,01H
+
+onhlp: db cr,lf,'OFF ON$'
+
+onoff: lxi d,ontab
+ lxi h,onhlp
+ ;Fall through to check input. [Toad Hall]
+
+; chkkey - parse and confirm keyword.
+; called with:
+; DE/ address of keyword table
+; HL/ address of help text
+; returns:
+; success: low byte of keyword value (from table) in A.
+; error: no return to caller. print error message and return to
+; main loop. (Since the main loop reloads the stack pointer,
+; we don't have to attempt to clean up the stack here)
+
+chkkey: call keycmd ; Parse a keyword (might not return)
+ sta temp1 ; Save the parsed value
+ call cfmcmd ; Request confirmation (might not return)
+ lda temp1 ; Get saved value
+ ret ; Return
+
+;[hh] fndkyw - find a keyword string from a table using
+; it's associated value
+; called with:
+; HL/ address of keyword table
+; A/ value associated with keyword string
+; returns:
+; success: HL points to first byte of keyword string
+; CY flag is cleared
+; error: HL points to error string (?Not found)
+; CY flag is set
+
+fndkyw: mov d,m ;get count of entries
+ inx h ;advance over count value
+fndkw1: mov b,m ;get string length
+ inr b ;account for $
+ inx h ;advance over length value
+ shld temp1 ;save string pointer
+fndkw2: inx h ;loop over string
+ dcr b
+ jnz fndkw2
+ mov c,m ;get keyword value from table
+ cmp c ;do they match?
+ jz fndkw3 ;Yup
+ inx h ;bump to next keyword
+ inx h ;
+ dcr d ;decrement entry count
+ jnz fndkw1 ;check the remaining keywords
+ lxi h,kywdnf ;point to not found message
+ stc ;give calling routine a not found flag
+ ret
+fndkw3: ora a ;clear CY to tell caller we succeeded
+ lhld temp1 ;restore the saved string pointer
+ ret
+
+kywdnf: db cr,lf,'?Not found$' ;not found message
+
+;
+; This is the SHOW command.
+
+show: call cfmcmd
+;* Reconcile this and status.
+ call clrtop ;[hh] Clear screen first
+ call stat01 ;For now just cop out.
+ jmp kermit
+
+; This is the STATUS command.
+
+status: call cfmcmd
+ call clrtop ;[hh] Clear screen first
+ call stat01
+ jmp kermit
+
+; processor for SHOW, STATUS and <escape>S commands
+; called by: show, status, intchr
+
+stat01: lda fileio ;Are we in transmit?
+ ora a
+ jz sta01b ;No
+ lxi d,xmtst ;Yes,say so
+ call prtstr
+
+; The following block of code - down to RET - re-ordered by [DJR]
+; DJR January 1987 to get SHOW/STATUS output in the same [DJR]
+; (alphabetical) order as SET's HELP. [DJR]
+sta01b:
+ call stautr ;[MF]Show AUTORECEIVE state
+ call stabcc ; Tell current block check type
+ call stabsz ; Tell user about multi-sector buffers
+ call stacol ;[MF]COLLISION state
+ call stadbg ; [DJR] Debug mode
+ call stacurd ; [DJR] Current disk
+ call stahfs ; Tell user if file sizez are hidden during DIR
+ call staesc ; Tell current escape character
+ call stafil ; Tell about file type
+ call staflo ;[10] Tell about flow control
+ call staibm ; Tell about IBM flag
+ call stainc ;[MF]Tell about incomplete file disposition
+;
+; Ask user to press a key before continuing
+;
+ call pausit ; wait for a while till user presses a key
+;
+ call staeco ; Tell about local echo flag
+ call stalog ; [pcc003] Tell about log file status
+ call stapar ; Tell about parity
+ lhld prttab ;[hh] Got a port table? (is pointer nonzero?)
+ mov a,h ;[hh]
+ ora l ;[hh]
+ cnz stapor ;[hh] If so, tell which port we're using
+ call stalpt ; Tell about printer copy flag
+ call starps ;[MF]Show receive packet length
+ call starsp ;[gnn] tell rec. start-of-pkt char
+ call stasps ;[MF]Show send packet length
+ call stassp ;[gnn] tell send start-of-pkt char
+ lhld spdtab ; Got a speed table? (is pointer nonzero?)
+ mov a,h
+ ora l
+ cnz staspd ; If so, tell what speed we're running.
+ call statac ; Tell about TAC flag/intercept character.
+ call statim ; Tell about timer flag
+ call stusr ;[7] Tell about user
+ call statvt ; Tell about what emulation we are doing
+ call stawrn ; Tell about file-warning flag
+ ret
+
+; stautr - Show Autoreceive setting [MF]
+;
+stautr: lxi d,autrst ;[MF]Point to "Autoreceive" string
+ call prtstr ;[MF]and print it
+ lda autorc ;[MF]Get Autoreceive flag
+ jmp staton ;[MF]Say "on" or "off" and return
+
+; Show the value of the LOCAL-ECHO flag (On or Off).
+
+staeco: lxi d,locst ;Get the address of the local echo string.
+ call prtstr
+ lda ecoflg ;Get the local echo flag.
+ jmp staton ;Say ON or OFF, and return
+
+; Show the value of the VT52-EMULATION flag (On, Off, or Not Supported).
+; Also show terminal display mode (regular, quiet)
+
+statvt: lxi d,vtdpst ;[MF]Get address of terminal display string
+ call prtstr ;[MF]Print it
+ lxi d,vtdpsr ;[MF]Assume a regular (loud) display
+ lda quietd ;[MF]Get "quiet" flag
+ ora a ;[MF]a quiet display?
+ jz statva ;[MF]No, print "regular" message
+ lxi d,vtdpsq ;[MF]Yes, point to "quiet" string
+statva: call prtstr ;[MF]and print it
+ lxi d,vtemst ; Get the address of the VT52 emulation string.
+ call prtstr
+ lda vtflg ; Get the VT52 emulation flag.
+ cpi 0ffh ; isterminal emulation possible?
+ jnz statv0 ; yes, maybe
+ lxi h,inms11 ; ... no, load up not implemented message ...
+ jmp prvtv ; so tell user
+
+
+statv0: mov c,a ; save it to C
+ lxi h,sttert ; get table listing what we can do
+ mov b,m ; get number of terminal types to b
+statv1: inx h ; point to first entry
+ mov e,m ; get length of entry
+ mvi d,0
+ inx h ; point to text part of entry
+ xchg ; save address in de
+ dad d ; start + length
+ inx h ;... + 1 for the dollar...
+ inx h ; plus point to seconcd copy of ter. type value
+ cmp m ; is it the one we want?
+ jz prvtv ; yes, then print the terminal type value
+ dcr b ; have we completed?
+ rz ; yes, then just exit back to status
+ jmp statv1 ; else try next entry. HL points to next -1
+
+prvtv: jmp prtstr ; print string from DE
+ ;[MF]and return
+
+; Show the value of the FILE-MODE flag (ASCII, Binary, or Default).
+
+stafil: lxi d,cpmst ; Get the address of the file mode message.
+ call prtstr
+ lda cpmflg ; Get the file mode flag.
+ lxi d,defstr ; Assume Default (0).
+ ora a ; Is it?
+ jz prtstr ; If so, say so, and return.
+ lxi d,ascstr ; Not default, assume ASCII
+ cpi 1 ; Is it ASCII?
+ jz prtstr ; Say ASCII, and return
+ lxi d,binstr ; Not default or ASCII, must be binary
+ jmp prtstr ; Print type, and return.
+;
+;Show current disposition for incomplete files [MF]
+;
+stainc: lxi d,incst ;[MF]Announce what's to be shown
+ call prtstr ;[MF]...
+ lxi d,dscstr ;[MF]Assume "discard"
+ lda incflg ;[MF]Get flag
+ ora a ;[MF]Really discarding incomplete files?
+ jz prtstr ;[MF]Yes, say so and return
+ lxi d,kepstr ;[MF]No, say we're keeping incomplete files
+ jmp prtstr ;[MF]and return
+
+; show if file sizes are hidden during DIR (Would have thought this
+; obvious, but its in for completeness
+stahfs: lxi d,hfsod ; get hide file size on dir
+ call prtstr
+ lda hidefs
+ jmp staton ; say if on or off
+
+; Show the value of the IBM-MODE flag (On or Off).
+
+staibm: lxi d,ibmst ;IBM string.
+ call prtstr
+ lda ibmflg ; Get IBM flag.
+ jmp staton ; Print its value and return
+
+; Show the value of the FILE-WARNING flag (On or Off).
+
+stawrn: lxi d,filst ; File warning string.
+ call prtstr
+ lda flwflg ; File warning flag.
+ jmp staton ; Say ON or OFF
+
+; Show the value of the PRINTER flag (On or Off).
+
+stalpt: lxi d,prst ;Printer copy string
+ call prtstr
+ lda prnflg ;Printer ON/OFF flag
+ jmp staton ; Say ON or OFF
+
+
+; Show status of log file
+stalog: lxi d,logst ;[pcc003] Logging lead-in message
+ call prtstr ;[pcc003]
+; name of logging file
+; Code derived from [JD's] code for GET, and uses his FNBUF [DJR]
+ lxi d,fnbuf ;[DJR] point to destination
+ lxi h,lognam ;[DJR] source of filespec
+ mov a,m ;[DJR] get drive byte
+ ora a ;[DJR] zero = default disc
+ jnz stalg1 ;[DJR] if drive has been specified
+ lda curdsk ;[DJR] otherwise get the default
+stalg1: adi 'A'-1 ;[DJR] make it printable
+ stax d ;[DJR] into dest block
+ inx d ;[DJR]
+ mvi a,':' ;[DJR] colon after drive
+ stax d ;[DJR]
+ inx d ;[DJR]
+
+ mvi c,8 ;[DJR] length of name part
+ lxi h,lognam+1 ;[DJR] start of name
+ mvi b,0 ;[DJR] first-time-thru flag
+stalga: mov a,m ;[DJR] get a char from the name
+ inx h ;[DJR] pass it
+ cpi ' ' ;[DJR] end of this part of name?
+ jz stalgb ;[DJR] yes, skip rest...
+ stax d ;[DJR] else drop char into dest
+ inx d ;[DJR] increment dest ptr
+ dcr c ;[DJR] decrement count
+ jnz stalga ;[DJR] and continue if more to go
+
+stalgb: mov a,b ;[DJR]
+ ora a ;[DJR] first time thru?
+ jnz stalgc ;[DJR] no, no period
+ mvi a,'.' ;[DJR] period between parts
+ stax d ;[DJR]
+ inx d ;[DJR]
+ mvi b,0ffh ;[DJR] not first time thru anymore
+ mvi c,3 ;[DJR] length of ext part
+ lxi h,lognam+9 ;[DJR] start of extension
+ jmp stalga ;[DJR] keep copying
+
+stalgc: mvi a,'$'
+ stax d ;[DJR] end the name string
+ lxi d,fnbuf ;[DJR] Print the file name
+ call prtstr ;[DJR]
+
+ lxi d,logst2 ;[DJR] second part of message
+ call prtstr ;[DJR]
+
+; Show status of logging
+ lda logflg ;[pcc003] get the flag
+ ani 7FH ;[pcc003] ignore open flag
+ cpi 2 ;[pcc003] is it suspended?
+ jnz staton ;[pcc003] no, must be on or off
+ lxi d,susstr ;[pcc003] suspended
+ jp prtstr ;[pcc003] print and return
+
+; Show the value of the PARITY flag (Odd, Even, Mark, Space, or None).
+
+stapar: lxi d,parst ;Parity string.
+ call prtstr
+ lda parity ;Get the parity setting.
+ lxi d,pnonst ;Assume parity is NONE
+ cpi parnon ;Were we right?
+ jz prtstr ;Yep, go say None, and return
+ lxi d,pmrkst ;Get ready to say Mark
+ cpi parmrk ;Is it mark?
+ jz prtstr ;Yep, go say Mark, and return
+ lxi d,pspcst ;Get ready to say Space
+ cpi parspc ;Is it space?
+ jz prtstr ;Yep, go say Space, and return
+ lxi d,poddst ;Get ready to say Odd
+ cpi parodd ;Is it odd?
+ jz prtstr ;Yep, go say Odd, and return
+ lxi d,pevnst ;Must be Even.
+ jmp prtstr ;Say Even, and return.
+
+; [gnn] Show start of packet characters
+stassp: lxi d,sspmsg ;message of send s-o-p
+ call prtstr
+ lda sndsop
+ adi 'A'-1 ;convert to printable character
+ mov e,a
+ mvi c,conout
+ jmp bdos ;and print it
+starsp: lxi d,rspmsg ;rec. s-o-p message
+ call prtstr
+ lda rcvsop
+ adi 'A'-1 ;convert to printable character
+ mov e,a
+ mvi c,conout
+ jmp bdos ;and print it
+;
+;[MF]Show receive packet length
+;
+starps: lxi d,rpsmsg ;[MF]Point to message
+ call prtstr ;[MF]and print it
+ lda rpsiz ;[MF]Get receive packet length
+ mov l,a ;[MF]Put in HL
+ mvi h,0 ;[MF]...
+ jmp nout ;[MF]Print receive packet length in decimal
+;
+;[MF]stasps - Print send packet length
+;
+stasps: lxi d,spsmsg ;[MF]Point to message
+ call prtstr ;[MF]and print it
+ lda spsiz ;[MF]Get send packet length
+ mov l,a ;[MF]into HL
+ mvi h,0 ;[MF]...
+ jmp nout ;[MF]and print in decimal
+
+;[hh] Show the current port (if known).
+
+stapor: lxi d,porst ;[hh]
+ call prtstr ;[hh]
+ lda port ;[hh] Get current port value
+ lxi h,spdust ;[hh] Assume undefined (this error msg is fine)
+ cpi 0FFH ;[hh] Is it?
+ jz stat73 ;[hh] Yup. Say so
+ lhld prttab ;[hh] Address of port keyword table
+ call fndkyw ;[hh] Look for correct keyword string
+ jnc stpr1 ;[hh] Found a match
+ lxi h,spdust ;[hh] No match found - say it's undefined
+stpr1: jmp stat73 ;[hh] Print it and return
+
+; Show the current line speed (if known).
+
+staspd: lxi d,spdst
+ call prtstr
+ lda speed ;Get current speed.
+ lxi h,spdust ;Assume undefined.
+ cpi 0FFH ;Is it?
+ jz stat73 ;Yes.
+ lhld spdtab ;Start scanning keyword table.
+ mov d,m ; get count of entries
+ inx h ; advance over it.
+stat70: mov b,m ;Get string length.
+ inr b ;Account for $.
+ inx h
+ shld temp1 ;Save string pointer.
+stat71: inx h ;Loop over string.
+ dcr b
+ jnz stat71
+ mov c,m ;Get speed value
+ cmp c ;Match?
+ jz stat72 ;Yes.
+ inx h ;Bump to next keyword.
+ inx h
+ dcr d ; decrement entry count
+ jnz stat70 ; if more left, check them.
+ lxi h,spdust ; can't find it. say it's undefined.
+ jmp stat73 ; print the message.
+
+stat72: lhld temp1 ;Restore saved string pointer.
+ xchg ;[MF] Set into DE for display
+ call prtstr ;[MF] Print speed
+ lxi h,spdst2 ;[MF] Point to "bps" message
+stat73: xchg ;Set into DE for display.
+ jmp prtstr ; print it, and return.
+
+; Show the current BLOCK-CHECK-TYPE (1-, 2-, or 3-character).
+
+stabcc: lxi d,bckst ;Get the string
+ call prtstr ;Print "Block check type: "
+ lda chktyp ;Get the type (character 1, 2, or 3)
+ mov e,a ;Put into E
+ mvi c,conout ;Want to print it
+ call BDOS ;Do so
+ lxi d,bckst1 ;Get rest of text ("-character")
+ jmp prtstr ;Print it and return
+;
+;[MF]stacol - Print "SET COLLISION" state
+;
+stacol: lxi d,collst ;[MF]Get message
+ call prtstr ;[MF]Print it
+ lxi h,coltab ;[MF]Point to COLLISION keywords
+ lda flwflg ;[MF]Get COLLISION state
+ call fndkyw ;[MF]Get COLLISION state
+ ;[MF](Since user doesn't control flwflg
+ ;[MF]directly, no need to check for errors
+ xchg ;[MF]Prepare for printing
+ jmp prtstr ;[MF]Print COLLISION state and return
+
+; Print the current escape character
+
+staesc: lxi d,escst ;Escape string.
+ call prtstr
+ call escpr ;Print the escape char.
+; jmp prcrlf ;removed [DJR] Print CR/LF and return [Toad Hall]
+ ret ;[DJR] added
+
+; Show number proportion of buffers used in multiple sector buffering
+stabsz: lxi d,bufsz1
+ call prtstr ; do first bit of string
+ lxi h,0
+ lda bufsec
+ mov l,a ; get size used...
+ call nout ;... to screen
+ lxi d,bufsz2 ; and then say max value
+ call prtstr
+ lxi h,0
+ lda maxbsc ; get max for this system
+ mov l,a
+ call nout ;.. thence to screen
+; jmp prcrlf ; removed [DJR] cr lf and out
+ ret ;[DJR]
+
+;
+; Show the value of the TIMER flag
+statim: lxi d,timmsg ;[jd]
+ call prtstr ;[jd]
+ lda timflg
+ jmp staton ;Tell whether it's on or off.
+
+; Show internal versions (edit strings)
+shover: call cfmcmd
+ call prcrlf
+ lxi d,version ;[MF]Point to Kermit version
+ call prtstr ;[MF]and show it
+ lxi d,modmsg ;[MF]Continue the message
+ call prtstr ;[MF]...
+ call prcrlf ;[MF]End the line
+ lxi h,vertab ; Get address of version list
+shovr1: mov e,m ; Get next word from list
+ inx h
+ mov d,m ; Next version string is in DE
+ inx h
+ mov a,d ; Test for zero (end of list)
+ ora e
+ jz shovr2 ; Done with list if zero
+ push h ; Save position in list
+ call prtstr ; Not zero. Print it.
+ call prcrlf ; Follow with crlf
+ pop h ; Restore position in list
+ jmp shovr1 ; and go see if there are any more.
+
+shovr2: lhld ovlver ; Get overlay version string
+ xchg ; into DE
+ call prtstr ; Print it
+ call prcrlf ; Output crlf
+ lhld family ;[11] New entry in overlay. Get string of
+ xchg ;[11] family of machines (eg apple) and print
+ call prtstr ;[11] it. For "common" m/c do a $ only.
+ jmp kermit ; Return to main loop.
+
+; table of pointers to version strings.
+vertab: dw mitver ; CPSMIT
+ dw comver ; CPSCOM
+ dw pk1ver ; CPSPK1
+ dw pk2ver ; CPSPK2
+ dw remver ; CPSREM
+ dw server ; CPSSER
+ dw ttver ; CPSTT
+ dw cpmver ; CPSCPM
+ dw wldver ; CPSWLD
+ dw cmdver ; CPSCMD
+ dw utlver ; CPSUTL
+ dw datver ; CPSDAT
+ dw 0 ; end of list
+
+; Show TACTrap status (On or Off, and intercept character)
+statac: lxi d,tacst ;"Current TACTrap status/char: "
+ call prtstr
+ lxi d,offstr ;Assume set off
+ lda tacflg ;Get the TACTrap char/flag
+ ora a ;Is it off?
+ jz prtstr ;Yep, go print OFF...
+ mvi c,conout ;Display...
+ mov e,a ;...the current intercept char
+ call bdos
+ jmp prcrlf
+
+; Show if flow control is set on or off
+staflo: lxi d,flost ; Flow control string
+ call prtstr
+ lda floctl ; get the flag
+ jmp staton
+
+; Show if Case sensitvity is on or off
+;stasens:
+; lxi d,senst ; case sensitivity string
+; call prtstr ;
+; lda casens
+; jmp staton ; say if its on or off
+
+
+; Show the current user. (Should do this under directory...)
+stusr:
+ mvi c,usrcod
+ mvi e,0ffh ;[9] get the current user
+ call bdos
+ mov l,a ;[9] print hl as a number...
+ mvi h,0
+ push h ;[9] got the user number
+ lxi d,usrst ;[9] tell the user number
+ call prtstr
+ pop h ;[9] now do number
+ call nout ;[6] using routine for writing packet nos.
+ ret
+
+;
+;
+; [DJR] Show debug mode
+stadbg:
+ lxi d,dbgst ;[DJR] Display string
+ call prtstr ;[DJR]
+ lda dbgflg ;[DJR] load flag
+ jmp staton ;[DJR]
+
+
+; [DJR] Show default disk
+stacurd:
+ lxi d,curdst ;[DJR]
+ call prtstr ;[DJR]
+ lda curdsk ;[DJR]
+ adi 'A'-1 ;[DJR]
+ mov e,a ;[DJR]
+ mvi c,conout ;[DJR]
+ jmp bdos ;[DJR]
+
+;
+; Display current state of a boolean flag.
+; called with A/ value (zero = Off, non-zero = On)
+
+staton: lxi d,onstr ; Assume it's on.
+ ora a ; Is it on?
+ jnz prtstr ; If so, say so, then return.
+ lxi d,offstr ; No, say off.
+ jmp prtstr ; Print the string, then return.
+
+; STRING command
+; get a string from the user and send it to the host.
+string: mvi a,cmtxt ; get the text
+ lxi d,stbuff ; where to put it
+ call comnd
+ jmp kermit ; if we cannot do it, then back to command level
+ sta strcnt ; save the string count
+ ana a ; if it is zero, then do nowt
+ jz kermit
+ call cfmcmd ;[MF]Otherwise, get a "confirm"
+ call selmdm ; then select the modem
+ lxi d,stbuff ; where to get the string
+stlop: ldax d ; get byte
+ inx d ; pointer plus one
+ push d ; update pointer, and save de, and the character
+ call setpar ; set whatever parity
+ mov e,a ; outmdm wants character in e
+ call outmdm ; send character in a to line
+ pop d
+ lda strcnt ; get the count
+ dcr a
+ sta strcnt ; less one
+ jnz stlop ; else still looping
+ call selcon ; re-select the console
+ jmp kermit
+
+; Print "(not implemented)".
+; here from vt52em, baud, prtset, stavt
+
+notimp: lxi d,inms12 ; Say it's not implemented.
+ call prtstr
+ jmp kermit ; Return to main loop.
+
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FRO RELEASE!
+
+; org ($+100h) AND 0FF00H
+
+IF lasm ; If using LASM, chain to the next file.
+ LINK CPSPK1 ;[obs] break down them big files...
+ENDIF;lasm
diff --git a/src/cpscpm.asm b/src/cpscpm.asm
new file mode 100644
index 0000000..49df54f
--- /dev/null
+++ b/src/cpscpm.asm
@@ -0,0 +1,932 @@
+; CPSCPM.ASM
+; 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
+; 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 duplicates the CP/M DIR and ERA functions so we don't have
+; to exit.
+;
+; revision history:
+;
+;edit 14, 1-Apr-1991 by MF. Correct a bug which crept in with edit 13 which
+; caused any control-key other than ^Y or ^Z to act like ^X after a key
+; had been depressed to halt output of the TYPE/PRINT commands.
+;edit 13, 25-Mar-1991 by MF. Make the TYPE command always abort to Kermit
+; command-level if ^C is entered on the console even if multiple files
+; are being typed via wild-cards. Make ^X typed on the console abort
+; typeout of the current file and begin typeout of the next file,
+; if any, otherwise go back to Kermit command-level.
+; The foregoing also applies to the PRINT command.
+;edit 12, 14-Feb-1991 by MF. Call "clrtop" in TYPE command at "type1"
+; rather than sending a <ff> directly to the terminal as some
+; terminals don't respond to <ff> characters. Thus the screen will be
+; cleared (if the terminal allows) before each file is typed.
+; Also use "getfil" rather than the bdos "openf" call to open
+; files for typing (label "type2"). This tightens up the code.
+; Zero "fcbcnt" before starting to type files (label "type0b").
+; This apparently fixes a phantom bug which caused incorrect lookup (and
+; hence garbage typeout) of files occassionally after a new disk
+; was inserted and a SET DEFAULT-DISK was performed to reset the disk
+; system. (It looked like parts of other files were being typed, as
+; if the directory had been misread or had not been reset.)
+;edit 11, 8-Feb-1991 by MF. Cause the bdos call for direct console input
+; in "ckchr" **not** to go thru the bdos trap but to call bdos at 0005h
+; directly. This corrects a bug wherein if commands such as INPUT
+; (which check to see if a keyboard key has been pressed) were executed
+; from a TAKE-file, the character following the terminator of such
+; commands was being interpreted as that keyboard input, thus causing
+; the next command in the TAKE-file to be unrecognized since its
+; first character had been eaten as a result of the keyboard check.
+; This bug **may** be the cause of a report received by Dr. Martin
+; J. Carter of Nottingham University in the U.K. in which Kermit
+; was reported to have read a character beyond a command terminator
+; in a TAKE-file, making the subsequent command unrecognizable since
+; its first character was missing.
+;edit 10, 29-Jan-1991 by MF. Use the big buffer for TYPE/PRINT commands.
+; Thus, edit 9 has been superseded.
+;edit 9, 29-Jan-1991 by MF. Corrected EOF check in TYPE command routine
+; following label "type20". a READF call, if successful, gives A=0
+; (not A=0FFH) and A not zero if failure. Thus the "INR A" instruction
+; checking for EOF was **always** nonzero. The reason the TYPE command
+; worked is that CP/M text files indicate the text end-of-file with a
+; Control-Z, in which case the TYPE routine branched correctly. In
+; other words, this edit is more for aesthetic purposes to satisfy
+; purists than something brought about by dire necessity!
+;edit 8, 28-Jan-1991 by MF. Added code courtesy of Dr. Martin J. Carter
+; of Nottingham University, UK, to use the big buffer for the COPY
+; command.
+;edit 7, 18-Sep-1990 by MF. Added RENAME routine to implement the
+; RENAME (FRENAME) command to rename a CP/M file.
+; Modified COPY routine to explicitly reject wild-carded filenames
+; by using COMND function CMOFI rather than functions CMIFI and
+; CMIFIN to get input and output filenames.
+; Modified ERA and COPY routines to not act upon the respective
+; commands until a "confirm" is typed. This prevents these
+; routines from taking off upon recognition of action characters
+; like "?", which can be quite annoying if one is an inexperienced user.
+; edit 6, March 11, 1987 by OBSchou. Added in the TYPE and PRINT commands
+; Both type to the screen, print also echoes to printer.
+;
+; edit 5 20 June, 1986. Added support for multiple file FCB buffering.
+;
+; edit 4: June 16, 1986 OBSchou at Loughborough University, UK
+; added in a test to prevent a DIR command issued from a TAKE command
+; being interruped by the next character in the take command buffer.
+; Also added code for USER nn. (Well, its OS related,is it not?)
+;
+; edit 3: July 8, 1984 (CJC)
+; Merge modifications from Toad Hall: support LASM (linked by CPSTT,
+; links to CPSWLD), use prcrlf where appropriate.
+;
+; edit 2: June 5, 1984 (CJC)
+; documentation and formatting; delete unused code (dir13); add module
+; version string.
+;
+; edit 1: May, 1984 (CJC)
+; extracted from CPMBASE.M80 version 3.9; modifications are described in
+; the accompanying .UPD file.
+;
+cpmver: db 'CPSCPM.ASM (14) 1-Apr-1991$' ; name, edit number, date
+
+npl EQU 04H ;Number of names per line for dir command.
+
+; This is the DIR command. Display the name and size of all files
+; matching the filespec.
+; here from: kermit
+;
+; Note: This is abstracted from Keith Peterson's DIRF.ASM
+; directory print function. Thanks again Keith.
+;
+;
+dir: lxi d,fcb ;Where to put the data, if any.
+ mvi a,cmifin
+ call comnd ;Parse a full or piece of file-spec
+ jmp dir2 ;Didn't get a FULL file-spec
+ jmp dir4 ;lets do it
+;
+;
+;Make FCB all '?' to match any file
+dir2: lda fcb
+ cpi ' ' ;CMIFIN leaves that as ' '
+ jnz dir2a ;he typed at least x:
+ xra a
+ sta fcb ;default drive
+dir2a: lxi h,fcb+1
+ mvi b,11 ;FN+FT count.
+
+dir3: mvi m,'?' ;Store '?'s in FCB.
+ inx h
+ dcr b
+ jnz dir3
+;Print signon message and drive name
+dir4: call getun ; get current user number
+ lda fcb
+ ora a ;if not zero, get default
+ jnz dir4a
+ lda curdsk ;get default
+dir4a: adi 'A'-1 ;Asciize it
+ sta dnam14+2 ;[4] add in user no, and Save it in message.
+ lda temp1+1 ;[4] most sig. user number
+ cpi '0' ;[4] if zero set space
+ jnz dir4b
+ mvi a,' ' ;[4] space
+dir4b: sta dnam14 ;[4]
+ lda temp1
+ sta dnam14+1 ;[4] ls user number digit
+ call prcrlf
+ lxi d,inms14 ;Point to message
+ call prtstr
+;
+;Initialize number of names per line counter
+ mvi a,npl ;Nr. names per line.
+ sta nnams ;Init counter.
+ lda hidefs ; are we doing file size?
+ ana a
+ jnz dir4c ; we are not showing file size,
+ lda nnams
+ inr a
+ sta nnams ; so we can show another name per line
+
+dir4c: xra a ; clear the flags ready for multi-sector buffering
+ sta fcbcnt ; clear fcb counter
+ sta mfflg1
+ sta mfflg2
+ sta mfflg3
+ lxi h,fcb0 ; reset pointer for fcb save space
+ shld xfcbptr
+;
+ call dir26 ;Get disk parameters
+ xra a ;[5] say first time round, so no spare fcbs
+ sta fcbcnt ;[5]
+dir5: call mfname ;get some names
+ jnc dir6 ;got one
+ jmp dir17 ;got none - do summary
+
+dir6: ;Check for console break
+ lda takflg ;[4] ... but not if issued from TAKE....
+ ana a ;[4]
+ jnz dir6a ;[4] we do the lot regardless.
+
+ mvi c,consta ;Ck status of kbd.
+ call bdos
+ ora a ;Any key pressed?
+ jz dir6a ;nope, keep going
+ mvi c,conin
+ call bdos ;gobble key
+ jmp dir17 ;and print summary only
+
+;Print an entry
+dir6a:
+ lxi h,fcb+1 ;point to Filename
+ mvi b,8 ;File name length.
+ call dir11 ;Type filename.
+ mvi a,'.' ;Period after FN.
+ call dir10
+ mvi b,3 ;Get the filetype.
+ call dir11
+ call dir25 ;print size
+ lxi h,nnams ;Point to names counter.
+ dcr m ;One less on this line.
+ push psw
+ cnz dir7 ;No cr-lf needed, do fence.
+ pop psw
+ cz dir12 ;Cr-lf needed.
+ jmp dir5
+
+;Print space, fence character, then space
+dir7: call dir9
+ mvi a,':' ;Fence character.
+ call dir10
+ jmp dir9
+
+; dir8 - Print two spaces
+; dir9 - Print one space
+; dir10 - Type char in A register
+dir8: call dir9
+dir9: mvi a,' '
+dir10: push b
+ push d
+ push h
+ mov e,a ;Char to E for CP/M.
+ mvi c,conout ;Write char to console function.
+ call bdos
+ pop h
+ pop d
+ pop b
+ ret
+
+;Type (B) characters from memory (HL)
+dir11: mov a,m
+ ani 7FH ;Remove CP/M 2.x attributes.
+ call dir10
+ inx h
+ dcr b
+ jnz dir11
+ ret
+
+;CR-LF routine. HL=NNAMS upon entry
+dir12: push b
+ push d
+ push h
+ call prcrlf ;Print CR/LF [Toad Hall]
+ pop h ;(did use call to dir10, but slooow)
+ pop d
+ pop b
+ mvi m,npl ;Number of names per line.
+ lda hidefs ; are we showing file size?
+ ana a
+ rnz ; no, so all ok
+ inr m ; else show another file per line
+ ret
+
+;Exit - All done, return via jmp (as for all main commands)
+dir16: call prcrlf
+ lda curdsk
+ dcr a ;relative to 0
+ mov e,a
+ mvi c,logdsk
+ call bdos ;back to "logged in" disk
+ jmp kermit ;...and return to kermit.
+
+;
+;Determines free space remaining
+;
+dir17: xra a
+ sta mfflg1 ;clean up MFNAME
+ sta mfflg2
+ lda fcb ; get drive number from FCB
+ ora a
+ jz dir18 ; default?
+ dcr a ; no, make requested drive current drive.
+ mov e,a
+ mvi c,logdsk
+ call bdos
+dir18: call sysspc ; get space available for current drive
+ push h
+ lxi d,inms15 ;"Drive "
+ call prtstr
+ lda fcb ;If no drive, get
+ ora a ;logged in drive
+ jnz dir24
+ mvi c,rddrv
+ call bdos
+ inr a
+dir24: adi 'A'-1
+ sta inms16
+ lxi d,inms16 ;"x has "
+ call prtstr
+ pop h ;Get number of bytes available
+ call nout
+ lxi d,inms17 ;"K bytes free"
+ call prtstr
+ jmp dir16 ;all done
+
+;Compute the size of the file
+
+dir25: lda hidefs ; do we show file size?
+ ana a ; if non zero, we dont.
+ rz ; so just return
+ mvi c,cflsz ;get file-size
+ lxi d,fcb
+ call bdos
+ lda fcbrno ;shift least sign. part
+ lxi b,0 ;init bc
+ mov l,a
+ ani 7
+ jz dir250 ;even K
+ lxi b,1 ;save for later
+dir250: push b ;save 0 or 1 to add to size
+ mvi b,3 ;shift 3 bits
+dir25a: xra a ;clear sign
+ lda fcbrno+1 ;get most sig byte
+ rar ;shift right
+ sta fcbrno+1 ;put back
+ lda fcbrno ;get least sig part
+ rar
+ sta fcbrno
+ dcr b ;loop 3 times
+ jnz dir25a
+ mov l,a ;size in HL
+ lda fcbrno+1
+ mov h,a
+ pop b ;get 0 or 1
+ dad b ;round up to KB used
+ lda bmask ;get (sectors/block)-1
+ rrc
+ rrc ;get (K/block)-1
+ rrc
+ ani 1FH
+ mov c,a
+ dad b ;add (K/block)-1 to size to round up
+ cma ;make a mask
+ ana l ;truncate after rounding up
+ mov l,a
+ push h
+ lxi b,-10 ;subtract 10
+ dad b
+ jc dir25d ;>= 10
+ call dir8 ; print a leading space
+ jmp dir25e
+
+dir25d: pop h ;get size again
+ push h
+ lxi b,-100 ;subtract 100
+ dad b
+ jc dir25e ;>= 100
+ call dir9 ; print another leading space
+dir25e: call dir9 ;a space
+ pop h ;get size back
+ call nout ;..go print it
+ mvi a,'k' ;..and follow with K size
+ call dir10
+ ret
+
+dir26: mvi c,gtdpar ;current DISK PARAMETER BLOCK
+ call bdos
+ inx h
+ inx h
+ mov a,m ;Get Block Shift Factor
+ sta bshiftf
+ inx h ;Bump to Block Mask
+ mov a,m ;get it
+ sta bmask
+ inx h
+ inx h
+ mov e,m ;Get Max Block number
+ inx h
+ mov d,m
+ xchg
+ shld bmax ;Put it away
+ ret
+;
+; ERA command - erase a CP/M file
+; here from: kermit
+
+era: mvi a,cmifi ;Parse a file-spec
+ lxi d,fcb ;into FCB
+ call comnd
+ jmp kermit ;bad parse
+ mvi a,cmcfm ;[MF]Get a confirm from the user
+ call comnd ;[MF]...
+ jmp kermit ;[MF]NO? try another command
+ lxi d,fcb
+ mvi c,sfirst ;check if valid
+ call bdos
+ inr a ;0 if FILE not found
+ jnz era1 ;found at least one
+ lxi d,erms15 ;"unable to find file"
+ call prtstr
+ jmp kermit
+
+era1: lxi d,fcb
+ mvi c,delf
+ call bdos
+ lxi d,inms18 ;" File(s) erased"
+ call prtstr
+ jmp kermit
+
+; USER - select a new user. This is an unusual routine in that the user
+; enters a number. The others take on/off or filename (except
+; set escape
+;
+user: mvi a,cmnum ; go parse a number
+ call comnd
+ jmp kermit ; if we can not do it, quit to command loop
+ mvi a,cmcfm ; get a confirm from the user
+ call comnd
+ jmp kermit ; if no, then try another command
+ lhld number ; else get the number...
+ xchg ; until a non valid digit is typed (eg cr)
+ lxi h,-32 ; if a carry, then ok
+ dad d ; ... else its above 32
+ jc user1
+ xchg ; restor number in hl again
+ mov a,l ; Lets save it
+ sta curusr ; as current user number
+ mov e,l ; get user no to e...
+ mvi c,usrcod
+ call bdos
+ call getun ; get user number to temp1 and temp2
+ lda temp2
+ cpi '0'
+ jnz user0 ; dont do ms digit if a zero
+ mvi a,' '
+user0: sta kerm1 ; save into string etc
+ sta dnam14 ; also for dir command
+ lda temp1
+ sta kerm1+1
+ sta dnam14+1 ; also for dir command
+ jmp kermit
+
+user1: lxi d,erms23 ; tell user sorry
+ call prtstr
+ jmp kermit
+
+
+;
+; TYPE - type a file or files to the console.
+;
+; This utility also used by print, where the characters printed to
+; the console are also copied to the printer if the prnfl flag
+; is non-zero. Uses mfname to type (print) multiple names.
+; Each file is preceeded with a formfeed character (usually clears
+; the screen on a VDU)
+;
+
+type: mvi a,cmifi ; parse a file name
+ lxi d,fcb ; let the parser know where the FCB is
+ call comnd
+ jmp type02 ; if error say so
+
+type0b:
+ xra a ; clear some flags for mfname
+ sta mfflg1
+ sta mfflg2
+ sta mfflg3
+ sta fcbcnt ;[12]...
+ lxi h,fcb0 ; reset the fcb pointers etc
+ shld fcbptr
+ call mfname
+ jc type02 ; match not found
+
+;[MF][10]The following code to type a file using a 1-sector buffer has
+;[MF][10]been replaced by code to use the "big buffer" -- 30-Jan-1991
+;type1: lxi d,buff ; point to the default DMA address
+; mvi c,setdma
+; call bdos ; tell bdos where to put the dma address
+; mvi a,ff ; do a form feed
+; call typit
+; xra a ; clear the character count
+; sta chrcnt
+;
+;type2: mvi c,openf ; open the file for reading
+; lxi d,fcb
+; xra a ; but first clear bits of fcb...
+; sta fcb+12
+; sta fcb+14
+; sta fcb+15
+; sta fcb+32
+; call bdos ; NOW open the file
+;
+;type20: mvi c,readf ; open up the file and read first sector
+; lxi d,fcb
+; call bdos
+;;[MF][9]Correct EOF test below (next two instructions)
+;; inr a ; if 0ffh returned, error. Assume EOF
+;; jz typex ; so exit from here
+; ora a ;[MF][9]If error, assume EOF
+; jnz typex ;[MF][9]so exit
+; lxi h,0 ; else clear the pointer into the file
+; shld typptr
+;
+;
+;type2a: lxi d,buff ;ok, so lets get the byte to print
+; lhld typptr
+; dad d ; add offset to the DMA base
+; mov a,m ; and get character to type (print)
+; ani 7fh ; make sure it is printable
+; cpi 20h ; is it a control character?
+; jp type3
+; cpi 09h ; if its a tab, then expand it
+; jnz type2b
+;
+;type2c: mvi a,' ' ; send a space
+; call typit ; type it
+; lda chrcnt ; get the number of chrs so far
+; ani 7h ; see of an 8th pos?
+; jnz type2c ; loop until all spaces done, then exit
+; jmp type4
+;
+;type2b: cpi cr ; is it a cr or lf?
+; jnz type2d
+; call typit ; do a cr
+; xra a
+; sta chrcnt ; cr of lf => clear character count
+; jmp type4 ; and exit
+;
+;type2d: cpi lf
+; jnz type2e
+; call typit ; print the character
+; xra a
+; sta chrcnt ; cr or lf clears the character count
+; jmp type4
+;
+;type2e: cpi cntlz ; is it end of file?
+; jnz type2f
+; jmp typex ; yes, so close and try for another file
+;
+;type2f: push psw ; control char - save the character
+; mvi a,'^' ; send control chars as ^A, for ex.
+; call typit
+; pop psw
+;
+;type3: call typit
+;
+;
+;type4: lhld typptr ; get the pointer
+; inx h
+; shld typptr ; up it by one character, and save it.
+; mov a,l ; lets see if the sector has been typed
+; ana a
+; jm type20 ; if 80h => read new sector
+; jmp type2a ; else just continue along
+
+;[MF][10]The following code uses the "big buffer" to read the file
+;[MF][10]which is to be typed
+;[12]Clear the screen explicitly as some terminals don't respond
+;[12]to the <ff> character.
+;type1: mvi a,ff ; do a form feed
+; call typit
+type1: call clrtop ;[12] Clear the screen
+ xra a ; clear the character count
+ sta temp1 ;[MF]alias column counter
+
+type2:
+;[12]Eliminate call to openf in favor of call to "getfil"
+; mvi c,openf ; open the file for reading
+ lxi d,fcb
+; xra a ; but first clear bits of fcb...
+; sta fcb+12
+; sta fcb+14
+; sta fcb+15
+; sta fcb+32
+; call bdos ; NOW open the file
+ call getfil ;[12] NOW open the file
+
+type20: call inbuf ;[MF]Fill input buffers
+ jmp typex ;[MF]Tru end-of-file reached
+ jmp type21 ;[MF]Begin typing/printing characters
+
+type2a: lda chrcnt ;[MF]Get buffer character counter
+ dcr a ;[MF]and decrement it
+ jm type20 ;[MF]Get more characters if needed
+type21: sta chrcnt ;[MF]else remember new buffer character counter
+ lhld bufpnt ;[MF]Now get character pointer
+ mov a,m ; and get character to type (print)
+ inx h ;[MF]Increment the pointer
+ shld bufpnt ;[MF]and remember it
+ ani 7fh ; make sure character is printable
+ cpi 20h ; is it a control character?
+ jp type3
+ cpi 09h ; if its a tab, then expand it
+ jnz type2b
+
+type2c: mvi a,' ' ; send a space
+ call typit ; type it
+ lda temp1 ;[MF]Get the number of characters so far
+ ani 7h ; see if an 8th pos?
+ jnz type2c ; loop until all spaces done, then exit
+ jmp type2a ;[MF]and continue
+
+type2b: cpi cr ; is it a cr or lf?
+ jnz type2d
+ call typit ; do a cr
+ xra a
+ sta temp1 ; cr or lf => clear character count
+ jmp type2a ;[MF]and continue
+
+type2d: cpi lf
+ jnz type2e
+ call typit ; print the character
+ xra a
+ sta temp1 ; cr or lf clears the character count
+ jmp type2a ;[MF]and continue
+
+type2e: cpi cntlz ; is it end of file?
+ jnz type2f
+ jmp typex ; yes, so close and try for another file
+
+type2f: push psw ; control char - save the character
+ mvi a,'^' ; send control chars as ^A, for ex.
+ call typit
+ pop psw
+
+type3: call typit
+ jmp type2a ; and continue along
+
+typex: mvi c,closf
+ lxi d,fcb
+ call bdos ; close the file
+ mvi a,cr ; send cr lf to screen/printer to clear buffers
+ call typit
+ mvi a,lf
+ call typit
+ call mfname ; and see if there are other files to type
+ jnc type1 ; yup, so go do it
+ xra a ; make sure the flag is reset
+ sta prnfl
+ jmp kermit ; then exit.
+
+typex0: mvi c,closf ;[MF]Close the file
+ lxi d,fcb ;[MF]...
+ call bdos ;[MF]...
+ mvi a,cr ;[MF]Clear buffers
+ call typit ;[MF]...
+ mvi a,lf ;[MF]...
+ call typit ;[MF]...
+ xra a ;[MF]Clear flag
+ sta prnfl ;[MF]...
+ lda takflg ;[MF]See if we're TAKEing commands
+ ani 1 ;[MF]from a file
+ cnz closet ;[MF]If we are, abort TAKE-file processing
+ jmp kermit ;[MF]Back to Kermit command-level
+
+; error for file not found for type
+type02: lxi d,nofile ; say no file name (its invalid)
+ call prtstr
+ xra a
+ sta prnfl ; clear the flag
+ jmp kermit ; so abort
+
+
+typit: mov e,a
+ call ckqtyp ; see if a cntl-c or other character from user
+ jmp typit2 ;[MF] Control-C entered, abort
+ jc typit1 ; CNTL-X entered, so abort file [MF]
+ push d ; save for a bit
+ call outcon ; send it to the console
+ lda temp1 ; update the number of characters sent[MF]
+ inr a
+ sta temp1 ;[MF]
+ pop d
+ lda prnfl ; see if we have to print it too
+ ana a
+ rz
+ call outprn ; send character to printer (buffer)
+ ret
+
+typit1: pop d ; adjust stack again
+ jmp typex ; and say we are done (for this file)
+
+typit2: pop d ;[MF] Adjust the stack
+ jmp typex0 ;[MF] and abort file typeout completely
+
+
+; CKQTYP - CHeck for requested Quiet TYPe (ie hang on a second)
+; Routine sees if the user has typed ANY key. If a key HAS been pressed
+; see if its a Control-c. If so, flag for an abort, else wait for
+; a second entry from the user. If its a Control C, flag an abort
+; else continue with the print.
+; note: only the DE registers maintained. All others destroyed.
+; **NOTE** CKQTYP now gives a nonskip return if Control-C is typed,
+; a skip-return with carry set if a Control-X is typed and a skip-return
+; with carry clear if any other character is typed as the second
+; character.
+
+ckqtyp: push d ; save the character to be printed
+ call ckchr ; see if user entered a character
+ ani 7fh ; strip parity etc
+ jz ckqty3 ; nothing entered, so go on as usual (See below)
+ cpi ctrlc ; control c?
+ jz ckqt1a ;[MF] Yup, give nonskip return
+ cpi 'X'-100o ;[MF] If Control-X,
+ jz ckqty1 ; yup, set carry and exit
+ckqty2: call ckchr ; another character to wait for (ie pause)
+ ani 7fh
+ jz ckqty2 ; wait until some input
+ cpi ctrlc ; if control c, abort
+ jz ckqt1a ;[MF] ...
+ cpi 'X'-100o ;[MF] Control-X?
+ jz ckqty1 ; yuss, so flag abort file [MF]
+ckqty3: pop d ; else restore the character to be typed [MF]
+; ret ; no, so continue with type/print
+ stc ;[MF]Set carry
+ cmc ;[MF]Then clear it
+ jmp rskp ;[MF] Continue with type/print (skip ret)
+
+ckqty1: pop d ; restore stack again
+ stc ; set carry and return
+; ret
+ jmp rskp ;[MF] ...
+
+ckqt1a: pop d ;[MF] Adjust stack
+ ret ;[MF] and return
+
+;[MF][14]No longer need these lines
+;ckqty3: pop d ; restore stack again
+;; ret
+; stc ;[MF] Clear carry
+; cmc ;[MF] ...
+; jmp rskp ;[MF] and give skip return
+
+ckchr: call selcon ; make sure we are talking to the console
+ mvi e,0ffh ; see if user has any input for us
+ mvi c,dconio
+; call bdos ;[11]Don't go thru bdos trap
+ call 0005h ;[11]Call bdos directly
+ ret ; This routine does not care what comes back
+
+
+;
+; COPY - routine to copy from a source file to a destination file
+; from the Kermit command state.
+;
+; Note. This could be tricky, as there are several forms of copy
+; copy d:source.ext d:dest.ext (Easy one)
+; copy d:source.ext d: (File to another drive)
+; copy d:source.??? d: (several files)
+; copy d:*.* d: (Several files)
+;
+; Initially, lets make it top one, and see how we go, ok?
+;
+;
+;Things to do for copy:
+; 1) get source name
+; 2) get target name
+; 3) if both source and destination = abort
+; 4) if source does not exist abort
+; 5) attempt to delete destination file if it exists
+; 6) open source and destination files
+; 7) copy file across
+; 8) close all files
+; 9) return to command mode
+;
+copy: ; Here goes...
+; 1) get source file name
+ mvi a,cmofi ; go parse a file name
+ ;[MF]Nonwild
+ lxi d,cfcbs ; use the source for copy FCB (Allows copy
+ call comnd ; from a TAKE file etc)
+ jmp kermit ; if error, abort
+
+; 2) get target name
+ mvi a,cmofi ; go parse a target file name
+ ;[MF]Again, nonwild
+ lxi d,cfcbd ; use destination fcb
+ call comnd ; get it
+ jmp kermit ;[MF]Couldn't.
+ mvi a,cmcfm ;[MF]Get a confirm from the user
+ call comnd ;[MF]...
+ jmp kermit ;[MF]No? try another command
+
+; 3) see if both target and source are equal
+copy0: mvi b,12 ; we are gonna test drive, file and extention
+ lxi d,cfcbs ; from source file name...
+ lxi h,cfcbd ; to destination file name
+ xra a ; clear flag for difference found
+ sta equflg
+copy1: ldax d ; get source file name character
+ cmp m ; test with targer file name
+ jz copy2 ; if equal, do nothing
+ lda equflg ; else update flage (ie files are different)
+ inr a
+ sta equflg
+copy2: inx h
+ inx d
+ dcr b
+ jnz copy1 ; up pointers and test for next char
+
+ lda equflg ; if still null, then its a daft thing to do
+ ana a
+ jnz copy3 ; its not a daft thing to do
+ lxi d,samems ; load up "File source and destination the same"
+ call prtstr ; tell user
+ jmp kermit ; and try again
+
+; 4) If source does not exist, abort. Assume we have a full file name.
+copy3:
+ lxi d,cfcbs ; load up source fcb
+ mvi c,openf ; open file
+ call bdos
+ inr a ; error on open?
+ jnz copy4
+ lxi d,nofile ; assume file not found
+ call prtstr
+ jmp kermit ; and die
+
+copy4: lxi d,cfcbd ; load up destination fcb
+ mvi c,delf ; destroy target name if it exists
+ call bdos ; ignore error messages
+ lxi d,cfcbd ; load up destination fcb
+ mvi c,makef ; make a file
+ call bdos
+ inr a ; make error?
+ jnz copy4a
+ lxi d,erms12 ; no directory space
+ call prtstr
+ jmp copy7 ; close source file
+
+copy4a: lxi d,cfcbd ; load up destination fcb...
+ mvi c,openf ; for open
+ call bdos
+ inr a ; error on open?
+ jnz copy5 ; could do with better error detection...
+ lxi d,erms15 ;... but assume its a disk full
+ call prtstr
+ jmp copy7 ; close source file and jmp kermit
+
+;copy5: lxi d,buff ; set default dma address to 80h
+; mvi c,setdma
+; call bdos
+;
+;copy6: lxi d,cfcbs ; copy routine proper.. get a sector
+; mvi c,readf
+; call bdos
+; ana a ; error reading the file?
+; jnz copy8 ; yes, then cope with it (could be EOF)
+; [MaJoC 910128] The above code, which reads single logical sectors,
+; is grossly inefficient with systems (most of them) with larger physical
+; disk blocks and a single shared read/write buffer. Use of INBUF below
+; is functionally equivalent at this level, but does actual disk reads
+; by the Big Buffer-ful.
+copy5:
+ xra a ; Initialise INBUF, to force reading of
+ sta seccnt ; the first Big Buffer-ful. Redundant
+ sta endsts ; if file opened by GETFIL (or variant).
+ sta eoflag ;[MF]...
+ lxi h,cfcbs ;[MF]Copy source fcb to default fcb
+ lxi d,fcb ;[MF]since INBUF uses the default fcb
+ lxi b,33 ;[MF]...
+ call mover ;[MF]...
+copy6:
+; INBUF returns a pointer to the next logical bufferful via bufpnt, filling
+; the Big Buffer as necessary, with skip return for success and nonskip on
+; error or EOF.
+ call inbuf ; Start of copy proper: get bufferful.
+ jmp copy8 ; Nonskip return: treat as EOF.
+ lhld bufpnt ; Skip return => OK: pick up buffer pointer.
+ xchg
+ mvi c, setdma ; Tell system where to write from.
+ call bdos
+; [majoc 910128: end]
+ lxi d,cfcbd ; send sector to destination
+ mvi c,writef
+ call bdos
+ ana a ; error on write (disk full?)
+ jz copy6 ; no error, so do another sector.
+ lxi d,erms17 ; say disk is full
+ call prtstr
+ lxi d,cfcbd ; close the output file...
+ mvi c,closf
+ call bdos
+ lxi d,cfcbd ; ... and then delete it
+ mvi c,delf
+ call bdos ; ... and then drop through to...
+
+copy7: lxi d,cfcbs ; here to close the source FCB
+ mvi c,closf
+ call bdos
+ jmp kermit
+
+copy8: lxi d,cfcbd ; orderly close of destination file
+ mvi c,closf
+ call bdos
+ jmp copy7 ; now close the source file as well.
+
+;
+;[MF]RENAME - Rename a file
+;
+rename: mvi a,cmofi ;[MF]Get nonwild filename
+ lxi d,cfcbs ;[MF]Use "COPY" fcb's
+ call comnd ;[MF]...
+ jmp kermit ;[MF]Couldn't get it.
+ mvi a,cmofi ;[MF]Get filespec to rename it to
+ lxi d,cfcbd ;[MF]...
+ call comnd ;[MF]...
+ jmp kermit ;[MF]Couldn't.
+renam0: lxi d,cfcbs ;[MF]See if file to be renamed exists
+ mvi c,openf ;[MF]by trying to open it
+ call bdos ;[MF]...
+ inr a ;[MF]Does the file exist?
+ jnz renam1 ;[MF]Yes
+ lxi d,nofile ;[MF]No, inform the user
+ call prtstr ;[MF]...
+ jmp kermit ;[MF]and bomb
+renam1: lxi d,cfcbd ;[MF]Point to rename filespec
+ mvi c,openf ;[MF]Set function code to
+ call bdos ;[MF]See if rename file exists
+ inr a ;[MF]Does it?
+ jz renam2 ;[MF]No
+ lxi d,erms31 ;[MF]Yes, complain
+ call prtstr ;[MF]...
+ jmp kermit ;[MF]and depart with tail between legs
+renam2: lxi h,cfcbd ;[MF]Now get rename filespec again
+ lxi d,cfcbs+16 ;[MF]and where to copy it to
+ lxi b,16 ;[MF]We copy drive, filename, filetype, extent
+ call mover ;[MF]...
+ lxi d,cfcbs ;[MF]Point to fcb for rename
+ mvi c,renam ;[MF]Get rename function
+ call bdos ;[MF]Try to rename the file
+ inr a ;[MF]Did we succeed?
+ jnz kermit ;[MF]Yes, done
+ lxi d,erms16 ;[MF]No, complain
+ call prtstr ;[MF]...
+ jmp kermit ;[MF]and start over
+
+
+IF lasm
+ LINK CPSWLD
+ENDIF;lasm [Toad Hall]
diff --git a/src/cpsdat.asm b/src/cpsdat.asm
new file mode 100644
index 0000000..729ca52
--- /dev/null
+++ b/src/cpsdat.asm
@@ -0,0 +1,648 @@
+; CPSDAT.ASM
+; 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.
+;
+; Pure and impure data areas. Previously of CPSUTL.ASM
+;
+; revision history:
+;
+;edit 19, 29-Mar-1991 by MF. Add flag "initak" (nonzero) which is cleared
+; after the initial automatic TAKE attempt of KERMIT.INI to allow
+; "unable to find file" complaints if not doing that initial TAKE.
+;edit 18, 21-Mar-1991 by MF. Renamed parameter vermin to revno (revision
+; level) since verno is already known as the "minor version number".
+;edit 17, 27-Feb-1991 by MF. Corrected typeo in "inms19" and commented out
+; "typptr" pointer as the TYPE command now uses the big buffer.
+; Also provided for a "minor version number" (1-26=A-Z) and message to
+; facilitate display of Kermit version in VERSION command (modmsg)
+;edit 16, 12-Feb-1991 by MF. Eliminated storage (message and variable)
+; for case sensitivity by commenting it out.
+;edit 15, 9-Dec-1990 by MF. Modified message for "directory file size"
+; status report to make it clearer when spoken by a speech synthesizer.
+;edit 14, 4-Dec-1990 by MF. Added message for Autoreceive status report.
+;edit 13, 30-Nov-1990 by MF. Added messages to display regular/quiet status
+; of terminal in SHOW and STATUS commands.
+;edit 12, 8-Nov-1990 by MF. Added a new message for Set Autoreceive.
+;edit 11, 2-Nov-1990 by MF. Moved overlay address to 7000H -- I didn't
+; realize I was **that** close to the limit until I made a couple of
+; cosmetic changes and REM CD bombed. This is still ver. 4.10 as it
+; hasn''t been released yet.
+;edit 10, 1-Nov-1990 by MF. Changed message at "spdst" to conform with
+; the change of "SET BAUD-RATE" to "SET SPEED".
+; Also added message "sdpst2" for speed status (staspd) routine
+;edit 9, 17-Oct-1990 by MF. Changed "packet-size" messages to use the
+; word "length" to conform with the nomenclature suggested in the
+; 6th edition of the Kermit Protocol Manual.
+;edit 8, 19-Sep-1990 by MF. Added error message for FRENAME command.
+;edit 7, 14-Sep-1990 by MF. Added storage/strings for SET COLLISION command.
+; Also added strings/storage for SET INCOMPLETE-FILE command.
+;edit 6, 9-Sep-1990 by MF. Added messages and storage for Remote commands.
+; and display of packet sizes
+; Moved overlay address to 06C00H for Version 4.10.
+; edit 5, 8 April, 1987 by OBSchou. Added new entry in jump table to call
+; code for an external terminal type. Added some new error messages
+; and added more to the packet space.
+;
+; edit 4, 30 March by OBSchou. Added in space for autoreceive.
+;
+; edit 3, 19 March, 1987 by OBSchou. Added some more strings etc, and
+; increased the stack space fro 32 entries to 64.
+;
+; edit 2, 11 March, 1987 by OBSchou.
+; Added in some more data and strings and things. Nothing special
+;
+; edit 1, 28 January, 1987 by OBSchou
+; Following file the data section of CPSUTL.ASM. This part of the
+; CPSUTL.ASM file now seperate as it ws getting too larg. Link to here
+; from CPSUTL.ASM (which now has only the utlity routines).
+; Also added in bits submitted by Dave Roberts of Leicester:
+; DJR 18th January 1987 - David J. Roberts.
+; Support for cosmetic changes in CPSMIT:
+; New strings DBGST and CURDST
+; CRLF in front of TIMMSG
+; LOGST changed, and new LOGST2
+;
+;
+datver: db 'CPSDAT.ASM (19) 29-Mar-1991$'
+
+
+
+;
+
+version:db 'Kermit-80 v4.'
+ db (verno/10) + '0' ; tenth's digit of version number
+ db (verno MOD 10) + '0' ; hundredth's digit
+IF revno ;[MF]If a revision level,
+ db revno+'@' ;[MF]put it in (range 1-26=A-Z)
+ENDIF ;revno [MF]
+ db ' $'
+modmsg: db ' has been built from the following modules:$';[MF]
+kerm: db 'Kermit-80 '
+kerm1: db 'nnx:>$' ;'x' filled in at startup with DRIVE name
+ ;'nn filled at startup and user with user number
+crlf: db cr,lf,'$'
+ermes1: db cr,lf,'?Unrecognized command$'
+ermes3: db cr,lf,'?Not confirmed$'
+ermes4: db '?Unable to receive initiate',cr,lf,'$'
+ermes5: db '?Unable to receive file name',cr,lf,'$'
+ermes6: db '?Unable to receive end of file',cr,lf,'$'
+erms10: db '?Unable to receive data',cr,lf,'$'
+erms11: db '?Disk full',cr,lf,'$'
+erms12: db '?Directory full',cr,lf,'$'
+erms14: db '?Unable to receive an acknowledgement from the host',cr,lf,'$'
+erms15: db cr,lf,'?Unable to find file',cr,lf,'$'
+erms16: db '?Unable to rename file$'
+erms17: db cr,lf,'?Disk full$'
+erms18: db cr,lf,'?Unable to tell host that the session is finished$'
+erms19: db cr,lf,'?Unable to tell host to logout$'
+erms20: db cr,lf,'?Kermit has not been configured for a target system$'
+erms21: db cr,lf,'?Consistency check on configuration failed$'
+erms22: db cr,lf,'?Error writing to log file',cr,lf,'$' ;[pcc005]
+erms23: db cr,lf,'?Invalid user number$'
+erms24: db cr,lf,'?Invalid Pause parameter$'
+erms25: db cr,lf,'?Invalid BUFFER-SIZE parameter$'
+erms26: db cr,lf,'?Invalid packet length (too long)$'
+erms27: db cr,lf,'?Invalid Checktype$'
+erms28: db cr,lf,'?Too many retries$'
+erms29: db cr,lf,'?Failed to exchange parameters$'
+erms30: db cr,lf,'?Failed to receive input string in alloted time$'
+erms31: db cr,lf,'?File already exists$' ;[MF]
+
+infms3: db bell,'Completed$'
+infms4: db bell,'Failed$'
+infms5: db '%Renaming file to $'
+infms6: db cr,lf,'[Closing the log file]$'
+infms7: db cr,lf,'[Connected to remote host. Type $'
+infms8: db 'C to return;',cr,lf,' type $'
+inms8a: db '? for command list]',cr,lf,'$'
+infms9: db cr,lf,'[Connection closed, back at micro]$'
+inms10: db 'Control-$'
+inms11: db ' Not implemented.$'
+inms12: db ' (Not implemented)',cr,lf,'$'
+inms13: db bell,'Interrupted$'
+inms14: db TAB,TAB,' Directory for drive '
+dnam14: db 'nnx:',cr,lf,'$' ;filled in by dir routine.
+inms15: DB CR,LF,TAB,TAB,'Drive $'
+inms16: DB ' has $';filled in by summary code with drive letter
+inms17: DB 'K bytes free',CR,LF,'$'
+inms18: DB CR,LF,'File(s) erased$',CR,LF
+inms19: db cr,lf,'[Transmitting file to host:'
+ db cr,lf,' 1. Lines automatically sent, and wait for possible reply'
+ db cr,lf,' 2. CONTROL-C aborts transfer'
+ db cr,lf,' 3. If transfer hangs, try a return to continue'
+ db cr,lf,' 4. on exit, you will be placed in CONNECT state.'
+ db cr,lf,'$'
+inms20: db 'R to send the same line again,'
+ db cr,lf,' or type $'
+inms21: db 'C to abort transmission.]',cr,lf,'$'
+inms22: db cr,lf,'[Transmission done. Connected normally '
+ db 'to remote host,'
+ db cr,lf,' type $'
+inms23: db 'Sending...$'
+inms24: db 'Receiving...$'
+inms25: db bell,'Warning: eighth bit cannot be sent$'
+inms26: db cr,lf,'For help, type ? at any point in a command$'
+inms27: db cr,lf,'[Logging suspended]',cr,lf,'$' ;[pcc003]
+inms28: db cr,lf,'[Logging resumed]',cr,lf,'$' ;[pcc003]
+inms29: db cr,lf,'[Transmission Aborted. Connected normally '
+ db 'to remote host,'
+ db cr,lf,' type $'
+autmes: db cr,lf,cr,lf,'[Automatically receiving; type ^C to abort]'
+ db cr,lf,cr,lf,'$' ;[MF]
+anymes: db cr,lf,cr,lf,' * * * Press any key to continue * * * '
+ db cr,lf,cr,lf,'$'
+escmes: db cr,lf,'Type the new escape character: $'
+tacmes: db cr,lf,'Type the new TAC intercept character: $'
+sopmes: db cr,lf,'Give the start-of-packet character: $' ;[gnn]
+padcms: db cr,lf,'Type the new padding character: $' ;[obs]
+xmthlp: db cr,lf,'R Send the same line again$'
+loghlp: db cr,lf,'Q Suspend logging' ;[pcc003]
+ db cr,lf,'R Resume logging$' ;[pcc003]
+inthlp: db cr,lf,'? This message'
+ db cr,lf,'C Close the connection'
+ db cr,lf,'0 (zero) Transmit a NULL'
+ db cr,lf,'P Toggle printer on/off' ;[pcc002]
+ db cr,lf,'S Status of the connection$'
+inhlp1: db cr,lf,'Typing another $'
+inhlp2: db ' will send it to the host'
+ db cr,lf,cr,lf,'Command>$'
+
+xmtst: db cr,lf,'Transmitting a file$'
+autrst: db cr,lf,'Autoreceive is$'
+locst: db cr,lf,'Local echo$'
+onstr: db ' on$'
+offstr: db ' off$'
+flost: db cr,lf,'Flow control$'
+;senst: db cr,lf,'Case sensetivity$'
+vtdpst: db cr,lf,'Terminal display is $'
+vtdpsr: db 'REGULAR$'
+vtdpsq: db 'QUIET$'
+vtemst: db cr,lf,'Terminal emulation is $'
+cpmst: db cr,lf,'File Mode$'
+defstr: db ' default$'
+ascstr: db ' ASCII$'
+binstr: db ' binary$'
+hfsod: db cr,lf,'Display file size on DIRECTORY command$'
+ibmst: db cr,lf,'IBM flag$'
+incst: db cr,lf,'Disposition for incomplete files is$'
+dscstr: db ' discard$'
+kepstr: db ' keep$'
+filst: db cr,lf,'File warning$'
+prst: db cr,lf,'Printer copy$'
+logst: db cr,lf,'Logging to $' ;[pcc003][DJR]
+logst2: db ' is$' ;[DJR]
+susstr: db ' suspended$' ;[pcc003]
+sspmsg: db cr,lf,'SEND start-of-pkt char ^$' ;[gnn]
+rspmsg: db cr,lf,'RECEIVE start-of-pkt char ^$' ;[gnn]
+spsmsg: db cr,lf,'SEND packet length $' ;[MF]
+rpsmsg: db cr,lf,'RECEIVE packet length $' ;[MF]
+escst: db cr,lf,'Escape char: $'
+bufsz1: db cr,lf,'Multi-sector buffering at $'
+bufsz2: db ' of a maximum of $'
+xmitst: db cr,lf,'Transmit protocol char: $'
+bckst: db cr,lf,'Block check type: $'
+bckst1: db '-character$'
+collst: db cr,lf,'File COLLISION: $';[MF]
+parst: db cr,lf,'Parity: $'
+pnonst: db 'none$'
+pmrkst: db 'mark$'
+pspcst: db 'space$'
+poddst: db 'odd$'
+pevnst: db 'even$'
+porst: db cr,lf,'Port in use is: $'
+spdst: db cr,lf,'Current speed is: $'
+spdst2: db ' bps$' ;[MF]
+spdust: db 'indeterminate (not SET)$'
+timmsg: db cr,lf,'Timer$' ;[DJR] Added CRLF like the others
+tacst: db cr,lf,'Current TACTrap Status/Intercept Character: $'
+usrst: db cr,lf,'Current user number: $'
+dbgst: db cr,lf,'Debugging$' ;[DJR]
+curdst: db cr,lf,'Current default disk: $' ;[DJR]
+spac15: db ' $' ; *** 15 spaces ***
+samems: db cr,lf,'?Source and destination files the same$'
+nofile: db cr,lf,'?File not found$'
+cmer00: db cr,lf,'?Program error: Invalid COMND call$'
+cmer01: db cr,lf,'?Ambiguous$'
+cmer02: db cr,lf,'?Illegal CP/M file specification$'
+cmer03: db cr,lf,'?Wild-cards not allowed in file specification$' ;[pcc006]
+cmer04: db cr,lf,'?Invalid user number$'
+cmer05: db cr,lf,'?Invalid \ parameter$'
+cmin00: db ' Confirm with carriage return$'
+cmin01: db ' Enter a number$'
+cmin02: db ' Confirm with carriage return or enter more$'
+
+; Diagnostic messages
+sstatm: db '<SState:> ',0
+rstatm: db '<RState:> ',0
+spackm: db '<Data transmitted> ',0
+rpackm: db '<Data received > ',0
+princr: db cr,lf,0
+;
+; Remote command messages [MF]
+;
+newfms: db cr,lf,'New file: $'
+pswdms: db cr,lf,'Password: $'
+acctms: db cr,lf,'Account: $'
+newnms: db cr,lf,'New name: $'
+msgms: db cr,lf,'Message: $'
+optms: db cr,lf,'Options: $'
+
+;
+ ;Impure data
+
+;COMND storage
+
+comchr: ds 1 ;[8] save space
+floctl: db 0 ;[8] flow control on/off flag
+;casens: db 0 ;[8] Upper/lower case sensitive
+cmstat: ds 1 ;What is presently being parsed.
+cmaflg: ds 1 ;Non-zero when an action char has been found.
+cmbflg: ds 1 ;[MF]Nonzero to allow a blank initial keyword
+cmqflg: ds 1 ;[MF]Nonzero to prevent character echoing
+ ;[MF]when entering commands
+cmccnt: ds 1 ;Non-zero if a significant char is found.
+cmsflg: ds 1 ;Non-zero when the last char was a space.
+cmostp: ds 2 ;Old stack pointer for reparse.
+cmrprs: ds 2 ;Address to go to on reparse.
+cmprmp: ds 2 ;Address of prompt.
+cmptab: ds 2 ;Address of present keyword table.
+cmhlp: ds 2 ;Address of present help.
+cmdbuf: ds 80H ;Buffer for command parsing.
+cmbufl equ $-cmdbuf-3 ; set a limit on the command buffer
+cmfcb: ds 2 ;Pointer to FCB.
+cmfcb2: ds 2 ;Pointer to position in FCB.
+cmfwld: ds 1 ;Wildcard flag
+cmcptr: ds 2 ;Pointer for next char input.
+cmdptr: ds 2 ;Pointer into the command buffer.
+cmkptr: ds 2 ;Pointer to keyword.
+cmsptr: ds 2 ;Place to save a pointer.
+slshsn: db 0 ; slash seen in command line
+slashc: db 0 ; count for number of characters in slash sequence
+slashn: db 0 ; number to be built for \xxx
+;
+oldsp: ds 2 ;Room for old system stack.
+ ds 80H ;Room for 64 levels of calls.[obs]
+stack: ds 2
+eoflag: ds 1 ;EOF flag;non-zero on EOF.
+curdsk: db 0 ;holds "logged" disk
+curusr: db 0 ;[8] holds "user" number
+rcvsop: db SOH ;[gnn] receive start-of-packet
+sndsop: db SOH ;[gnn] send start-of-packet
+prtcnt: db 0 ;[pcc008] prtchr fairness count
+timflg: db 0 ;[jd] timer flag: 0 -> no timer
+timval: dw 0 ;[jd] timer value
+wrn8: db 0 ;[jd] non-zero if 8-bit-lost warning sent
+qbchr: db '&' ;[jd] binary quote character.
+quot8: db 0 ;[jd] non-zero if doing 8-bit quoting
+logflg: db 0 ;Flag for a log file.
+ ;[pcc005] 0 = no log
+ ;[pcc005] x1 = logging on
+ ;[pcc005] x2 = suspended
+ ;[pcc005] 8xH (bit 7) = file open
+lognam: db 0 ;[pcc013] File to use for session logging
+ db 'KERMIT ' ;[pcc013]
+ db 'LOG' ;[pcc013]
+nexitf: db 0 ; set to 1 for exit to CPM after command tail
+takflg: db 0 ;[8] TAKE flag.
+ ; Bit zero = 1 for take file in progress
+ ; bit 4 = 1 if command line present/in progress
+ ; Note: Take has priority over command line.
+initak: db 0ffh ;[MF]Cleared after initial TAKE (KERMIT.INI)
+taknam: db 0 ;[8] use default drive
+ db 'KERMIT '
+ db 'INI' ;[8] Inital file to TAKE KERMIT.INI
+takptr: ds 2 ;[8] Pointer to position in TAKE file input
+takfcb: ds 12 ;[8] fcb space for take file
+ dw 0 ;[8] fill up extents etc with 00
+ dw 0
+ ds 16 ;[8] used by dos
+ dw 0
+ dw 0
+takdma: ds 128 ;[8]space to read TAKE file...
+prnbuf: ds 1 ; printer buffer. Output pointer
+ ds 1 ; input offset pointer
+ ds 256 ; give a large buffer
+ ds 10 ; and a little spare
+;
+;
+;
+; Transmit space
+;
+repcnt: db 0 ; repeat counter
+starc: db 0 ; star count
+rexbfl: db 0 ; retransmit flag (1=> retransmit)
+rexcnt: db 0 ; retransmit character count
+rexbuf: ds 128 ; max retransmit line length 128 characters
+xmtbuff:
+ ds 128 ; 128 byte sector buffer
+xmtptr: db 0 ; offset pointer to xmtbuff above
+xmtfcb: ds 36 ; fcb for transmit file.
+;
+;INPUT and STRING space
+strlen: db 0 ; length of the string from INPUT and STRING
+
+; Assorted other space
+errorc: db 0 ; error level set to xxx
+errorl: db 0 ; error level to test against
+
+remtxt: db 0 ; set <> 0 if D packets to screen
+
+hosths: ds 1 ; have we told the host to xoff? (is this duplicated)
+stbuff: ds 80h ; some space or the string buffer
+waitp: ds 2 ; wait command timer
+waitp1: ds 2 ; wait/input timer (copy of waitp)
+prntmp: ds 1 ; temporary space to put the caracter to print
+prnfl: db 0 ; printer flag. Used by TYPE/PRINT
+;[MF][17]Following line no longer needed as TYPE uses the big buffer
+;typptr: ds 2 ; pointer used by TYPE/PRINT
+equflg: db 0 ; set to non zero if copy files same
+nquiet: db 0 ; If non zero print from NOUT to display
+
+escflg: db 0 ;Escape flag (start off).
+fileio: db 0 ;Line-by-line from file (default off).
+xofflg: db 0 ;X-OFF (=^S) received from COMM-line
+ ;X-ON (=^Q) received resets this
+clkbit: dw 0 ; 32 bit pseudo clock
+ dw 0 ; MS bits of clock
+number: ds 2 ; Number in binary form from user input
+initflg:db 0 ; set to non zero when system initialised
+maxbsc: ds 1 ; save space to know how big system allows
+ ; for multi-sector buffering. (Usually 8k?)
+;
+; Multiple FCB storage space. Used for the DIR command
+; Later on, I want to shift this into space after the system
+; dependent stuff, but then it becomes messy with pointers
+; to pointers etc... [OBS]
+;
+xfcbptr:
+ ds 2 ; pointer to current fcb space
+fcbcnt: ds 1 ; Number of valid fcbs in space
+;
+fcb0: ds 12 ; 36 bytes requred for a single fcb
+fcblen EQU $-fcb0 ; length of a single fcb
+ ds maxfcb*fcblen ; space for maximum fcbs + 1
+;
+hidefs: db 0ffh ; flag <> 0 if we show file size in DIR
+
+; FCB sapce for COPY command
+cfcbs: ds 33 ; source fcb for copy file ops.
+ ;[MF]and FRENAME ops.
+cfcbd: ds 33 ; destination fcb for copy ops.
+ ;[MF]and FRENAME ops.
+
+colfcb: ds 33 ;[MF]Rename fcb for SET COLLISION
+
+; Command tail data space etc
+cbptr: db 2 ; command tail pointer (0= length of tail)
+cbuff: ds 128 ; temp. space for potential command tail
+
+strcnt: db 0 ; string count for string operations...
+
+vtyval: ds 1 ; holds row number for VT52 cursor positioning
+chrcnt: ds 1 ;Number of chars in the file buffer.
+
+; Various packet variables etc
+bytes: dw 0 ; 4 byte 'byte count' space
+ dw 0
+filcnt: ds 1 ;Number of chars left to fill.
+outpnt: ds 2 ;Position in packet.
+bufpnt: ds 2 ;Position in file buffer.
+fcbptr: ds 2 ;Position in FCB.
+datptr: ds 2 ;Position in packet data buffer.
+cbfptr: ds 2 ;Position in character buffer.
+pktptr: ds 2 ;Position in receive packet.
+size: ds 1 ;Size of data from gtchr.
+curchk: ds 1 ;Current checksum type
+inichk: ds 1 ;Agreed upon checksum type
+czseen: ds 1 ;Flag that control-Z was typed
+dscflg: ds 1 ;[MF]Discard file if nonzero
+pktnum: ds 1 ;Packet number.
+numpkt: ds 2 ;Total number of packets sent.
+numrtr: ds 2 ;Total number of retries.
+numtry: ds 1 ;Number of tries on this packet.
+oldtry: ds 1 ;Number of tries on previous packet.
+state: ds 1 ;Present state of the automaton.
+;*** start of new flags. Do not assume that just because these flags are
+; present that the feature is available. I simply put them in 'for future use'
+rcapas:
+rcap1: db 0 ; receive capabilties byte 0
+rcap2: db 0 ; receive cpabilities byte 1
+scapas:
+scap1: db 0 ; send capabilities byte 0
+scap2: db 0 ; send capabilities byte 1
+rtimeo: db 0 ; receive timeout
+stimeo: db 0 ; send timeout
+rpadc: db 0 ; receive pad character
+spadc: db 0 ; send pad character
+rrept: db 0 ; receive repeat prefix
+srept: db 0 ; send repeat prefix
+rwindo: db 0 ; receive window size
+swindo: db 0 ; send window size
+rdpkt:
+rlpkt: dw 0 ; receive long packet length
+sdpkt:
+slpkt: dw 0 ; send long packet length
+sdckt: db 0 ; send default checktype
+rdckt: db 0 ; receive checktype (should be same as sdckt)
+;*** end of new flags
+sohchr: db 1 ;Default Start-of-header chr is cntl-a
+; Kermit packet starts here
+; Byte 0 = start of packe character
+; 1 = length of packet
+; 2 = packet number
+; 3 = packet type (S R I Z E B etc)
+packet: ds 4 ;Packet (data is part of it).
+; Data part of packet (variable length - include checksum)
+data: ds 5AH ;Data and checksum field of packet.
+recpkt: ds 65H ;Receive packet storage (use the following).
+recpkx: db cr,'$' ;= = = buffer limit
+filbuf: ds 65H ;Character buffer.
+fnbuf: ds 20h ;[jd] file name buffer
+autorc: db 0 ;[obs] set to ON for autoreceive
+
+; Temporary data space. Sometimes accesses as 16 bits (eg temp1/2)
+;** Temp 1 & 2 must be in order
+lstchr: ;Last console input character.
+temp1: ds 1 ;Temporary storage.
+temp2: ds 1
+lincnt: ; used for counting lines in p20ln
+temp3: ds 1
+temp4: ds 1
+temp5: ds 1
+temp6: ds 1
+temp7: ds 1
+temp8: ds 1
+temp9: ds 1
+temp10: ds 1
+temp11: ds 1
+
+
+getrxflg:
+ ds 1 ;[obs 22]
+quietd: db 0 ;loud display during file transfers
+argblk: ds 20H ;Used for subroutine arguments
+
+maxfil EQU 2 ; currently, only two names used.
+fcbblk: ds maxfil*10H ;Used for a list of FCB's
+
+; [gnn] secondary filename storage (remote on send, local on get)
+remnam: ds 60 ;[gnn]
+remlen: ds 1 ;[gnn] length of name
+
+; Bookkeeping storage for multiple-sector buffering. The actual buffer
+; is somewhere in the system-dependent overlay. (at the end, I hope).
+nxtbuf: ds 2 ; Pointer to next sector
+seccnt: ds 1 ; Number of sectors buffered
+endsts: ds 1 ; Status for last read into buffer
+;
+;
+; [MF] Storage for Remote Command processing
+;
+;
+rdl: ds 1 ;[MF]Holds accumulated length of remote data
+;
+rcl: ds 1 ;[MF]Holds length of Remote command line arg
+;
+remdat: ds 95 ;[MF]Packet data buffer (plenty big)
+;
+rcom: ds 1 ;[MF] Remote Command type
+;
+rprmpt: dw 0 ;[MF]Address of prompt strings
+;
+rptr: dw 0 ;[MF]Remote command packet data pointer
+;
+rscode: ds 3 ;[MF]Holds Remote Set command ASCII code
+;
+;
+ org 7000h ; address for Kermit 4.11
+; ORG ($ + 0ffH) AND 0ff00H ; move to start of next page
+
+;
+; hooks for system-dependent routines:
+; This area is overwritten by the system-dependent overlay.
+;
+lnkflg: dw 0 ; linkage information for consistency check.
+lnkent: dw 0 ; more of the same.
+ovlver: dw 0 ; pointer to overlay's version string
+family: dw 0 ;*NEW* [10] address of the family overlay (not CPSSYS)
+;
+; Input/output routines. Note that outmdm and outcon may actually be the
+; same routine if selmdm and selcon do anything. (the same is true
+; of inpmdm and inpcon).
+;
+selmdm: jmp $-$ ; select modem for I/O
+outmdm: jmp $-$ ; output character in E to modem
+inpmdm: jmp $-$ ; read character from modem. return character or 0 in A.
+flsmdm: jmp $-$ ; flush pending input from modem
+selcon: jmp $-$ ; select console for I/O
+outcon: jmp $-$ ; output character in E to console
+inpcon: jmp $-$ ; read char from console. return character or 0 in A
+outlpt: jmp $-$ ; output character in E to printer
+lptstat:jmp $-$ ;*NEW*[10] see if printer ready to print a character
+ ; If 0ffh then ok, if 0h then not ok.
+extern: jmp $-$ ;*NEW for 4.09* If $-$ is not zero, then its a jump to
+ ; a routine to emulate any terminal type the user
+ ; wants to implement.
+xbdos: jmp 0 ;*NEW* address of the bdos trap in this section
+ ; of code. It is filled in initialisation.
+;
+; screen formatting routines
+clrlin: jmp $-$ ; erase current line
+clrspc: jmp $-$ ; erase current position (after backspace)
+delchr: jmp $-$ ; make delete look like backspace
+clrtop: jmp $-$ ; erase screen and go home
+;
+; these routines are called to display a field on the screen.
+scrend: jmp $-$ ; move to prompt field
+screrr: jmp $-$ ; move to error message field
+scrfln: jmp $-$ ; move to filename field
+scrnp: jmp $-$ ; move to packet count field
+scrnrt: jmp $-$ ; move to retry count field
+scrst: jmp $-$ ; move to status field
+rppos: jmp $-$ ; move to receive packet field (debug)
+sppos: jmp $-$ ; move to send packet field (debug)
+;
+sysinit: jmp $-$ ; program initialization
+sysexit: jmp $-$ ; program termination
+syscon: jmp $-$ ; remote session initialization
+syscls: jmp $-$ ; return to local command level
+sysinh: jmp $-$ ; help text for interrupt (escape) extensions
+sysint: jmp $-$ ; interrupt (escape) extensions, including break
+sysflt: jmp $-$ ; filter for incoming characters.
+ ; called with character in E.
+sysbye: jmp $-$ ; terminate remote session
+sysspd: jmp $-$ ; baud rate change routine.
+ ; called with value from table in DE
+sysprt: jmp $-$ ; port change routine.
+ ; called with value from table in HL
+sysscr: jmp $-$ ; screen setup for file transfer
+ ; called with Kermit's version string in DE
+csrpos: jmp $-$ ; move cursor to row B, column C
+sysspc: jmp $-$ ; calculate free space for current disk
+mover: jmp $-$ ; block move
+prtstr: jmp $-$ ; *** NEW *** prtstr moved to overlay
+;
+; Data initialized by system-dependent overlay:
+;
+pttab: ds 2 ; points to local equivalents to VT52 escape sequences
+spdtab: ds 2 ; address of baud rate command table, or zero
+spdhlp: ds 2 ; address of baud rate help table, or zero
+prttab: ds 2 ; address of port command table, or zero
+prthlp: ds 2 ; address of port help table, or zero
+timout: ds 2 ; Initial value for fuzzy timeout
+vtflg: ds 1 ; VT52 emulation flag
+escchr: ds 1 ; Storage for the escape character.
+speed: ds 2 ; storage for the baud rate
+port: ds 2 ; storage for port value
+prnflg: ds 1 ;[hh] printer copy flag (overlay may need it)
+dbgflg: ds 1 ; debugging flag
+ecoflg: ds 1 ; Local echo flag (default off).
+flwflg: ds 1 ; File warning flag (default on).
+ibmflg: ds 1 ; IBM flag (default off).
+cpmflg: ds 1 ; File mode flag (ascii/binary/default)
+incflg: ds 1 ;[MF]Incomplete flag (keep/discard)
+ ;[MF](default discard)
+parity: ds 1 ; Current parity.
+spsiz: ds 1 ; Send packet size.
+rpsiz: ds 1 ; Receive packet size.
+stime: ds 1 ; Send time out.
+rtime: ds 1 ; Receive time out.
+spad: ds 1 ; Send padding.
+rpad: ds 1 ; Receive padding.
+spadch: ds 1 ; Send padding char.
+rpadch: ds 1 ; Receive padding char.
+seol: ds 1 ; Send EOL char.
+reol: ds 1 ; Receive EOL char.
+squote: ds 1 ; Send quote char.
+rquote: ds 1 ; Receive quote char.
+chktyp: ds 1 ; Checksum type desired
+tacflg: ds 1 ; TACTrap flag (zero=off, nonzero=on; when non-zero,
+ ; contains current TAC intercept character)
+tacchr: ds 1 ; TAC intercept character
+bufadr: ds 2 ; Pointer to big buffer for multiple-sector I/O
+bufsec: ds 1 ; Number of sectors big buffer can hold (0 means 256)
+ffussy: ds 1 ; if nonzero, don't permit <>.,;?*[] in CP/M filespec.
+; space used by directory command; here because space calculation is
+; (operating) system-dependent
+bmax: ds 2 ; highest block number on drive
+bmask: ds 1 ; (records/block)-1
+bshiftf: ds 1 ; number of shifts to multiply by rec/block
+nnams: ds 1 ; counter for filenames per line
+
+lnksiz equ $-lnkflg ; length of linkage section, for consistency check.
+
+ END START
diff --git a/src/cpsdef.asm b/src/cpsdef.asm
new file mode 100644
index 0000000..46e3ba6
--- /dev/null
+++ b/src/cpsdef.asm
@@ -0,0 +1,287 @@
+; 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 definitions used by both modules of Kermit.
+;
+; revision history:
+;
+;edit 9, 30-Nov-1990 by MF. Make "fairness" count "prfair" be 50 so
+; console gets checked a bit more often.
+; edit 8, 11-Sep-1990 by MF. Make default RECEIVE and SEND packet-size
+; 80 (per Kermit standard) as packet size is adjustable in Version
+; 4.10.
+; edit 7 16-Jun-86 OBSchou. Added cmnum in the command opcodes. This gets a
+; number from the user inot variable number. No checking on overflow.
+;
+; edit 6 13-May-86 OBSchou. BDOS calls trapped to check for console use
+; as we want to substitute in commands from a TAKE file. Trapping
+; means I dont have to go through an check ever BDOS call...
+;
+; edit 5: 22-Apr-86 by Bertil Schou, Loughborough University, UK
+; moved some definitions from the CP4SYS.ASM file to here for
+; Kermit version 4.06
+;
+; edit 4: 6-Feb-85 by Charles Carvalho
+; modify pcc007: replace ffussy assembly switch with runtime test.
+; add "getvnm" - get CP/M version number.
+;
+; edit 3: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
+;
+;pcc007 2-Jan-85 vjc modules:cp4def,cp4cmd
+; Cmifil is too fussy about what characters to accept in a
+; filespec. My CP/M manual says any printable character is ok
+; except <>.,;:?*[], and lower case. In practice, even those work
+; sometimes. Kermit itself uses '&' if file warning is on,
+; and then won't let you reference the file. Allow all
+; printable characters except those above. Add conditional
+; ffussy, so that if not ffussy, all special characters will be
+; allowed, just convert lower to upper-case.
+;
+;pcc008 2-Jan-85 vjc modules:cp4def,cp4tt,cp4utl
+; Keyboard input during CONNECT mode can get locked out if
+; there is enough input from the modem port to keep prtchr
+; busy. This can happen for example, if the printer is running
+; at the same speed as the modem line, leaving you helpless to
+; turn it off or abort the host. Add a fairness count, so that
+; at least every prfair characters we look at console input.
+;
+; edit 2: July 10, 1984 (CJC)
+; Remove defines for TRUE and FALSE, during reorganization for LASM
+; compatibility. If we're using LASM, this file is linked by CP4KER
+; or CP4TYP, and links to CP4MIT or CP4LNK. Also, push comments around
+; a little.
+;
+; edit 1: May, 1984 (CJC)
+; extracted from CPMBASE.M80 version 3.9; modifications are described
+; in the accompanying .UPD file.
+;
+
+;Symbolic Definitions for some ASCII characters
+;
+soh EQU 01O ;ASCII SOH (Control-A)
+cntlc EQU 03O ;ASCII ETX (Control-C)
+ctrlc EQU 03O ;ASCII ETX (Control-C)
+bell EQU 07O ;ASCII BEL (Control-G)
+bs EQU 10O ;ASCII backspace (Control-H)
+tab EQU 11O ;ASCII Tab (Control-I)
+lf EQU 12O ;ASCII Line Feed (CTRL-J)
+ff EQU 14O ;ASCII Form Feed (CTRL-L)
+cr EQU 15O ;ASCII Carriage Return (CTRL-M)
+space EQU 20h ;ASCII Space
+xon EQU 21O ;ASCII XON (Control-Q)
+xoff EQU 23O ;ASCII XOFF (Control-S)
+esc EQU 33O ;ASCII ESCape
+semico EQU 3bh ;ASCII Semicolon
+subt EQU 32O ;ASCII SUB (CTRL-Z)
+cntlz EQU subt ;ASCII SUB (Control-z) [6]
+ctrlz EQU subt ;ASCII SUB (Control-z)
+del EQU 177O ;ASCII DELete (rubout)
+;
+;BDOS calls
+IF NOT cpsker ;[6] If CPSKER is truem then system indep. stuff. We want
+ ;to trap BDOS calls and test for console activity
+bdos EQU 0005H ;BDOS entry point, for the following functions:
+ENDIF ;NOT cpsker [6]
+;
+;Function Name Function Input Parameters Output Parameter
+;============= ======== ================ ================
+; (ALL Function Numbers are passed in Register C)
+conin EQU 01H ;Read Console NONE ASCII Char in A
+conout EQU 02H ;Write Console ASCII Char in E NONE
+auxin EQU 03H ;Auxiliary input
+rdrin EQU 03H ;Read Reader NONE ASCII Char in A
+lstout EQU 05H ;Write List ASCII Char in E NONE
+dconio EQU 06H ;Direct Con I/O ASCII Char in E I/O Status in A
+ ; if E=0FEH,
+ ; Input if E=0FFH
+prstr EQU 09H ;Print String String-Address NONE
+ ; in DE (term=$)
+rdstr EQU 0AH ;Read Buffer Buffer-Address Read Buffer filled
+; in DE
+; Read Buffer Byte Function
+; 1 Maximum Buffer Length
+; 2 Current Buffer Length (returned value)
+; 3-n Data (returned values)
+;
+consta EQU 0BH ;Console Stat NONE LSB(A)=1 if char ready
+getvnm EQU 0CH ;Version Number NONE H=0 (CP/M), L=BDOS ver
+inbdos EQU 0DH ;Init BDOS NONE NONE
+logdsk EQU 0EH ;LOG-In disk Value in E NONE
+ ; A=0,B=1,...
+openf EQU 0FH ;Open File FCB-Addr in DE Byte Addr.of FCB,
+ ; or 0FFH if not
+closf EQU 10H ;Close File FCB-Addr in DE Byte Addr.of FCB,
+ ; or 0FFH if not
+sfirst EQU 11H ;Search File FCB-Addr in DE Byte Addr.of FCB(0-3),
+ ; or 0FFH if not
+snext EQU 12H ;Search next FCB-Addr in DE Byte Addr.of next FCB,
+ ; or 0FFH if not
+delf EQU 13H ;Delete File FCB-Addr in DE Byte Addr.of FCB(0-3),
+ ; or 0FFH if not
+readf EQU 14H ;Read Record FCB-Addr in DE 0=successful read
+ ; 1=read past EOF
+ ; 2=reading random data
+writef EQU 15H ;Write Record FCB-Addr in DE 0=successful write
+ ; 1=ERROR extending
+ ; 2=End of disk data
+ ; 255=No more DIR space
+makef EQU 16H ;Make File FCB-Addr in DE 0-3= success,
+ ; 255= no more dir space
+renam EQU 17H ;Rename File FCB-Addr in DE 0-3= success,
+ ; 255= file not found
+rdlog EQU 18H ;Ret. Log Code NONE Login Vector in HL
+rddrv EQU 19H ;Read Drive # NONE # of logged in drive in
+ ; (A=0,B=1,C=2....)
+setdma EQU 1AH ;Set DMA Addr. Addr. of 128 NONE
+ ; byte buffer in DE
+wrtprt EQU 1CH ;Write prot dsk NONE NONE
+getrov EQU 1DH ;Get R/O Vect. NONE HL= R/O Vect. value
+setfat EQU 1EH ;Set File Attr. FCB-Addr.in DE Dir. code in A
+gtdpar EQU 1FH ;Get DSK par. NONE HL=DPB Address
+usrcod EQU 20H ;Get/Set Usr.Cd E=0FFH (get) A=current code (get)
+ ; E-code (set) A=no value (set)
+rrand EQU 21H ;Read Random FCB-Addr in DE A=Return code
+wrand EQU 22H ;Write Random FCB-Addr in DE 1=read'g unwritten data
+ ; 2=(not used)
+ ; 3=can't close curr. ext
+ ; 4=seek to unwr. ext.
+ ; 5=dir overflow(write)
+ ; 6=seek past End of DSK
+cflsz EQU 23H ;Comp File Sz. FCB Addr.in DE Rand.Rec.field set to
+ ; File size
+setrar EQU 24H ;Set Rand. Rec. FCB-Addr.in DE Rand.Rec.field set
+
+; CPM 2 only:
+punout EQU 04H ;Write Punch ASCII Char in E NONE
+gtiob EQU 07H ;Get I/O status NONE I/O Status in A
+ptiob EQU 08H ;Put I/O status I/O Status in E NONE
+getalv EQU 1BH ;Get All.Vect. NONE All.Vect in HL
+
+; CPM 3 only:
+auxout EQU 04H ;Auxiliary output
+auxist EQU 07H ;Get AUXIN: status A=FF if character
+ ; ready, A=0 if none
+auxost EQU 08H ;Get AUXOUT: status A=FF if ready, A=0
+ ; if not ready
+getfs EQU 2EH ;Get free space E=drive # rec free in dma addr
+;
+parevn EQU 00H ;Even parity.
+parmrk EQU 03H ;Mark parity.
+parnon EQU 06H ;No parity (eighth bit is data).
+parodd EQU 09H ;Odd parity.
+parspc EQU 0CH ;Space parity.
+
+defpar EQU parnon ;Default parity.
+ibmpar EQU parmrk ;IBM COMTEN's parity.
+
+fcb EQU 5CH ;Location of File Control Block.
+fcbext equ fcb+12
+fcbrno equ fcb+33
+buff EQU 80H ;Location of file output buffer (DMA).
+bufsiz EQU 80H ;Size of DMA.
+
+maxfcb equ 64 ; maximum of 64 fcbs to be stored in multiple fcb bock
+
+maxpkt EQU '~'-' '+2O;Maximum size of a packet.
+maxtry EQU 05O ; Number of retries on a packet.
+imxtry EQU 20O ; Number of retries send initiate.
+prfair EQU 50 ;[pcc008] Prtchr fairness count
+
+; opcodes for command parser
+cmkey EQU 01H ;Parse a keyword.
+cmifi EQU 02H ;Parse an input file spec (can be wild).
+cmofi EQU 03H ;Parse an output file spec.
+cmcfm EQU 04H ;Parse a confirm.
+cmtxt EQU 05H ;Parse text.
+cmnum EQU 06h ;Parse a number
+cmifin EQU 10H ;Parse an input file spec (but no
+ ;Error output
+
+;[4] from CP4SYS.ASM
+;
+;=========================================================================
+; 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
+
+;[4] From CP4SYS.ASM
+;
+;
+;
+; Protocol parameters. Some of these can be changed with commands.
+;
+
+drpsiz SET 50H ;Default receive packet size. (maximum is 5EH)
+dspsiz SET 50H ;Default send packet size. (maximum is 5EH)
+dstime SET 08H ;Default send time out interval.
+drtime SET 05 ;Default receive time out interval
+
+dspad EQU 00H ;Default send padding.
+drpad EQU 00H ;Default receive padding.
+dspadc EQU 00H ;Default send padding char.
+drpadc EQU 00H ;Default receive padding char.
+dseol EQU CR ;Default send EOL char.
+dreol EQU CR ;Default receive EOL char.
+dsquot EQU '#' ;Default send quote char.
+drquot EQU '#' ;Default receive quote char.
+dschkt EQU '1' ;Default checksum type
+;
+
+; Define VT or Terminal type values
+vtdefo EQU 0 ;VT52 emulation by terminal itself.
+vtdefv EQU 1 ;VT52 emulation by ttab tables in CPXVDU.ASM etc
+vtdefd EQU 2 ;Dumb Terminal (Just prints)
+vtdefe EQU 3 ;Termianl emulation done outside (in overlay)
+
+
+; If this is being assembled by LASM, we need to LINK to one of two modules;
+; if we're not using LASM, no problem.
+; CPSKER.ASM defines "cpsker" TRUE, and CPXTYP.ASM defines it FALSE, so we can
+; determine what's going on.
+IF lasm AND cpsker ; building CP4KER with LASM?
+ LINK CPSMIT ; yes, chain to next piece.
+ENDIF;lasm AND cpsker
+IF lasm AND NOT cpsker ; LASM, but not building CP4KER?
+ LINK CPXLNK ; yes, chain to different piece.
+ENDIF;lasm AND NOT cpsker
diff --git a/src/cpsker.asm b/src/cpsker.asm
new file mode 100644
index 0000000..254d056
--- /dev/null
+++ b/src/cpsker.asm
@@ -0,0 +1,315 @@
+; CPSKER.ASM
+; 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
+; 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 is the header for the system-independent portion of KERMIT, which
+; consists of the following files (in this order):
+;
+; CPSKER.ASM - this file
+; CPSDEF.ASM - definitions for both KERMIT and KERSYS
+; CPSMIT.ASM - \initialization, main loop, miscellaneous commands
+; CPSCOM.ASM - /(BYE, EXIT, LOG, SET, SHOW, and STATUS) (Part1 of 2)
+; CPSPK1.ASM - \the KERMIT protocol handler (SEND, RECEIVE, LOGOUT,
+; CPSPK2.ASM - / and FINISH commands) (In two parts)
+; CPSREM.ASM - REMOTE commands etc
+; CPSSER.ASM - SERVER commands etc (Empty as yet)
+; CPSTT.ASM - the transparent commands (TRANSMIT, CONNECT)
+; CPSCPM.ASM - CP/M commands (DIR, ERA)
+; CPSWLD.ASM - the wildcard handler
+; CPSCMD.ASM - the command parser
+; CPSUTL.ASM - utility routines
+; CPSDAT.ASM - Data space and the overlay link space
+;
+; When building the system-independent part with M80 or MAC80, CPSKER
+; INCLUDEs the other files; when building with LASM, each file LINKs to
+; the next file.
+;
+; For now, the system-dependent routines are all in CPSSYS.ASM, with
+; the actual configuration defined in CPSTYP.ASM.
+;
+; revision history (latest first):
+;
+; Begin CP/M Kermit-80 version 4.11.
+;edit 32, 1-Apr-1991 by MF. Official release of work to date as CP/M Kermit
+; (Kermit-80) Version 4.11.
+; Modified edit level of cpscpm.asm to reflect a bug fix for the TYPE
+; command introduced with edit 13.
+;edit 31, 29-Mar-1991 by MF. Modified edit levels of cpsker.asm,
+; cpscom.asm and cpsdat.asm to reflect rename of parameter vermin to
+; revno (revision level) and change of SET COLLISION REPLACE to
+; SET COLLISION OVERWRITE to conform with C-Kermit. Modified
+; edit level of cpsrem.asm to reflect change from REMOTE SET FILE
+; COLLISION REPLACE to REMOTE SET FILE COLLISION OVERWRITE.
+; Modified edit level of cpsutl.asm to reflect code tightening and
+; edit levels of cpsmit.asm and cpspk2.asm to close any open TAKE-file
+; and abort take-file processing if ^C is typed from the console
+; Also corrected ^Z test in cpsmit.asm in INPUT command ("inp2b")
+; Implement "file not found" complaint if a TAKE command can't find
+; the TAKE-file and it's not the initial TAKE (KERMIT.INI)
+; Modified edit level of cpscpm.asm to reflect modification of the
+; TYPE and PRINT commands to cancel file typeout/printout completely
+; if ^C is entered on the console (either immediately or after a key
+; has been pressed to induce a pause) and to immediately begin
+; typeout/printout of the next file (if the filespec was wild-carded)
+; if ^X is entered (either immediately or after a key has been pressed
+; to induce a pause).
+; Modified edit levels of cpsmit.asm and cpscom.asm to reflect addition
+; of the STAY command as a synonym for SET NO-EXIT.
+;edit 30, 27-Feb-1991 by MF. Modified edit levels of cpscom.asm,
+; cpsmit.asm, cpsutl.asm and cpsdat.asm to reflect provision for
+; a "revision level" field (1-26=A-Z), addition of QUIT as a synonym
+; for the EXIT command, recognition of C, R and S as abbreviations
+; for the CONNECT, RECEIVE and SEND commands, respectively, display
+; of Kermit version in the VERSION command and a fix to the TAKE-file
+; input routine "r1tchr" to prevent semicolons from being interpreted
+; as command separators during TAKE-file execution. This last fix
+; allows such commands as REMOTE DELETE *.*;* to Kermit-32 to
+; operate as expected.
+;edit 29, 14-Feb-1991 by MF. Updated edit levels of cpscom.asm,
+; cpscpm.asm, cpsdat.asm and cpsrem.asm to reflect bug fixes,
+; code tightening and simplified routine "remcli" (in cpsrem.asm)
+; which gets text to be passed on to a remote Kermit in REMOTE
+; Kermit commands.
+;edit 28, 8-Feb-1991 by MF. Changed edit level of cpscpm.asm to reflect
+; a bug fix to make TAKE-files work properly with commands such as
+; INPUT which check the keyboard for input.
+;edit 27, 30-Jan-1991 by MF. Changed edit levels of cpscpm.asm, cpsrem.asm,
+; cpstt.asm and cpsutl.asm to reflect bug fixes and enhancements
+;edit 26, 17-Jan-1991 by MF. Changed edit level of cpscmd.asm to
+; reflect fixes to allow leading spaces/tabs to be ignored when
+; parsing keywords (this was the intent but the code never worked
+; correctly) and to blank the entire fcb in "cmifil" to allow successive
+; COPY commands to function properly. Also changed edit level of
+; cpspk1.asm to reflect further work on "disk full" error reporting.
+;edit 25, 14-Jan-1991 by MF. Incremented edit level of cpspk1.asm to
+; reflect bug fix to "disk full" error reporting code so <cr><lf>
+; is not sent directly to the Remote Kermit. This per a report from
+; Russell Lang of Australia's Monash University.
+;edit 24, 10-Jan-1991 by MF. Modified edit level of cpxtyp.asm to
+; reflect addition of "terminal required" message for some.
+; machines.
+;edit 23, 7-Jan-1991 by MF. Modified edit levels of cpxtyp.asm, cpxswt.asm,
+; cpxbbi.asm to reflect addition of Ampro Little Board support.
+;edit 22, 3-Jan-1991 by MF. Incremented edit levels of cpspk1.asm/cpspk2.asm
+; to reflect further mods to "sdata" and "inchr" routines.
+;edit 21, 2-Jan-1991 by MF. Incremented edit level of cpspk1.asm to reflect
+; code cleanup in "sdata" routine.
+;edit 20, 26-Dec-1990 by MF. Modified edit level of CPSCMD.ASM to reflect
+; fix to allow leading white space to be skipped in lines from
+; TAKE-files as well as from the CP/M command-line tail; this per a
+; phoned-in bug-report to Dr. Martin J. Carter of Nottingham
+; University in the U.K. (PPZMAJOC@vax.ccc.nottingham.ac.uk)
+;edit 19, 14-Dec-1990 by MF. Modified edit level of cpspk2.asm to reflect
+; modification to "gofil" to allow drive specifications in 2nd
+; filename of GET and RECEIVE commands; also modified edit levels of
+; cpspk1.asm and cpsrem.asm to reflect addition of "<<>>" around
+; "X" or "F" packets coming as a reply to a REMOTE command and
+; deletion of an unnecessary instruction before label remc2d
+; in cpsrem.asm.
+;edit 18, 9-Dec-1990 by MF. Modified edit levels for Version 4.10
+; yet another time to reflect changes in CPSDAT.ASM to clarify
+; "File size on DIR" status message.
+;edit 17, 4-Dec-1990 by MF. Adjusted edit levels of cpscom.asm/cpsdat.asm
+; to reflect addition of Autoreceive status to SHOW/STATUS display.
+;edit 16, 30-Nov-1990 by MF. Adjusted edit levels of cpscom.asm/cpsdat.asm
+; to reflect fix to SHOW/STATUS routines to show terminal display
+; mode (quiet/regular). Also adjusted edit level of cpsutl.asm to reflect
+; change to routine "p20ln" to use "pausit" to save code space.
+; Adjusted edit level of cpsdef.asm to reflect change in "fairness"
+; counter prfair from 100 to 50 to make terminal a bit more responsive
+; during CONNECTs.
+;edit 15, 27-Nov-1990 by MF. Adjusted edit level of cpspk1.asm to reflect
+; a bug fix.
+;edit 14, 27-Nov-1990 by MF. Again adjusted edit level of cpspk1.asm to
+; reflect modifications of "disk-full"and SET INCOMPLETE-FILES behavior.
+;edit 13, 23 Nov-1990 by MF. Adjusted edit level of cpspk1.asm to reflect
+; code changes for "disk full" processing.
+;edit 12, 8-Nov-1990 by MF.
+; Adjusted edit levels shown for cpscom.asm/cpspk1.asm/cpsdat.asm to
+; reflect bug fixes and code revisions.
+;edit 11, 5-Nov-1990 by MF.
+; Cosmetic changes for main help text for COPY and RENAME commands.
+; Begin CP/M Kermit-80 version 4.10.
+;edit 10, 2-Nov-1990 by MF. Moved Overlay address to 7000H (cpsdat.asm).
+;edit 9, 1-Nov-1990 by Mike Freeman (BPA). Cosmetic changes (command-name
+; changes: SET BAUD-RATE==>SET SPEED, FCOPY==>COPY, FRENAME==>RENAME,
+; STRING==>OUTPUT, REMOTE CWD==>REMOTE CD per suggestions of FDC
+; to aid in uniformity of nomenclature for various Kermits.
+;edit 8, 30-Oct-1990 by Michael Freeman; 301 N.E. 107th Street;
+; Vancouver, WA 98685 USA; Telephone (206)574-8221.
+; Work: Bonneville Power Administration
+; P.O. Box 491 M/S MORF
+; Vancouver, WA USA 98666
+; Telephone (206)690-2307
+; Implemented FRENAME command to rename a CP/M file.
+; Implemented many Remote commands, variable-length packets up thru
+; 94 characters in length. Fixed a bug in CPSCOM.ASM in the
+; routine "getnp" and a bug in CPSCOM.ASM which caused garbage to appear
+; on the screen when PRTSTR was called with QUIETD flag set.
+; Modified code in module CPSCMD.ASM to skip leading spaces and tabs
+; when getting Kermit commands from the CP/M command line. This also
+; obviates the necessity to type a leading semicolon to separate the
+; Kermit command from the Kermit commands on the CP/M command line.
+; Fixed code in CPSPK2.ASM which handles file collision detection
+; and resulting file rename per my entries in CPKERM.BWR.
+; and included fix by Russell Lang of Dept. of Electrical and Computer
+; Engineering, Monash University, Australia, to prevent renamed
+; files with SET WARNING ON from having the attributes (e.g., R/O)
+; copied from original file. Mr. Lang's E-mail address is:
+; Russell Lang Email: rjl@monu1.cc.monash.edu.au Phone: (03) 565 3460
+; Department of Electrical and Computer Systems Engineering
+; Monash University, Australia
+; Also fixed a bug in CPSPK2.ASM which prevented completion messages
+; from being displayed if terminal was set to QUIET.
+; Implemented most proposed SET FILE-COLLISION (COLLISION) commands.
+; Implemented SET INCOMPLETE file disposition command.
+; Implemented a few of the proposed REMOTE SET commands.
+; Implemented other fixes suggested in CPKERM.BWR.
+; Moved overlay address to 6C00H.
+; Changed location of .printx in this file so LASM doesn't complain.
+; In system-dependent modules, included HP-125 support.
+; Also modified Telcon Zorba code in CPXHEA.ASM to enable setting
+; of baud-rates and sending of a break.
+; Included Russell Lang of Monash Univ. Australia's implementation
+; for the Microbee series of computers (CPXBEE.ASM).
+; Fixed COMPUPRO version of Kermit to compile correctly and to
+; conform to current syntax for setting baud-rate.
+; edit 7, September, 1987. Added files for SERVER and REMOTE
+; modules (CPSSER/CPSREM). SERVER is still empty, and may be
+; only wishfull thinking. I have ideas, but I dont think I
+; will have the time to implement it.
+;
+; edit 6: 30 March, 1987 by OBSchou. Start Kermit-80 V4.09 with the
+; overlay address at 6000h. Also adjusted the INCLUDEs to allow
+; M80 to assmeble these files.
+;
+; edit 5: 20 June, 1986. Have added so much code etc that the overlay had to
+; be moved again.. give it to 5000h. This starts off Kermit-80 V4.08
+;
+; edit 4 22 April 1986
+; Start work on 4.06. This should clear up a couple of bugs, add in
+; a few features, and split the system dependent stuff into
+; smaller units.
+;
+; edit 3a 7 March 86 OBSchou Loughborough england. Minor additions
+; to cpsker.asm, cpscmd.asm and cpspkt.asm.
+;
+; edit 3: February 10, 1985 (CJC)
+; Update for v4.05; add "verno" so CPSUTL doesn't have to change
+; just because some other module did.
+;
+; edit 2: September 10, 1984 (CJC)
+; Update for v4.03.
+;
+; edit 1: July 27, 1984 (CJC)
+; Created to allow assembly of Kermit by LASM as well as MAC80 and M80.
+
+verno EQU 11 ; minor version number
+revno EQU 0 ;[MF]Revision level
+ ;[MF]0-26 yields A-Z
+
+; Version 4.10 of Kermit consists of the following edit levels:
+; cpsker.asm edit 32
+; cpsdef.asm edit 9
+; cpsmit.asm edit 30
+; cpscom.asm edit 13
+; cpspk1.asm edit 23
+; cpspk2.asm edit 11
+; cpsrem.asm edit 13
+; cpsser.asm edit 1
+; cpstt.asm edit 12
+; cpscpm.asm edit 14
+; cpswld.asm edit 4
+; cpscmd.asm edit 13
+; cpsutl.asm edit 30
+; cpsdat.asm edit 19
+; cpxlnk.asm edit 8 (cpslnk.asm is not assembled with cpsker, but it
+; defines the linkage area expected by cpsker, and so must
+; match the description in cpsutl.asm)
+; cpxswt.asm edit 10
+;
+; Version 4.10 of Kermit has been tested with the following edit levels of
+; the system-dependent files:
+; cpxtyp.asm edit 34
+; cpxsys.asm edit 40
+; cpxhea.asm edit 4
+; cpxtor.asm edit 4
+; cpxbbi.asm edit 4 (Ampro Little Board)
+;
+; Version 4.10 of Kermit is still to be tested fully against all known systems
+; so far included in the system dependent overlays.
+;
+
+
+FALSE equ 0
+TRUE equ NOT FALSE
+
+cpsker equ TRUE ; building system-independent part
+debug equ FALSE ; set false for running system. True => does some
+ ; unusual or unexpected things.
+;
+; Assembler type. Define the appropriate one TRUE, the rest FALSE. (We can't
+; use ASM, because it cannot handle multiple input files)
+mac80 EQU FALSE ; For assembly via MAC80 cross-assembler.
+m80 EQU false ; For assembly via Microsoft's M80.
+lasm EQU true ; For assembly via LASM, a public-domain
+ ; assembler.
+;
+; Get the other modules...
+
+IF lasm ; If we're linking, go on to the next file.
+ LINK CPSDEF
+ENDIF;lasm
+
+; If we're still here, we must be using M80 or MAC80. M80 doesn't
+; like ENDs inside conditionals, but the END statement has to be
+; in CPSUTL for LASM (otherwise, we'd need a file containing just an
+; END statement). So, we leave off the IF m80 OR mac80 conditional
+; that ought to be around these INCLUDEs. No problem until the next
+; incompatible assembler comes along...
+; Let's first say where we are:
+;
+.printx * CPSKER.ASM (or nearest offer) *
+;
+.printx * CPSDEF.ASM *
+ INCLUDE CPSDEF.ASM ; definitions
+.printx * CPSMIT.ASM *
+ INCLUDE CPSMIT.ASM ; initialization, main loop, some commands
+.printx * CPSCOM.ASM *
+ INCLUDE CPSCOM.ASM ; part of command/status/set etc
+.printx * CPSPK1.ASM *
+ INCLUDE CPSPK1.ASM ; KERMIT protocol handler (Part 1)
+.printx * CPSPK2.ASM *
+ INCLUDE CPSPK2.ASM ; KERMIT protocol handler (Part 2)
+.printx * CPSREM.ASM *
+ INCLUDE CPSREM.ASM ; Kermit REMOTE code (little in it, as yet)
+.printx * CPSSER.ASM *
+ INCLUDE CPSSER.ASM ; Kermit SERVER code (As yet, empty)
+.printx * CPSTT.ASM *
+ INCLUDE CPSTT.ASM ; transparent communication handler
+.printx * CPSCPM.ASM *
+ INCLUDE CPSCPM.ASM ; CP/M command support (DIR, ERA)
+.printx * CPSWLD.ASM *
+ INCLUDE CPSWLD.ASM ; wildcard handler
+.printx * CPSCMD.ASM *
+ INCLUDE CPSCMD.ASM ; command parser
+.printx * CPSUTL.ASM *
+ INCLUDE CPSUTL.ASM ; Various utilities and data, and END [ToadHall]
+.printx * CPSDAT.ASM *
+ INCLUDE CPSDAT.ASM
+ END ; MAC80 ignores END's in included files...
diff --git a/src/cpsmit.asm b/src/cpsmit.asm
new file mode 100644
index 0000000..f41ee70
--- /dev/null
+++ b/src/cpsmit.asm
@@ -0,0 +1,834 @@
+; CPSMIT.ASM
+; 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-independent initialization, the main
+; loop, and the commands that don't have any place better to go.
+; All the SET xxx and status routines now in CPSCOM.ASM as CPSMIT.ASM
+; was getting too big.
+;
+; revision history:
+;
+;edit 30, 29-Mar-1991 by MF. When looking up a TAKE-file in a TAKE command
+; and the file is not found, complain if it's not the first TAKE of
+; the current program execution (the automatic TAKE of KERMIT.INI)
+;edit 29, 25-Mar-1991 by MF. Add STAY command as a synonym for SET NO-EXIT
+; command per Martin J. Carter of Nottingham University in the U.K.
+;edit 28, 21-Mar-1991 by MF. Modify code after "inp2a" in INPUT command
+; so a ^C will halt TAKE-file processing
+;edit 27, 27-Feb-1991 by MF. Add QUIT as a synonym for EXIT per code of
+; Dr. Martin J. Carter of Nottingham University, U.K. Recognizing QUIT
+; helps those who forget they're not in MS-Kermit, C-Kermit,
+; Kermit-32 etc. Also add commands so that CONNECT, RECEIVE and SEND may
+; be abbreviated to C, R and S, respectively.
+;edit 26, 5-Nov-1990 by MF. Cosmetic changes to main HELP messages for
+; COPY and RENAME commands.
+;edit 25, 1-Nov-1990 by MF. Made the following command-name changes in the
+; interest of uniformity of nomenclature (per suggestions of FDC):
+; FCOPY to COPY, FRENAME to RENAME and STRING to OUTPUT.
+; This means we'll have to type "CO" for CONNECT and "REC" for
+; RECEIVE but with REMOTE now with us we have to do the latter anyway.
+;edit 24, 18-Sep-1990 by MF. Implemented FRENAME command to rename a
+; CP/M file.
+;edit 23, 9-Sep-1990 by MF. Implemented commands to be sent to a
+; remote Kermit Server (Remote commands).
+; Implemented setting of packet sizes for RECEIVE and SEND.
+; Put DIRECTORY/STRING help texts in proper alphabetical position.
+; edit 22, July 6th, 1987 by OBSchou. Added a dummy Commandline to be
+; loaded for debugging purposes as DDT destroys any command line at 80H
+; Also fixed a bug or two...
+;
+; edit 21, April 8th, 1987.
+; Various bits, including more SET SENDRECEIVE options, and make
+; PADDING and PADCHAR valid options. Have I wasted my time, or
+; there still systems that use padding?? Fixed a bug in the INPUT
+; command so we know how many characters there are to check for. Also
+; hived off the SET commands to make a new file, CPSCOM.ASM thereby
+; reducing the size of CPSMIT.ASM. Also rename COPY command to FCOPY
+; hence retaining a single C to imply connect.
+;
+; edit 20, March 30, 1987 by OBSchou.
+; added code for no exit to CPM if a command tail is done (optional)
+; by the SET NO-EXIT command. Added bits for SET AUTORECEIVE to enable
+; or inhibit automatic receive of several files (if something is coming
+; along from the remote side, do a receive. Toss first packet away.)
+; This is first step to SERVER???
+; Also added back the INPUT command.
+;
+; edit 19, March 16, 1987. Moved the code to check for and execute
+; command tails (See Richard Russells submission below).
+; Added flags to exit to CP/M after executing a command tail.
+; The KERMIT.INI file is taken before the command tail is issued.
+;
+; edit 18, March 11, 1987 by OBSchou.
+; Added in code for TYPE <file> and PRINT <file>. Hope to add COPY
+; later on. Also added in code submitted by Richard Russel, to accept
+; a command tail on entry to kermit (eg KERMIT CONNECT). This facility
+; if used, will replace the automatic TAKE function on loading Kermit.
+; Unfortunately, you will not be dropped back to CP/M after the command
+; In the future, it may be possible to either accept several commands
+; on the command tail, and possibly accept the automatic TAKE facility
+; as well. Low on my list of things to do.
+;
+; edit 17, January 28, 1987 by OBSchou for DJ Roberts of Leicester
+; Also added a couple of fixes [obs]
+;
+; DJR January 1987 David J. Roberts.
+; USER made a SET option
+; STATUS output placed in alphabetical order
+; Report DEBUG mode and default disk
+; Name of LOG file on SHOW/STATUS display
+;
+;
+; edit 16 December 1st, OBSchou. Fixed bug in that if the overlay is not in
+; place or correct then prtstr is not called to print the error message
+; (As prtstr has been moved out of the system independent code)
+;
+; edit 15 November 10, 1986 by OBSchou. Re-inserted Pause and Break
+; commands for release.
+;
+; edit 14 August 29, 1986. Removed PAUSE,BREAK,INPUT and SET CASE as
+; these have not been fully coded or debugged. (For next
+; version of Kermit-80...). Also tidied up a bit.
+;
+; 13 by OBSchou for Godfrey Nix. He writes:
+; edit August 11,1986 Godfrey Nix, Nottingham University [gnn]
+; To insert code for setting the packet start character on
+; both send and receive packets (default is still 01H)
+; and make GET and RECEIVE to be separate;
+; use with edits to CP4PKT, CP4UTL
+;
+; edit 12: 19 June, 1986 by OBSchou. Added PAUSE and BREAK facility.
+; Breaks simulate a call to sysint which tests for a B being passed.
+; Note this is only useful if the system dependent code supports breaks,
+; and an appropriate message is returned if breaks are not possible.
+; Also added is the command entry for INPUT, which waits for a string
+; from the host for a given time. The time is a very variable counter
+; incremented every BDOS call. Trial and error will give a reasonable
+; value. STRING acceps a string from the use and then sends it on
+; to the host. These new commands allow a user to (almost) set up auto
+; log on files, where BREAKS/INPUT/STRING/STRING partially emulate a user
+; (AI LURES OK and all that). Still could do with a test, eg if not a
+; correctly returned string go back n steps. This would make a fairly
+; simple TAKE command a lot more complicated.
+;
+;edit 11: 30 May, 1986 OBSchou. Added in a couple of more routines and such
+;
+;edit 10: 27 May, 1986 OBSchou. Added in support for USER function
+; removed XMIT test and routine, but also added SET FLOW-CONTROL
+; (set for XON/XOFF flow control in both directions) and a
+; SET CASE-SENSITIVE ON/OFF (if on => a # A, if ON => a=A)
+;
+;edit 9: 13 May, 1986 OBSchou, Loughborough University, UK
+; Added in code for SET XMIT character to allow setting of the
+; character to wait for from the host during TRANSMIT. It is
+; a line feed by default. Also added a TAKE command, to take: commands
+; from a named disk file. If a file is TAKEn, then all BDOS calls
+; are trapped and tested for console input. If so, we substitute a
+; character (or buffer) from the TAKE file specified.
+; This may also be used in the future for a CPKERMIT.INI
+; to be evaluated during Kermit initialsation.
+;
+; edit 8: February 6, 1895
+; Add a PORT status/show routine for those machines that have more
+; than one they can talk to. It also required a port storage variable
+; a la SPEED and the necessary code to handle it in the SET routine.
+; [Hal Hostetler]
+;
+; edit 7: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
+;
+;pcc003-pcc005 2-Jan-85 vjc modules:cp4mit,cp4tt,cp4utl
+; These edits must all be installed together and change the way
+; logging is handled. The log file spec is moved to a separate
+; fcb, and not opened until an actual CONNECT command is given.
+; This takes care of a NASTY bug that if you used any other file
+; command between the LOG and CONNECT, the log file would get
+; written over the last file used. This also allows logging to
+; be "permanently" enabled until an CLOSE (new command) for all
+; CONNECT sessions, like most other kermits do. If a log file
+; already exists, it will be appended to. Also add two new
+; CONNECT mode commands <esc>Q to suspend logging and <esc>R to
+; resume. <esc>R means something else during TRANSMIT, but
+; logging is never on then, so there shouldn't be any conflict.
+; I also changed the write code, so that it can handle one more
+; character after the XOFF is send to stop the host. This allows
+; a little "slop" for systems that don't stop immediately (such
+; as TOPS10), but it didn't help much.
+;
+;pcc012 4-Jan-85 vjc modules:cp4mit,cp4tt,cp4utl
+; Use the big buffer for the log file. Move the log file back
+; into the common fcb and only save the drive, name, and
+; extension between connects. Add new routines to cp4utl to
+; create or append to an existing file, and to conditionally
+; advance buffers only if in memory. Remove edit pcc003 that
+; allows one more character after the xoff, since it didn't
+; really work very well and does not fit in well with the way
+; the buffer advancing routines are set up. If someone still
+; thinks this would be useful, it could be put back in with a
+; little more work.
+;
+; While testing this edit, I also noticed another bug that
+; the command parsing routines do not limit or check the
+; length of command lines or file specs, trashing what ever
+; comes after them. Currently because of where the fcb and
+; command buffer are located, this does not usually cause a
+; problem, but could if an extremely long line was typed in,
+; or in the future multiple fcbs defined elsewhere in memory
+; were used. Maybe this should be put on the bug list
+; somewhere.
+;
+;pcc013 8-Jan-85 vjc modules:cp4mit,cp4utl,cp4typ
+; Replace CLOSE command to cancel session logging to SET
+; LOGGING ON/OFF. This seems to fit in with the command
+; structure better. Default the log file to KERMIT.LOG
+; incase no previous LOG command. Logging is also enabled
+; by LOG command, as before.
+;
+; edit 6: September 8, 1984
+; Add VERSION command, to display the internal version strings.
+; Move command tables here from CP4UTL, and translate string
+; lengths in them to decimal (how many fingers do YOU got?).
+; Replace some jump tables with dispatch addresses in tables.
+; Make help text for SET command consistent with top level help text.
+;
+; edit 5: August 21, 1984
+; Add word at 0100H to allow us to exit cleanly from DDT (shifting
+; entry section by two bytes).
+;
+; edit 4: August 3, 1984 (CJC)
+; Remove "mover" from entry section, as it now lives in CP4SYS.
+;
+; edit 3: July 27, 1984 (CJC)
+; Merge LASM support from Toad Hall: most of CP4MIT is now in CP4UTL.
+; When assembling with LASM, CP4MIT is linked by CP4DEF; it links to
+; CP4PKT. Add SET TACTRAP command. Separate out display routines so
+; we can eventually do "SHOW <parameter>". Save both bytes of baud
+; rate in speed, and check both bytes when displaying baud rate. Move
+; header info to CP4KER.ASM. Add onoff and chkkey routines to simplify
+; SET command (Toad Hall)
+;
+; edit 2: June 8, 1984
+; formatting and documentation; delete unreferenced variables and some
+; unnecessary labels; move setpar here from cp4pkt; add module version
+; string; make this version 4.01.
+;
+; edit 1: May, 1984
+; extracted from CPMBASE.M80 version 3.9; modifications are described
+; in the accompanying .UPD file.
+
+;
+ ASEG
+ ORG 100H
+
+; The CCP invokes programs with a CALL 100H, with the stack pointer set to
+; 100H. When we exit to CP/M, we do so with a RET, avoiding a warm boot.
+; Unfortunately, DDT starts programs with a jump, not a call, so when we
+; attempt to return to CP/M, we blow the stack and use the word at 100H as
+; the new PC. Put a 0 there so we reboot instead of dying horribly.
+; (Fortunately, this happens to be two NOP's).
+ dw 0
+ jmp start ; Bypass entry section
+
+;
+; Entry section for system-independent part. This contains
+; jumps to routines needed by the system support module.
+;
+entries:
+ jmp kermit ; reentry address
+ jmp nout ; output HL in decimal
+entsiz equ $-entries ; length of entry section
+;
+; End of entry section. As a consistency check, the expected
+; length of this section is stored by the system-dependent
+; module in the linkage section at the end of Kermit, and
+; tested at initialization.
+
+mitver: db 'CPSMIT.ASM (30) 29-Mar-1991$' ; name, edit number, date
+;
+;
+; Initialization
+;
+start: lxi h,0 ; Clear out hl pair
+ dad sp ; and fetch the system stack pointer
+ shld oldsp ; and save for later restoral
+ lxi sp,stack ; move in our own stack.
+ lxi d,version ; print Kermit version
+ call prtstx ; before we do too much (Use fudged prtstr)
+ mvi c,rddrv ;Get our logged in drive
+ call BDOS
+ inr a ;relative 1
+ sta CURDSK ;and save it for later
+
+ lda vtflg ; [OBS] Hangover from VT52 ems not possible...
+ cpi 0ffh ; ... if 0ff stored, assume terminal = off
+ mvi a,vtdefo
+ jnz start0
+ sta vtflg ; if 0ffh make it VT52 off
+start0:
+
+
+IF debug
+;vvvvvvvvvvvvvvvv remove this for run time
+; OBS edit 22 - add in a dummy command line to 80H
+ lxi h,dcomln ;[22] load up dummy command line
+ lxi d,81h ;[22] where to put it
+ lxi b,endcoml-dcomln
+ mov a,c ; get length to a
+ sta 80h ; ... and save as command line length
+ call mover ; ... and save rest of line
+ jmp starta
+dcomln: db 'set baud 4800',semico
+ db 'set dir on',semico
+ db 'dir'
+ db 0,0 ; just to make up space
+endcoml:
+;^^^^^^^^^^^^^^^^ remove this for run time
+ENDIF ;debug
+
+
+starta:
+;
+; Make sure the overlay is in place...
+;
+ lhld lnkflg
+ mov a,h
+ ora l ; if lnkflg is still zero,
+ jz start1 ; the configuration overlay is missing.
+ lxi d,-lnksiz ; if it's not equal to lnksiz,
+ dad d ; we've probably got the wrong
+ mov a,h ; version of the configuration overlay.
+ ora l
+ jnz start2
+ lhld lnkent ; make sure the overlay knows how long
+ lxi d,-entsiz ; our entry section is, so they don't miss.
+ dad d
+ mov a,h
+ ora l
+ jnz start2
+ ; might be ok.
+ lxi h,bdos ; set xbdos address to bdos trap in our code.
+ shld xbdos+1 ; (they may never use it...)
+ call sysinit ; do system-dependent initialization
+ lda bufsec ; get the max no of buffers allowed by system
+ sta maxbsc ; save for SET BUFFER use to compare
+ lxi d,inms26 ; offer some advice on getting help
+ call prtstr
+ lxi h,buff ;[19] we copy any potential command tail across
+ lxi d,cbuff
+ lxi b,80h ;[19] copy all 128 bytes. May use none.
+ call mover
+ lda 80h ; see if there is a command tail...
+
+ ana a
+
+
+
+; Remove for runtime use
+; xra a ; make out there is no command tail
+; Runtime => no XRA above
+
+ jz startz
+ dcr a
+ jz startz ; one character tail...
+ lda takflg ; if more characters, say we are have tail
+ ori 10h ; set bit 4
+ sta takflg
+ sta nexitf ; exit back to CP/M after command line
+startz:
+ mvi a,0ffh ; when here, system basically initiallised,...
+ sta initflg ; apart from KERMIT.INI, so say initialised.
+
+ call take1 ;[9] take a KERMIT.INI file
+ xra a ;[MF] Say we've done it
+ sta initak ;[MF] ...
+ jmp kermit ; Start main loop.
+
+start1: lxi d,erms20 ; "Kermit has not been configured"
+ call prtstx ; print error message (Use bodge for prtstr)
+ jmp exit2 ; and exit.
+
+start2: lxi d,erms21 ; "Consistency check on configuration failed"
+ call prtstx ; print error message
+ jmp exit2 ; and exit.
+;
+;This is the main KERMIT loop. It prompts for and gets the users commands.
+
+kermit: lxi sp,stack ; get new stack pointer, old one might be bad.
+ call selcon ; make sure console is selected.
+ xra a
+ sta mfflg1 ;reset MFNAME
+ sta mfflg2 ;ditto
+ sta mfflg3
+ sta getrxflg ; clear the get/receive flag
+ ;0=> receive, non 0 => get
+ sta cmbflg ;[MF]Initial keyword must not be blank
+ sta cmqflg ;[MF]Allow character-echoing during commands
+ sta remtxt ;[MF] Clear remote-text-to-screen flag
+ lda curdsk ; update the prompt
+ adi 'A'-1
+ sta kerm1+2
+ call getun ;[11] get the user number into temp1/2
+ lda temp1+1 ;[11] get ms value of user number
+ cpi '0' ;[11] less than 10 => do a space
+ jnz kerm4 ;[11] else do MS digit of user number
+ mvi a,' ' ;[11]
+kerm4: sta kerm1 ;[11]
+ lda temp1 ;[11] get ls digit of user number
+ sta kerm1+1 ;[11] save that
+ lda takflg ; are we in TAKE or command line??
+ ani 11h ; strip out both bits
+ jnz kerm5 ; still in either or both...
+ lda nexitf ; if neither, and no-exit-flag set, we quit.
+ ana a
+ jnz exit ;... back to CP/M, else as you were...
+kerm5:
+ lxi d,kerm
+ call prompt ;Prompt the user.
+
+kerm7: lxi d,comtab
+ lxi h,tophlp
+ call keycmd ; Get a keyword
+ xchg ; Get result (dispatch address) into HL
+ pchl ; Dispatch.
+
+; here from: log, setcom, read, cfmcmd
+kermt3: lxi d,ermes3 ;"Not confirmed"
+ call prtstr
+ jmp kermit ;Do it again.
+
+; Structure of command table:
+;
+; 1) Number of entries.
+; 2) Each entry is arranged as follows:
+; a) length of command in bytes.
+; b) 'name of command and $-sign'
+; c) address of routine to process command
+;
+; ---> Note this command table is in alphabetic order.
+;
+
+comtab: db 32 ; added remote
+ ;[obs] added in COPY command, now called FCOPY
+ ;[obs] removed remote simply to issue V4.09
+ ;[MF]Make FCOPY/FRENAME COPY/RENAME for
+ ;[MF]Version 4.10
+ ;[MF]Add QUIT as a synonym for EXIT and
+ ;[MF]C, R and S as abbreviations for
+ ;[MF]CONNECT, RECEIVE and SEND, respectively
+ ;[MF]Add STAY as a synonym for SET NO-EXIT
+ db 5, 'BREAK$'
+ dw break
+ db 3, 'BYE$'
+ dw bye
+ db 1,'C$'
+ dw telnet ;[MF]Abbreviation for CONNECT
+ db 7, 'CONNECT$'
+ dw telnet
+ db 4,'COPY$'
+ dw copy
+ db 9, 'DIRECTORY$'
+ dw dir
+ db 5, 'ERASE$'
+ dw era
+ db 4, 'EXIT$'
+ dw exit
+ db 6, 'FINISH$'
+ dw finish
+ db 3, 'GET$'
+ dw read ; [gnn] entry for GET
+ db 4, 'HELP$'
+ dw help
+ db 5, 'INPUT$'
+ dw input
+ db 3, 'LOG$'
+ dw log
+ db 6, 'LOGOUT$'
+ dw logout
+ db 6, 'OUTPUT$'
+ dw string
+ db 5, 'PAUSE$'
+ dw pause
+ db 5, 'PRINT$'
+ dw printf ;[obs] print a file
+ db 4,'QUIT$'
+ dw exit ;[MF]Synonym for EXIT
+ db 1,'R$'
+ dw read0 ;[MF]Abbreviation for RECEIVE
+ db 7, 'RECEIVE$'
+ dw read0 ; [gnn] not same as GET now
+ db 6, 'REMOTE$'
+ dw remote
+ db 6,'RENAME$'
+ dw rename ;[MF]
+ db 1,'S$'
+ dw send ;[MF]Abbreviation for SEND
+ db 4, 'SEND$'
+ dw send
+ db 3, 'SET$'
+ dw setcom
+ db 4, 'SHOW$'
+ dw show
+ db 6, 'STATUS$'
+ dw status
+ db 4,'STAY$'
+ dw noexit ;STAY (SET NO-EXIT)
+ db 4, 'TAKE$' ;[9]
+ dw take
+ db 8, 'TRANSMIT$'
+ dw xmit
+ db 4, 'TYPE$'
+ dw type ;[obs] type a file command
+ db 7, 'VERSION$'
+ dw shover
+; db 4, 'USER$' ; removed [DRJ]
+; dw user ;[10] removed [DRJ]
+; top-level help message. Caps indicate keywords.
+; this text is also printed by the HELP command.
+
+tophlp:
+ db cr,lf,'BREAK to send a break to the host'
+ db cr,lf,'BYE to host (LOGOUT) and exit to CP/M'
+ db cr,lf,'CONNECT to host on selected port'
+ db cr,lf,'COPY to copy a CP/M file'
+ db cr,lf,'DIRECTORY of current used Micro-disk'
+ db cr,lf,'ERASE a CP/M file'
+ db cr,lf,'EXIT to CP/M'
+ db cr,lf,'FINISH running Kermit on the host'
+ db cr,lf,'GET a file from the host'
+ db cr,lf,'HELP by giving this message'
+ db cr,lf,'INPUT to make the micro wait for a string from the host'
+ db cr,lf,'LOG the terminal sessions to a file'
+ db cr,lf,'LOGOUT the host'
+ db cr,lf,'OUTPUT to send a specified string to the host'
+ db cr,lf,'PAUSE to wait for a little time'
+ db cr,lf,'PRINT a file to the printer'
+ db cr,lf,'QUIT to CP/M'
+ db cr,lf,'RECEIVE file from host'
+ db cr,lf,'REMOTE to send commands to a remote server'
+ db cr,lf,'RENAME to rename a CP/M file'
+ db cr,lf,'SEND file to host'
+ db cr,lf,'SET a parameter'
+ db cr,lf,'SHOW the parameters'
+ db cr,lf,'STATUS of Kermit'
+ db cr,lf,'STAY at Kermit command-level after a command tail'
+ db cr,lf,'TAKE commands from a file' ;[9]
+ db cr,lf,'TRANSMIT file to host (in connect state)'
+ db cr,lf,'TYPE a file to the console'
+ db cr,lf,'VERSION of Kermit running' ;[pcc005]
+; db cr,lf,'USER to set a different user number' ;removed [DJR]
+ db '$' ;[obs] added it here to allow for expansion
+
+;
+; This is the BREAK command. It sends a 'B' to the system dependent
+; interrupt routines (test for escape-cokebottle xxx) and do a break
+; if the overlay can. Else, we tell user not to be so silly.
+break: call cfmcmd ; get return
+ mvi a,'B' ; were gonna do a break if the overlay can
+ call sysint ; try doing it..
+ jmp kermit ; if we can do it, else
+ lxi d,inms12 ;... say not implemented
+ jmp kermit
+
+;
+;
+; This is the BYE command. It tells the remote KERSRV to logout,
+; then exits.
+
+bye: call cfmcmd
+ call logo ;Tell the main frame to logout.
+ jmp kermit ;If it fails, don't exit.
+ call sysbye ; success. do system-dependent cleanup
+ jmp exit1 ;Exit Kermit.
+
+; This is the EXIT command. It leaves KERMIT and returns to CP/M.
+; alternate entries: exit1, from BYE command;
+; exit2, from initialization (if it fails)
+
+exit: call cfmcmd ; confirm...
+exit1: call sysexit ; do system-dependent termination
+exit2:
+ jmp 0 ; return to CP/M via JUMP instead of RET.
+
+; lhld oldsp ;Get back the system stack
+; sphl ;and restore it.
+; ret ;Then return to system.
+
+; Input command. Syntax:
+; INPUT [Wait period] [string]
+; where
+; Wait period is a time period to wat for
+; string is a string to expect back from the host. Control
+; characters are entered as \ and an octal number.
+;
+; I can see uses for this command from other routines...
+;
+input: mvi a,cmnum ; first get the number
+ call comnd ; get it
+ jmp kermit ; if we dont understand it...
+ lhld number
+ shld waitp ; and save as the wait period
+ lxi d,stbuff ; where to put the string
+ mvi a,cmtxt ; get text
+ call comnd
+ jmp kermit ; not quite correct...
+ sta strcnt ; string count returned in a
+ call cfmcmd ; get a confirm
+
+ lhld waitp ; multiply the number by
+ dad h
+ dad h ; ... 4
+ dad h ; ... 8
+ inx h ; but make sure it is at least 1
+ shld waitp ; and save it away again
+ shld waitp1 ; save in case we need to reset counter
+
+; Right, now wait for characters comming from the line, within the
+; time allowed (very fuzzy). Compare with STRING buffer
+;
+inp1: xra a
+ sta repcnt ; clear the host prompt chars.counter
+inp2: lhld waitp ; have we waited long enough
+ dcx h
+ shld waitp ; count less one
+ mov a,h ; test to see if both zero
+ ora l
+ jnz inp20 ; nope
+ mvi a,3 ; error is three ie total failure
+ sta errorc
+ jmp inp5 ; take error exit
+
+inp20: call rd1chl ; read a character from the line
+ ani 7fh ; set flags
+ jnz inp4 ; Not zero => we have a character from host
+ call ckchr ; see if *WE* have a character from console
+ push psw ; restore to modem
+ call selmdm ; reselect the modem port
+ pop psw
+ ani 7fh ; strip parity (should not be there)
+ jnz inp2a ; if a null, try again
+ lda strcnt ; if the string length is zero, dont wait.
+ ana a
+ jnz inp2 ; so loop back again
+ jmp kermit ; else drop out
+
+inp2a: cpi cntlc ; do we want to abort?
+;[MF]Change following line
+; jz kermit ; in which case exit back to command loop
+ jnz inp2b ;[MF] No
+ lda takflg ;[MF] Yes, are we TAKEing
+ ani 1 ;[MF] commands from a file?
+ cnz closet ;[MF] Yes, close and reset to get
+ ;[MF] commands from the command-line
+ jmp kermit ;[MF] and exit back to command loop
+inp2b: cpi cntlz ; if control z exit back to command loop
+ jz kermit ; else try for other characters [MF]
+ jmp inp2
+
+inp4: mov e,a ; save it for a while
+ lda repcnt ; see if this character matches with one in buffer
+ lxi h,stbuff ; point to string buffer
+ add l ; make hl = hl + a
+ mov l,a
+ mvi a,0 ; ie make hl = hl + character count
+ adc h
+ mov h,a ; not using xra, as that clears the Carry flag
+ mov a,e ; get the character back again
+ cmp m ; is it = to what we expect?
+ jnz inp1 ; no, clear counter and try again
+ lda repcnt ; yes, then update the pointer, and ...
+ inr a ; ... see if we have received all ...
+ sta repcnt ; ... we should have received
+ lhld waitp1 ; get original counter
+ shld waitp ; and reset the loop (timer) counter
+ mov e,a ; save length into E again
+ lda strcnt ; get the length to compare
+ sub e ; if (e) > string length, we have it
+ jnz inp2 ; else wait for a little longer
+
+ xra a ; no errors
+ sta errorc
+ jmp kermit ; so say nothing
+;else if error...
+
+inp5: lxi d,erms30 ; say message not receive in time...
+ call prtstr
+ jmp kermit ; have string, so exit
+
+;
+;
+
+; This is the HELP command. It gives a list of the commands.
+
+help: call cfmcmd
+ lxi d,tophlp ;The address of the help message.
+ call p20ln ;Print at most 20 lines then pause
+; call prtstr
+ jmp kermit
+;
+; This is the LOG command. It logs a session to a file.
+
+log: mvi a,cmofi ;[pcc005] Parse an output file spec.
+ lxi d,fcb ;[pcc012] where to put it
+ call comnd
+ jmp kermt3
+ call cfmcmd
+ lxi h,fcb ;[pcc012] copy file name and ext
+ lxi d,lognam ;[pcc012] to a safe place
+ lxi b,12 ;[pcc012] 12 bytes
+ call mover ;[pcc012] zap ...
+ mvi a,1 ;[pcc005] set flag for logging
+ sta logflg ;[pcc005]
+ jmp kermit ;[pcc005]
+
+;
+; PAUSE [Wait period]. Just wait for a couple of tics...
+pause: mvi a,cmnum ; get the number of the wait period
+ call comnd ; get it
+ jmp kermit ; we canna do it, so get next command
+ lhld number
+ xchg ; move to d
+ lhld clkbit+1 ; get clock bits 8 to 23
+ mov a,h ; strip ms bit so we have space for a possible carry
+ ani 7fh
+ mov h,a
+ dad d ; add the number (ie get the number to wait to
+ shld number ; save it somewhere
+;
+; Now, wait for time to be equal to newer NUMBER with Carry
+ploop:
+ call clock ; increment clock
+ lda takflg ; test if keyboard interrupt.. not for takes
+ ana a
+ jnz ploop1 ; do nothing for take command files
+ mvi c,dconio ; get status from console
+ mvi e,0ffh ; just get the character
+ call bdos
+ ana a ; if non zero return, then quit
+ jnz kermit ; we got something, so quit
+ploop1: lhld number
+ xchg
+ lhld clkbit+1 ; get bits 8 to 23
+ mov a,h
+ ani 7fh ; make it 15 bits for a carry...
+ mov h,a
+ mov a,e ; now, do (DE with carry) - HL
+ sub l
+ mov e,a
+ mov a,d
+ sbb h
+ ora e ; a = OR of result
+ jnz ploop
+ jmp kermit ; otherwise we are done.
+
+; PRINT - Print a file to the console and printer.
+; This command is active only from the command level, and not
+; from the connect state. Unfortunately, the print command is
+; not going to be a background utility.
+printf: mvi a,0ffh ; set the print flag on
+typent: sta prnfl ; Type file entry. Common for PRINT and TYPE
+ call type ; and do the rest of the print via type
+ xra a
+ sta prnfl ; next clear the print flag
+ jmp kermit
+
+; TYPE - Type a file to the console.
+; This command is really the same as the print command, but the output
+; is not copied to the printer.
+typef: xra a ; we want to clear the printer on flag
+ jmp typent ; go to the type entry in printfile above
+
+
+;
+; This is the TAKE command. It take input from a file.
+; TAKE1 is the entry for automatically TAKE-ing KERMIT.INI (or whatever
+; the file name at taknam is) from the default drive
+; [18] code added to accept command tails. See note [18] above
+;
+take: mvi a,cmifi ;[9] Get filename from user
+ lxi d,takfcb ;[9] Take file fcb space
+ call comnd ;[9] get the file spec
+ jmp kermit ;[9] User failed to specify a good file spec
+ call take2 ;[MF] Now TAKE the file
+ jmp kermit ;[MF] Go back to main Kermit command loop
+;
+take1: lxi b,12 ;[9] copy default drive and file name to take fcb
+ lxi d,takfcb
+ lxi h,taknam
+ call mover ;[9] and do it (all other extents etc are zero)
+;[MF][30]No longer need the following line
+; jmp take2 ; got the file name, now take it.
+;
+ ;[9] get the file name, now lets open it
+;
+take2:
+ lda takflg ; check to see we have not tak-take
+ ani 1 ; if set, we are in a take already
+;[MF]We can do the following test/call more efficiently
+; jz take21
+; call closet ; so close current take file
+ cnz closet ;[MF] So close current take file
+take21:
+ mvi c,setdma
+ lxi d,takdma ;[9] tell bdos where to send data
+ call BDOS
+ xra a ;[9] clear all these extents etc
+ sta takfcb+14
+ sta takfcb+32
+ lxi d,takfcb ;[9] open the file
+ mvi c,openf ;[9] open the file
+ call BDOS
+ inr a ;[9] if FF returned, problems
+;[MF]Complain if failure and not seeking KERMIT.INI
+; jz kermit ;[9] for now, say nowt if no ini file. Else..
+ jz ntake ;[9] We'll say file not found
+ ;[MF] unless the initial TAKE (KERMIT.INI)
+; jmp take3 ; a test
+; mvi c,readf ;[9] read first bytes from file
+; lxi d,takfcb ;[9]
+; call BDOS
+
+take3: lxi h,0
+ shld takptr ;[9] point to first byte of take file
+ lda takflg ; get current flag
+ ori 1 ;[9] and set flag to tell Kermit we're taking
+ sta takflg
+;[MF][30]Redo next lines so can flag initial TAKE of KERMIT.INI
+; call rnsect ;[9] read a sector
+; jmp kermit ;(Should use a ret, but this will do)
+ jmp rnsect ;[9] read a sector and return
+
+ntake: lda initak ;[MF]Is this the initial TAKE (KERMIT.INI)?
+ ora a ;[MF]...
+ rnz ;[MF]Yes, don't complain
+ lxi d,erms15 ;[9] Say file not found
+ call prtstr
+;[MF][30]Make next line a "jmp" since we've called TAKE2
+; call rstdma ;[9] reset the DMA addres for other files
+; jmp kermit
+ jmp rstdma ;[9] reset the DMA addres for other files
+ ;[MF] and return
+
+
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FRO RELEASE!
+
+; org ($+100h) AND 0FF00H
+
+IF lasm
+ LINK CPSCOM
+ENDIF ;lasm
diff --git a/src/cpspk1.asm b/src/cpspk1.asm
new file mode 100644
index 0000000..6ea4831
--- /dev/null
+++ b/src/cpspk1.asm
@@ -0,0 +1,1904 @@
+; CPSPK1.ASM
+; 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
+; 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-independent) routines that implement
+; the KERMIT protocol, and the commands that use them:
+; RECEIVE, SEND, FINISH, and LOGOUT.
+;
+; revision history:
+;
+;edit 23, 16-Jan-1991 by MF. The bug of (22) was not fixed (although
+; the error described needed to be corrected). Really fixed the bug this:
+; time. changed "lda 'E'" after "ptch9b" to "mvi a,'E'" -- Zilog
+; mnemonic thinking must've addled my brain!
+;edit 22, 14-Jan-1991 by MF. Fix bug in the code which sends an "E" packet
+; to the remote Kermit on encountering "disk full" so that
+; uncontrollified <CR><LF> is not copied to the packet data area (and
+; hence sent to the remote Kermit). This should fix a bug reported
+; by Russell Lang of Monash University in Australia wherein a PC
+; running Kermit in Server mode complained of invalid characters when
+; receiving the "disk full" error packet from CP/M Kermit.
+;edit 21 of 3-Jan-1991 by MF. Reverse part of edit 20 which flushes comm
+; input at EOF send: the problem of multiple copies of packets being
+; sent when a stream of files being sent is partially interrupted with
+; ^X has been fixed by modifying "inchr" in CPSPK2.ASM.
+;edit 20, 2-Jan-1991 by MF. Tightened up code just after "sdata1" and around
+; "sdat14". Added code to flush comm input after user has typed ^X
+; or ^Z to interrupt file sends so that duplicate packets are not
+; sent after the interrupt character (especially ^X) has been typed.
+;edit 19, 14-Dec-1990 by MF. Place "<<>>" around "F" and "X" packets coming
+; as replies to REMOTE commands a la VMS Bliss Kermit.
+; Also type each character of "X" or "F" packet explicitly in case
+; dollar-signs are part of the filename (as in VMS Bliss Kermit
+; when a REMOTE TYPE is given and SET FILE NAMING FULL is in effect).
+; Expanded code is at label rfil3f.
+;edit 18, 27-Nov-1990 by MF. Fix bug introduced with edit 17 which resulted
+; in "E" packet being sent twice when receiving file(s) and disk-full
+; occurred. Sorry about that, folks!
+;edit 17, 27-Nov-1990 by MF. When receiving files, make the decision as to
+; whether to delete a partially-received file on a "disk full"
+; condition subject to the setting of the SET INCOMPLETE-FILES
+; switch in conformity with the behavior of MSDOS Kermit.
+; An "E" packet is still sent to the remote Kermit. Also try to close
+; any incomplete file whether deleting it or not (labels rdat16 and
+; rdat3a). If keeping incomplete files, try to write outstanding
+; buffers to disk, giving an error if the disk is full.
+;edit 16, 23-Nov-1990 by MF. When receiving, cause the file being written
+; to disk to **always** be deleted and an "E" packet to be sent when a
+; "disk full" condition is encountered (per suggestion of
+; RJL@MONU1.CC.MONASH.EDU.AU).
+;edit 15, 15-Nov-1990 by MF. Changed code for the Receive Complete state
+; to always go into RECEIVE if AUTORECEIVE is on. This will happen
+; most of the time anyway as most mainframe Kermits issue a prompt
+; after a single SEND command (wild-carded or not), thus guaranteeing
+; that the modem status check of Kermit-80 ver. 4.09 would **always**
+; have characters ready for input (the mainframe Kermit's prompt),
+; defeating the status check and the Console input check (originally
+; intended to drop the user out of the loop if he/she typed a key with
+; no comm input present). Eliminate "any key" message there also.
+; the user can drop out by hitting ^C.
+; Of course, none of the foregoing applies if the Receive Complete
+; state occurs as the result of a "Get" command where Autoreceive
+; is meaningless and we just drop back to Kermit command-level.
+;edit 14, 1-Oct-1990 by MF. Added code to send an "I" packet before an
+; "R" packet in GET command.
+; Modified routine "sinit" to ignore "E" packets when sending an
+; "i" packet (per KPROTO.DOC).
+;edit 13, 14-Sep-1990 by MF. Added code to implement SET FILE COLLISION
+; and SET INCOMPLETE commands.
+;edit 12, 9-Sep-1990 by MF. Added code to prevent packet counts
+; from being displayed during Remote commands. Fixed
+; AUTORECEIVE code, file colision Rename algorithm and eliminated
+; multiple display of initial messages during GET/RECEIVE.
+; edit 11, 28 July, 1987 by OBSchou. Commented out capas etc support
+; (Long packets etc) as this is not worth the effort coding... but
+; I have left what WAS done for any enthusiast. Also set in a few
+; to NOT write to screen if SET TERMINAL QUIET set. Hopefully speeds
+; up transfers on systems taking forever to update screens.
+;
+; edit 10, 8 April, 1987 by OBSchou. Tarted up all sorts of bits n bobs
+; to cope with all the new aditions for Kermit-80 V 4.09
+; Look for the [10] for most cahnges. spar and rpar largely replaced
+;
+; edit 9, March 30th by OBSchou. Set bits for automatically receiving
+; another file if a remote sender sends files in seperate sessions.
+; The code simply checks the serial line, and if there is some
+; activity, assume its another SEND INIT packet. As there is no
+; simple way to go to receive with the control-a, just ignore the
+; packet. Causes one retry on the sender, but so what. Really
+; should make it a server gizzmo.
+;
+; edit 8: January 28, 1987 by OBSchou
+; Two major issues: firstly split CPSPKT.ASM into CPSPK(1 2).ASM
+; making it far easier to handle this file.
+; Second, some mode to the GET routines to correctly print the file
+; name instead of the fireworks. Trouble was with GET <file> <file>
+; and RECEIVE <file>. However, new bugs discovered...
+;
+; edit 7: August 11, 1986 Godfrey N. Nix [gnn] Nottingham University
+; To ignore echoed packets (ie send 'S' receive 'S' before 'A');
+; To allow character other than SOH for packet header (see also
+; updates to CP4MIT and CP4UTL for other code needed);
+; To permit SEND and RECEIVE to specify a host filename which
+; is of a different structure to that of CP/M.
+;
+; edit 6a: [OBSchou] 7 March, 1985.
+; Edited file with additions from MJ Carter. He writes:
+; 25th September 1985, M J Carter [majoc], Nottingham University
+; Code in gofil() amended, for exactly the same reasons to the
+; alteration to cmifil() in cpscmd.asm. If there is any deep
+; reason why gofil() has to be used instead of a call to comnd(cmofil),
+; I can't see it. The bug (on a British Micro Mimi 803) caused
+; gofil() to overwrite existing files in GET and RECEIVE, even
+; with file warning SET ON.
+;
+;edir 6: November 22, 1984
+; Change SEND's 'Unable to find file' error exit from calling
+; error3 to calling prtstr instead. I don't know about you, but
+; I greatly dislike having messages dumped into pre-existing
+; junk on the screen where I have to spend lots of time hunting
+; for them. [Hal Hostetler]
+;
+; edit 5: September 9, 1984
+; Call flsmdm in init to flush old input when starting transfers.
+; Select console before returning from inpkt.
+; Replace inline code with calls to makfil/clofil to set up for
+; multisector buffering on output.
+; Remove superfluous call to clrlin in error3.
+;
+; edit 4: August 21, 1984 (CJC)
+; Fix comment in inpkt: packet is terminated by NUL on return, not CR.
+; If debugging, display the outgoing packet before putting the EOL
+; character on, so the dumped packet doesn't get overwritten.
+;
+; edit 3: July 27, 1984
+; add link directive for LASM. CP4PKT is linked by CP4MIT, and links
+; to CP4TT. Add Toad Hall TACtrap to permit operations through a TAC.
+;
+; edit 2: June 8, 1984
+; formatting and documentation; remove some unused labels; move setpar
+; to cp4mit.m80; add module version string; make all arithmetic on
+; 'pktnum' modulo 64; apply defaults correctly for missing parameters
+; in send-init packet (and corresponding ack).
+;
+; edit 1: May, 1984
+; extracted from CPMBASE.M80 version 3.9; modifications are described
+; in the accompanying .UPD file.
+;
+pk1ver: db 'CPSPK1.ASM (23) 16-Jan-1991$' ; name, edit number, date
+
+; GET command [gnn]
+; here from: kermit
+
+read: mvi a,0ffh ;[obs 8] we are doing a get
+ sta getrxflg ;[obs 8] so set flag
+ lxi d,remdat ;Where to put the text (if any.)
+ mvi a,cmtxt
+ call comnd ;Get either some text or a confirm.
+ jmp kermt3 ; Didn't get anything.
+ ora a ;Get any chars?
+ jz kermt3 ;[gnn] GET must have a filename
+ sta rdl ;Store the number of chars.
+ xchg ;Get pointer into HL.
+ mvi m,'$' ;Put in a dollar sign for printing.
+ call init ;Clear the line and initialize the buffers.
+ lda quietd ; quiet display?
+ ana a
+ jz read01 ;[MF]No, go ahead and position cursor
+ call prcrlf ;[MF]Yes, keep from overwriting the prompt
+ jmp read00 ;[MF]and write filename
+read01: call scrfln ;Position cursor [MF]
+read00: lxi d,remdat ;Print the file name, in either case
+ call prtstr
+ jmp read0a ;[gnn] go get local name if any
+
+
+; enter here for RECEIVE command [gnn]
+read0: mvi a,0 ;[gnn]
+ sta rdl ;[gnn][MF] flag entry as receive, not get
+ sta getrxflg ;[obs 8] doing a receive, so reset flag
+ call init ;clear line, initialise buffers
+read0a: lxi d,remnam ;[gnn] save local name here
+ mvi a,cmtxt ;[gnn]
+ call comnd ;[gnn] read second filename if present
+ jmp kermt3 ;[gnn] error exit
+ sta remlen ;[gnn] save length of name, may be zero
+ sta getrxflg ;[obs 8] May also be receive <fnam> so
+ ;[obs 8]pretend get for printing filename
+ lda rdl ;[gnn] look at first name
+ ora a ;[gnn] receive or get?
+ jz read1 ;[gnn] receive
+
+ mvi a,'I' ;[MF]Set state to send "I" packet
+ sta state ;[MF]...
+
+; jmp read12 ;[obs] [gnn] does not want this
+
+read1: ;call init ;Clear the line and initialize the buffers.
+read12: xra a
+ sta czseen ;Clear the ^X/^Z flag initially.
+ lxi h,0
+ shld numpkt ;Set the number of packets to zero.
+ shld numrtr ;Set the number of retries to zero.
+ sta pktnum ;Set the packet number to zero.
+ sta numtry ;Set the number of tries to zero.
+ lda quietd ; quiet display?
+ ana a
+ jnz read13 ; yes, so dont write...
+ call scrnrt ;Position cursor
+ lxi h,0
+ call nout ;Write the number of retries.
+read13: lda rdl ;[MF]Get or receive?
+ ora a ;[MF]...
+ jnz read2 ;[MF]Get, don't reset state
+ mvi a,'R'
+ sta state ;Set the state to receive initiate.
+ ;...
+;
+;RECEIVE state table switcher.
+
+read2: lda quietd ; noisy display?
+ ana a
+ jnz read21 ; no, a quiet one
+ lda remtxt ;[MF] In Remote command?
+ ora a
+ jnz read21 ;[MF] Yes, don't write to screen
+ call scrnp ;Position cursor
+ lhld numpkt
+ call nout ;Write the current packet number.
+read21: lda state ;Get the state.
+ cpi 'D' ;Are we in the DATA receive state?
+ jnz read22
+ call rdata
+ jmp read2
+
+read22: cpi 'X' ; F packet but not an F packet?
+ jnz read3 ; nope, so try next one
+ call rfile ; 'get' the filename (but dont open it)
+ jmp read2
+
+read3: cpi 'F' ;Are we in the FILE receive state?
+ jnz read4
+ call rfile ;Call receive file.
+ jmp read2
+
+read4: cpi 'R' ;Are we in the Receive-Initiate state?
+ jnz read5
+ call rinit
+ lda state ;[jd] get new state
+ cpi 'F' ;[jd] went into receive state?
+ jnz read2 ;[jd] no
+ lxi d,inms24 ;[jd] yes, get receiving... message
+ call finmes ;[jd] go print it
+ jmp read2
+
+read5: cpi 'C' ;Are we in the Receive-Complete state?
+ jnz read6
+ lxi d,infms3 ;Put in "Complete" message.
+ lda czseen ;Or was it interrupted?
+ ora a ; . . .
+ jz read5a ;No.
+ xra a ;Yes, clear flag.
+ sta czseen ; ...
+ lxi d,inms13 ;Issue "interrupted" message.
+read5a: lda remtxt ;[MF] Doing a Remote command?
+ ora a
+ cz finmes ;Print completion message in right place if not
+;
+ lda rdl ;[MF]Receive or Get?
+ ora a ;[MF]...
+ jnz kermit ;[MF]Get, Autoreceive means nothing.
+ lda autorc ; see if we want autoreceives
+ ana a
+ jz kermit ;[MF]No autoreceives, so drop out
+ lxi d,autmes ;[MF]Yes, tell the user what we're doing
+ call prtstr ;[MF]...
+ jmp read1 ;[MF]Try another Receive (we get one
+ ;[MF]retry from the sender as the ^A is lost)
+
+read6: cpi 'Y' ;[MF]Simple ack (from remote command)?
+ jz kermit ;[MF]Yes
+
+ cpi 'I' ;[MF]Exchanging parameters via info packet?
+ jnz read7 ;[MF]No
+ call sinit ;[MF]Yes, send the packet
+ lda state ;[MF]Now see what happened
+ cpi 'X' ;[MF]Did we exchange parameters successfully?
+ jz read6a ;[MF]Yes, go send the filespec
+ cpi 'A' ;[MF]No, are we in abort state?
+ jnz read2 ;[MF]No, try again
+ jmp kermit ;[MF]Yes, it's a real disaster, we must stop
+read6a: lda rdl ;[MF]Get length of filespec
+ sta argblk+1 ;[MF]as length of packet
+ mov c,a ;[MF]We must copy the filespec
+ mvi b,0 ;[MF]...
+ lxi h,remdat ;[MF]from the temporary buffer
+ lxi d,data ;[MF]to the packet data area
+ call mover ;[MF]Do it.
+; for GET we must send the name of the file we want [gnn]
+
+ mvi a,'1' ;Start with single character checksum
+ sta curchk ;Save the type
+ xra a ;Start a packet zero.
+ sta argblk
+ mvi a,'R' ;Receive init packet.
+ call spack ;Send the packet.
+ jmp kermt3 ; Die!
+ xra a
+ sta czseen ;Clear the ^X/^Z flag initially.
+ lxi h,0
+ shld numpkt ;Set the number of packets to zero.
+ sta pktnum ;Set the packet number to zero.
+ sta numtry ;Set the number of tries to zero.
+ mvi a,'R' ;[MF]Set state to Receive-Initiate
+ sta state ;[MF]...
+ jmp read21 ;[MF]and go around again
+ ;[MF]without retyping packet-number
+
+read7: cpi 'A' ;Are we in the Receive-"Abort" state?
+ jnz read8
+read8: lxi d,infms4 ;Anything else is equivalent to "abort".
+ call finmes
+ jmp kermit
+;
+; Receive routines
+
+; Receive init
+; called by: read
+
+rinit: lda numtry ;Get the number of tries.
+ cpi imxtry ;Have we reached the maximum number of tries?
+ jm rinit2
+ lxi d,ermes4
+ call error3 ;Move cursor and print an error message.
+ jmp abort ;Change the state to abort.
+
+rinit2: inr a ;Increment it.
+ sta numtry ;Save the updated number of tries.
+ mvi a,'1' ;Reset block check type to single character
+ sta curchk ;Store as current type for initialization
+ call rpack ;Get a packet.
+ jmp nak ; Trashed packet: nak, retry.
+ cpi 'S' ;Is it a send initiate packet?
+ jnz rinit3 ;If not see if its an error.
+rini2a: lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ xra a
+ sta numtry ;Reset the number of tries.
+ lda argblk ;Returned packet number. (Synchronize them.)
+ call countp
+ lda argblk+1 ;Get the number of arguments received.
+ lxi h,data ;Get a pointer to the data.
+ call spar ;Get the data into the proper variables.
+ lxi h,data ;Get a pointer to our data block.
+ call rpar ;Set up the receive parameters.
+ sta argblk+1 ;Store the returned number of arguments.
+ mvi a,'Y' ;Acknowledge packet.
+ call spack ;Send the packet.
+ jmp abort ; Failed, abort.
+ lda inichk ;Now switch to agreed upon check-type
+ sta curchk ;For all future packets
+ mvi a,'F' ;Set the state to file send.
+ sta state
+ ret
+
+rinit3: cpi 'E' ;Is it an error packet.
+ jnz nak0 ;If not NAK whatever it is.
+ call error
+ jmp abort
+;
+; Receive file
+; called by: read
+
+rfile: lda numtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm rfile1
+ lxi d,ermes5
+ call error3 ;Move cursor and print an error message.
+ jmp abort ;Change the state to abort.
+
+rfile1: inr a ;Increment it.
+ sta numtry ;Save the updated number of tries.
+ call rpack ;Get a packet.
+ jmp nak ; Trashed packet: nak, retry.
+ cpi 'S' ;Is it a send initiate packet?
+ jnz rfile2 ; No, try next type.
+ lda oldtry ;Get the number of tries.
+ cpi imxtry ;Have we reached the maximum number of tries?
+ jm rfil12 ;If not proceed.
+ lxi d,ermes4
+ call error3 ;Move cursor and print an error message.
+ jmp abort ;Change the state to abort.
+
+rfil12: inr a ;Increment it.
+ sta oldtry ;Save the updated number of tries.
+ lda pktnum ;Get the present packet number.
+ dcr a ;Decrement
+ ani 3FH ; modulo 64
+ mov b,a
+ lda argblk ;Get the packet's number
+ cmp b ;Is the packet's number one less than now?
+ jnz nak0 ;No, NAK and try again.
+ call updrtr ;Update the retry count.
+ xra a
+ sta numtry ;Reset the number of tries.
+ lxi h,data ;Get a pointer to our data block.
+ call rpar ;Set up the parameter information.
+ sta argblk+1 ;Save the number of arguments.
+ mvi a,'Y' ;Acknowledge packet.
+ call spack ;Send the packet.
+ jmp abort ; Failed, abort.
+ ret
+
+rfile2: cpi 'Z' ;Is it an EOF packet?
+ jnz rfile3 ; No, try next type.
+ lda oldtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm rfil21 ;If not proceed.
+ lxi d,ermes6
+ call error3 ;Move cursor and print an error message.
+ jmp abort ;Change the state to abort.
+
+rfil21: call tryagn
+ ret
+
+rfile3: cpi 'F' ;Start of file?
+ jnz rfil3b
+ mov c,a ;[MF]Save packet type
+ lda remtxt ;[MF]Doing a remote server command?
+ ora a ;[MF]...
+ mov a,c ;[MF]Restore packet type
+ jnz rfil3d ;[MF]If yes, same as x packet
+ call compp
+ jnz nak0 ;No, NAK it and try again.
+ call countp
+ mov c,a ;[MF]
+ lda remtxt ;[MF]Doing a remote command?
+ ora a ;[MF]...
+ mov a,c ;[MF]
+ jnz rfil3a ;[MF]Yes, don't open a file
+ call gofil ;Get a file to write to, and init output buffer.
+ jmp abort
+rfil3a: lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ call ackp
+ mvi a,'D' ;Set the state to data receive.
+ sta state
+ lda czseen ;Check if we punted a file
+ cpi 'Z' ;and didn't want any more
+ rz ;If that was the request, keep telling other end
+ xra a ;Otherwise, clear flag (^X is only for one file)
+ sta czseen ;And store the flag back
+ ret
+
+rfil3b: cpi 'X' ;Start of 'file?' , but not a file?
+ jnz rfile4
+rfil3d: call compp
+ jnz nak0 ;No, NAK it and try again.
+ call countp
+
+ call selcon ;[MF]Select Console
+ lda argblk+1 ; get length
+ ora a ;[MF]Anything to write?
+ jz rfil3e ;[MF]No
+ push psw ;[MF]Yes, save character count
+ mvi e,'<' ;[MF]Write "<<" as in VMSKermit
+ push d ;[MF]...
+ call outcon ;[MF]...
+ pop d ;[MF]...
+ call outcon ;[MF]...
+ pop psw ;[MF]Restore character count
+ lxi h,data ; lets write the filename (?) to display
+rfil3f: push psw ;[MF]Save loop counter
+ mov e,m ;[MF]Get character to write
+ inx h ;[MF]and increment character pointer
+ push h ;[MF]Save the pointer
+ call outcon ;[MF]Write character to display
+ pop h ;[MF]Restore pointer
+ pop psw ;[MF]and loop counter
+ dcr a ;[MF]Decrement the counter
+ jnz rfil3f ;[MF]Display entire filename
+ mvi e,'>' ;[MF]Put in ">>" as in VMSKermit
+ push d ;[MF]...
+ call outcon ;[MF]...
+ pop d ;[MF]...
+ call outcon ;[MF]...
+ call prcrlf ;[MF]New line
+rfil3e: lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ call ackp
+ mvi a,'D' ; expecting a D packet
+ sta state
+ lda czseen ;Check if we punted a file
+ cpi 'Z' ;and didn't want any more
+ rz ;If that was the request, keep telling other end
+ xra a ;Otherwise, clear flag (^X is only for one file)
+ sta czseen ;And store the flag back
+ ret
+
+rfile4: cpi 'B' ;End of transmission.
+ jnz rfile5
+ call compp
+ jnz nak0 ;No, NAK it and try again.
+ xra a ;No data. (Packet number already in argblk).
+ sta argblk+1
+ mvi a,'Y' ;Acknowledge packet.
+ call spack ;Send the packet.
+ jmp abort
+ mvi a,'C' ;Set the state to complete.
+ sta state
+ ret
+
+rfile5: cpi 'E' ;Is it an error packet.
+ jnz abort
+ call error
+ jmp abort
+;
+; Receive data
+; called by: read
+
+rdata: lda numtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm rdata1
+ lxi d,erms10
+ call error3 ;Display error message.
+rdat16: lda remtxt ;[MF]Is a Remote command in progress?
+ ora a ;[MF]...
+ jnz abort ;[MF]Yes, don't worry about file disposition
+ lda incflg ;[MF]Are we keeping incomplete files?
+ ora a ;[MF]...
+ jnz rdat17 ;[MF]Yes
+ lxi d,fcb ;[MF]No, close the file, ignoring errors
+ push d ;[MF]while protecting the pointer
+ mvi c,closf ;[MF]...
+ call bdos ;[MF]...
+ pop d ;[MF]Now delete the file, ignoring errors
+ mvi c,delf ;[MF]...
+ call bdos ;[MF]...
+ jmp abort ;Change the state to abort.
+rdat17: call clofil ;[MF]Try to close the file, writing
+ ;[MF]outstanding buffers to disk
+ jmp rdat37 ;[MF]We can't, the disk is full
+ jmp abort ;[MF]Change the state to "abort"
+
+rdata1: inr a ;Increment it.
+ sta numtry ;Save the updated number of tries.
+ call rpack ;Get a packet.
+ jmp nak ; Trashed packet: nak, retry.
+ cpi 'D' ;Is it a data packet?
+ jnz rdata2 ; No, try next type.
+ call compp ;check for correct packet number (zero flag = ok)
+ jz rdat14 ;its correct
+ lda oldtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm rdat12 ;If not proceed.
+ lxi d,erms10
+ call error3 ;Display err msg.
+ jmp rdat16 ;[MF]Change the state to abort.
+
+rdat12: call tryagn
+ ret
+
+rdat14: call countp
+ lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ lda argblk+1 ;Get the length of the data.
+ call ptchr
+ jmp rdat3b ;[MF] Unable to write out chars;abort.
+ xra a
+ sta numtry ;Reset the number of tries.
+ sta argblk+1 ;No data. (Packet number still in argblk.)
+ mov c,a ;Assume no data
+ lda czseen ;Check if control-X typed
+ ora a ; . . .
+ jz rdat15 ;Zero if not typed
+ mov c,a ;Get the type of character typed
+ mvi a,1 ;One data character
+ sta argblk+1 ;Save the count
+ mov a,c ;Get the possible data character
+ sta data ;Store in data area
+rdat15: mvi a,'Y' ;Acknowledge packet.
+ call spack ;Send the packet.
+ jmp rdat16 ;[MF]
+ ret
+
+rdata2: cpi 'F' ;Start of file?
+ jnz rdata3 ; No, try next type.
+ lda oldtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm rdat21 ;If not proceed.
+ lxi d,ermes5
+ call error3 ;Display err msg.
+ jmp rdat16 ;[MF]Change the state to abort.
+
+rdat21: call tryagn
+ ret
+
+rdata3: cpi 'Z' ;Is it a EOF packet?
+ jnz rdata4 ;Try and see if its an error.
+ call compp
+ jnz nak0 ;No, NAK it and try again.
+ call countp
+ lda argblk+1 ;Get the data length
+ cpi 1 ;Have one item?
+ jnz rdat33 ;If not, ignore data
+ lda data ;Yes, get the character
+ cpi 'D' ;Is it a 'D' for discard?
+ jz rdat36 ;If so, punt file
+rdat33: lda remtxt ;[MF]Writing text to disk?
+ ora a ;[MF]...
+ jnz rdat38 ;[MF]No, don't close file
+ call clofil ;Finish off the file.
+ jmp rdat37 ; Give up if the disk is full.
+rdat38: xra a ;Since we kept the file,
+ sta czseen ;don't say it was discarded.
+ lda numtry ;Get the number of tries. [MF]
+ sta oldtry ;Save it. [MF]
+ call ackp ;[MF]
+ jmp rdat39 ;[MF]and get ready to get more files
+rdat36: lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ call ackp
+ lda remtxt ;[MF]Is a Remote command in progress?
+ ora a ;[MF]...
+ jnz rdat39 ;[MF]Yes, don't worry about file disposition
+ lda dscflg ;[MF]Is the file being punted because
+ ora a ;[MF]of a collision?
+ jnz rdat39 ;[MF]Yes, don't delete the existing file
+ lda incflg ;[MF]No, are we keeping incomplete files?
+ ora a ;[MF]...
+ jnz rdat3a ;[MF]Yes
+ lxi d,fcb ;[MF]No, close the file,
+ mvi c,closf ;[MF]ignoring errors
+ push d ;[MF]...
+ call bdos ;[MF]...
+ pop d ;[MF]Now delete the file,
+ mvi c,delf ;[MF]ignoring errors
+ call bdos ;[MF]...
+ jmp rdat39 ;[MF]and continue
+rdat3a: call clofil ;[MF]Try to close the file, writing
+ ;[MF]outstanding buffers to disk
+ jmp rdat37 ;[MF]Can't, disk is full
+rdat39: mvi a,'F'
+ sta state
+ ret
+
+rdat37: call ptchr9 ; Send "?Disk full" on the error line [MF]
+ ; and to the remote Kermit [MF]
+rdat3b: lda remtxt ;[MF]Doing a Remote command?
+ ora a ;[MF]...
+ jnz abort ;[MF]Yes, just abort
+ lxi d,fcb ;[MF]Close the file, ignoring errors
+ push d ;[MF]Protect fcb pointer
+ mvi c,closf ;[MF]...
+ call bdos ;[MF]...
+ pop d ;[MF]Restore pointer
+ lda incflg ;[MF]Are we keeping incomplete files?
+ ora a ;[MF]...
+ jnz abort ;[MF]Yes, just abort transfer
+ mvi c,delf ;[MF]No, delete the file, ignoring errors
+ call bdos ;[MF]...
+ jmp abort ;[MF] abort transfer
+
+rdata4: cpi 'E' ;Is it an error packet.
+ jnz rdat16 ;[MF]
+ call error
+ jmp rdat16 ;[MF]
+;
+; SEND command
+; here from: kermit
+
+send: mvi a,cmifi ;Parse an input file spec.
+ lxi d,fcb ;Give the address for the FCB.
+ call comnd
+ jmp kermit ; Give up on bad parse.
+; section to get remote filename [gnn]
+ lxi d,remnam ;[gnn] where to put filename
+ mvi a,cmtxt ;[gnn]
+ call comnd ;[gnn] get the text to end of the line
+ jmp kermt3 ;[gnn] failure in reading buffer
+ sta remlen ;[gnn] save length (may be zero)
+;
+ xra a
+ sta mfflg1 ; clear flags...
+ sta mfflg2
+ sta mfflg3 ;[gnn]
+ sta fcbcnt ;[gnn] clear fcbcount
+ lxi h,fcb0 ;[gnn] and fcb pointer
+ shld xfcbptr
+;
+ call mfname ;handle (multi) files
+ jnc send14 ;got a valid file-name
+ lxi d,erms15
+ call prtstr ;Display error msg. ([hh] where it's visible)
+ jmp kermit
+
+send14: call init ;Clear the line and initialize the buffers.
+ xra a
+ sta pktnum ;Set the packet number to zero.
+ sta numtry ;Set the number of tries to zero.
+ sta wrn8 ;[jd] we haven't sent the 8-bit-lost warning
+ lxi h,0
+ shld numpkt ;Set the number of packets to zero.
+ shld numrtr ;Set the number of retries to zero.
+ lda quietd ; a quiet display?
+ ana a
+ jnz send15 ; yup, dont write
+ call scrnrt ;Position cursor
+ lxi h,0
+ call nout ;Write the number of retries.
+send15: mvi a,'1' ;Reset to use single character checksum
+ sta curchk ;For startup
+ mvi a,'S'
+ sta state ;Set the state to receive initiate.
+ ;...
+;
+;SEND state table switcher
+
+send2: lda quietd ; a quiet display?
+ ana a
+ jnz send21 ; yes, so dont write
+ call scrnp ;Position cursor
+ lhld numpkt
+ call nout ;Write the packet number.
+send21: lda state ;Get the state.
+ cpi 'D' ;Are we in the data send state?
+ jnz send3
+ call sdata
+ jmp send2
+
+send3: cpi 'F' ;Are we in the file send state?
+ jnz send4
+ call sfile ;Call send file.
+ jmp send2
+
+send4: cpi 'Z' ;Are we in the EOF state?
+ jnz send5
+ call seof
+ jmp send2
+
+send5: cpi 'S' ;Are we in the send initiate state?
+ jnz send6
+ call sinit
+ lda state ;[jd] get state back
+ cpi 'F' ;[jd] into file send state yet?
+ jnz send2 ;[jd] no
+ lxi d,inms23 ;[jd] yes, print sending...
+ call finmes ;[jd]
+ jmp send2
+
+send6: cpi 'B' ;Are we in the eot state?
+ jnz send7
+ call seot
+ jmp send2
+
+send7: cpi 'C' ;Are we in the send complete state?
+ jnz send8 ;No...
+ lxi d,infms3 ;Yes, write "Complete" message.
+ lda czseen ;Or was it interrupted?
+ ora a ; . . .
+ jz send7a ;No.
+ lxi d,inms13 ;Yes, then say "Interrupted" instead.
+send7a: call finmes
+ jmp kermit
+
+send8: cpi 'A' ;Are we in the send "abort" state?
+ jnz send9
+ lxi d,infms4 ;Print message.
+ call finmes
+ jmp kermit
+
+send9: lxi d,infms4 ;Anything else is equivalent to "abort".
+ call finmes
+ jmp kermit
+;
+; Send routines
+
+; Send initiate
+; called by: send
+
+sinit: lda numtry ;Get the number of tries.
+ cpi imxtry ;Have we reached the maximum number of tries?
+ jm sinit2
+ lxi d,erms14
+ call error3 ;Display ermsg
+ jmp abort ;Change the state to abort.
+
+sinit2: inr a ;Increment it.
+ sta numtry ;Save the updated number of tries.
+ mvi a,'1' ;Reset to use single character checksum
+ sta curchk ;For startup
+ lda chktyp ;Get our desired block check type
+ sta inichk ;Store so we tell other end
+ lxi h,data ;Get a pointer to our data block.
+ call rpar ;Set up the parameter information.
+ sta argblk+1 ;Save the number of arguments.
+ lda numpkt ;Get the packet number.
+ sta argblk
+ lda state ; load state (I or S)
+
+ call spack ;Send the packet.
+ jmp abort ; Failed, abort.
+ call rpack ;Get a packet.
+ jmp r ; Trashed packet don't change state, retry.
+ cpi 'Y' ;ACK?
+ jnz sinit3 ;If not try next.
+ call compp ;compare packets. If ok, zero flag set
+ rnz ;If not try again.
+ call countp ;increment packet number modulo 64
+ lda argblk+1 ;Get the number of pieces of data.
+ lxi h,data ;Pointer to the data.
+ call spar ;Read in the data. (decode what they want)
+ lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ xra a
+ sta numtry ;Reset the number of tries.
+ lda state ; se if S or I state
+ cpi 'I' ; I state, so set X as next state
+ jnz sinita
+sinitb: mvi a,'X'
+ sta state
+ ret
+
+sinita: lda inichk ;Get the agreed upon block check type
+ sta curchk ;Store as type to use for packets now
+ mvi a,'F' ;Set the state to file send. (Assumed)
+ sta state
+ call getfil ;Open the file.
+ ret ; assume success; mfname thinks the file exists.
+
+sinit3: cpi 'N' ;NAK?
+ jnz sinit4 ;If not see if its an error.
+ call updrtr ;Update the number of retries.
+ lda pktnum ;Get the present packet number.
+ inr a ;Increment
+ ani 3FH ; modulo 64
+ mov b,a
+ lda argblk ;Get the packet's number.
+ cmp b ;Is the packet's number one more than now?
+ rnz ;If not assume its for this packet, go again.
+ xra a
+ sta numtry ;Reset number of tries.
+ mvi a,'F' ;Set the state to file send.
+ sta state
+ ret
+
+sinit4: cpi 'E' ;Is it an error packet.
+ jnz abort
+ lda state ;[MF]Get state
+ cpi 'I' ;[MF]If an "I" packet was sent,
+ jz sinitb ;[MF]Ignore the error, pretend success
+ call error ;[MF]else display the error info
+ jmp abort ;[MF]and abort
+;
+; Send file header
+; called by: send
+;[5a] Question [majoc]: Why could not the filename
+; parsing have been done by comnd, like all the rest?
+
+sfile: lda numtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm sfile1
+ lxi d,erms14
+ call error3
+ jmp abort ;Change the state to abort.
+
+sfile1: inr a ;Increment it.
+ sta numtry ;Save the updated number of tries.
+ xra a ;Clear A
+ sta czseen ;No control-Z or X seen
+ lxi h,data ;Get a pointer to our data block.
+ shld datptr ;Save it.
+; use remote name if given, else use local name [gnn]
+ lda remlen ;[gnn] anything given?
+ ora a ;[gnn]
+ jnz sfile4 ;[gnn] use remote name
+
+ lxi h,fcb+1 ;Pointer to the file name in the FCB.
+ shld fcbptr ;Save position in FCB.
+ mvi b,0 ;No chars yet.
+ mvi c,0
+sfil11: mov a,b
+ cpi 8H ;Is this the ninth char?
+ jnz sfil12 ;If not proceed.
+ mvi a,'.' ;Get a dot.
+ lhld datptr
+ mov m,a ;Put the char in the data packet.
+ inx h
+ shld datptr ;Save position in data packet.
+ inr c
+sfil12: inr b ;Increment the count.
+ mov a,b
+ cpi 0CH ;Twelve?
+ jp sfil13
+ lhld fcbptr
+ mov a,m
+ ani 7fH ;Turn off CP/M 2 or 3's high bits.
+ inx h
+ shld fcbptr ;Save position in FCB.
+ cpi '!' ;Is it a good character?
+ jm sfil11 ;If not get the next.
+ lhld datptr
+ mov m,a ;Put the char in the data packet.
+ inx h
+ shld datptr ;Save position in data packet.
+ inr c
+ jmp sfil11 ;Get another.
+
+sfil13: mov a,c ;Number of char in file name.
+ sta argblk+1
+ lhld datptr
+ mvi a,'$'
+ mov m,a ;Put in a dollar sign for printing.
+ lda quietd ; a quiet display
+ ana a
+ jnz sfi13a ; yes, dont write
+ call scrfln ;Position cursor
+sfi13a: lxi d,data ;Print the file name though, in either case
+ call prtstr
+ lda pktnum ;Get the packet number.
+ sta argblk
+ mvi a,'F' ;File header packet.
+ call spack ;Send the packet.
+ jmp abort ; Failed, abort.
+ call rpack ;Get a packet.
+ jmp r ; Trashed packet don't change state, retry.
+ cpi 'Y' ;ACK?
+ jnz sfile2 ;If not try next.
+ call compp
+ rnz ;If not hold out for the right one.
+sfil14: call countp
+ lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ xra a
+ sta numtry ;Reset the number of tries.
+ sta bytes ;[10] clear the "bytes transferred" counter
+ sta bytes+1 ;[10]
+ sta bytes+2 ;[10]
+ sta bytes+3 ;[10]
+ call gtchr ;Fill the first data packet
+ jmp sfil16 ;Error go see if its EOF.
+; ;Got the chars, proceed.
+ sta size ;Save the size of the data gotten.
+ mvi a,'D' ;Set the state to data send.
+ sta state
+ ret
+
+sfil16: cpi 0FFH ;Is it EOF?
+ jnz abort ;If not give up.
+ mvi a,'Z' ;Set the state to EOF.
+ sta state
+ ret
+
+sfile2: cpi 'N' ;NAK?
+ jnz sfile3 ;Try if error packet.
+ call updrtr ;Update the number of retries.
+ lda pktnum ;Get the present packet number.
+ inr a ;Increment
+ ani 3FH ; modulo 64
+ mov b,a
+ lda argblk ;Get the packet's number.
+ cmp b ;Is the packet's number one more than now?
+ rnz ;If not go try again.
+ jmp sfil14 ;Just as good as a ACK;go to the ACK code.
+
+sfile3: cpi 'E' ;Is it an error packet.
+ jnz abort
+ call error
+ jmp abort
+
+; copy remote name into packet to send [gnn]
+sfile4: xchg ;[gnn] keep pointer to packet
+ lxi h,remnam ;[gnn] set pointer to name
+ mov c,a ;[gnn] keep count of length
+ mov b,a ;[gnn] and set as loop counter
+sfil41: mov a,m ;[gnn] get a character
+ stax d ;[gnn] copy it to packet
+ inx h ;[gnn]
+ inx d ;[gnn] move pointers
+ dcr b ;[gnn]
+ mov a,b ;[gnn]
+ ora a ;[gnn] done them all?
+ jnz sfil41 ;[gnn] repeat until done
+ xchg ;[gnn] get final position
+ shld datptr ;[gnn] and save it
+ jmp sfil13 ;[gnn] now go and send packet
+
+;
+; Send data
+; called by: send
+
+sdata: lda numtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm sdata1
+ lxi d,erms14
+ call error3
+ jmp abort ;Change the state to abort.
+
+sdata1: inr a ;Increment it.
+ sta numtry ;Save the updated number of tries.
+ lxi h, data ;Get a pointer to our data block.
+ shld datptr ;Save it.
+ lxi h,filbuf ;Pointer to chars to be sent.
+ shld cbfptr ;Save position in char buffer.
+ mvi b,1 ;First char.
+sdat11: lhld cbfptr
+ mov a,m
+ inx h
+ shld cbfptr ;Save position in char buffer.
+ mov c,a ;[jd] preserve character temporarily
+ lda quot8 ;[jd] doing eighth-bit quoting?
+ ora a ;[jd]
+ mov a,c ;[jd] restore char
+ jnz sdat4 ;[jd] using eighth-bit quoting, no warning
+ lda parity ;[jd] get parity
+ cpi parnon ;[jd] none?
+ mov a,c ;[jd] restore character
+ jz sdat4 ;[jd] no parity, leave char alone
+ lda wrn8 ;[jd] look at warning flag
+ ora a ;[jd] have we already given the warning?
+ jnz sdat5 ;[jd] yes, skip this
+ mov a,c ;[jd] restore character...
+ ani 80h ;[jd] examine parity
+ jz sdat5 ;[jd] no parity, no warning.
+ call parwrn ;[jd] ...print warning - parity lost
+ mvi a,0ffh ;[jd] remember that we sent the message
+ sta wrn8 ;[jd]
+sdat5: mov a,c ;[jd] restore character again
+ ani 7fh ;[jd] strip parity so not checksummed
+sdat4: lhld datptr
+ mov m,a ;Put the char in the data packet.
+ inx h
+ shld datptr ;Save position in data packet.
+ inr b ;Increment the count.
+ lda size ;Get the number of chars in char buffer.
+ cmp b ;Have we transfered that many?
+ jp sdat11 ;If not get another.
+ lda size ;Number of char in char buffer.
+ sta argblk+1
+ lda pktnum ;Get the packet number.
+ sta argblk
+ mvi a,'D' ;Data packet.
+ call spack ;Send the packet.
+ jmp abort ; Failed, abort.
+ call rpack ;Get a packet.
+ jmp r ; Trashed packet don't change state, retry.
+ cpi 'Y' ;ACK?
+ jnz sdata2 ;If not try next.
+ call compp
+ rnz ;If not hold out for the right one.
+ lda argblk ;Get the packet number back
+ call countp
+ lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ xra a
+ sta numtry ;Reset the number of tries.
+ lda argblk+1 ;Get the data length
+ cpi 1 ;Check if only 1 character?
+ jnz sdat15 ;If not, just continue
+ lda data ;Got one character, get it from data
+ cpi 'Z' ;Want to abort entire stream?
+ jnz sdat14 ;If not, check for just this file
+ sta czseen ;Yes, remember it
+ jmp sdat16 ;[MF] and set EOF state
+sdat14: cpi 'X' ;Desire abort of current file?
+ jnz sdat15 ;If not, just continue
+ sta czseen ;Yes, remember that
+ jmp sdat16 ;[MF] and set EOF
+sdat15: lda czseen ;Also get control-Z flag
+ ora a ;Check if either given
+ jz sdat12 ;If neither given, continue
+sdat16: mvi a,'Z' ;Change state to EOF
+ sta state ; . . .
+ ret ;And return
+
+sdat12: call gtchr
+ jmp sdat13 ;Error go see if its EOF.
+ sta size ;Save the size of the data gotten.
+ ret
+
+sdat13: cpi 0FFH ;Is it EOF?
+ jnz abort ;If not give up.
+ mvi a,'Z' ;Set the state to EOF.
+ sta state
+ ret
+
+sdata2: cpi 'N' ;NAK?
+ jnz sdata3 ;See if is an error packet.
+ call updrtr ;Update the number of retries.
+ lda pktnum ;Get the present packet number.
+ inr a ;Increment
+ ani 3FH ; modulo 64
+ mov b,a
+ lda argblk ;Get the packet's number.
+ cmp b ;Is the packet's number one more than now?
+ rnz ;If not go try again.
+ jmp sdat12 ;Just as good as a ACK;go to the ACK code.
+
+sdata3: cpi 'E' ;Is it an error packet.
+ jnz abort
+ call error
+ jmp abort
+;
+; Send EOF
+; called by: send
+
+seof: lda numtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm seof1
+ lxi d,erms14
+ call error3
+ jmp abort ;Change the state to abort.
+
+seof1: inr a ;Increment it.
+ sta numtry ;Save the updated number of tries.
+ lda pktnum ;Get the packet number.
+ sta argblk
+ xra a
+ sta argblk+1 ;No data.
+ lda czseen ;Check if C-Z or C-X typed
+ ora a ; . . .
+ jz seof14 ;If not aborted, just keep going
+ mvi a,'D' ;Tell other end to discard packet
+ sta data ;Store in data portion
+ mvi a,1 ;One character
+ sta argblk+1 ;Store the length
+seof14: mvi a,'Z' ;EOF packet.
+ call spack ;Send the packet.
+ jmp abort ; Failed, abort.
+ call rpack ;Get a packet.
+ jmp r ; Trashed packet don't change state, retry.
+ cpi 'Y' ;ACK?
+ jnz seof2 ;If not try next.
+ call compp
+ rnz ;If not hold out for the right one.
+seof12: call countp
+ lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ xra a
+ sta numtry ;Reset the number of tries.
+ mvi c,closf ;Close the file.
+ lxi d,fcb
+ call bdos
+;* Check if successful
+ lda czseen ;Desire abort of entire stream?
+ cpi 'Z' ;Desire abort of entire stream?
+ jz seof13 ;If so, just give up now
+ call mfname ;Get the next file.
+ jc seof13 ; No more.
+ call getfil ;and open it (assume success)
+ xra a ;Clear A
+ sta czseen ;Since we have not aborted this file
+ mvi a,'F' ;Set the state to file send.
+ sta state
+ ret
+
+seof13: mvi a,'B' ;Set the state to EOT.
+ sta state
+ ret
+
+seof2: cpi 'N' ;NAK?
+ jnz seof3 ;Try and see if its an error packet.
+ call updrtr ;Update the number of retries.
+ lda pktnum ;Get the present packet number.
+ inr a ;Increment
+ ani 3FH ; modulo 64
+ mov b,a
+ lda argblk ;Get the packet's number.
+ cmp b ;Is the packet's number one more than now?
+ rnz ;If not go try again.
+ jmp seof12 ;Just as good as a ACK;go to the ACK code.
+
+seof3: cpi 'E' ;Is it an error packet.
+ jnz abort
+ call error
+ jmp abort
+;
+; Send EOT
+; called by: send
+
+seot: lda numtry ;Get the number of tries.
+ cpi maxtry ;Have we reached the maximum number of tries?
+ jm seot1
+ lxi d,erms14
+ call error3
+ jmp abort ;Change the state to abort.
+
+seot1: inr a ;Increment it.
+ sta numtry ;Save the updated number of tries.
+ lda pktnum ;Get the packet number.
+ sta argblk
+ xra a
+ sta argblk+1 ;No data.
+ mvi a,'B' ;EOF packet.
+ call spack ;Send the packet.
+ jmp abort ; Failed, abort.
+ call rpack ;Get a packet.
+ jmp r ; Trashed packet don't change state, retry.
+ cpi 'Y' ;ACK?
+ jnz seot2 ;If not try next.
+ call compp
+ rnz ;If not hold out for the right one.
+seot12: call countp
+ lda numtry ;Get the number of tries.
+ sta oldtry ;Save it.
+ xra a
+ sta numtry ;Reset the number of tries.
+ mvi a,'C' ;Set the state to file send.
+ sta state
+ ret
+
+seot2: cpi 'N' ;NAK?
+ jnz seot3 ;Is it error.
+ call updrtr ;Update the number of retries.
+ lda pktnum ;Get the present packet number.
+ inr a ;Increment
+ ani 3FH ; modulo 64
+ mov b,a
+ lda argblk ;Get the packet's number.
+ cmp b ;Is the packet's number one more than now?
+ rnz ;If not go try again.
+ jmp seot12 ;Just as good as a ACK;go to the ACK code.
+
+seot3: cpi 'E' ;Is it an error packet.
+ jnz abort
+ call error
+ jmp abort
+;
+; This routine sets up the data for init packet (either the
+; Send_init or ACK packet).
+; called by: rinit, rfile, sinit
+;
+; Called by rinit, rfile and sinit. See what WE want from the other fella
+;
+; [11] by OBS - Stripped out all the new capas code etc and reverted
+; to Good Ol' Basic Kermit again!
+; Those keen should study the followin gode with care, and remove
+; or add semicolons as indicated.
+;
+; See also SPAR which decodes what comes in. It also decodes bits in
+; the "capability" fields. (Two CAPAS files allowed from remote
+; machines, but we will only send one at max.) Note that not all
+; if any of the capability bits will be used.
+;
+; Definitions - init packet (data section only.. rest of header assumed OK)
+; Byte 0 Maximum length I want to send
+; 1 The Timeout I want you to use
+; 2 Number of PAD characters I want tot use (May be null)
+; 3 The PAD character I want to use (May be Null)
+; 4 The End-of-Line character I will use (Carriage Return)
+; 5 The control character Quote Character I will use (#)
+; 6 The parity bit Quote Character I will use (&)
+; 7 The Checktype I will use
+; 8 The repeat prefix I will use (Null, as we cannot to repeats)
+; 9 Capability Byte 0 (See SPAR for defs)
+; 10 Capability byte 1 ( --- " --- but we will not send it.)
+; 11 The number of packets I will send per window (not used)
+; 12 MAXL1 - Long packet size, ms count
+; 13 MAXL2 - Long packet size, ls count
+;
+;
+; Enter with HL pointing to the "data" part of the packet.
+
+;
+; older part of rpar follows...
+;
+;
+rpar: lda rpsiz ;Get the receive packet size.
+ adi space ;Add a space to make it printable.
+ mov m,a ;Put it in the packet.
+ inx h ;Point to the next char.
+ lda rtime ;Get the receive packet time out.
+ adi space ;Add a space.
+ mov m,a ;Put it in the packet.
+ inx h
+ lda rpad ;Get the number of padding chars.
+ adi space
+ mov m,a
+ inx h
+ lda rpadch ;Get the padding char.
+ adi 100O ;Uncontrol it.
+ ani 7FH
+ mov m,a
+ inx h
+ lda reol ;Get the EOL char.
+ adi space
+ mov m,a
+ inx h
+ lda rquote ;Get the quote char.
+ mov m,a
+ inx h
+ mvi m,'Y' ;[jd] we know how to do 8-bit quoting
+ lda parity ;[jd]
+ cpi parnon ;[jd] parity none?
+ jz rpar1 ;[jd] yes, keep going
+ lda qbchr ;[jd] no, better request 8-bit quoting
+ mov m,a
+
+rpar1:
+ inx h ;Advance to next
+ lda chktyp ;Get desired block check type
+ mov m,a ;Store it
+ inx h ;Advance pointer
+
+; Comment out the next two lines for capas etc. WILL require debugging
+ mvi a,8 ; this id the older end for this routine. May be useful.
+ ret
+
+; [11] Rest not needed for now, commented out
+; [10] (to ret)
+; New additions to rpar follows...
+
+; lda rcap1 ; get the first capability byte
+; ani 3eh ; mask out bit 0, ie only one CAPAS byte
+; adi space ; tochar it
+; mov m,a
+; inx h
+; mvi m,space ; No windows, ie space to packet
+; inx h
+; push h ; we need the HL regs for maths.
+; lhld rdpkt ; get receive packet length
+; lxi d,95 ; we want hl div 95 and hl mod 95
+; call divide ; return with divsion in hl, remainder in de
+; mov a,l ; two sets of bytes
+; pop h
+; adi space ; tochar(maxl1)
+; mov m,a
+; inx h
+; mov a,l
+; adi space ; tochar(maxl2)
+; mov m,a
+;
+; done all, set databytes = 12 and return
+; mvi a,12 ; 12 bits of data
+; ret
+
+;[11] End of commented out code for rpar
+
+
+;
+; This routine reads in all the send_init packet information.
+; called by: rinit, sinit
+
+;[11] As for rpar, restore the "old" kermit code for non-capas Kermit.
+;[10] (to ret at end)
+;
+; SPAR - routine to decode parameters received from the remote end
+;
+; Called by rinit,sinit
+;
+; Entry: a: Number of databytes in packet
+; hl: Pointer to "data" part of packet
+;
+;spar: sta temp4 ; save for a while
+; ; first clear some variables
+; lda dspsiz ; get default "send" packet length
+; sta spktl
+; lda dstime ; get default time-out
+; sta stimeo
+; xra a ; set no pad characters by default
+; sta spad
+; lda dspadc ; get the default padding character
+; sta spadc
+; mvi a,cr ; default end of line character (CR)
+; sta seol
+; mvi a,dsquot ; default quote character
+; sta squote
+; mvi a,dsbqut ; default binary quote character
+; sta qbchr
+; mvi a,dschkt ; set checktype = 1 for inits
+; sta inichk
+; mvi a,space ; no repeat prefixing ( otherwise ~)
+; sta srept
+;
+; Now follows the "capabilities" bits... 5 bits per capas byte.
+;
+; Note: Before extracting any data bits, apply unchar() to get the
+; six ls bits. If bit 0 = 1 the a subsequent capaa byte follows
+;
+; Byte0: Bit 0: Set to 1 if there are subsequent CAPAS bytes
+; 1: (Cap. 5) Set to 1 for long packets. Second byte
+; AFTER the last capas byte has packet length DIV 95
+; and Thire byte has length MOD 95
+; 2: (Cap. 4) Sliding Windows. If used, first byte AFTER
+; last capas byte has TOCHAR(no. of packets in window)
+; 3: (Cap. 3) Ability to accept "A" (attribute packets)
+; 4: (Cap. 2) Reserved
+; 5: (Cap. 1) Reserved
+; Byte 2 onward: not used in this implementation. Any capas bytes sent
+; will be stored, however.
+;
+; lda temp4 ; get the number of bytes to test
+; mov c,a ; to a count register
+; mov a,m ; get first byte
+; call decc ; unchar it, and decrement c
+; sta spsiz ; save a send packet size
+; jz sparx ; if no more, exit
+;
+; mov a,m ; get timout
+; call decc
+; sta stime ; save timeout
+; jz sparx
+;
+; mov a,m ; get pad characters
+; call decc
+; sta spadc ; save it
+; jz sparx
+;
+; mov a,m ; get pad character count
+; call decc
+; sta spad
+; jz sparx
+;
+; mov a,m ; get send EOL
+; call decc
+; sta seol
+; jz sparx
+;
+; mov a,m ; get control quote character
+; call decc
+; sta squote
+; jz sparx
+;
+; mov a,m ; get binary (parity) quote char
+; mov b,a ; this time we actually WANT accumulator
+; cpi space ; are we doing 8th bit quoteing
+; jz spar1 ; dont know, assume not
+; cpi 'N' ; definately not?
+; jz spar1
+; cpi 'Y' ; definately - use &
+; jz spar2
+; sta squote ; else save the new character
+;spar2: lda parity ; see if we are using the parity bit
+; cpi parnon ; no parity => no quoting
+; jz spar3 ; yup, so use the default quote character &
+;
+;spar1: xra a ; save not quoting
+; sta squote
+;spar3: call decc ; update counters etc
+; jz sparx
+;
+; mov a,m ; get repeat prefixing
+; call decc
+; push psw ; save flags
+; cpi space-32 ; we want it?
+; jz spar4
+; sta srept
+;spar4: pop psw ; restore flags
+; jz sparx
+;
+; lxi d,scapas ; point to start of capability byte(s)
+; push psw ; must do this...
+;spar5: pop psw ; cos we restore the spack
+; mov a,m
+; call decc ; get scap1 (or n)
+; sta scap1
+; push psw
+; ani 01 ; another byte following?
+; jnz spar5
+; pop psw ; see if any other data bytes (Windows etc)
+; jz sparx
+;
+; mov a,m ; get window size
+; call decc
+; sta swindo
+; jz sparx
+;
+; mov a,m ; get long packets ms bits
+; call decc ;
+; mov d,a ; unchared ms bits-ish
+; mov a,m
+; call decc ; ls bits-ish
+; push h ; and we are doing maths
+; push b ; and an intermediate result in c
+; push psw ; we want flags and the ls bits...
+; mvi b,0
+; mov c,d ; get ms bits-ish to bc
+; push b ; get number to hl
+; pop h
+; now multipy by 95
+; dad h ;*2
+; dad h ;*4
+; dad h ;*8
+; dad h ;*16
+; push h ; *16 to ...
+; pop d ; ... de
+; dad h ;*32
+; dad d ; *(32+16) = *48
+; dad h ; *96
+; mov a,l ; *(96-1)
+; sub c
+; mov l,a
+; mov a,0
+; sbb h
+; mov h,a
+; pop psw ; restore ls bitsish
+; mov e,a
+; mvi d,0
+; dad d ; *95 + ls bits. Phew.
+; shld sdpkt ; save long packet length
+; pop b
+; pop h ; restore regs
+;
+;sparx: ret ; if here, (assume) no more data to read in
+;[10] routines required follow
+;decc: mov a,m ; get data byte
+; sui space ; unchar it
+; inx h ; increment input pointer
+; dcr c ; decrement data counter
+; ret ; return
+;[10] end or spar replacement
+
+;[11] Restore older spar....
+; Older spar follows...
+spar: sta temp4 ;Save the number of arguments.
+; Initialize some variables to their required default values, so we use
+; the right values even if the remote Kermit doesn't send the full packet:
+; ; we don't do anything with timeout values yet.
+; ; no default pad count/pad character?
+ mvi a,cr ; EOL character = carriage-return
+ sta seol
+ mvi a,'#' ; quote character = '#'
+ sta squote
+ mvi a,'&' ; eighth-bit quote character = '&'
+ sta qbchr
+ mvi a,'1' ; block-check = 1-character-checksum
+ sta inichk
+;
+ mov a,m ;Get the max packet size.
+ sbi space ;Subtract a space.
+ sta spsiz ;Save it.
+ lda temp4
+ cpi 3 ;Fewer than three pieces?
+ rm ;If so we are done.
+ inx h
+ inx h ;Increment past the time out info.
+ mov a,m ;Get the number of padding chars.
+ sbi space
+ sta spad
+ lda temp4
+ cpi 4 ;Fewer than four pieces?
+ rm ;If so we are done.
+ inx h
+ mov a,m ;Get the padding char.
+ adi 100O ;Re-controlify it.
+ ani 7FH
+ sta spadch
+ lda temp4
+ cpi 5 ;Fewer than five pieces?
+ rm ;If so we are done.
+ inx h
+ mov a,m ;Get the EOL char.
+ sbi space
+ sta seol
+ lda temp4
+ cpi 6 ;Fewer than six pieces?
+ rm ;If so we are done.
+ inx h
+ mov a,m ;Get the quote char.
+ sta squote
+ lda temp4 ;Get the amount of data supplied
+ cpi 7 ;Have an 8-bit quote?
+ rm ;If not there, all done
+ inx h ;Yes, get the character
+ mvi a,0 ;[jd]
+ sta quot8 ;[jd] assume not quoting
+ mov a,m ;Get the supplied character
+ cpi 'N' ;[jd] No?
+ jz spar1 ;[jd] then don't try to do it
+ cpi space ;[jd] maybe they don't know about it...
+ jz spar1 ;[jd] then don't try to do it.
+ cpi 'Y' ;[jd] Yes?
+ jnz spar2 ;[jd] if not 'Y', assume it's a quote char.
+ lda parity ;[jd] using parity?
+ cpi parnon ;[jd] no, don't need quoting...
+ jz spar1 ;[jd]
+ mvi a,0ffh ;[jd] else turn on...
+ sta quot8 ;[jd] ...quote flag
+ jmp spar1
+
+;[11] Note: If capas etc required, beware of the next two lables, as these
+; are used elswhere.
+
+spar2: sta qbchr ;[jd] use their quote char (should validate)
+ mvi a,0ffh
+ sta quot8 ;[jd] turn quote flag and fall thru...
+
+spar1: lda temp4 ;Determine if block check type given
+ cpi 8 ;Is the field there?
+ rm ;If not, all done
+ inx h ;Point to the character
+ mov a,m ;Get the value
+ mov b,a ;Copy value
+ lda chktyp ;Get our type
+ cmp b ;Is it our desired type?
+ rnz ; If not, use default (1-character-checksum)
+ sta inichk ; Match, store as type to use after init
+ ret ; and return
+;[10] end of replacement
+;[11] end of replacement of replacement (ie back to original code)
+;
+
+; Copy characters from packet to disk (or screen)
+; called by: rdata
+
+ptchr: sta temp1 ;Save the size.
+ lda remtxt ;[MF]Get remote command flag
+ ora a ;[MF]Remote command in progress?
+ jnz ptchr0 ;[MF]Yes, don't check for file collisions
+ lda flwflg ;[MF]Get File Warning (Set Collision) flag
+ cpi 3 ;[MF]SET COLLISION DISCARD?
+ jnz ptchr0 ;[MF]No
+ lda dscflg ;[MF]Yes, get "discard" flag
+ ora a ;[MF]Discarding file?
+ jz ptchr0 ;[MF]No
+ mvi a,'X' ;[MF]Yes, simulate a user rejection
+ sta czseen ;[MF]...
+ jmp rskp ;[MF]and pretend success
+ptchr0: ;[MF]
+ lxi h,data ;Beginning of received packet data.
+ shld outpnt ;Remember where we are.
+ lda rquote
+ mov b,a ;Keep the quote char in b.
+ mvi c,0 ;[jd] assume no 8-bit quote char
+ lda quot8 ;[jd] doing 8-bit quoting?
+ ora a
+ jz ptchr1 ;[jd] no, keep going
+ lda qbchr ;[jd] else get 8-bit quote char
+ mov c,a ;[jd] keep this in c
+ptchr1: lxi h,temp1
+ dcr m ;Decrement # of chars in packet.
+ jm rskp ;Return successfully if done.
+ lda remtxt ; to screen only?
+ ana a
+ jnz ptchr2 ; dont do any disk stuff
+ lxi h,chrcnt ;Number of chars remaining in dma.
+ dcr m ;Decrement.
+ jp ptchr2 ;Continue if space left.
+ call outbuf ;Output it if full.
+ jmp ptchr9 ; Error return if disk is full.
+ptchr2: lhld outpnt ;Get position in output buffer.
+ mov a,m ;Grab a char.
+ inx h
+ shld outpnt ;and bump pointer.
+ mvi e,0 ;[jd] assume nothing to OR in.
+ cmp c ;[jd] is it the binary quote char?
+ jnz ptch2a ;[jd] no, keep going
+ mvi e,80h ;[jd] include parity bit
+ lda temp1
+ dcr a
+ sta temp1 ;[jd] decrement character count
+ mov a,m ;[jd] get next character
+ inx h
+ shld outpnt
+ptch2a: cmp b ;Is it the quote char?
+ jnz ptchr3 ;[jd] changed to ptchr3 so includes parity
+ mov a,m ;Get the quoted character
+ inx h
+ shld outpnt ;and bump pointer.
+ lxi h,temp1
+ dcr m ;Decrement # of chars in packet.
+ mov d,a ;Save the char.
+ ani 80H ;Turn off all but the parity bit.
+ ora e ;[jd] let parity come from either (???)
+ mov e,a ;Save the parity bit.
+ mov a,d ;Get the char.
+ ani 7FH ;Turn off the parity bit.
+ cmp b ;Is it the quote char?
+ jz ptchr3 ;If so just go write it out.
+ cmp c ;[jd] maybe it's the 8-bit prefix character?
+ jz ptchr3 ;[jd] then don't controllify.
+ mov a,d ;Get the char.
+ adi 40H ;Make the character a control char again.
+ ani 7FH ;Modulo 128.
+ptchr3: ora e ;Or in the parity bit.
+ sta temp3 ; save for a while
+ lda remtxt ; to screen or disk?
+ ana a
+ lda temp3
+ jz ptch31 ; to disk
+ push h
+ push d
+ push b
+ mov e,a ; to display
+ mvi c,dconio
+ call bdos
+ pop b
+ pop d
+ pop h
+ jmp ptchr1 ; continue
+
+ptch31: lhld bufpnt ;Destination buffer.
+ mov m,a ;Store it.
+ inx h
+ shld bufpnt ;Update the pointer
+ jmp ptchr1 ;and loop to next char.
+
+ptchr9: lxi d,erms11 ; "?Disk full"
+ push d ;[MF] Save pointer
+ call error3 ; put it on the error line
+ pop d ;[MF] Restore pointer
+ lxi h,data ;[MF] Where to put the message for "e" packet
+ lda argblk ;[MF] Get packet-number
+ call countp ;[MF]Increment it
+ sta argblk ;[MF] as packet to send
+ xra a ;[MF] Zero length of packet data
+ sta temp1 ;[MF] ...
+ptch9a: ldax d ;[MF] Get a character to copy
+ cpi cr ;[MF] No more to copy?
+ jz ptch9b ;[MF] Yes, we can send the packet
+ mov m,a ;[MF] No, copy the character
+ inx d ;[MF] and increment source/dest pointers
+ inx h ;[MF] ...
+ lda temp1 ;[MF] Get character count
+ inr a ;[MF] and increment it
+ sta temp1 ;[MF] ...
+ jmp ptch9a ;[MF] Copy entire error message
+ptch9b: mvi m,0 ;[MF]Put in a zero
+ lda temp1 ;[MF] Get number of characters in the message
+ sta argblk+1 ;[MF] and store as number of packet data chars
+ mvi a,'E' ;[MF] Make it an error packet
+ call spack ;[MF] Send the error packet
+ nop ;[MF] Don't really care if
+ nop ;[MF] the send fails since we're
+ nop ;[MF] bombing off anyway
+ ret ; take error return.
+;
+; Fill a data packet from file
+; called by: sfile, sdata
+
+gtchr: lda squote ;Get the quote char.
+ mov c,a ;Keep quote char in c.
+ lda curchk ;Get current block check type
+ sui '1' ;Get the extra overhead
+ mov b,a ;Get a copy
+ lda spsiz ;Get the maximum packet size.
+ sui 5 ;Subtract the overhead.
+ sub b ;Determine max packet length
+ sta temp1 ;This is the number of chars we are to get.
+ lxi h,filbuf ;Where to put the data.
+ shld cbfptr ;Remember where we are.
+ mvi b,0 ;No chars.
+gtchr1: lda temp1
+ dcr a ;Decrement the number of chars left.
+ jp gtchr2 ;Go on if there is more than one left.
+ mov a,b ;Return the count in A.
+ jmp rskp
+
+gtchr2: sta temp1
+ lda chrcnt ;Space left in the DMA.
+ dcr a
+;* Can improve order here.
+ jm gtchr3
+ sta chrcnt
+ jmp gtchr4
+
+gtchr3: call inbuf ;Get another buffer full.
+ jmp gtch30 ; If no more return what we got.
+ jmp gtchr4 ;If we got some, proceed.
+
+gtch30: mov a,b ;Return the count in A.
+ ora a ;Get any chars?
+ jnz rskp ;If so return them.
+ jmp gtceof ;If not, say we found the end of the file.
+
+gtchr4: lhld bufpnt ;Position in DMA.
+ mov a,m ;Get a char from the file.
+ inx h
+ shld bufpnt
+ mov d,a ;Save the char.
+ ani 80H ;Turn off all but parity.
+ mov e,a ;Save the parity bit.
+ jz gtch4a ;[jd] no parity, skip this check...
+ lda quot8 ;[jd] doing eighth-bit quoting?
+ ora a
+ jz gtch4a ;[jd] no, just proceed normally
+ lda temp1 ;[jd] get space remaining
+ cpi 2 ;[jd] 3 chrs left (one cnted already)?
+ jm gtchr9 ;[jd] no, skip this
+ dcr a ;[jd] decrement space remaining
+ sta temp1 ;[jd] put back.
+ lhld cbfptr ;[jd] Position in character buffer.
+ lda qbchr ;[jd] get quote character
+ mov m,a ;]jd] Put the quote char in the buffer.
+ inx h ;[jd] increment destination buffer pointer
+ shld cbfptr ;[jd] store the pointer back
+ inr b ;[jd] Increment the char count.
+ mvi e,0 ;[jd] no parity bit to OR in.
+;[jd] fall thru...
+
+gtch4a: mov a,d ;Restore the char.
+ ani 7FH ;Turn off the parity.
+ mov d,a ;[jd] save here for later...
+ cpi space ;Compare to a space.
+ jm gtchr5 ;If less then its a control char, handle it.
+ cpi del ;Is the char a delete?
+ jz gtchr5 ;Go quote it.
+ lda quot8 ; Are we doing 8th-bit quoting?
+ ora a
+ jz gtch4c ; if not, skip this test and restore character.
+ lda qbchr ; get 8th-bit quote character
+ cmp d ; same as current character?
+ jz gtch4b ; yes, have to quote it...
+gtch4c: mov a,d ; no. get character back again.
+ cmp c ;Is it the quote char?
+ jnz gtchr8 ;If not proceed.
+gtch4b: lxi h,temp1 ;[jd] point to char count
+ dcr m ;[jd] decrement (know room for at least one)
+ lhld cbfptr ;Position in character buffer.
+ mov m,c ;Put the (quote) char in the buffer.
+ inx h
+ shld cbfptr
+ inr b ;Increment the char count.
+ mov a,d ;[jd] restore character again
+ jmp gtchr8
+
+gtchr5:
+ ;[gnn] ignore parity for checking
+; ora e ;Turn on the parity bit.
+
+ cpi ('Z'-100O) ;Is it a ^Z?
+ jnz gtchr7 ;If not just proceed.
+ lda cpmflg ;Was the file created by CPM...
+ cpi 1 ;in ASCII-mode ?
+ jz gtch52 ;Control-Z stops text
+ cpi 2 ;in BINARY mode?
+ jz gtchr6 ;Yes, pass the ^Z
+;At this point file-mode is DEFAULT.
+;If the rest of the record is filled with ^Zs, we're at EOF, otherwise
+;its a regular character.
+ lhld bufpnt ;since CHRCNT is ZERO at EOF-time
+ lda chrcnt ;(set by INBUF5 B.G.E)
+ mov d,a ;Get the number of chars left in the DMA.
+gtch51: dcr d
+ mov a,d
+ jp gtch53 ;Any chars left?
+gtch52: xra a ;If not, get a zero.
+ sta chrcnt ;Say no more chars in buffer.
+ mov a,b ;Return the count in A.
+ jmp rskp
+
+;Scan rest of buffer for non ^Z -- If we find a non ^Z, fall into gtchr6.
+;If we get to the end of the buffer before finding a non ^Z, fall into gtch52.
+gtch53: mov a,m ;Get the next char.
+ inx h ;Move the pointer.
+ cpi ('Z'-100O) ;Is it a ^Z?
+ jz gtch51 ;If so see if the rest are.
+
+gtchr6: mvi a,('Z'-100O) ;Restore the ^Z.
+gtchr7: sta temp2 ;Save the char.
+ lxi h,temp1 ;Point to the char total remaining.
+ dcr m ;Decrement it.
+ lhld cbfptr ;Position in character buffer.
+ mov m,c ;Put the quote in the buffer.
+ inx h
+ shld cbfptr
+ inr b ;Increment the char count.
+ lda temp2 ;Get the control char back.
+ adi 40H ;Make the non-control.
+ ani 7fH ;Modulo 200 octal.
+gtchr8: lhld cbfptr ;Position in character buffer.
+ ora e ;Or in the parity bit.
+ mov m,a ;Put the char in the buffer.
+ inx h
+ shld cbfptr
+ inr b ;Increment the char count.
+ jmp gtchr1 ;Go around again.
+
+gtchr9: ;[jd] not enough room left in buffer...
+ lhld bufpnt
+ dcx h
+ shld bufpnt ;[jd] back up over last character
+ lxi h,chrcnt ;[jd] point to character count
+ inr m ;[jd] increment it
+ mov a,b ;[jd] count of chars transferred
+ jmp rskp ;[jd] return it
+
+gtceof: mvi a,0FFH ;Get a minus one.
+ ret
+;
+
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FRO RELEASE!
+
+; org ($+100h) AND 0FF00H
+
+IF lasm
+ LINK CPSPK2 ;[obs] Link to part two of the packet file
+ENDIF ;lasm
diff --git a/src/cpspk2.asm b/src/cpspk2.asm
new file mode 100644
index 0000000..b246967
--- /dev/null
+++ b/src/cpspk2.asm
@@ -0,0 +1,1336 @@
+; CPSPK2.ASM
+; 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
+; 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-independent) routines that implement
+; the KERMIT protocol, and the commands that use them:
+; RECEIVE, SEND, FINISH, and LOGOUT.
+;
+; revision history:
+;
+;edit 11, 21-Mar-1991 by MF. After "inchr7", close TAKE-file (if any) so
+; ^C will halt all processing (including commands from TAKE-files)
+; and put the user back at Kermit command-level.
+;edit 10, 3-Jan-1991 by MF. Modify routine "inchr" after label "inchr5" to
+; not take retry (nonskip) return if ^X/^Z seen on the Console. This
+; will prevent multiple copies of packets being sent if user aborts
+; some files in a stream being sent via ^X and is a better fix to this
+; problem than flushing comm input before sending the "Z" packet
+; requesting the remote Kermit to discard the current file being
+; received (as implemented in CPSPK1.ASM edit of 2-jan-1991).
+;edit 9, 14-Dec-1990 by MF. Modified "gofil" routine to allow for
+; specification of a drive in the local filespec for GET and
+; RECEIVE commands. Thus commands such as
+; GET HELLO.TXT B:GOODBYE.TXT
+; and
+; RECEIVE B:GOODBYE.TXT
+; now work as expected.
+;edit 8, 22-Oct-1990 by MF. Fixed bug in completion-message routine
+; "finmes" wherein the completion message was not printed if the
+; terminal was set to QUIET because the message pointer was clobbered
+; by prcrlf.
+;edit 7, 14-Sep-1990 by MF. Add hooks for SET COLLISION command.
+; Eliminate commented-out old file warning rename routine.
+; Clear communication input buffers (call flsmdm) before
+; BYE, FINISH and LOGOUT commands.
+;edit 6, 9-Sep-1990 by MF. Implemented fixes in CPKERM.BWR for
+; garbage printout during quiet transfers and for file existence/
+; rename algorithm.
+; Also implemented hooks for Remote commands.
+; edit 5, 18 June 1990 by Russell Lang [rjl@monu1.cc.monash.edu.au]
+; When trying to generate a unique file name on receive, zero
+; the attribute bits between file opening attempts. This is
+; to fix a bug which caused the unique file name to have the
+; attributes of the already existing file. If the attribute
+; was R/O, a bdos error occured later when an attempt was made
+; to write to the file.
+;
+; edit 4, 27 October, 1987 By OBSchou. Changed the rename routine to
+; be more like the MSDOS issue.
+;
+; edit 3, 28 July, by OBSchou. Added traps to NOT print to screen during
+; file transfers if quietd is non zero (ie we SET TERMINAL QUIET)
+; This hopefully speeds up transfers in systems spending an age
+; updating the screen.
+;
+; edit 2, 8 April, 1987 by OBSchou. Minor edit to put drive and user number
+; in the "filename" field on the transfer screen. This means that the
+; offset on the line foe the file name proper has moved along 4 space.
+; Also, it writes 15 spaces AFER the xxd: string to clear the field
+; of any prevous file. Needed for thos terminals that cannot
+; clear to end of line...
+;
+; edit 1, 28 January, 1987 by OBSchou.
+; Hived off about 1/2 of CPSPKT.ASM to form two (smaller => easier
+; to handle) files.
+;
+;
+
+pk2ver: db 'CPSPK2.ASM (11) 21-Mar-1991$' ; name, edit number, date
+
+
+;
+; Get the file name (including host to micro translation)
+; called by: rfile
+
+gofil: xra a
+ sta fcb ;Set the drive to default to current.
+ lxi h,data ;Get the address of the file name.
+; allow use of local name if one was given [gnn]
+ lda remlen ;[gnn]
+ ora a ;[gnn] anything there?
+ jz gofil0 ;[gnn] no, use the one in the data packet
+ lxi h,remnam ;[gnn] yes, use this instead
+ lda remnam+1 ;[MF]Get 2nd char of local filename
+ cpi ':' ;[MF]Was a drive specified?
+ jnz gofil0 ;[MF]No, proceed as of old
+ mov a,m ;[MF]Yes, get drive
+ ani 5fh ;[MF]Force uppercase
+ sui 'A'-1 ;[MF]Make valid drive for fcb
+ sta fcb ;[MF]and store in fcb
+ inx h ;[MF]Skip drive and delimiter
+ inx h ;[MF]...
+gofil0: ;[gnn] continue to set up the file [gnn]
+;
+ shld datptr ;Store the address.
+ lxi h,fcb+1 ;Address of the FCB.
+ shld fcbptr ;Save it.
+ xra a
+ sta temp1 ;Initialize the char count.
+ sta temp2
+ mvi b,' '
+gofil1: mov m,b ;Blank the FCB.
+ inx h
+ inr a
+; cpi 0CH ;Twelve?[5a]
+ cpi 0BH ; Eleven? [5a]
+ jm gofil1
+ mvi m,0 ; [5a] Specify extent 0
+gofil2: lhld datptr ;Get the NAME field.
+ mov a,m
+ cpi 'a' ;Force upper case
+ jm gofl2a ;
+ ani 5FH ;
+gofl2a: inx h
+ cpi '.' ;Seperator?
+ jnz gofil3
+ shld datptr ;[jd] update ptr (moved from above)
+ lxi h,fcb+9H
+ shld fcbptr
+ lda temp1
+ sta temp2
+ mvi a,9H
+ sta temp1
+ jmp gofil6
+
+gofil3: ora a ;Trailing null?
+ jz gofil7 ;Then we're done.
+ shld datptr ;[jd] no, can update ptr now.
+ lhld fcbptr
+ mov m,a
+ inx h
+ shld fcbptr
+ lda temp1 ;Get the char count.
+ inr a
+ sta temp1
+ cpi 8H ;Are we finished with this field?
+ jm gofil2
+gofil4: sta temp2
+ lhld datptr
+ mov a,m
+ inx h
+ shld datptr
+ ora a
+ jz gofil7
+ cpi '.' ;Is this the terminator?
+ jnz gofil4 ;Go until we find it.
+gofil6: lhld datptr ;Get the TYPE field.
+ mov a,m
+ cpi 'a' ;Force upper case
+ jm gofl6a ;
+ ani 5FH ;
+gofl6a: ora a ;Trailing null?
+ jz gofil7 ;Then we're done.
+;[jd] move above two lines so we don't increment pointer if char is null
+ inx h
+ shld datptr
+ lhld fcbptr
+ mov m,a
+ inx h
+ shld fcbptr
+ lda temp1 ;Get the char count.
+ inr a
+ sta temp1
+ cpi 0CH ;Are we finished with this field?
+ jm gofil6
+gofil7: lhld datptr
+ mvi m,'$' ;Put in a dollar sign for printing.
+ lda quietd ; quiet display?
+ ana a
+ jnz gofi70 ; yes, so skip it.
+ call scrfln ;Position cursor
+gofi70: lxi d,data ;Print the file name
+ lda getrxflg ;[obs 8] are we doing a get or receive?
+ ana a ;[obs 8]
+ jz gofi7a ;[obs 8] if zero, receive
+ lxi d,remnam ;[obs 8]
+gofi7a: ;[obs 8]
+
+ call prtstr
+gofi7b: xra a ;[MF]Zero "discard" flag
+ sta dscflg ;[MF]...
+ lda flwflg ;Is file warning on?
+ ora a
+ jz gofil9 ;If not, just proceed.
+ mvi c,openf ;See if the file exists.
+ lxi d,fcb
+ call bdos
+ cpi 0FFH ;Does it exist?
+ jz gofil9 ;If not create it.
+;
+ lda flwflg ;[MF]Get flag again
+ cpi 3 ;[MF]SET COLLISION DISCARD?
+ jnz gofi7h ;[MF]No
+ mvi a,0ffh ;[MF]Yes, order rejection of the file
+ sta dscflg ;[MF]...
+ jmp rskp ;[MF]and pretend successful open
+gofi7h: push psw ;[MF]Save Collision status
+ lxi d,infms5
+ call error3
+ pop psw ;[MF]Restore Collision status
+ cpi 1 ;[MF]SET COLLISION RENAME?
+ jz gofi7i ;[MF]Yes, same as SET WARNING ON
+ ;[MF]If we come here, SET COLLISION BACKUP
+ lxi h,fcb ;[MF]Copy original fcb to a safe place
+ lxi d,colfcb ;[MF]...
+ lxi b,33 ;[MF]...
+ call mover ;[MF]...
+ ;[MF]and fall into rename code
+gofi7i: ;[MF]
+;
+; Replacement file name renamer routine. Incomming
+; files are renamed in this manner:
+; original file name: filex.ext
+; first rename: filex001.ext
+; ... ...
+; ninth rename filex009.ext
+; 10th rename fail - would we really want 10
+; files of the same name??
+;
+;
+; 1)
+; Assume that we need to "rename" the file, so lets make sure
+; that there is a full. 8 character filename. (We make it if
+; it does not already exist)
+; 1a) If full file name, last character is to be replaced
+; by a zero. This gives us up to no#ine renames.
+; 2)open file
+; 2a)If exists, increment last character by one
+; 2b)if = '9' then abort
+; 2c)If does not exist, got 2)
+; 3)we have a valid 'renamed' file
+;
+;Part 1) - fill out filename part
+
+ mvi c,8 ; max 8 characters to test for
+ mvi a,'0' ; spaces to be replaced by a zero.
+ lxi h,fcb+8 ; start at the end
+gofi7c: mov m,a ; put a zero in here
+ dcr c ; come to the end?
+ jz gofi7d ; should not have, but just in case...
+ dcx h ; previous chararcter
+ mov a,m ; get it
+ cpi ' ' ; if this character a space as well, zero it
+ mvi a,'0' ; set it to ascii zero just in case...
+ jz gofi7c ;
+;
+; Part 2) open the file (if success, then it exists)
+
+gofi7d:
+;zero the attribute bits. [rjl@monu1.cc.monash.edu.au]
+ lxi h,fcb+1 ;[rjl]
+ mvi c,11 ;[rjl]
+gofi7z: mov a,m ;[rjl]
+ ani 07fh ;[rjl]
+ mov m,a ;[rjl]
+ inx h ;[rjl]
+ dcr c ;[rjl]
+ jnz gofi7z ;[rjl]
+ lxi d,fcb
+ mvi c,openf
+ call BDOS
+ inr a ; if 0ffh returned, error (ie does not exist)
+ jz gofi7e
+ lda fcb+8 ; get last character
+ inr a
+ sta fcb+8
+ cpi '9'+1 ; more than '9' => too far, lets give up.
+ jnz gofi7d ; else try again
+;Giving up, so lets exit
+ lxi d,erms16 ;
+ call prtstr
+ ret ; return to error routine
+
+gofi7e: lxi d,fnbuf ; make the file name into a character string
+ lxi h,fcb+1 ; point to source file name, less drive name
+ mvi c,8 ; 11 characters (8+3) + dot to copy across
+;
+gofi7f: mov a,m ; get character
+ stax d
+ inx h
+ inx d
+ dcr c
+ jnz gofi7f ; loop until all done
+
+ mvi a,'.' ; then the dot
+ stax d
+ inx d
+
+ mvi c,3 ; then the file extention
+
+gofi7g: mov a,m
+ stax d
+ inx h
+ inx d
+ dcr c
+ jnz gofi7g ; loop until extention copied across
+
+ mvi a,'$' ; dollar terminate string
+ stax d
+ lxi d,fnbuf ;[MF]Point to string
+ call prtstr ; write string to console
+
+ lda flwflg ;[MF]Get warning (SET COLLISION) flag
+ cpi 2 ;[MF]SET COLLISION BACKUP?
+ jnz gofil9 ;[MF]No
+ lxi h,fcb ;[MF]Yes, get new filename fcb
+ lxi d,colfcb+16 ;[MF]Where to copy to for rename
+ lxi b,16 ;[MF]Copy 16 bytes
+ call mover ;[MF]...
+ lxi d,colfcb ;[MF]Point to rename fcb
+ mvi c,renam ;[MF]Rename function
+ call bdos ;[MF]Try to rename original file
+ cpi 0ffh ;[MF]Did we win?
+ jnz gofl82 ;[MF]Yes
+ lxi d,erms16 ;[MF]No, complain and bomb
+ jmp error3 ;[MF]...
+gofl82: lxi h,colfcb ;[MF]Now recopy original filename into fcb
+ lxi d,fcb ;[MF]to create new file with original name
+ lxi b,16 ;[MF]...
+ call mover ;[MF]...
+;
+;
+;Now lets make the file (create it)
+
+gofil9: call makfil ; Create the file.
+ jmp gofl91 ; Disk was full.
+ jmp rskp ; Success.
+
+gofl91: lxi d,erms11
+ call error3
+ ret
+;
+; This is the FINISH command. It tells the remote KERSRV to exit.
+; here from kermit
+
+finish: call cfmcmd
+ call selmdm ;[MF]Select modem
+ call flsmdm ;[MF]Flush buffers
+ call selcon ;[MF]Select keyboard again
+ xra a
+ sta numtry ;Inititialize count.
+ mvi a,'1' ;Reset block check type to single character
+ sta curchk ; . . .
+
+finsh1: lda numtry ;How many times have we tried?
+ cpi maxtry ;Too many times?
+ jm finsh3 ;No, try it.
+finsh2: lxi d,erms18 ;Say we couldn't do it.
+ call prtstr
+ jmp kermit ;Go home.
+
+finsh3: inr a ;Increment the number of tries.
+ sta numtry
+ xra a
+ sta argblk ;Make it packet number zero.
+ mvi a,1
+ sta argblk+1 ;One piece of data.
+ lxi h,data
+ mvi m,'F' ;Finish running Kermit.
+ mvi a,'G' ;Generic command packet.
+ call spack
+ jmp finsh2 ; Tell the user and die.
+ call rpack ;Get an acknowledgement.
+ jmp finsh1 ; Go try again.
+ cpi 'Y' ;ACK?
+ jz kermit ;Yes, we are done.
+ cpi 'E' ;Is it an error packet?
+ jnz finsh1 ;Try sending the packet again.
+ call error1 ;Print the error message.
+ jmp kermit
+;
+; This is the LOGOUT command. It tells the remote KERSRV to logout.
+; here from: kermit
+
+logout: call cfmcmd
+ call logo ;Send the logout packet.
+ jmp kermit ;Go get another command
+ jmp kermit ; whether we succeed or not.
+
+; do logout processing.
+; called by: bye, logout
+
+logo: call selmdm ;[MF]Select modem
+ call flsmdm ;[MF]Flush buffers
+ call selcon ;[MF]Select keyboard again
+ xra a
+ sta numtry ;Inititialize count.
+ mvi a,'1' ;Reset block check type to single character
+ sta curchk ; . . .
+
+logo1: lda numtry ;How many times have we tried?
+ cpi maxtry ;Too many times?
+ jm logo3 ;No, try it.
+logo2: lxi d,erms19 ;Say we couldn't do it.
+ call prtstr
+ ret ;Finished.
+
+logo3: inr a ;Increment the number of tries.
+ sta numtry
+ xra a
+ sta argblk ;Make it packet number zero.
+ mvi a,1
+ sta argblk+1 ;One piece of data.
+ lxi h,data
+ mvi m,'L' ;Logout the remote host.
+ mvi a,'G' ;Generic command packet.
+ call spack
+ jmp logo2 ; Tell the user and die.
+ call rpack ;Get an acknowledgement
+ jmp logo1 ; Go try again.
+ cpi 'Y' ;ACK?
+ jz rskp ;Yes, we are done.
+ cpi 'E' ;Is it an error packet?
+ jnz logo1 ;Try sending the packet again.
+ call error1 ;Print the error message.
+ ret ;All done.
+;
+; Packet routines
+
+; Send_Packet
+; This routine assembles a packet from the arguments given and sends it
+; to the host.
+;
+; Expects the following:
+; A - Type of packet (D,Y,N,S,R,E,F,Z,T)
+; ARGBLK - Packet sequence number
+; ARGBLK+1 - Number of data characters
+; Returns: nonskip if failure
+; skip if success
+; called by: read, rinit, rfile, rdata, sinit, sfile, sdata, seof, seot,
+; finish, logout, nak, ackp
+
+spack: sta argblk+2
+ lxi h,packet ;Get address of the send packet.
+ lda sndsop ;[gnn] send start-of-pkt char.
+ mov m,a ;Put in the packet.
+ inx h ;Point to next char.
+ lda curchk ;Get current checksum type
+ sui '1' ;Determine extra length of checksum
+ mov b,a ;Copy length
+ lda argblk+1 ;Get the number of data chars.
+ adi ' '+3 ;Real packet character count made printable.
+ add b ;Determine overall length
+ mov m,a ;Put in the packet.
+ inx h ;Point to next char.
+ lxi b,0 ;Zero the checksum AC.
+ mov c,a ;Start the checksum.
+ lda argblk ;Get the packet number.
+ adi ' ' ;Add a space so the number is printable.
+ mov m,a ;Put in the packet.
+ inx h ;Point to next char.
+ add c
+ mov c,a ;Add the packet number to the checksum.
+ mvi a,0 ;Clear A (Cannot be XRA A, since we can't
+ ; touch carry flag)
+ adc b ;Get high order portion of checksum
+ mov b,a ;Copy back to B
+ lda argblk+2 ;Get the packet type.
+ mov m,a ;Put in the packet.
+ inx h ;Point to next char.
+ add c
+ mov c,a ;Add the packet number to the checksum.
+ mvi a,0 ;Clear A
+ adc b ;Get high order portion of checksum
+ mov b,a ;Copy back to B
+spack2: lda argblk+1 ;Get the packet size.
+ ora a ;Are there any chars of data?
+ jz spack3 ; No, finish up.
+ dcr a ;Decrement the char count.
+ sta argblk+1 ;Put it back.
+ mov a,m ;Get the next char.
+ inx h ;Point to next char.
+ add c
+ mov c,a ;Add the packet number to the checksum.
+ mvi a,0 ;Clear A
+ adc b ;Get high order portion of checksum
+ mov b,a ;Copy back to B
+ jmp spack2 ;Go try again.
+
+spack3: lda curchk ;Get the current checksum type
+ cpi '2' ;Two character?
+ jz spack4 ;Yes, go handle it
+ jnc spack5 ;No, go handle CRC if '3'
+ mov a,c ;Get the character total.
+ ani 0C0H ;Turn off all but the two high order bits.
+ ;Shift them into the low order position.
+ rlc ;Two left rotates same as 6 rights
+ rlc ; . . .
+ add c ;Add it to the old bits.
+ ani 3FH ;Turn off the two high order bits. (MOD 64)
+ adi ' ' ;Add a space so the number is printable.
+ mov m,a ;Put in the packet.
+ inx h ;Point to next char.
+ jmp spack7 ;Go store eol character
+
+;Here for 3 character CRC-CCITT
+
+spack5: mvi m,0 ;Store a null for current end
+ push h ;Save H
+ lxi h,packet+1 ;Point to first checksumed character
+ call crcclc ;Calculate the CRC
+ pop h ;Restore the pointer
+ mov c,e ;Get low order half for later
+ mov b,d ;Copy the high order
+ mov a,d ;Get the high order portion
+ rlc ;Shift off low 4 bits
+ rlc ; . . .
+ rlc ; . . .
+ rlc ; . . .
+ ani 0FH ;Keep only low 4 bits
+ adi ' ' ;Put into printing range
+ mov m,a ;Store the character
+ inx h ;Point to next position
+
+;Here for two character checksum
+
+spack4: mov a,b ;Get high order portion
+ ani 0FH ;Only keep last four bits
+ rlc ;Shift up two bits
+ rlc ; . . .
+ mov b,a ;Copy back into safe place
+ mov a,c ;Get low order half
+ rlc ;Shift high two bits
+ rlc ;to low two bits
+ ani 03H ;Keep only two low bits
+ ora b ;Get high order portion in
+ adi ' ' ;Convert to printing character range
+ mov m,a ;Store the character
+ inx h ;Point to next character
+ mov a,c ;get low order portion
+ ani 3FH ;Keep only six bits
+ adi ' ' ;Convert to printing range
+ mov m,a ;Store it
+ inx h ;Bump the pointer
+
+spack7: lda dbgflg
+ ora a ; is debugging enabled?
+ jz spack8
+ push h ; yes. save address of end of packet
+ mvi m,0 ; null-terminate the packet for display
+ lda quietd ; a quiet display?
+ ana a
+ jnz spac7a ; so dont say a thing
+ call sppos ; position cursor
+ lxi h,packet+1 ; print the packet
+ call dmptxt
+ lda prnflg ; is the printer on too?
+ ana a
+ jz spac7a
+ lxi h,sstatm ; print state
+ call printm ; dumptext but to printer
+ lda state
+ mov e,a
+ call outprn
+ lxi h,princr ; cr lf to printer
+ call printm
+ lxi h,spackm
+ call printm
+ lxi h,packet+1
+ call printm
+ lxi h,princr
+ call printm
+ lxi h,princr
+ call printm
+
+spac7a: pop h ; restore address of end of packet
+spack8: lda seol ;Get the EOL the other host wants.
+ mov m,a ;Put in the packet.
+ inx h ;Point to next char.
+ xra a ;Get a null.
+ mov m,a ;Put in the packet.
+; Write out the packet.
+outpkt: call selmdm ; Set up for output to comm port if iobyt
+ lda spad ;Get the number of padding chars.
+ sta temp1
+outpk2: lda temp1 ;Get the count.
+ dcr a
+ ora a
+ jm outpk6 ;If none left proceed.
+ sta temp1
+ lda spadch ;Get the padding char.
+ call setpar ;Set parity appropriately
+ mov e,a ;Put the char in right AC.
+ call outmdm ;Output it.
+ jmp outpk2
+
+outpk6: lxi h,packet ; Point to the packet.
+outlup: mov a,m ; Get the next character.
+ ora a ; Is it a null?
+ jz outlud ; If so return success.
+ call setpar ; Set parity for the character
+ mov e,a ; Put it in right AC
+ call outmdm ; and output it.
+; TAC trap: If this character is the TAC intercept character, and the TAC
+; trap is enabled, we have to output it twice. If the TAC trap is enabled,
+; tacflg contains the intercept character. (The current character cannot
+; be NUL, so we don't have to worry about doubling nulls in the message)
+ lda tacflg ; get current intercept character, or zero.
+ cmp m ; compare against current data character.
+ jnz outpk8 ; if different, do nothing.
+ call setpar ; match. set appropriate parity,
+ mov e,a ; put it in the right register,
+ call outmdm ; and output it a second time.
+outpk8:
+ inx h ; Increment the char pointer.
+ jmp outlup
+
+outlud: call selcon ; select console
+ jmp rskp ; and return success
+;
+; Receive_Packet
+; This routine waits for a packet to arrive from the host. It reads
+; characters until it finds a SOH. It then reads the packet into packet.
+;
+; Returns: nonskip if failure (checksum wrong or packet trashed)
+; skip if success, with
+; A - message type
+; ARGBLK - message number
+; ARGBLK+1 - length of data
+; called by: rinit, rfile, rdata,
+; sinit, sfile, sdata, seof, seot, finish, logout
+
+rpack: call inpkt ;Read up to the end-of-line character
+ jmp r ; Return bad.
+rpack0: call getchr ;Get a character.
+ jmp rpack ; Hit eol;null line;just start over.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jnz rpack0 ; No, go until it is.
+rpack1: call getchr ;Get a character.
+ jmp r ; Hit end of line, return bad.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jz rpack1 ; Yes, then go start over.
+ sta packet+1 ;Store in packet also
+ mov c,a ;Start the checksum.
+ lda curchk ;Get block check type
+ sui '1' ;Determine extra length of block check
+ mov b,a ;Get a copy
+ mov a,c ;Get back length character
+ sui ' '+3 ;Get the real data count.
+ sub b ;Get total length
+ sta argblk+1
+ mvi b,0 ;Clear high order half of checksum
+ call getchr ;Get a character.
+ jmp r ; Hit end of line, return bad.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jz rpack1 ; Yes, then go start over.
+ sta argblk
+ sta packet+2 ;Save also in packet
+ add c
+ mov c,a ;Add the character to the checksum.
+ mvi a,0 ;Clear A
+ adc b ;Get high order portion of checksum
+ mov b,a ;Copy back to B
+ lda argblk
+ sui ' ' ;Get the real packet number.
+ sta argblk
+ call getchr ;Get a character.
+ jmp r ; Hit end of line, return bad.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jz rpack1 ; Yes, then go start over.
+ sta temp1 ;Save the message type.
+ sta packet+3 ;Save in packet
+ add c
+ mov c,a ;Add the character to the checksum.
+ mvi a,0 ;Clear A
+ adc b ;Get high order portion of checksum
+ mov b,a ;Copy back to B
+ lda argblk+1 ;Get the number of data characters.
+ sta temp2
+ lxi h,data ;Point to the data buffer.
+ shld datptr
+rpack2: lda temp2
+ sui 1 ;Any data characters?
+ jm rpack3 ; If not go get the checksum.
+ sta temp2
+ call getchr ;Get a character.
+ jmp r ; Hit end of line, return bad.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jz rpack1 ; Yes, then go start over.
+ lhld datptr
+ mov m,a ;Put the char into the packet.
+ inx h ;Point to the next character.
+ shld datptr
+ add c
+ mov c,a ;Add the character to the checksum.
+ mvi a,0 ;Clear A
+ adc b ;Get high order portion of checksum
+ mov b,a ;Copy back to B
+ jmp rpack2 ;Go get another.
+
+rpack3: call getchr ;Get a character.
+ jmp r ; Hit end of line, return bad.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jz rpack1 ; Yes, then go start over.
+ sui ' ' ;Turn the char back into a number.
+ sta temp3
+;Determine type of checksum
+
+ lda curchk ;Get the current checksum type
+ cpi '2' ;1, 2 or 3 character?
+ jz rpack4 ;If zero, 2 character
+ jnc rpack5 ;Go handle 3 character
+ mov a,c ;Get the character total.
+ ani 0C0H ;Turn off all but the two high order bits.
+ ;Shift them into the low order position.
+ rlc ;Two left rotates same as six rights
+ rlc ; . . .
+ add c ;Add it to the old bits.
+ ani 3FH ;Turn off the two high order bits. (MOD 64)
+ mov b,a
+ lda temp3 ;Get the real received checksum.
+ cmp b ;Are they equal?
+ jz rpack7 ;If so, proceed.
+rpack9: call updrtr ;If not, update the number of retries.
+ ret ;Return error.
+
+;Here for three character CRC-CCITT
+
+rpack5: lhld datptr ;Get the address of the data
+ mvi m,0 ;Store a zero in the buffer to terminate packet
+ lxi h,packet+1 ;Point at start of checksummed region
+ call crcclc ;Calculate the CRC
+ mov c,e ;Save low order half for later
+ mov b,d ;Also copy high order
+ mov a,d ;Get high byte
+ rlc ;Want high four bits
+ rlc ; . . .
+ rlc ;And shift two more
+ rlc ; . . .
+ ani 0FH ;Keep only 4 bits
+ mov d,a ;Back into D
+ lda temp3 ;Get first value back
+ cmp d ;Correct?
+ jnz rpack9 ;No, punt
+ call getchr ;Get a character.
+ jmp r ; Hit end of line, return bad.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jz rpack1 ; Yes, then go start over.
+ sui ' ' ;Remove space offset
+ sta temp3 ;Store for later check
+ ;...
+
+;Here for a two character checksum and last two characters of CRC
+
+rpack4: mov a,b ;Get high order portion
+ ani 0FH ;Only four bits
+ rlc ;Shift up two bits
+ rlc ; . . .
+ mov b,a ;Save back in B
+ mov a,c ;Get low order
+ rlc ;move two high bits to low bits
+ rlc ; . . .
+ ani 03H ;Save only low two bits
+ ora b ;Get other 4 bits
+ mov b,a ;Save back in B
+ lda temp3 ;Get this portion of checksum
+ cmp b ;Check first half
+ jnz rpack9 ;If bad, go give up
+ call getchr ;Get a character.
+ jmp r ; Hit end of line, return bad.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jz rpack1 ; Yes, then go start over.
+ sui ' ' ;Remove space offset
+ mov b,a ;Save in safe place
+ mov a,c ;Get low 8 bits of checksum
+ ani 3FH ;Keep only 6 bits
+ cmp b ;Correct value
+ jnz rpack9 ;Bad, give up
+rpack7: lhld datptr
+ mvi m,0 ;Put a null at the end of the data.
+ lda temp1 ;Get the type.
+ jmp rskp
+;
+; inpkt - receive and buffer packet
+; returns: nonskip if error (timeout)
+; skip if success; packet starts at recpkt (which holds the SOH)
+; and is terminated by a null.
+; console is selected in either case.
+; called by: rpack
+
+inpkt: lxi h,recpkt ;Point to the beginning of the packet.
+ shld pktptr
+inpkt1: call inchr ;Get first character
+ jmp r ;Return failure
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jnz inpkt1 ;if not, ignore leading junk
+ jmp inpkt3 ;else go put it in packet
+
+inpkt2: call inchr ;Get a character.
+ jmp r ; Return failure.
+ lxi h,rcvsop ;[gnn] Is it receive start-of-pkt char.
+ cmp m ;[gnn]
+ jnz inpkt3 ;if not continue
+ lxi h,recpkt ;else throw away what we've got so far
+ shld pktptr ;
+inpkt3: lhld pktptr ;
+ mov m,a ;Put the char in the packet.
+ inx h
+ shld pktptr
+ mov b,a
+ lxi d,-recpkx ;Start over if packet buffer overflow
+ dad d ;
+ jc inpkt ;buffer overflow
+ lda reol ;Get the EOL char.
+ cmp b
+ jnz inpkt2 ;If not loop for another.
+;[gnn] *** added by Godfrey Nix Nottingham University ***
+;[gnn] to allow Kermit server to echo our packets back
+ lxi h,recpkt+3 ;[gnn] point to packet type
+ lda packet+3 ;[gnn] get the one we sent
+ cmp m ;[gnn] are they the same?
+ jz inpkt ;[gnn] yes, get another packet
+;[gnn] *** end of patch *****
+ ;...
+ ;...
+
+;Begin IBM change/fdc
+;This moved from OUTPK7 -- it appears that waiting until we're
+;ready to send a packet before looking for turnaround character
+;is long enough for it to get lost. Better to look now.
+
+ lda ibmflg ;Is this the IBM?
+ ora a
+ jz inpkt6 ;If not then proceed.
+ lda state ;Check if this is the Send-Init packet.
+ cpi 'S'
+ jz inpkt6 ;If so don't wait for the XON.
+inpkt5: call inchr ;Wait for the turn around char.
+ jmp inpkt6
+ cpi xon ;Is it the IBM turn around character?
+ jnz inpkt5 ;If not, go until it is.
+inpkt6: lhld pktptr ;Reload packet pointer
+;End IBM change/fdc.
+ dcx h ;Back up to end of line character
+ mvi m,0 ;Replace it with a null to stop rpack:
+ call selcon ;We've got the packet. Return to console.
+
+ lda dbgflg ; Is debugging enabled?
+ ora a
+ jz inpkt7
+ inx h ; Point to next char.
+ lda quietd ; a quiet display?
+ ana a
+ jnz inpkt7 ; so dont say a thing
+ call rppos ; position cursor
+ lxi h,recpkt+1 ; print the packet
+ call dmptxt
+
+ lda prnflg ; is the printer on too?
+ ana a
+ jz inpkt7
+ lxi h,rstatm ; print state
+ call printm ; dumptext but to printer
+ lda state
+ mov e,a
+ call outprn
+ lxi h,princr ; cr lf to printer
+ call printm
+ lxi h,rpackm
+ call printm
+ lxi h,recpkt+1
+ call printm
+ lxi h,princr
+ call printm
+ lxi h,princr
+ call printm
+
+
+inpkt7: lxi h,recpkt
+ shld pktptr ;Save the packet pointer.
+ jmp rskp ;If so we are done.
+
+; getchr - get next character from buffered packet.
+; returns nonskip at end of packet.
+; called by: rpack
+
+getchr: lhld pktptr ;Get the packet pointer.
+ mov a,m ;Get the char.
+ inx h
+ shld pktptr
+ ora a ;Is it the null we put at the end of the packet?
+ jnz rskp ;If not return retskp.
+ ret ;If so return failure.
+;
+;
+; inchr - character input loop for file transfer
+; returns: nonskip if timeout or character typed on console
+; (console selected)
+; skip with character from modem in A (parity stripped
+; if necessary; modem selected)
+; preserves bc, de, hl in either case.
+; called by: inpkt
+
+inchr: push h ; save hl and bc
+ push b
+ lhld timout ;Get initial value for timeout
+ shld timval ;[jd]
+inchr0: call selmdm ;select modem
+ call inpmdm ;Try to get a character from the modem
+ ora a
+ jz inchr2 ;if zero, nothing there.
+ mov b,a
+ lda parity ;Is the parity none?
+ cpi parnon
+ mov a,b
+ jz inchr1 ;If so just return.
+ ani 7FH ;Turn off the parity bit.
+inchr1: pop b ;restore registers
+ pop h
+ jmp rskp ;take skip return, character in A
+
+inchr2: call selcon ;select console
+ call inpcon ; Try to get a character from the console
+ ora a
+ jz inchr6 ;If not go do timer thing
+ cpi cr ;Is it a carriage return?
+ jz inchr4 ;If so return
+ cpi ('Z'-100O) ;Control-Z?
+ jz inchr5 ;Yes, go flag it
+ cpi ('C'-100O) ;Control-C?
+ jz inchr7 ;re-enter, he wants to get out
+ cpi ('X'-100O) ;Control-X?
+ jnz inchr6 ;No, ignore it. do timer thing.
+inchr5: adi 100O ;Convert to printing range
+ sta czseen ;Flag we saw a control-Z
+ jmp inchr6 ;[MF] and do timer thing
+inchr4: pop b ; restore registers
+ pop h
+ ret ;And return
+
+inchr6: lda timflg ;[jd] pick up timer flag
+ ora a ;[jd] are we allowed to use timer?
+ jz inchr0 ;[jd] no, don't time out
+ lhld timval ; decrement fuzzy time-out
+ dcx h ;
+ shld timval ;((timout-1) * loop time)
+ mov a,h ;(Retry if not time-out)
+ ora l ;
+ jnz inchr0 ;
+ call updrtr ;Count as retry (?)
+ pop b ;restore registers
+ pop h
+ ret ;and return to do retry
+
+inchr7: call clrtop ;[hh] clear screen and home cursor
+ lda takflg ;[MF]Take-file in progress?
+ ani 1 ;[MF]...
+ cnz closet ;[MF]Yes, close it and reset TAKE-flag
+ ;[MF]so all processing is halted
+ jmp kermit ;[hh] then re-enter kermit
+
+;
+; CRCCLC - Routine to calculate a CRC-CCITT for a string.
+;
+; This routine will calculate a CRC using the CCITT polynomial for
+; a string.
+;
+; call with: HL/ Address of null-terminated string
+; 16-bit CRC value is returned in DE.
+; Registers BC and HL are preserved.
+;
+; called by: spack, rpack
+
+crcclc: push h ;Save HL
+ push b ;And BC
+ lxi d,0 ;Initial CRC value is 0
+
+crccl0: mov a,m ;Get a character
+ ora a ;Check if zero
+ jz crccl1 ;If so, all done
+ push h ;Save the pointer
+ xra e ;Add in with previous value
+ mov e,a ;Get a copy
+ ani 0FH ;Get last 4 bits of combined value
+ mov c,a ;Get into C
+ mvi b,0 ;And make high order zero
+ lxi h,crctb2 ;Point at low order table
+ dad b ;Point to correct entry
+ dad b ; . . .
+ push h ;Save the address
+ mov a,e ;Get combined value back again
+ rrc ;Shift over to make index
+ rrc ; . . .
+ rrc ; . . .
+ ani 1EH ;Keep only 4 bits
+ mov c,a ;Set up to offset table
+ lxi h,crctab ;Point at high order table
+ dad b ;Correct entry
+ mov a,m ;Get low order portion of entry
+ xra d ;XOR with previous high order half
+ inx h ;Point to high order byte
+ mov d,m ;Get into D
+ pop h ;Get back pointer to other table entry
+ xra m ;Include with new high order half
+ mov e,a ;Copy new low order portion
+ inx h ;Point to other portion
+ mov a,m ;Get the other portion of the table entry
+ xra d ;Include with other high order portion
+ mov d,a ;Move back into D
+
+ pop h ;And H
+ inx h ;Point to next character
+ jmp crccl0 ;Go get next character
+
+crccl1: pop b ;Restore B
+ pop h ;And HL
+
+ ret ;And return, DE=CRC-CCITT
+
+CRCTAB: DW 00000H
+ DW 01081H
+ DW 02102H
+ DW 03183H
+ DW 04204H
+ DW 05285H
+ DW 06306H
+ DW 07387H
+ DW 08408H
+ DW 09489H
+ DW 0A50AH
+ DW 0B58BH
+ DW 0C60CH
+ DW 0D68DH
+ DW 0E70EH
+ DW 0F78FH
+
+CRCTB2: DW 00000H
+ DW 01189H
+ DW 02312H
+ DW 0329BH
+ DW 04624H
+ DW 057ADH
+ DW 06536H
+ DW 074BFH
+ DW 08C48H
+ DW 09DC1H
+ DW 0AF5AH
+ DW 0BED3H
+ DW 0CA6CH
+ DW 0DBE5H
+ DW 0E97EH
+ DW 0F8F7H
+;
+; This is where we go if we get an error during a protocol communication.
+; error prints the error packet on line 6 or so, and aborts the
+; transfer.
+; called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot
+; error1 print CRLF followed by the error packet.
+; called by: finish, logout
+; error2 just prints the error packet.
+; error3 positions cursor and prints error message specified in DE.
+; called by: rinit, rfile, rdata, sinit, sfile, sdata, seof,
+; seot, parwrn, gofil, outbuf
+
+error: lda quietd ; a quiet display?
+ ana a
+ jnz error0 ; so dont say a thing
+ lda remtxt ;[MF]Doing a remote command?
+ ora a ;[MF]...
+ jnz error0 ;[MF]Yes, don't position cursor
+ call screrr ;Position the cursor.
+error0: mvi a,'A' ;Set the state to abort.
+ sta state
+ jmp error2
+
+error1: lxi d,crlf ;Print a CRLF.
+ lda quietd ; a quiet display?
+ ana a
+ jnz error2 ; so dont say a thing
+ call prtstr
+error2: lda argblk+1 ;Get the length of the data.
+ mov c,a
+ mvi b,0 ;Put it into BC
+ lxi h,data ;Get the address of the data.
+ dad b ;Get to the end of the string.
+ mvi m,'$' ;Put a dollar sign at the end.
+ lxi d,data ;Print error message
+ lda remtxt ;[MF]Doing a remote command?
+ ora a ;[MF]...
+ jnz errr2a ;[MF]Yes, print message, quiet or not!
+ lda quietd ; a quiet display?
+ ana a
+ rnz ; so dont say a thing
+errr2a: call prtstr
+ ret
+
+error3: lda quietd ; a quiet display?
+ ana a
+ rnz ; so dont say a thing
+ lda remtxt ;[MF]Doing a remote command?
+ ora a ;[MF]...
+ jnz err3a ;[MF]Yes, don't position cursor
+ push d ;Save the pointer to the message.
+ call screrr ;Position the cursor.
+ pop d ;Get the pointer back.
+err3a: call prtstr ;Print error message
+ ret
+;
+; Set up for file transfer.
+; called by read, send.
+
+init: lxi d,version ; point at Kermit's version string
+ lda quietd ; a quiet display?
+ ana a
+ jnz init1 ; so dont say a thing
+ call sysscr ; fix up screen
+init1: call selmdm ; select modem
+ call flsmdm ; purge any pending data
+ call selcon ; select console again.
+ ret
+
+; Set state to ABORT
+; called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot,
+; nak, ackp
+
+abort: mvi a,'A' ;Otherwise abort.
+ sta state
+ ret
+
+; nak - send NAK packet
+; here from: rinit, rfile, rdata
+; nak0 - update retry count and send NAK packet
+; here from: rinit, rfile, rdata, tryagn
+
+nak0: call updrtr ;Update number of retries.
+nak: lda pktnum ;Get the packet number we're waiting for.
+ sta argblk
+ xra a ;No data.
+ sta argblk+1
+ mvi a,'N' ;NAK that packet.
+ call spack
+ jmp abort ; Give up.
+ ret ;Go around again.
+
+; increment and display retry count
+; called by: rfile, sinit, sfile, sdata, seof, seot,
+; nak, rpack, inchr, tryagn
+
+updrtr: lhld numrtr
+ inx h ;Increment the number of retries
+ shld numrtr
+ lda remtxt ;[MF]Doing a remote server command?
+ ora a ;[MF]...
+ rnz ;[MF]Yes, keep mum
+ lda quietd ; a quiet display?
+ ana a
+ rnz ; so dont say a thing
+ call scrnrt ;Position cursor
+ lhld numrtr ;[MF]
+call nout ;Write the number of retries.
+ ret
+
+; [jd] this routine prints parity warnings. All registers are
+; saved except for a.
+; called by: sdata
+
+parwrn: push b
+ push d
+ push h
+ lxi d,inms25
+ call error3
+ pop h
+ pop d
+ pop b
+ ret
+;[jd] end of addition
+
+; print message in status field. address of message is in DE.
+; called by: read, send
+
+finmes: lda quietd ; a quiet display?
+ ana a
+ jz finme0 ; so do usual stuff
+ push d ;[MF]Save pointer to completion message
+ call prcrlf ; best do a new line
+ pop d ;[MF]Restore completion message pointer
+ call prtstr ; and send message
+ mvi e,space ; send a space or two
+ mvi c,dconio
+ push b
+ push d
+ call bdos
+ pop d
+ pop b
+ call bdos
+ ret ; and exit back
+;
+;else for screaming screens...
+
+finme0: push d ;Save message.
+ call scrst ;Position cursor
+ pop d ;Print the termination message
+ call prtstr
+ ret ; may not want this **************
+
+ mvi c,4 ;[2] copy across user no and drive
+ lxi h,kerm1 ;[2] as we have the text already
+finme1: mov e,m
+ push h ;[2] conout probably destroys these
+ push b
+ call conout
+ pop b
+ pop h
+ inx h ;[2] next character
+ dcr c ;[2] ah, but have we done?
+ jnz finme1 ;[2] nope
+ lxi d,spac15 ;[2] send 15 spaces (clears previous filename)
+ call prtstr ;[2]
+ call scrend ;Position cursor for prompt
+ ret
+
+; Compare expected packet number against received packet number.
+; return with flags set (Z = packet number valid)
+; called by: rfile, rdata, sinit, sfile, sdata, seof, seot
+
+compp: lda pktnum ;Get the packet Nr.
+ mov b,a
+ lda argblk
+ cmp b
+ ret
+
+; Increment the packet number, modulo 64.
+; called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot
+
+countp: inr a ;Increment packet Nr.
+ ani 3FH ;Turn off the two high order bits
+ sta pktnum ;Save modulo 64 of number
+ lhld numpkt
+ inx h ;Increment Nr. of packets
+ shld numpkt
+ ret
+
+; Send an ACK-packet
+; called by: rfile, rdata, tryagn
+
+ackp: xra a
+ sta numtry ;Reset number of retries
+ sta argblk+1 ;No data. (The packet number is in argblk)
+ mvi a,'Y' ;Acknowledge packet
+ call spack ;Send packet
+ jmp abort
+ ret
+
+; ?
+; called with A/ current retry count
+; called by: rfile, rdata
+
+tryagn: inr a ;Increment it.
+ sta oldtry ;Save the updated number of tries.
+ lda pktnum ;Get the present packet number.
+ dcr a ;Decrement
+ ani 3FH ; modulo 64
+ mov b,a
+ lda argblk ;Get the packet's number
+ cmp b ;Is the packet's number one less than now?
+ jnz nak0 ;No, NAK it and try again.
+ call updrtr ;Update the number of retries.
+ call ackp
+ ret
+
+; Output a null-terminated string to the console. We assume that the
+; console has been selected. Called with HL = address of string.
+; called by: spack, inpkt
+
+dmptxt: mov a,m ; get character from string
+ ora a
+ rz ; done if null
+ push h ; save string address
+ mov e,a ; move character to E for outcon
+ call outcon ; output character to console
+ pop h ; restore string address
+ inx h ; point past printed character
+ jmp dmptxt ; go output rest of string
+
+
+; Output a null-terminated string to the PRINTER We assume that the
+; console has been selected. Called with HL = address of string.
+; called by: spack, inpkt
+
+printm: mov a,m ; get character from string
+ ora a
+ rz ; done if null
+ push h ; save string address
+ mov e,a ; move character to E for outcon
+ call outprn ; output character to printer
+ pop h ; restore string address
+ inx h ; point past printed character
+ jmp printm ; go output rest of string
+
+
+;
+; test if character in A is the start of header character. We get
+; the start of packet character from sohchr, which can be SET
+tstsoh: push b ; save these registers for a bit
+ mov c,a ; we have to test if this is the character
+ lda sohchr
+ cmp c ; if zero, then it is
+ mov a,c ; restore accumulator but not flags
+ pop b
+ ret ; return with flags set
+;
+
+
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FRO RELEASE!
+
+; org ($+100h) AND 0FF00H
+
+
+IF lasm
+ LINK CPSREM
+ENDIF;lasm
diff --git a/src/cpsrem.asm b/src/cpsrem.asm
new file mode 100644
index 0000000..2f480b9
--- /dev/null
+++ b/src/cpsrem.asm
@@ -0,0 +1,1149 @@
+; CPSREM.ASM
+; 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
+; 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-independent) routines that implement
+; the REMOTE commands of the KERMIT protocol.
+;
+; revision history:
+;
+;edit 13, 21-Mar-1991 by MF. Renamed REMOTE SET FILE COLLISION REPLACE to
+; REMOTE SET FILE COLLISION OVERWRITE and modified the corresponding
+; help text slightly.
+;edit 12, 13-Feb-1991 by MF. Simplified code at "remcl0" to get REMOTE
+; command arguments by calling "cmgtch" in order to get command-line
+; characters directly. This means that command-line characters are
+; passed literally (except for prefixingand space-compression) to the
+; remote Kermit and that one need not send "?" or <esc> as "\"-prefixed
+; octal numbers in order to avoid immediate action by CP/M Kermit.
+;edit 11, 30-Jan-1991 by MF. Corrected code to always require entry of at least
+; one argument in the REMOTE COPY, REMOTE DELETE (REMOTE ERASE),
+; REMOTE MESSAGE, REMOTE RENAME and REMOTE TYPE commands. This is
+; done by branching to KERMT3 (the "not confirmed" code) if the
+; first argument isn't given. This should correct a bug which occurred
+; in numerous places in which the character immediately following
+; that specifying the flavor of a Generic command was not defined if
+; the first of multiple (at least two) arguments was left blank but
+; subsequent arguments were not. This should correct a problem
+; encountered by Russell Lang of Monash University In Australia when
+; he did a REMOTE MESSAGE command with a blank first argument (the
+; user id) and a nonblank second argument (the message text) from
+; CP/M Kermit to Ms-Kermit in Server mode.
+;edit 10, 14-Dec-1990 by MF. Put "<<>>" around "x" or "F" packet replies
+; to REMOTE commands as in VMS Bliss Kermit and eliminate unnecessary
+; instruction before label remc2d.
+;edit 9, 1-Nov-1990 by MF. Changed REMOTE CWD to REMOTE CD in the quest for
+; uniformity of nomenclature (per request of FDC).
+;edit 8, 29-Oct-1990 by MF. Corrected Remote command code to properly
+; prefix control characters (repeat prefix (~) isn't done in CP/M
+; yet).
+;edit 7, 17-Oct-1990 by MF. Changed verb "REMOTE SEND-MESSAGE" to
+; "REMOTE MESSAGE" to conform with the nomenclature suggested in
+; Chapter 10 of the 6th edition of the Kermit Protocol Manual.
+;edit 6, 10-Oct-1990 by MF. Corrected Remote command code to
+; properly prefix the control-character prefix character and the
+; eighth-bit quotation prefix character. Remote Set commands
+; now function correctly.
+; Also change the REMOTE SET FILE COLLISION ASK value to 5 per
+; Kermit Digest V12 #6 (though I still have no idea how the local
+; Kermit is supposed to answer).
+;edit 5, 5-Oct-1990 by MF. Coded many Remote Set commands.
+; The commands I have omitted deal with Attribute packets which
+; don't make much sense on a CP/M system.
+; Note also that for those Remote Set commands which take a
+; numeric argument, no range-checking is done here.
+; Also note that, for now, REMOTE SET FILE-COLLISION ASK is
+; equivalent to REMOTE SET FILE-COLLISION DISCARD because
+; (a) that's what the Kermit Digest indicated and (b) no mechanism
+; has been proposed for the Remote Kermit to query the Local Kermit.
+;edit 4, 29-Sep-1990 by MF. Corrected code to ignore error packets in
+; response to sending an "I" packet, per KPROTO.DOC
+;edit 3, 9-Sep-1990 by MF. Extensively revised this file to implement
+; Remote commands except for the following:
+; REMOTE JOURNAL, REMOTE MAIL, REMOTE PRINT, REMOTE PROGRAM,
+; REMOTE SET, REMOTE VARIABLE.
+;edit 2 ... MF Dunno where edit 2 went (shown in Version string).
+; edit 1: September 8th, 1987. Created this file from bits of the two packet files.
+; The commands supported by this system are all the REMOTE commands,
+; to allow users to acces remote host systems via Kermit. Added REMOTE
+; command table and REMOTE DIR command.
+;
+;
+remver: db 'CPSREM.ASM (13) 21-Mar-1991$' ; name, edit number, date
+
+;
+; REMOTE command - quite similar to the SET command
+remote: call selmdm ;Select modem
+ call flsmdm ;Flush buffers
+ call selcon ;Back to keyboard
+ lxi d,remtab ; remote commands table
+ lxi h,remhlp ; remote help table
+ call keycmd ; get result
+ xchg
+ pchl ; and do it
+
+
+
+
+; REMOTE command table. Works the same way as every other table etc.
+;
+remtab: db 19 ; nineteen commands so far
+ db 2,'CD$'
+ dw remcd ; remote cd command
+ db 4,'COPY$'
+ dw remcpy ; remote copy command
+ db 6,'DELETE$'
+ dw remdel ; remote delete command
+ db 9,'DIRECTORY$'
+ dw remdir ; remote directory command
+ db 10,'DISK-USAGE$'
+ dw remdsk ; remote disk-usage command
+ db 5,'ERASE$'
+ dw remdel ; remote erase command (same as delete)
+ db 6,'FINISH$'
+ dw finish ; same as finish
+ db 4,'HELP$'
+ dw remhep ; remote help command
+ db 4,'HOST$'
+ dw remhos ; remote host command
+ db 6,'KERMIT$'
+ dw remker ; remote Kermit command
+ db 5,'LOGIN$'
+ dw remlgi ; remote login
+ db 6,'LOGOUT$'
+ dw logout ; same as logout
+ db 7,'MESSAGE$'
+ dw remmsg ; remote message command
+ db 6,'RENAME$'
+ dw remren ; remote rename
+ db 3,'SET$'
+ dw remset ; remote set command
+ db 5,'SPACE$'
+ dw remdsk ; remote space command (same as disk-usage)
+ db 6,'STATUS$'
+ dw remsta ; remote status (of server) command
+ db 4,'TYPE$'
+ dw remtyp ; remote type command
+ db 3,'WHO$'
+ dw remwho ; remote who command
+
+remhlp: db cr,lf,'CD - change default directory for remote server'
+ db ' operations'
+ db cr,lf,'COPY - copy files on a remote system'
+ db cr,lf,'DELETE - delete files on a remote system'
+ db cr,lf,'DIRECTORY - list a directory on a remote system'
+ db cr,lf,'DISK-USAGE - show disk usage on a remote system'
+ db cr,lf,'FINISH - stop a remote server'
+ db cr,lf,'HELP - get help from a remote server'
+ db cr,lf,'HOST - execute a command on a remote system'
+ db cr,lf,'KERMIT - tell a remote server to execute a Kermit '
+ db 'command'
+ db cr,lf,'LOGIN - send user-identification to a remote server'
+ db cr,lf,'LOGOUT - stop and logout a remote server'
+ db cr,lf,'MESSAGE - send a message to a remote system user'
+ db cr,lf,'RENAME - rename files on a remote system'
+ db cr,lf,'SET - set remote server parameters'
+ db cr,lf,'SPACE - show disk-usage on a remote system'
+ db cr,lf,'STATUS - Get status of a remote server'
+ db cr,lf,'TYPE - type files on a remote system'
+ db cr,lf,'WHO - show current users on a remote system'
+ db '$'
+
+
+;Description of remote commands
+
+;
+; Packets start with an I packet in place of S/R packet. An X
+; packet is the same as an F (filename) packet except the 'file'
+; is not applicable. Copy X packet data field to display. Set
+; options so that no data is written to disk during D packets.
+; (REMTXT <> 0)
+;
+;Packets:
+; we we comments
+; send receive
+; I
+; ACK
+; Command packet
+; Ack or
+; Init
+; ACK
+; X Dummy header.
+; ACK
+; D listing from remote end
+; ACK We got it
+; ....
+; ACK last packet received ok
+; Z
+; ACK
+; B
+; ACK end of transaction.
+;
+;**Note** If the Remote system gives a simple ack to the command packet,
+;that is, a "short reply" is given, the data, if any, in the packet
+;is displayed and the transaction ends. The outline shown above is for a
+;"long reply".
+;
+; Remote commands
+;
+; Remote Copy - Copy file(s) on remote system
+;
+remcpy: lxi h,newfms ;Second argument prompt
+ shld rprmpt ;...
+ mvi a,'K' ;Generic type
+remcp0: sta remdat ;into packet
+ mvi a,2 ;Packet has at least two characters
+ sta rdl ;...
+ mvi a,'G' ;Generic command
+ sta rcom ;...
+ lxi d,remdat+2 ;Point to data buffer
+ call remcli ;Get filespec (if any) from command line
+ ora a ;Anything typed?
+ jz kermt3 ;No, we must have an argument
+ mov b,a ;Save length
+ adi space ;Yes, make encoded field length
+ sta remdat+1 ;and store in packet data area
+ lda rdl ;Get packet length so far
+ add b ;Count answer length
+ sta rdl ;and remember new packet size
+ lhld rprmpt ;Point to "new file" prompt
+ xchg ;...
+ shld rptr ;Save data pointer
+ call prompt ;Prompt the user
+ lhld rptr ;Get data pointer again
+ inx h ;Skip encoded field-length
+ xchg ;...
+ call remcli ;get user's answer
+ lhld rptr ;Restore pointer
+ mov c,a ;Save answer length
+ adi space ;Convert to encoded field length
+ mov m,a ;Put length in packet
+ lda rdl ;Get accumulated data length
+ add c ;plus data length
+ adi 1 ;plus field length character
+ sta rdl ;and remember it
+ jmp remcom ;and branch to common code
+;
+; Remote Cd - Change Directory
+;
+remcd: lxi h,pswdms ;Second argument prompt
+ shld rprmpt ;...
+ mvi a,'C' ;Generic cd
+remcd0: sta remdat ;into packet
+ mvi a,1 ;Packet is at least one character long
+ sta rdl ;...
+ mvi a,'G' ;Generic command
+ sta rcom ;...
+ lxi d,remdat+2 ;Point to data buffer
+ call remcli ;Get filespec (if any) from command line
+ mov b,a ;Save answer length (may be zero)
+ adi space ;Make encoded field length
+ sta remdat+1 ;and store in packet data area
+ lda rdl ;Get length so far
+ add b ;Count answer length
+ adi 1 ;and field length character
+ sta rdl ;and remember current packet-size
+ lda remdat ;Get generic packet flavor
+ cpi 'C' ;Remote CD?
+ jnz remcd1 ;No
+ mov a,b ;Get length of possible directory spec
+ ora a ;Did the user give a directory spec?
+ jz remcom ;No, we can process the command immediately
+ mvi a,0ffH ;Yes, password follows, make it not echo
+ sta cmqflg ;...
+remcd1: lhld rprmpt ;Point to "password" prompt
+ xchg ;...
+ shld rptr ;Save data pointer
+ mvi a,0ffH ;Allow blank password
+ sta cmbflg ;...
+ call prompt ;Prompt the user
+ lhld rptr ;Restore data pointer
+ xchg ;...
+ inx d ;and increment it
+ call remcli ;Get user's answer
+ ora a ;Password given?
+ jz remcom ;No, proceed with command
+ mov c,a ;Yes, save answer length
+ adi space ;Convert to encoded field length
+ lhld rptr ;Get data pointer
+ mov m,a ;Put length in packet
+ lda rdl ;Get accumulated data length
+ adi 1 ;Count encoded field length
+ add c ;plus data length
+ sta rdl ;and remember packet-size
+ jmp remcom ;Branch to common code
+;
+; Remote Delete (Erase) command
+;
+remdel: mvi a,'E' ;Delete (Erase) command
+remdl0: sta remdat ;...
+ mvi a,1 ;At least one character in packet
+ sta rdl ;...
+ mvi a,'G' ;Generic command
+ sta rcom ;...
+ lxi d,remdat+2 ;Point to data field
+ call remcli ;Get filespec
+ mov b,a ;Save length
+ lda remdat ;Get packet type
+ cpi 'E' ;If Generic Delete
+ jz remdl1 ;We must have an argument
+ cpi 'T' ;Ditto for Generic Type
+ jz remdl1 ;...
+ mov a,b ;Else get back character count
+ ora a ;Answer typed?
+ jz remcom ;No, process packet as is
+remdl1: mov a,b ;Get character count again
+ ora a ;Anything typed?
+ jz kermt3 ;No, we must have an argument (Delete/Type)
+ adi space ;Yes, encode field length
+ sta remdat+1 ;and put in packet
+ lda rdl ;Get packet length so far
+ add b ;Count length of filespec
+ adi 1 ;Count field length character
+ sta rdl ;and store packet length
+ jmp remcom ;and do our stuff
+;
+; Remote Directory command
+;
+remdir: mvi a,'D' ;generic directory command
+ jmp remdl0 ;Do common code
+;
+; Remote Disk-usage (Space) command
+;
+remdsk: mvi a,'U' ;Disk-usage generic command
+ jmp remdl0 ;Do common code
+;
+; Remote Help command
+;
+remhep: mvi a,'H' ;generic help command
+ jmp remdl0 ;Do common code
+;
+; Remote Host command
+;
+remhos: mvi a,'C' ;Remote Host command
+remho0: sta rcom ;...
+ xra a ;Zero packet length
+ sta rdl ;...
+ lxi d,remdat ;Point to packet data buffer
+ call remcli ;Get host command
+ ora a ;Anything typed?
+ jz kermt3 ;No, don't let the user get away with this
+ sta rdl ;Yes, store packet length
+ jmp remcom ;and do the command
+;
+; Remote Kermit command
+;
+remker: mvi a,'K' ;Remote Kermit command
+ jmp remho0 ;Do common code
+;
+; Remote Login command
+;
+remlgi: mvi a,'G' ;Generic command
+ sta rcom ;...
+ mvi a,'I' ;Generic type
+ sta remdat ;into packet
+ mvi a,1 ;At least one character in packet
+ sta rdl ;...
+ lxi d,remdat+2 ;Point to data buffer
+ call remcli ;Get userid (if any) from command line
+ ora a ;Userid typed?
+ jz remcom ;No, nothing more to do
+ mov b,a ;Yes, save length
+ adi space ;Make encoded field length
+ sta remdat+1 ;and store in packet data area
+ lda rdl ;Get packet length
+ add b ;Count id length
+ adi 1 ;and field length character
+ sta rdl ;and remember accumulated length
+ xchg ;Save data pointer
+ shld rptr ;...
+ mvi a,0ffH ;Allow blank answers
+ sta cmbflg ;...
+ sta cmqflg ;Passwords don't echo
+ lxi d,pswdms ;Point to "password" prompt
+ call prompt ;Prompt the user
+ lhld rptr ;Get data pointer
+ xchg ;Put in DE
+ inx d ;Skip encoded field-length
+ call remcli ;Get password, if any
+ ora a ;Anything typed?
+ jz remcom ;No, do command immediately
+ mov c,a ;Yes, save answer length
+ adi space ;Convert to encoded field length
+ lhld rptr ;Get pointer
+ mov m,a ;Put length in packet
+ lda rdl ;Get accumulated data length
+ adi 1 ;Count encoded field length
+ add c ;Count "password" field length
+ sta rdl ;and remember new packet length
+ xchg ;Save data pointer
+ shld rptr ;...
+ xra a ;Allow echoing again for "account" field
+ sta cmqflg ;...
+ lxi d,acctms ;Point to "account" prompt
+ call prompt ;Prompt the user
+ lhld rptr ;Get data pointer
+ xchg ;into DE
+ inx d ;Skip encoded field length
+ call remcli ;Get "account" field, if any
+ ora a ;Anything typed?
+ jz remcom ;No, do the command now
+ mov c,a ;Yes, save length of answer
+ adi space ;Convert to encoded field length
+ lhld rptr ;Get data pointer
+ mov m,a ;Put length in packet
+ lda rdl ;Get accumulated data length
+ adi 1 ;Count encoded field length
+ add c ;plus "account" length
+ sta rdl ;and remember it
+ jmp remcom ;Branch to common code
+;
+; Remote Rename command
+;
+remren: lxi h,newfms ;Second argument prompt
+ shld rprmpt ;...
+ mvi a,'R' ;generic rename
+ jmp remcp0 ;Do common code
+;
+; Remote Message command
+;
+remmsg: lxi h,msgms ;Second argument prompt
+ shld rprmpt ;...
+ mvi a,'M' ;generic message
+ jmp remcp0 ;Do common code
+;
+;Remote Set command
+;
+remset: mvi a,6 ;Packet data area has at least six chars
+ sta rdl ;...
+ mvi a,'S' ;Remote Set command
+ sta remdat ;...
+ mvi a,'G' ;It's a generic command
+ sta rcom ;...
+ mvi a,'#' ;Encoded field-length for SET type
+ sta remdat+1 ;which is three chars long
+ lxi d,rmstab ;Point to Set command table
+ lxi h,rmshlp ;and the help table
+ call keycmd ;Find out which command is to be executed
+ xchg ;Put dispatch address in HL
+ pchl ;Go do the command
+;
+; Common code for Remote Set commands that take an argument
+;
+remscm: lxi d,remdat+6 ;We get an argument from the user
+ mvi a,cmtxt ;...
+ call comnd ;...
+ jmp kermt3 ;Couldn't get one.
+ ora a ;Did the user give one?
+ jz kermt3 ;a blank answer isn't acceptable
+ mov c,a ;Save length of answer
+ adi space ;Convert to encoded field-length
+ sta remdat+5 ;and put in packet data area
+ lda rdl ;Get current data length
+ add c ;Count length of answer
+ sta rdl ;and store new data length
+ call cfmcmd ;Get a "confirm"
+ jmp remcom ;Do common Remote command code
+;
+; Common code for Remote Set commands requiring another table lookup
+;
+remsc1: call chkkey ;Get user's selection
+ sta remdat+6 ;and put into the packet data area
+ mvi a,'!' ;Encoded field length for 1 char
+ sta remdat+5 ;Put in packet
+ lda rdl ;Get accumulated packet data length
+ adi 1 ;Count length of answer (1 char)
+ sta rdl ;and store as new packet data length
+ jmp remcom ;Go do common Remote command processing
+;
+; Remote Status (of server) command
+;
+remsta: call cfmcmd ;Get return
+ mvi a,'Q' ;Command type (Server Status)
+ sta remdat ;...
+ mvi a,'G' ;Generic Kermit command
+ sta rcom ;...
+ mvi a,1 ;1 character in packet
+ sta rdl ;...
+ jmp remcom ;Do common code
+;
+; Remote Type command
+;
+remtyp: mvi a,'T' ;generic type command
+ jmp remdl0 ;Do common code
+;
+; Remote Who command
+;
+remwho: lxi h,optms ;Second argument prompt
+ shld rprmpt ;...
+ mvi a,'W' ;generic who
+ jmp remcd0 ;Do common code
+
+; Common code for Remote commands
+;
+remcom:
+ mvi a,0ffH ; Make sure returned info is sent
+ sta remtxt ;to the user's screen rather than to a file
+ lda rcom ;Get packet-type
+ cpi 'G' ;Is it a generic command?
+ jnz remc0e ;No, go clear the screen
+ lda remdat ;Yes, get generic command type
+ cpi 'S' ;Is it a Remote Set command?
+ jz remc0f ;Yes, don't clear the screen
+remc0e: call clrtop ; clear the screen
+remc0f: xra a
+ sta numtry ; reset retries
+ sta czseen
+ sta pktnum
+ lxi h,0
+ shld numpkt
+ shld numrtr ; clear some variables
+
+ mvi a,'1' ; reset block check type
+ sta curchk
+remcm0: mvi a,'I' ; init state
+ sta state
+ call sinit ; do sendinit with I packet (??)
+ lda state ; now see if we are in the 'X' state
+ cpi 'X'
+ jz remco0 ;Yup, all is in order
+ cpi 'A' ;No, in abort state?
+ jnz remcm0 ;No, try I-packet again
+ jmp kermit ;Yes, like Danny Boy, we must die.
+ ;If we get this far, either the "I" packet
+ ;was understood or the Server couldn't
+ ;handle it and we ignored the error.
+ ;In either case, we can proceed.
+
+
+
+remco0: xra a
+ sta numtry ; reset retries
+ sta czseen
+ sta pktnum
+ lxi h,0
+ shld numpkt
+ shld numrtr ; clear some variables
+ mvi a,'1' ;Make sure we use
+ sta curchk ;1-character checksum
+ lda rdl ;Get packet-length (number of bytes to copy)
+ ora a ;Anything to copy?
+ jz remcm1 ;No
+ sta temp1 ;Yes, save loop counter
+ lda spsiz ;Get max packet size
+ sui 5 ;less overhead
+ sta temp2 ;gives max chars we can send
+ lxi d,remdat ;Copy from private buffer
+ lxi h,data ;to packet data area
+ lda qbchr ;Get eightgh-bit quoting prefix char
+ mov b,a ;Save it
+ lda squote ;Get control-char quoting char
+ mov c,a ;and save it
+remc0a: lda temp2 ;Get characters to go in packet
+ dcr a ;and decrement it
+ sta temp2 ;...
+ jm remc0x ;We can't copy any more
+ ldax d ;Get a packet data character
+ cpi space ;Is it a control char?
+ jm remc0b ;Yes, quote it
+ cmp c ;Is it the control-char prefix?
+ jz remc0b ;Yes, quote it
+ lda quot8 ;No, is eighth-bit quoting in effect?
+ ora a ;...
+ jz remc0c ;No, just copy the character
+ ldax d ;Get character again
+ cmp b ;Is it the eighth-bit quote char?
+ jnz remc0d ;No, just copy it
+remc0b: mov m,c ;Yes, quote the character
+ inx h ;Increment the dest. pointer
+ lda temp2 ;Get chars to go
+ dcr a ;Decrement
+ sta temp2 ;...
+ jm remc0x ;Can't copy any more
+ lda rdl ;Count quote prefix
+ inr a ;...
+ sta rdl ;...
+remc0c: ldax d ;Get character again
+ cpi space ;If not a control char,
+ jp remc0d ;just copy the character, else
+ adi 40H ;Convert to printing character
+ ani 7fH ;modulo 128
+remc0d: mov m,a ;Copy the character
+ inx h ;Increment the pointers
+ inx d ;...
+remc0x: lda temp1 ;Get loop counter
+ dcr a ;and decrement it
+ sta temp1 ;...
+ jnz remc0a ;Copy entire packet data area
+;
+remcm1: xra a
+ sta argblk ; set packet no zero
+ lda rdl ;Number of bytes in packet
+ sta argblk+1 ;into argument block
+ lda rcom ;Remote command
+ call spack ;Send the packet
+ jmp kermt3 ;Nogo, die!
+ jmp remco2 ;Try to get an answer
+
+remco1: call nak0 ;Nak packet
+;
+
+remco2: lda numtry ;Get number of retries
+ inr a ; update retries
+ cpi maxtry ;To many retries?
+ jm remc2a ;No
+ lxi d,erms28 ;Yes, complain
+ call prtstr ;...
+ jmp kermit ;and abort
+
+remc2a: sta numtry
+ call rpack ;Get a packet
+ jmp remco1 ;Couldn't get one.
+ cpi 'E' ;Error packet?
+ jnz remc2b ;No
+ lda rcom ;What kind of packet did we send?
+ cpi 'G' ;If it wasn't generic,
+ jnz remc2f ;there is no need to start a new message line
+ lda remdat ;Packet was generic
+ cpi 'S' ;Was it a Remote Set?
+ cz prcrlf ;Yes, start a new line since the screen
+ ;isn't blank and we would clobber the command-
+ ;line otherwise
+remc2f: call error0 ;Yes, inform the user
+ jmp kermit ;and abort to main command loop
+remc2b: cpi 'S' ;Send-init?
+ jnz remc2c ;No
+ call rini2a ;Initialize parameters
+ lda state ;Get state
+ cpi 'A' ;If abort,
+ jz kermit ;Go back to main command loop
+ mvi a,'X' ;Set state to text-display
+ sta state ;...
+ jmp read2 ;Get more packets
+remc2c: cpi 'N' ;Nacked packet?
+ jz remco2 ;Yes, try again
+ sta state ;Save packet type
+ call selcon ;Select Console
+ lxi h,data ;Point to data
+ lda argblk+1 ;Anything in packet data?
+ ora a ;...
+ jz remco6 ;No
+ push h ;Yes, save pointer
+ push psw ;and character count
+ mvi e,'<' ;Type "<<" as in VMSKermit
+ push d ;...
+ call outcon ;...
+ pop d ;...
+ call outcon ;...
+ pop psw ;Restore character counter
+ pop h ;and data pointer
+remc2d: ora a ;...
+ jz remc2e ;No more characters
+ dcr a ;Decrement loop counter
+mov e,m ;Get character
+ inx h ;Increment pointer
+ push psw ;Save loop counter
+ push h ;Save data pointer
+ call outcon ;Type on Console
+ pop h ;Restore pointer
+ pop psw ;Restore loop counter
+ jmp remc2d ;Type all packet data
+remc2e: mvi e,'>' ;Type ">>" as in VMSKermit
+ push d ;...
+ call outcon ;...
+ pop d ;...
+ call outcon ;...
+ call prcrlf ;End the line
+remco6: lda state ;Get packet type again
+ cpi 'Y' ;If simple ack,
+ jz kermit ;Done, else
+ call ackp ;Acknoledge the packet
+ call countp ;Count the packet
+ mvi a,'D' ;Set to data-receive
+ sta state ;...
+ jmp read2 ; do the same as read a file, but echo
+ ; to the screen.. Dont close non-open files.
+;
+;
+;REMCLI - Get command-line for Remote commands
+;
+remcli: xra a ;Zero accumulated length
+ sta rcl ;...
+ mov b,a ;[12]...
+;
+;[MF][12]Eliminate following code which calls "comnd" in favor of code which
+;[MF][12]calls "cmgtch" directly so that characters are sent without
+;[MF][12]alteration or inadvertent action ("?" or <esc>). The only thing
+;[MF][12]lost is the ability to produce any ASCII character via
+;[MF][12]octal numbers prefixed with "\" but this isn't used much in remote
+;[MF][12]commands anyway.
+;
+;remcl0: mvi a,cmtxt ;We get arbitrary text
+; call comnd ;from the command-line
+; jmp kermt3 ;We couldn't get any.
+; ora a ;Anything given?
+; jz remcl1 ;No, done
+; push b ;Save BC
+; mov c,a ;Save length
+; lda rcl ;Get accumulated length
+; add c ;plus current word length
+; adi 1 ;plus a space
+; sta rcl ;and save accumulated length
+; mvi a,space ;Put in a space separator
+; stax d ;...
+; inx d ;Increment pointer
+; pop b ;Restore BC
+; jmp remcl0 ;Get text to end-of-line
+;remcl1: lda rcl ;Get accumulated length
+; ora a ;Anything typed?
+; rz ;No
+; dcr a ;Yes, don't count final space
+; push psw ;Save count
+; dcx d ;Point to final space
+; xra a ;Zap it
+; stax d ;...
+; pop psw ;Restore count
+;
+;[MF][12]Simplified code follows
+;
+remcl0: call cmgtch ;[12]Get a character from the user
+ ani 7fh ;[12]Turn off minus bit
+ cpi cr ;[12]If end-of-line,
+ jz remclx ;[12]We're done
+ cpi lf ;[12]...
+ jz remclx ;[12]...
+ stax d ;[12]else store the character
+ inr b ;[12]and count it
+ inx d ;[12]Increment character buffer pointer
+ cpi esc ;[12]is character an <esc>?
+ jz remcl2 ;[12]Yes
+ cpi ff ;[12]an <ff>?
+ jz remcl1 ;[12]Yes, diddle command buffer pointer
+ cpi '?' ;[12]a "?"?
+ jnz remcl0 ;[12]No, just get more characters
+remcl1: push h ;[12]Protect HL
+ lhld cmdptr ;[12]get "cmgtch"'s character pointer
+ inx h ;[12]and reverse the action at "cmgtc4"
+ ;[12]since we don't need a "confirm" and
+ ;[12]infinite loops are beaucoup bad news
+ shld cmdptr ;[12]...
+ pop h ;[12]Restore HL
+remcl2: push psw ;[12]Save the character
+ xra a ;[12]Zero the action flag so we get input
+ sta cmaflg ;[12]to end-of-line without special action
+ pop psw ;[12]Restore the character
+ jmp remcl0 ;[12]Get more characters
+remclx: mov a,b ;[12]Get accumulated text length
+ sta rcl ;[12]and remember it
+;
+ ret ;Return
+;
+;Remote set values
+;
+; REMOTE SET FILE TYPE 300 0 = TEXT, 1 = BINARY
+; REMOTE SET FILE NAMES 301 0 = CONVERTED, 1 = LITERAL
+; REMOTE SET FILE COLLISION 302 0 = RENAME, 1 = OVERWRITE,
+; 2 = BACKUP, 3 = APPEND,
+; 4 = DISCARD, 5 = ASK
+; REMOTE SET FILE REPLACE 303 0 = PRESERVE, 1 = DEFAULT
+; REMOTE SET FILE INCOMPLETE 310 0 = DISCARD, 1 = KEEP
+; REMOTE SET INCOMPLETE (same as above)
+; REMOTE SET BLOCK-CHECK 400 number (1, 2, or 3)
+; REMOTE SET RECEIVE PACKET-LENGTH 401 number (10-9024)
+; REMOTE SET RECEIVE TIMEOUT 402 number (any, 0 = no timeout)
+; REMOTE SET RETRY 403 number (any, 0 = no limit)
+; REMOTE SET SERVER TIMEOUT 404 number (any, 0 = no timeout)
+;REMOTE SET FILE BLOCKSIZE 311 number
+;REMOTE SET FILE RECORD-LENGTH 312 number
+;REMOTE SET FILE RECORD-FORMAT 313 F (fixed), V (variable), etc...
+;This is just for the record, to assign these numbers to these commands
+;for somebody who needed them. Details to be filled in later.
+;
+;Remote Set command table
+;
+rmstab: db 7 ;seven entries
+ db 16,'BLOCK-CHECK-TYPE$'
+ dw remsbc ;Remote Set Block Check
+ db 4,'FILE$'
+ dw remsfl ;Remote Set File
+ db 10,'INCOMPLETE$'
+ dw remsfi ;Remote Set (file) Incomplete
+ db 7,'RECEIVE$'
+ dw remsrc ;Remote Set Receive
+ db 7,'REPLACE$'
+ dw remsfr ;Remote Set (file) Replace
+ db 5,'RETRY$'
+ dw remsry ;Remote Set Retry
+ db 14,'SERVER-TIMEOUT$'
+ dw remsst ;Remote Set Server Timeout
+;
+rmshlp: db cr,lf,'BLOCK-CHECK-TYPE for a remote server'
+ db cr,lf,'FILE parameters for a remote server'
+ db cr,lf,'INCOMPLETE file disposition for a remote server'
+ db cr,lf,'RECEIVE parameters for a remote server'
+ db cr,lf,'REPLACE file attribute handling for a remote server'
+ db cr,lf,'RETRY maximum for a remote server'
+ db cr,lf,'SERVER-TIMEOUT interval for a remote server'
+ db '$'
+;
+;Remote Set File tables
+;
+rsftab: db 8 ;eight entries
+ db 10,'BLOCK-SIZE$'
+ dw remsbs ;Remote Set File Block-size command
+ db 9,'COLLISION$'
+ dw remsfc ;Remote Set File Collision command
+ db 10,'INCOMPLETE$'
+ dw remsfi ;Remote Set File Incomplete command
+ db 5,'NAMES$'
+ dw remsfn ;Remote Set File Names command
+ db 13,'RECORD-FORMAT$'
+ dw remsrf ;Remote Set File Record-format
+ db 13,'RECORD-LENGTH$'
+ dw remsrl ;Remote Set File Record-length
+ db 7,'REPLACE$'
+ dw remsfr ;Remote Set File Replace command
+ db 4,'TYPE$'
+ dw remsft ;Remote Set File Type command
+;
+rsfhlp: db cr,lf,'BLOCK-SIZE of files for a remote server'
+ db cr,lf,'COLLISION action on filename conflicts for a remote'
+ db ' server'
+ db cr,lf,'INCOMPLETE file disposition for a remote server'
+ db cr,lf,'NAMES translation of files for a remote server'
+ db cr,lf,'RECORD-FORMAT of files for a remote server'
+ db cr,lf,'RECORD-LENGTH for a remote server'
+ db cr,lf,'REPLACE file attribute handling for a remote server'
+ db cr,lf,'TYPE of files for a remote server'
+ db '$'
+;
+;Remote Set File Record-format tables
+;
+rcftab: db 2 ;two entries
+ db 5,'FIXED$'
+ db 'F','F' ;Remote Set File Record-format Fixed command
+ db 8,'VARIABLE$'
+ db 'V','V' ;Remote Set File Record-format Variable cmd
+;
+rcfhlp: db cr,lf,'FIXED VARIABLE'
+ db '$'
+;
+;Remote Set Receive tables
+;
+rrctab: db 2 ;two entries
+ db 13,'PACKET-LENGTH$'
+ dw remrpl ;Remote Set Receive Packet-length command
+ db 7,'TIMEOUT$'
+ dw remsrt ;Remote Set Receive Timeout command
+;
+rrchlp: db cr,lf,'PACKET-length TIMEOUT'
+ db '$'
+;
+;Remote Set File-collision table
+;
+rfctab: db 6 ;six entries
+ db 6,'APPEND$'
+ db '3','3' ;Set collision append
+ db 3,'ASK$'
+ db '5','5' ;Set collision ask
+ db 6,'BACKUP$'
+ db '2','2' ;Set collision backup
+ db 7,'DISCARD$'
+ db '4','4' ;Set collision discard
+ db 9,'OVERWRITE$'
+ db '1','1' ;Set collision overwrite
+ db 6,'RENAME$'
+ db '0','0' ;Set collision rename
+;
+rfchlp: db cr,lf,'ASK about existing files on a remote system'
+ db cr,lf,'APPEND to existing files on a remote system'
+ db cr,lf,'BACKUP (rename) existing files on a remote system'
+ db cr,lf,'DISCARD new versions of existing files on a'
+ db ' remote system'
+ db cr,lf,'OVERWRITE existing files on a remote system'
+ db cr,lf,'RENAME new versions of existing files on a'
+ db ' remote system'
+ db '$'
+;
+;Remote Set File-Incomplete tables
+;
+rfitab: db 2 ;2 entries
+ db 7,'DISCARD$'
+ db '0','0' ;Remote Set File Incomplete Discard
+ db 4,'KEEP$'
+ db '1','1' ;Remote Set File Incomplete Keep
+;
+rfihlp: db cr,lf,'DISCARD KEEP'
+ db '$'
+;
+;Remote Set File-Names tables
+;
+rfntab: db 2 ;two entries
+ db 9,'CONVERTED$'
+ db '0','0' ;Remote Set File Names Converted
+ db 7,'LITERAL$'
+ db '1','1' ;Remote Set File Names Literal
+;
+rfnhlp: db cr,lf,'CONVERTED LITERAL'
+ db '$'
+;
+;Remote Set File Replace tables
+;
+rfrtab: db 2 ;two entries
+ db 8,'PRESERVE$'
+ db '0','0' ;Remote Set File Replace Preserve
+ db 7,'DEFAULT$'
+ db '1','1' ;Remote Set File Replace Default
+;
+rfrhlp: db cr,lf,'PRESERVE DEFAULT'
+ db '$'
+;
+;Remote Set File Type tables
+;
+rfttab: db 2 ;two entries
+ db 6,'BINARY$'
+ db '1','1' ;Remote Set File Type Binary
+ db 4,'TEXT$'
+ db '0','0' ;Remote Set File Type Text
+;
+rfthlp: db cr,lf,'BINARY TEXT'
+ db '$'
+;
+; Remote Set Block-check
+;
+remsbc:
+IF lasm
+ lxi h,'40' ;1st 2 chars of "400"
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'04'
+ENDIF ;NOT lasm
+ shld remdat+2 ;Store in correct order
+ mvi a,'0' ;Put last char of type in buffer
+ sta remdat+4 ;...
+ lxi d,blktab ;Point to block-check table
+ lxi h,blkhlp ;and help table
+ jmp remsc1 ;Do common code
+;
+;Remote Set File command
+;
+remsfl: lxi d,rsftab ;Point to Remote Set File tables
+ lxi h,rsfhlp ;...
+remsf0: call keycmd ;Get user's selection
+ xchg ;Put dispatch address in HL
+ pchl ;and obey the user's most fervent desires
+;
+;Remote Set Receive command
+;
+remsrc: lxi d,rrctab ;Point to the appropriate tables
+ lxi h,rrchlp ;...
+ jmp remsf0 ;and do command
+;
+;Remote Set Block-size command
+;
+remsbs:
+IF lasm
+ lxi h,'31' ;1st 2 chars of Set code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'13'
+ENDIF ;NOT lasm
+ shld remdat+2 ;Store chars in correct order
+ mvi a,'1' ;Put last char in buffer
+ sta remdat+4 ;...
+ jmp remscm ;and do common Remote Set code
+;
+;Remote Set File-collision command
+;
+remsfc:
+IF lasm
+ lxi h,'30' ;Put set type code in buffer
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'03'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'2' ;...
+ sta remdat+4 ;...
+ lxi d,rfctab ;Point to tables
+ lxi h,rfchlp ;...
+ jmp remsc1 ;and do common code
+;
+;Remote Set File Incomplete command
+;
+remsfi:
+IF lasm
+ lxi h,'31' ;Establish command keyword code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'13'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'0' ;...
+ sta remdat+4 ;...
+ lxi d,rfitab ;Point to tables
+ lxi h,rfihlp ;...
+ jmp remsc1 ;and do common code
+;
+;Remote Set File-Names command
+;
+remsfn:
+IF lasm
+ lxi h,'30' ;Set command code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'03'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'1' ;...
+ sta remdat+4 ;...
+ lxi d,rfntab ;Point to the appropriate tables
+ lxi h,rfnhlp ;...
+ jmp remsc1 ;and do common code
+;
+;Remote Set File Record Format command
+;
+remsrf:
+IF lasm
+ lxi h,'31' ;Set command code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'13'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'3' ;...
+ sta remdat+4 ;...
+ lxi d,rcftab ;Point to proper tables
+ lxi h,rcfhlp ;...
+ jmp remsc1 ;and do common code
+;
+;Remote Set File Record Length command
+;
+remsrl:
+IF lasm
+ lxi h,'31' ;Set command code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'13'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'2' ;...
+ sta remdat+4 ;...
+ jmp remscm ;and do common code
+;
+;Remote Set File Replace command
+;
+remsfr:
+IF lasm
+ lxi h,'30' ;Set command code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'03'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'3' ;...
+ sta remdat+4 ;...
+ lxi d,rfrtab ;Point to tables
+ lxi h,rfrhlp ;...
+ jmp remsc1 ;and do common code
+;
+;Remote Set File Type command
+;
+remsft:
+IF lasm
+ lxi h,'30' ;Set command code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'03'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'0' ;...
+ sta remdat+4 ;...
+ lxi d,rfttab ;Point to tables
+ lxi h,rfthlp ;...
+ jmp remsc1 ;and go to common code
+;
+;Remote Set Receive Packet-length command
+;
+remrpl:
+IF lasm
+ lxi h,'40' ;Set command code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'04'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'1' ;...
+ sta remdat+4 ;...
+ jmp remscm ;and do common code
+;
+;Remote Set Receive Timeout command
+;
+remsrt:
+IF lasm
+ lxi h,'40' ;Set code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'04'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'2' ;...
+ sta remdat+4 ;...
+ jmp remscm ;and do common code
+;
+;Remote Set Retry command
+;
+remsry:
+IF lasm
+ lxi h,'40' ;Set code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'04'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'3' ;...
+ sta remdat+4 ;...
+ jmp remscm ;Go to common code
+;
+;Remote Set Server Timeout command
+;
+remsst:
+IF lasm
+ lxi h,'40' ;Set code
+ENDIF ;lasm
+IF NOT lasm
+ lxi h,'04'
+ENDIF ;NOT lasm
+ shld remdat+2 ;...
+ mvi a,'4' ;...
+ sta remdat+4 ;...
+ jmp remscm ;Do common code
+
+
+
+
+
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FOR RELEASE
+
+; ORG ($+100H) AND 0FF00H
+
+
+IF lasm
+ LINK CPSSER
+ENDIF ;lasm
diff --git a/src/cpsser.asm b/src/cpsser.asm
new file mode 100644
index 0000000..d49ebe0
--- /dev/null
+++ b/src/cpsser.asm
@@ -0,0 +1,44 @@
+; CPSSER.ASM
+; 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
+; 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-independent) routines that implement
+; the SERVER part of the KERMIT protocol.
+;
+; revision history:
+;
+;
+; edit 1: September, 1987. Created CPSSER.ASM from bits from the two CPSPK?
+; files.
+; The code herein is to allow remote systems to communicate to
+; this Kermit running in SERVER mode. Note that not every server
+; command will be supported, mind...
+;
+server: db 'CPSSER.ASM (1) 8-SEP-87$' ; name, edit number, date
+
+
+
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FOR RELEASE!
+
+; org ($+100h) AND 0FF00H
+
+
+IF lasm
+ LINK CPSTT
+ENDIF;lasm
diff --git a/src/cpstt.asm b/src/cpstt.asm
new file mode 100644
index 0000000..41a30af
--- /dev/null
+++ b/src/cpstt.asm
@@ -0,0 +1,862 @@
+; CPSTT.ASM
+; 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 code for the TRANSMIT and CONNECT commands,
+; which communicate with a host which is not running KERMIT.
+;
+; revision history:
+;
+;edit 12, 31-Jan-1991 by MF. Delete call to "inbuf" after "xmit1" in
+; the TRANSMIT command. "getfil" initializes various counters so that
+; when "in1chr" is first called, "inbuf" will be called immediately
+; and will read sectors of the file to be transmitted from disk.
+; This, along with a fix to "in1chr" in CPSUTL.ASM, fixes a bug
+; discovered by Lance Tagliapietra of the University of Wisconsin at
+; Platteville wherein the TRANSMIT command was failing to transmit some
+; characters in files over one sector in length. See CPSUTL.ASM,
+; edit 29.
+; edit 11, 10 September, a987, by OBSchou. Modified TRANSMIT command
+; to TRANSMIT <file> <string>
+;
+; edit 10, 27 August, 1987 by OBSchou. Fixed bugs in Transmit, but I may
+; be introducing problems for IBM/CMS or half duplex systems. What
+; does this combination do??
+;
+; edit 9 30 March, 1987 by OBSchou to replace the TRANSMIT routine.
+; Syntax is now TRANSMIT file after a previous
+; INPUT <wait time> <string to wait for>
+;
+; edit 8 19 June, 1986 by OBSchou. Modified the interupt testing routine
+; to see if the command was a 'D' (Drop the line), in which case also
+; do a 'C', ie disconnect. This is really a little too much of a
+; system dependent thing.
+; For now, Ill leave it here, and possibly move it later.
+;
+; edit 7 30 May 1986 OBSchou. Moved xon/xoff control (ie XON/OFF sent to host)
+; out to CPSUTL so that ther printer routine can use it too.
+;
+; edit 6 30 April, 1986 by OBSchou.
+; Fixed transmit bug, so as soon as the protocol character is
+; received from the host is received then another line is sent.
+; added in a comchr (ds 1) to save the character read from the comm
+; line in prtchr, and is restored in a on return.
+;
+; edit 5 7 March, 1986 by OBSchou Loughborough University.
+; Need to save the E register before calling outmdm (in CPSSYS.ASM)
+; if doing Half duplex. Push/pop DE should sort this problem
+;
+; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
+;
+;pcc002 28-Dec-84 modules:cp4tt,cp4utl
+; Add connect mode <esc>P command to toggle printer on
+; and off. Conflicts with "official" recommended commands
+; in protocol manual, but I don't think CP/M will ever get
+; a PUSH command.
+;
+;pcc003-pcc005 2-Jan-85 vjc modules:cp4mit,cp4tt,cp4utl
+; These edits must all be installed together and change the way
+; logging is handled. The log file spec is moved to a separate
+; fcb, and not opened until an actual CONNECT command is given.
+; This takes care of a NASTY bug that if you used any other file
+; command between the LOG and CONNECT, the log file would get
+; written over the last file used. This also allows logging to
+; be "permanently" enabled until an CLOSE (new command) for all
+; CONNECT sessions, like most other kermits do. If a log file
+; already exists, it will be appended to. Also add two new
+; CONNECT mode commands <esc>Q to suspend logging and <esc>R to
+; resume. <esc>R means something else during TRANSMIT, but
+; logging is never on then, so there shouldn't be any conflict.
+; I also changed the write code, so that it can handle one more
+; character after the XOFF is send to stop the host. This allows
+; a little "slop" for systems that don't stop immediately (such
+; as TOPS10), but it didn't help much.
+;
+;pcc008 2-Jan-85 vjc modules:cp4def,cp4tt,cp4utl
+; Keyboard input during CONNECT mode can get locked out if
+; there is enough input from the modem port to keep prtchr
+; busy. This can happen for example, if the printer is running
+; at the same speed as the modem line, leaving you helpless to
+; turn it off or abort the host. Add a fairness count, so that
+; at least every prfair characters we look at console input.
+;
+;pcc012 4-Jan-85 vjc modules:cp4mit,cp4tt,cp4utl
+; Use the big buffer for the log file. Move the log file back
+; into the common fcb and only save the drive, name, and
+; extension between connects. Add new routines to cp4utl to
+; create or append to an existing file, and to conditionally
+; advance buffers only if in memory. Remove edit pcc003 that
+; allows one more character after the xoff, since it didn't
+; really work very well and does not fit in well with the way
+; the buffer advancing routines are set up. If someone still
+; thinks this would be useful, it could be put back in with a
+; little more work.
+;
+; While testing this edit, I also noticed another bug that
+; the command parsing routines do not limit or check the
+; length of command lines or file specs, trashing what ever
+; comes after them. Currently because of where the fcb and
+; command buffer are located, this does not usually cause a
+; problem, but could if an extremely long line was typed in,
+; or in the future multiple fcbs defined elsewhere in memory
+; were used. Maybe this should be put on the bug list
+; somewhere.
+;
+; edit 3: July 27, 1984
+; Allow assembly with LASM: to CP4TT is linked by CP4PKT, and links
+; to CP4CPM; remove exclamation points so as not to confuse LASM.
+; Add Toad Hall TACtrap to TRANSMIT command (TAC intercept character
+; is only doubled if it's data; when typed by the user, they're not
+; automatically doubled)
+;
+; edit 2: June 7, 1984
+; formatting and documentation; add module version number; make sure
+; console is selected when leaving intchr.
+;
+; edit 1: May, 1984
+; extracted from CPMBASE.M80 version 3.9; modifications are described
+; in the accompanying .UPD file.
+
+ttver: db 'CPSTT.ASM (12) 31-Jan-1991$'
+
+; This is the TRANSMIT command. It attempts to send a file, even
+; though there is no KERMIT on the other side.
+; here from: kermit
+;
+; [OBS] I have replaced the routine, so that TRANSMIT <filename> <wait string>
+; will send a line at a time to the host in a manner similar to MSKERMIT
+;
+;
+xmit: mvi a,cmofi ;Parse an input file spec (non-wild).
+ lxi d,fcb ;Give the address for the FCB.
+ call comnd
+ jmp kermit ;Give up on bad parse.
+;
+ lxi d,stbuff ; where to put the string
+ mvi a,cmtxt ; get text
+ call comnd
+ jmp kermit ; not quite correct...
+ sta strcnt ; string count returned in a
+ ana a ; if its zero, make it 1 character (CR)
+ jnz xmit0
+ mvi a,1
+ sta strcnt
+ mvi a,cr
+ sta stbuff
+;
+xmit0: call cfmcmd
+ call getfil ;Open file.
+ cpi 0FFH ;Succeed?
+ jnz xmit1
+ lxi d,erms15
+ call prtstr ;Display error msg.
+ jmp kermit
+
+;
+; New TRANSMIT routine - transmit a file, line by line, to a remote host
+; waiting each time for one or more characters to be returned
+; as a remote host prompt. It could be as simple as a CR or LF
+; character. Repeat until the complete file has been sent, then
+; close the transmitted file, and drop into the connect state so the
+; user can tidy up at the host end.
+;get the file to send, open it up, and read first sector from disk
+
+xmit1: lxi d,inms19 ; say we are send a file to the host
+ call prtstr
+
+ xra a
+ sta repcnt ; clear the host prompt chars. counter
+ sta starc ; clear star count
+;[MF][12]Delete the following call to "inbuf" as the call to "getfil"
+;[MF][12]above will have initialized counters and flags so that when
+;[MF][12]"in1chr" is called, "inbuf" will be called immediately and will
+;[MF][12]immediately read from disk. Counters and flags will then be
+;[MF][12]properly set up to read all characters of the file to be
+;[MF][12]transmitted.
+; call inbuf ; read one sector from disk
+; jmp xmtex ; exit if error
+
+
+xmt10: xra a ; clear retransmit flag and count etc
+ sta rexbfl ; retransmit flag (1=> retransmit)
+ sta rexcnt ; character counter
+
+xmt1: call xmt1ch ; send a character
+ ani 7fh ; strip any parity
+ cpi cr ; have we reached the end of the line
+ jnz xmt1 ; nope, loop around again
+
+; Now wait for a string back from the host. Compare with STRING buffer
+;
+ xra a ; clear the character count
+ sta rexcnt
+;
+ call selcon ; sent a line, send a star to console
+ mvi e,'*'
+ call outcon
+ lda starc ; update star count
+ inr a
+ sta starc
+ cpi 60 ; sent 60 stars?
+ jnz xmt1a ; nope...
+ xra a
+ sta starc
+ call prcrlf
+xmt1a:
+
+xmt3: lda eoflag ; have we hit end of file?
+ ana a
+ jnz xmtex ; yup, so quit.
+ xra a
+ sta repcnt ; clear the host prompt chars.counter
+xmt2: call rd1chl ; read a character from the line
+ ani 7fh ; set flags
+ jnz xmt4 ; Not zero => we have a character from host
+ call ckchr ; see if *WE* have a character from console
+ push psw ; restore to modem
+ call selmdm
+ pop psw
+ ani 7fh ; stip parity (should not be there)
+ jnz xmt2a ; if a null, try again
+ lda strcnt ; if the string length is zero, dont wait.
+ ana a
+ jz xmt1 ; so loop back again
+ jmp xmt4 ; else test for xon/off and incomming string
+
+xmt2a: cpi cntlc ; do we want to abort?
+ jz xmtex ; in which case drop through to connect mode
+ cpi cntlz ; if control z exit back to command loop
+ jnz xmt2b ; else try for other characters
+ lxi d,fcb ; close file before exiting to command loop
+ mvi c,closf
+ call bdos
+ jmp kermit
+
+xmt2b: cpi cr ; a cr => resend last line
+ jnz xmt2 ; nope, then ignore it
+ mvi a,1
+ sta rexbfl ; else we want to resend the line.
+ jmp xmt1
+
+xmt4: jmp xmt6 ; skit xoff test for now...*****************
+
+ cpi xoff ; xoff from host?
+ jnz xmt6
+xmt5: call rd1chl ; else see if XOFF comming
+ ani 7fh
+ jnz xmt6 ; assume an xoff
+ call ckchr ; anything at console?
+ push psw
+ call selmdm
+ pop psw
+ ani 7fh
+ cpi cntlc ; control-c == abort & play terminal
+ jz xmtex
+ ana a ; anything else?
+ jz xmt5 ;loop again
+
+xmt6: mov e,a ; save it for a while
+ lda repcnt ; see if this character matches with one in buffer
+ lxi h,stbuff ; point to string buffer
+ add l ; make hl = hl + a
+ mov l,a
+ mvi a,0
+ adc h
+ mov h,a ; not using xra, as that clears the Carry flag
+ mov a,e ; get the character back again
+ cmp m ; is it = to what we expect?
+ jnz xmt3 ; no, clear counter and try again
+ lda repcnt ; yes, then update the pointer, and ...
+ inr a ; ... see if we have received all ...
+ sta repcnt ; ... we should have received
+ mov e,a ; save length into E again
+ lda strcnt ; get the length to compare
+ sub e ; if (e) > string length, we have it
+ jz xmt10 ; so send next line (clear counters etc)
+ jmp xmt2 ; else wait for a little longer
+
+
+;
+; Routine below sends a character to the line. It sends up to a CR, and then
+; it waits for a reply. This routine is called from xmt1, so if at
+; end of file, return. Then XMT1 will drop through
+; to connect.
+xmt1ch: ; send a character from the xmtbuf to the line
+ call selmdm ; just in case it uses it
+ lda eoflag ; have we hit end of file
+ ana a ; set flags
+ jnz xmt1c1 ; no, so dont...
+ mvi a,cr ; load up a carriage return
+xmt1c1: call get1xc ; get the character to send
+ cpi lf ; dont send line feeds
+; jz xmt1c1
+ cpi cntlz ; if control z, then we are at end of the file
+ jz xmtex ; so close the file and drop into telcon
+ cpi 20h ; control character?
+ jp xmt11 ; no, so ok
+ cpi cr ; cr, and tabs ok to send
+ jz xmt11
+ cpi tab
+ jz xmt11
+ jmp xmt1c1 ; else try for another character
+
+xmt11: call setpar ; else set parity etc
+ push psw ; we want to keep this for a while
+ mov e,a ; we need character in e
+ call outmdm
+ pop psw ; restore the character we sent
+ mov e,a ; now, if a TAC is set on..
+ lda tacflg
+ ana a
+ mov a,e ; (return must have sent character in a)
+ jz xmt1c2 ; test for xon/off
+ lda tacchr ;... get the tac character
+ cmp e ; do we send it again?
+ jnz xmt1c2 ; test for xon/off
+ push psw ; save character for return. Already set E...
+ call outmdm
+ pop psw
+
+xmt1c2: ret
+
+get1xc: ; get a character from the sector or re-transmit buffer read
+; into a. Read a new sector if we run out.
+;
+; First, see if we do a retransmit
+ lda rexbfl
+ ana a ; if zero, a genuine line
+ jz get1x1
+; have to retransmit a line
+ lxi h,rexbuf
+ lda rexcnt ; add counter to buffer base
+ mvi d,0
+ mov e,a
+ dad d
+ inr a ; update pointer
+ sta rexcnt
+ mov a,m ; get next character to send
+ ret ; and exit
+
+get1x1: call in1chr ; get a character from the file.
+ mov c,a ; save it to the retransmit buffer
+ lda rexcnt
+ mov e,a
+ mvi d,0
+ lxi h,rexbuf
+ dad d ; point to next position
+ inr a
+ sta rexcnt ; update the character pointer
+ mov a,c ; restore character to a
+ mov m,c ; get character to c
+ ret
+
+
+
+; read a character from the line.
+rd1chl:
+ call selmdm ; select the modem
+ call inpmdm ; get input from the modem
+ ani 7fh ; strip parity
+ ; may UPPERCASE-ify if case sensitivity off
+ ret ; return to caller
+
+; End of transmit routine. Close input file name, and say we are dropping
+; throught to telnet. Note that if eof not found, it is assumed that
+; this is the ABORT exit.
+
+xmtex:
+ lxi d,fcb ; close the transmitted file
+ mvi c,closf
+ call bdos
+ call selcon ; make sure we are talking to the console
+
+ lda eoflag ; end of file or abort exit?
+ lxi d,inms22 ; assume eof...
+ ana a
+ jz xmtex1
+ lxi d,inms29 ; we were wrong, its an abort.
+xmtex1: jmp telnt1 ; and drop through to connect mode
+ ; telnet does the printing
+
+
+
+;
+; telnet - the CONNECT command.
+; here from: kermit
+; telnt1 - entry to connect mode from TRANSMIT command
+; here from: xend
+
+telnet: call cfmcmd
+ lxi d,infms7 ;Output start of message
+; enter here from TRANSMIT command.
+telnt1: call prtstr
+ call escpr ;Print the escape char.
+ lxi d,infms8 ;Output some more of the message
+ call prtstr
+ call escpr ;Print the escape char again.
+ lxi d,inms8a ;Print the remainder of the message
+ call prtstr
+ call syscon ;do system-dependent stuff
+ lda logflg ;[pcc005] Want a log?
+ ora a ;[pcc005]
+ cnz logopn ;[pcc005] Open if so
+
+chrlup: call prtchr ;See if char at port (send to console).
+ call conchr ;See if char at console (send to port).
+ jmp kermit ;requested to end session - go to command loop.
+ jmp chrlup ;Go do it again.
+;
+;
+; prtchr - copy characters from comm line to console
+; returns: nonskip, console selected.
+; called by: xnext, rexmit, telnet
+;
+
+prtchr: call selmdm ; select modem port
+ call inpmdm ; try to get a character from it
+ push psw ; restore to console
+ call selcon ; select console
+ pop psw ; restore the (possible character) read
+ ora a ; test character
+ jnz prtch0 ; if non-zero, process it.
+ sta prtcnt ;[pcc008] zero out prt fairness count
+ ret ; return.
+
+prtch0: ani 7FH ; drop parity bit.
+ sta comchr ;[6] save it in case we need it again
+ lda vtflg ;[9] get the vt52 emulation flag
+ cpi vtdefe ;[9] are we doing external emulation?
+ lda comchr ;[9] collect character again
+ jz extern ;[9] jup, go do it.
+
+ ana a ; set flags. it may be a null
+ jz prtchr ; ignore null (filler)
+ cpi del ; ignore delete, too
+ jz prtchr
+ cpi xon ;Is it an XON?
+ jz prtxon ;yes
+ cpi xoff ;Is it an XOFF?
+ jz prtxof ;yes
+ mov e,a ;Set the char aside.
+ lda vtflg ;Get the VT52 emulation flag.
+ cpi vtdefv ;Is the flag set for VT52 (ie 1)
+ ;0 = none
+ ;1 = VT52
+ ;2 = external
+ ;3 = dumb (traps non printing chars)
+ ;0ffh not possible by local code (Will change)
+ jnz prtch1 ;If not, don't do this stuff.
+ lda escflg ;Get the escape flag.
+ ora a ;Are we working on an escape sequence?
+ jz prtch2 ;If not, continue.
+ call vt52 ;If so, work on it some more
+ jmp prtchr ;try for more characters.
+
+prtch2: mov a,e ;normal text.
+ cpi esc ;Is the char an escape?
+ jnz prtch1 ;If not skip on.
+ mvi a,1
+ sta escflg ;Set the escape flag: escape seen.
+ jmp prtchr ;Get another char...
+
+prtch1: cpi vtdefe ; are we doing external emulation?
+ jnz prtch3 ; assume we continue on
+ lxi h,extern+1 ; get address of external emulator
+ mov a,h ; se if address = 0 (not implemented)
+ ora l
+ jz prtch3 ; not external, assume we just carry on
+ pchl ; go do external emulation. RET back to caller
+
+prtch3: cpi vtdefd ; are we trapping all non printing characters?
+ jnz prtch4 ; nope, something else
+ lda comchr ; Dumb terminal. Lets test the character
+ cpi cr ; cr then ok
+ jz prtch4 ; its ok
+ cpi lf ; lf then ok
+ jz prtch4
+ cpi tab
+ jz prtch4 ; assume tabs are expanded
+ cpi space ; if less than 20H ignore it
+ rm ; return if a control character
+
+prtch4: call sysflt ; ok to print this character (in E)?
+ ora a
+ jz prtchr ; no, skip it.
+ lda logflg ;Get the log flag.
+ cpi 81H ;[pcc003] Are we logging
+ cz logit ;[pcc003] Do so if needed
+ call selcon ; select console
+ lda prnflg ;Get Print parallel flag
+ ora a
+ cnz outlpt ; output to printer if flag set
+ call outcon ; output to console.
+ lxi h,prtcnt ;[pcc008] point to prt fairness count
+ inr m ;[pcc008] bump
+ mov a,m ;[pcc008] get it in a
+ cpi prfair+1 ;[pcc008] time to be fair?
+ jm prtchr ;[pcc008] no, go around again.
+ mvi m,0 ;[pcc008] reset count
+ lda comchr ;[6] restore that character read from comm line
+ ret ;[pcc008] and return
+
+; I don't think we want to print xon/xoff - this should be
+; flow control only across the link between us and the host.
+; (besides, IBM host xon's don't make sense to most micros)
+; remember xon/xoff state in xofflg (zero = xon, non-zero = xoff)
+prtxon: xra a ;Yes, reset XOFF flag
+prtxof: sta xofflg
+ jmp prtchr ; look for another character
+; ;[pcc005] Log file routines
+
+;[pcc005]
+; logopn - open the log file
+; Open the log file and append to it if it already exists
+; or create one if not.
+
+logopn:
+ mvi a,ctrlz ;[9] ignore control-z in log files
+ cmp e ;[9] well, was it?
+ rz ;[9] yes, to ignore it.
+ lxi h,lognam ;[pcc012] copy name
+ lxi d,fcb ;[pcc012] to fcb
+ lxi b,12 ;[pcc012] 12 bytes
+ call mover ;[pcc012] copy it
+ call appfil ;[pcc012] open file for appending
+ jmp logerr ;[pcc012] error
+ lxi h,logflg ;[pcc005] point to log flag
+ mvi a,80H ;[pcc005] file open flag
+ ora m ;[pcc005] or in contents of logflg
+ mov m,a ;[pcc005] and store back
+ lxi d,inms28 ;[pcc005] assume logging is on
+ cpi 81H ;[pcc005] check
+ jz prtstr ;[pcc005] print msg if true
+ lxi d,inms27 ;[pcc005] no, must be suspended
+ jmp prtstr ;[pcc005] print and return
+
+;
+; logit - output character in E to log file.
+; we assume the host recognizes xon/xoff. (we probably shouldn't)
+; modem port is selected.
+; preserves de
+; called by: prtchr
+
+logit: lxi h,chrcnt ;[pcc012] point to buffer count
+ dcr m ;[pcc012] and decrement
+ jp logit1 ;[pcc012] continue if ok
+ push d ;[pcc012] save de
+ call outadv ;[pcc012] advance buffer if in memory
+ call logwrt ;[pcc012] sigh, time to write to disk
+ pop d ;[pcc012] restore de
+ lda logflg ;[pcc012] get logging flag
+ ora a ;[pcc012] Did we quit because of an error
+ rz ;[pcc012] return now if so
+logit1: lhld bufpnt ;[pcc012] get buffer pointer
+ mov m,e ;Store the char.
+ inx h
+ shld bufpnt
+ ret ;[pcc012] and return
+
+;[pcc012]
+; logwrt - write to log file with XON/XOFF since it may take a while.
+
+logwrt: call sndxoff ;[7] send and xoff to host
+ call outbuf ;[pcc012] output the buffer and advance
+ call logerr ;[pcc005] quit if error
+ call sndxon ;[send an xon to host
+ ret ;[pcc012]
+
+;[pcc005]
+; logcls - Close the log file and reset the flag
+
+logcls: lxi d,infms6 ;[pcc005] Tell user we are closing file.
+ call prtstr ;[pcc005]
+ call clofil ;[pcc012] and do it
+ jmp logerr ;[pcc005] jump if error
+ lxi h,logflg ;[pcc005] point to flag
+ mov a,m ;[pcc005] get it
+ ani 7FH ;[pcc005] clear the open bit
+ mov m,a ;[pcc005] and store back
+ ret ;[pcc005]
+
+;[pcc005]
+; logerr - here on a variety of logging errors
+; just close the file and disable logging
+; called from logopn,logptr,logcls
+
+logerr: lxi d,erms22 ;[pcc005] Error message
+ call prtstr ;[pcc005] print it
+ mvi c,closf ;[pcc005] Close the file.
+ lxi d,fcb ;[pcc012]
+ call bdos ;[pcc005]
+ xra a ;[pcc005] clear logflg
+ sta logflg ;[pcc005] so don't try again
+ ret ;[pcc005]
+;
+;
+; VT52 emulation.
+; called by: prtchr
+; A/ contents of escflg (guaranteed non-zero)
+; E/ current character
+; modem is selected.
+;
+vt52: cpi 1 ; first character after escape?
+ jnz vt52y ; no, must be doing cursor positioning.
+;
+; E contains the character that followed the escape.
+; valid characters are:
+; A - cursor up
+; B - cursor down
+; C - cursor right
+; D - cursor left
+; F - enter graphics mode (hard to do on a non-vt52)
+; G - exit graphics mode
+; H - home
+; I - reverse linefeed
+; J - erase to end of screen
+; K - erase to end of line
+; Y - cursor positioning leadin
+; Z - identify terminal as VT52
+; [ - enter hold-screen mode (not supported)
+; \ - exit hold-screen mode (not supported)
+; > - enter alternate-keypad mode? (not supported)
+; = - exit alternate-keypad mode? (not supported)
+;
+; Invalid sequences are handled as the VT52 does - the escape and
+; the following character are swallowed, never to be seen again.
+; For <esc>E, the translation table may contain just '$' (no action),
+; or may be used as clear-and-home, as in the Heath/Zenith H19.
+;
+ mov a,e ; get the second character of the sequence.
+ cpi 'Y' ; if cursor lead-in handle it.
+ jnz vt52a ; if not, go on.
+ mvi a,2 ; state = 2: row follows.
+ sta escflg ; update the flag.
+ ret ; back for another character
+
+vt52a: cpi 'Z' ; VT52 ID query?
+ jz vt52id ; yes. claim to be one.
+ cpi 'A' ;Less than an 'A'?
+ jm vtig ;Yes - ignore.
+ cpi 'K'+1 ;Greater than 'K'?
+ jp vtig ;Yes - ignore.
+ sui 'A' ;Else make into index.
+ rlc ;Multiply by four.
+ rlc ;(Shift left twice.)
+ lhld pttab ;Load base addr of table.
+ mov e,a ;Move a into de pair.
+ mvi d,00H ;Zero out high byte.
+ dad d ;Double add index+offset.
+ xchg ;Exchange de with hl.
+ call selcon ; select console
+ call prtstr ;and syscall.
+vtig: ;Ignore escape sequence.
+ xra a ;Reset the ol' escape flag.
+ sta escflg
+ ret ;Return home.
+
+; here for <esc>Z. Tell the host we're a VT52. (Sure we are...)
+vt52id: mvi a,esc ; response is escape...
+ call setpar ; (need correct parity)
+ mov e,a
+ call outmdm ; (console already selected)
+ mvi a,'/' ; ... slash ...
+ call setpar ; (with parity)
+ mov e,a
+ call outmdm
+ mvi a,'K' ; ... K.
+ call setpar
+ mov e,a
+ call outmdm
+ jmp vtig ; clear escape-sequence flag and return.
+
+; here when escflg isn't 0 or 1 - processing cursor positioning sequence.
+vt52y: cpi 2 ; looking for row? (y-coordinate)
+ jnz vt52x ; no, must be column.
+ mov a,e ; yes. get coordinate
+ sui (' '-1) ; convert from ascii (1 = top line)
+ sta vtyval ; store for later
+ mvi a,3 ; advance to next state (x coord)
+ sta escflg ; store it
+ ret ; try for another character
+
+; here when escflag isn't 0, 1, or 2 - it must be 3. (right?)
+; E holds the last character of the cursor positioning sequence.
+vt52x: xra a ; end of escape sequence, reset state.
+ sta escflg
+ mov a,e ; get column (' ' is left margin)
+ sui (' '-1) ; make left margin be one
+ mov c,a ; stash column in c
+ lda vtyval ; get row number
+ mov b,a ; in b
+ call selcon ; select console
+ call csrpos ; call system-dependent cursor positioner
+ ret ; all through.
+;
+;
+; conchr - copy character from console to comm line, processing
+; (kermit's) escape sequences.
+; Enter and exit with console selected.
+; nonskip return: transparent mode terminated.
+; skip return: still in transparent mode.
+; called by: rexmit, telnet
+
+conchr: call inpcon ;Try to get a character from the console
+ ani 07FH ;Keep only 7 bits
+ jz rskp ;Null means nothing there.
+ mov e,a ;Move the char for comparison.
+ sta lstchr ;Save it
+ lda escchr ;Get the escape char.
+ cmp e ;Is it an escape char?
+ jz intchr ;If so go process it.
+ call selmdm ; select the modem
+ mov a,e ;Get the char.
+ call setpar ;Set parity (if any).
+ mov e,a ;Restore it.
+ push d ; need to save e in case we are half dplx [5]
+ call outmdm ;Output the char to the port.
+ pop d ; Just in case we are half dplx [5]
+ call selcon ; reselect console
+ lda ecoflg ;Get the echo flag.
+ ora a ;Is it turned on?
+ jz rskp ;If not we're done here.
+ mov a,e ;Get the char.
+ ani 7FH ;Turn off the parity bit.
+ mov e,a
+ call outcon ; echo the character.
+ jmp rskp ; use skip return
+;
+; transparent escape character has been typed. dispatch on second
+; character. (console is still selected)
+; here from: conchr
+
+intchr: call inpcon ; get another character from the console
+ ora a ; zero means no character available yet.
+ jz intchr ; If so, loop until we get a char.
+ mov b,a ;Save the actual char.
+ cpi ctrlc ;is it Control-C?
+ jz contc ;yes
+ ani 137O ;Convert to upper case.
+ cpi 'C' ;Is it close?
+ jnz intch0 ;If not proceed.
+contc: lxi d,infms9 ;Say we are back.
+ call prtstr
+ call syscls ; call system-dependent close routine
+ lda logflg ;Get the log flag.
+ ora a ;[pcc005] Check if open
+ cm logcls ;[pcc005] Close if needed
+ ret
+
+;Here if not a 'C' or '^C'
+
+intch0: cpi 'S' ;Is it status?
+ jnz inch01 ;If not, proceed.
+ call stat01 ;Print out the status stuff.
+ call prcrlf ;[pcc011] add a crlf
+ jmp rskp ;return from conchr
+
+inch01:
+inch03: mov a,b ;Get the char.
+ cpi '?' ;Is it a help request?
+ jnz intch1 ;If not, go to the next check.
+inch3a: lda logflg ;[pcc003] Logging flag
+ ora a ;[pcc003] see if active
+ jp inch04 ;[pcc005] jump if no file open
+ lxi d,loghlp ;[pcc003] yes, tell about R AND Q
+ call prtstr ;[pcc003]
+inch04: lxi d,inthlp ;If so, get the address of the help message.
+ call prtstr
+ call sysinh ; print system-dependent help message
+ lxi d,inhlp1 ; Tell about doubling the escape character
+ call prtstr
+ call escpr ;Print escape character
+ lxi d,inhlp2 ;Print the rest
+ call prtstr
+ jmp intchr ;Get another char.
+
+intch1: mov a,b ;Get the character.
+ cpi '0' ;Is it '0', to send a null?
+ jnz intch3 ;No.
+ xra a ;Yes, send an ASCII zero.
+ call setpar ; with the correct parity
+ mov e,a
+ call selmdm ; (to the modem...)
+ call outmdm
+ call selcon ; return with console selected
+ jmp rskp
+
+intch3: lda escchr ;Get the escape char.
+ cmp b ;Is it the escape char?
+ jnz intch4 ;[pcc002] jump if not
+ mov a,b ;Get the char.
+ call setpar
+ mov e,a ;Restore it.
+ call selmdm
+ call outmdm ;Output it.
+ call selcon ;We promised console would be selected...
+ jmp rskp ;Return, we are done here.
+intch4: mov a,b ;[pcc002] get it again
+ ani 137o ;[pcc002] in upper case
+ cpi 'P' ;[pcc002] toggle printer?
+ jnz intch5 ;[pcc003] nope
+ lda prnflg ;[pcc002] get printer flag
+ xri 01h ;[pcc002] complement it
+ sta prnflg ;[pcc002] and put back
+ jmp rskp ;[pcc002]
+intch5: lda logflg ;[pcc003] get log flag
+ ora a ;[pcc003] See if open
+ jp intch7 ;[pcc003] no, skip R and Q
+ mov a,b ;[pcc003] get back chr
+ ani 137o ;[pcc003] make upper case
+ cpi 'R' ;[pcc003] Is it R
+ jnz intch6 ;[pcc003] Jump if not
+ mvi a,81H ;[pcc003] set flag for logging
+ sta logflg ;[pcc003] put it back
+ lxi d,inms28 ;[pcc003] message
+ call prtstr ;[pcc003]
+ jmp rskp ;[pcc003] done
+intch6: cpi 'Q' ;[pcc003] Quit logging?
+ jnz intch7 ;[pcc003] no
+ mvi a,82H ;[pcc003] flag for open, but suspended
+ sta logflg ;[pcc003] store away
+ lxi d,inms27 ;[pcc003] keep them informed
+ call prtstr ;[pcc003]
+ jmp rskp ;[pcc003]
+intch7: ;[pcc003]
+
+intchz: mov a,b ; not recognized. get saved copy back.
+ push psw ;[8] save as we will want to test for 'D'
+ call sysint ; interpret system-dependent sequences
+ jmp intchy ; done. [10] Now see if D. If so, do a C.
+ pop psw ;[10] tidy stack
+ mvi e,'G'-100O ;Otherwise send a beep.
+ call outcon ; to the console.
+ jmp rskp
+
+intchy: pop psw ;[10] adjust stack
+ ani 5fh ;[10] strip parity, make it upper case
+ cpi 'D' ;[10] was it a D?
+ jz contc ;[10] yup, so to the equivalent of an escape-C
+ jmp rskp
+;
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FOR RELEASE!
+
+; org ($+100h) AND 0FF00H
+IF lasm
+ LINK CPSCPM
+ENDIF;lasm
diff --git a/src/cpsutl.asm b/src/cpsutl.asm
new file mode 100644
index 0000000..3081232
--- /dev/null
+++ b/src/cpsutl.asm
@@ -0,0 +1,1227 @@
+; CPSUTL.ASM
+; 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.
+;
+; Utility routines, pure and impure data.
+;
+; revision history:
+;
+;edit 31, 21-Mar-1991 by MF. Implement edit 30 without checking takflg after
+; "r1tch1" as we are **always** TAKEing from a file if we get to that
+; point in the code. Makes for simplicity.
+;edit 30, 27-Feb-1991 by MF. When TAKEing characters from a TAKE-file,
+; view semicolons as normal characters (not command separators).
+; This will allow such commands as REMOTE DELETE *.*;* to work
+; properly from TAKE-files without having to revert to old code in
+; cpsrem.asm at "remcl0" to decode Remote command arguments. TAKE-files
+; ought not (in my opinion) to have multiple commands per line anyway.
+;edit 29, 30-Jan-1991 by MF. Fix bug in IN1CHR which decremented "chrcnt"
+; once too often after a call to INBUF (which predecrements it
+; already). This, along with a fix in CPSTT.ASM, fixes a bug in the
+; TRANSMIT command wherein certain characters in the file were not
+; being transmitted. This bug was reported to me by Lance Tagliapietra
+; of the University of Wisconsin at Platteville, WI (Email:
+; <TAGLANCE@ucs.UWPLATT.EDU>).
+; (he suggested not predecrementing "chrcnt" in INBUF" but this
+; breaks code in routine "GTCHR" from CPSPK1.ASM so it's better
+; to modify IN1CHR in this module and XMIT in CPSTT.ASM).
+;edit 28, 30-Nov-1990 by MF. Modify routine "p20ln" to use "pausit" routine
+; rather than explicitly checking for Console input to eliminate
+; redundant code. Also fix spelling in "p20ln"'s comments.
+;edit 27, 9-Sep-90 by MF. Put RET in routine PAUSIT per CPKERM.BWR.
+; edit 26, September, 1987. Added pause-it routine to wait for a user keysroke.
+;
+; edit 25, August 19, 1987 by OBSchou. Fixed a few bugs here and there.
+;
+; edit 24, April 8, 1987 by OBSchou. Added routine to return one character
+; from a section of several sectors worth of file. This routine needed
+; for TRANSMIT.
+;
+; edit 23, March 11, 1986 by OBSchou for Richard Russell
+; Bug in the TAKE code, such that a new sector was read in after 256
+; bytes, and not the CPM value. A jnz is now jp in the test to see if
+; the file buffer has bben exhausted. Many thanks for finding this
+; bug. I have never used TAKE files more than 128 bytes long.
+;
+; edit 22, January 28, 1986 by OBSchou.
+; split off the data areas from CPSUTL to CPSDAT.ASM (All in line
+; with keeping individual files relatively small)
+;
+; edit 21 August, 1986 by OBSchou. Sorted a few more bugs in printer buffer
+; etc. Have yet to try this with a real printer The code, apart from
+; actually printing works OK.
+;
+; edit 26 20 August, 1986 by OBSchou for Godfrey Nix:
+; edit 8-Aug-86 by Godfrey N. Nix [gnn] Nottingham University
+; Added two extra bytes for storage of the send and receive
+; start-of-packet characters. Used by CP4PKT, and altered
+; by SET option in CP4MIT. Also added message strings for
+; use by show routines. Added remote filename buffer and length byte.
+;
+; edit 11: June 20, 1986 by OBSchou. Added multi-fcbs for the DIR command
+; together with some bug clearing and new routines. Had to move
+; the overlay to 5000h as we ran out of space...
+;
+; edit 10: June 16, 1986 OBSchou. Added a pseudo clock and check for printer
+; ready whenever one enters BDOS... This may slow things down a little
+; but adds in (hopefully) pseudo background printing...
+;
+; edit 9 30-May-86 OBSchou. Added XON/XOFF routines here for the world
+; at large to use. Also added two new entries in the overlay tables.
+; One to give the address of the family of machines using the overlay,
+; the other to the routine for giving printer status.
+;
+; edit 8: 27-May-86 OBSchou. Added code to check BDOS calls for info from
+; the console. If so, and the take flag (takflg) is set then we
+; substitute our own characters. Simple, a little tatty...
+; Also added bits for SET CASE-SENSITIVE and SET FLOW=CONTROL, and
+; removed the XMIT rubbish. This is a prelude to better TRANSMIT
+;
+; edit 7: 22 April, 1986 by OBSchou Lohghborough University
+; Prlude to more changee, this time make overlay address to 4000h
+; May revert back to ($+0ffh) AND 0ff00h as address for overlay.
+; This gives us space to make quite a few modifications to the system
+; dependent part without much fear of having to change this overlay
+; address. Should also fix the Osborne problem of having to have io
+; routines ii memory above 16k. I know I should not be introducing
+; such system dependent rot here, but it wont be too difficult to fill
+; memory to 4000h.
+;
+; edit 6: February 6, 1985
+; Added a storage location for the port value (PORT, just below
+; SPEED) which is used by the port status routine, and moved the
+; printer copy flag (PRNFLG:) into the communications area so
+; that the machine dependant overlay can toggle it. [Hal Hostetler]
+; Added ffussy flag for filename checking. Generate the version
+; string from 'verno', which is set in CP4KER, because CP4KER has the
+; list of modules and their edit numbers. [Charles Carvalho]
+;
+; edit 5: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
+;
+;pcc002 28-Dec-84 modules:cp4tt,cp4utl
+; Add connect mode <esc>P command to toggle printer on
+; and off. Conflicts with "official" recommended commands
+; in protocol manual, but I don't think CP/M will ever get
+; a PUSH command.
+;
+;pcc003-pcc005 2-Jan-85 vjc modules:cp4mit,cp4tt,cp4utl
+; These edits must all be installed together and change the way
+; logging is handled. The log file spec is moved to a separate
+; fcb, and not opened until an actual CONNECT command is given.
+; This takes care of a NASTY bug that if you used any other file
+; command between the LOG and CONNECT, the log file would get
+; written over the last file used. This also allows logging to
+; be "permanently" enabled until an CLOSE (new command) for all
+; CONNECT sessions, like most other kermits do. If a log file
+; already exists, it will be appended to. Also add two new
+; CONNECT mode commands <esc>Q to suspend logging and <esc>R to
+; resume. <esc>R means something else during TRANSMIT, but
+; logging is never on then, so there shouldn't be any conflict.
+; I also changed the write code, so that it can handle one more
+; character after the XOFF is send to stop the host. This allows
+; a little "slop" for systems that don't stop immediately (such
+; as TOPS10), but it didn't help much.
+;
+;pcc006 2-jan-85 VJC modules:cp4cmd,cp4utl
+; Problems with "?" in filespecs. On reparse, may cause action
+; flag to be reset at wrong point, requiring multiple <CR>'s
+; to terminate the line or other weird stuff. Also need to
+; check flag and complain if wild-cards illegal.
+;
+;pcc008 2-Jan-85 vjc modules:cp4def,cp4tt,cp4utl
+; Keyboard input during CONNECT mode can get locked out if
+; there is enough input from the modem port to keep prtchr
+; busy. This can happen for example, if the printer is running
+; at the same speed as the modem line, leaving you helpless to
+; turn it off or abort the host. Add a fairness count, so that
+; at least every prfair characters we look at console input.
+;
+;pcc012 4-Jan-85 vjc modules:cp4mit,cp4tt,cp4utl
+; Use the big buffer for the log file. Move the log file back
+; into the common fcb and only save the drive, name, and
+; extension between connects. Add new routines to cp4utl to
+; create or append to an existing file, and to conditionally
+; advance buffers only if in memory. Remove edit pcc003 that
+; allows one more character after the xoff, since it didn't
+; really work very well and does not fit in well with the way
+; the buffer advancing routines are set up. If someone still
+; thinks this would be useful, it could be put back in with a
+; little more work.
+;
+; While testing this edit, I also noticed another bug that
+; the command parsing routines do not limit or check the
+; length of command lines or file specs, trashing what ever
+; comes after them. Currently because of where the fcb and
+; command buffer are located, this does not usually cause a
+; problem, but could if an extremely long line was typed in,
+; or in the future multiple fcbs defined elsewhere in memory
+; were used. Maybe this should be put on the bug list
+; somewhere.
+;
+;pcc013 8-Jan-85 vjc modules:cp4mit,cp4utl,cp4typ
+; Replace CLOSE command to cancel session logging to SET
+; LOGGING ON/OFF. This seems to fit in with the command
+; structure better. Default the log file to KERMIT.LOG
+; incase no previous LOG command. Logging is also enabled
+; by LOG command, as before.
+;
+; edit 4: September 9, 1984
+; Move command tables and associated help text to CP4MIT. Add
+; makfil/clofil routines and modify outbuf to write files in big
+; chunks. Update Kermit's version to 4.03.
+;
+; edit 3: August 21, 1984
+; Make inbuf read files in big chunks to minimize disk start/stop
+; delays. Buffer size and address is specified by system-dependent
+; overlay.
+;
+; edit 2: August 3, 1984
+; move "mover" to CP4SYS to allow use of Z80 block move instruction.
+;
+; edit 1: July 27, 1984
+; extracted from CP4MIT.M80 edit 2, as part of LASM support. This is
+; the last file linked for the system-independent code.
+;
+utlver: db 'CPSUTL.ASM (31) 21-Mar-1991$'
+
+; Set the parity for a character in A.
+; called by: spack, rexmit, logit, vt52, conchr, intchr
+
+setpar: push h ;Save HL.
+ push b
+ lxi h,parity
+ mov c,m ;Get the parity routine.
+ mvi b,0
+ lxi h,parjmp ;Get the first address.
+ dad b
+ pchl
+
+parjmp: jmp even
+ jmp mark
+ jmp none
+ jmp odd
+ jmp spacep
+
+none: jmp parret ;Don't touch the parity bit.
+
+even: ani 7FH ;Strip parity.
+ jpe parret ;Already even, leave it.
+ ori 80H ;Make it even parity.
+ jmp parret
+
+mark: ori 80H ;Turn on the parity bit.
+ jmp parret
+
+odd: ani 7FH ;Strip parity.
+ jpo parret ;Already odd, leave it.
+ ori 80H ;Make it odd parity.
+ jmp parret
+
+spacep: ani 7FH ;Turn off the parity bit.
+ jmp parret
+
+parret: pop b
+ pop h ;Restore HL.
+ ret
+;
+; Print the escape char.
+; called by: stat01, telnet, intchr
+
+escpr: lda escchr ;Get the escape char.
+escpr1: cpi ' ' ;Is it a control char?
+ jp escpr2
+ push psw ; save the character
+ lxi d,inms10 ;Output "Control-".
+ call prtstr
+ pop psw ; restore the character
+ ori 100O ;De-controlify.
+escpr2: mvi c,conout ;Output the char
+ mov e,a
+ call bdos
+ ret
+
+; fetch keyword; if unsuccessful, return to command level.
+; called by: kermit, setcom
+
+keycmd: mvi a,cmkey
+ call comnd
+ jmp keycm2 ;no match
+ ret
+
+keycm2: lxi d,ermes1 ;"Unrecognized Command"
+ call prtstr
+ jmp kermit ;Do it again.
+
+; request confirmation; if unsuccessful, return to command level
+; called by: bye, exit, help, log, setcom, show, status, send,
+; finish, logout, telnet
+
+cfmcmd: mvi a,cmcfm
+ call comnd
+ jmp kermt3 ;"Not confirmed"
+ ret
+;
+
+; This routine prints the number in HL on the screen in decimal.
+; Uses all ACs.
+; called by: cp4sys, read, send, updrtr, dir, user
+
+nout: mvi a,'0' ; fill tempx with zeros
+ call filltmp
+
+ lxi b,-10 ;Get some useful constants.
+nout1: lxi d,-1
+
+nout2: dad b ;Subtract as many 10s as possible.
+ inx d ;Count them.
+ jc nout2 ;If some left keep going.
+ push h ;save remainder - 10
+ xchg ;Swap the remainder and the quotient.
+ mov a,h ;Get the number of 10s found.
+ ora l ;check for quotient non zero
+ cnz nout1 ;If non zero, recurse.
+ pop h ;Get the remainder - 10
+ mov a,l ;in a
+ adi '0'+10 ;Make the number printable and add the 10 back
+ call shiftmp ; cycle temp registers
+ sta temp1 ; and save digit
+ mov e,a ;Output the digit.
+ lda nquiet ; are we to be quiet?
+ ana a
+ rnz ; yup, so return here rather than frm bdos
+ mvi c,conout
+ jmp bdos
+
+; prcrlf - print a CR/LF. (Saves no registers.) [Toad Hall]
+; prtstr - print string pointed to by DE (now in overlay section.. see prtstx)
+; called by: lots of places.
+prcrlf: lxi d,crlf ;Point to the CR/LF
+ jmp prtstr ; Use the one in the overlay
+
+; prtstx is funtionally the same as prtstr in the overaly but is here as
+; we may need a print a string routine in case the overlay is
+; either incorrect version or simply not present.
+prtstx: ; PRTSTR moved to overlay, but we do need the
+ ; same function for writing the sign-on
+ ; message and error message if the overlay
+ ;is not present. Thence prtstx
+ mvi c,prstr ; output string
+ jmp bdos ;a CALL followed by a RET becomes a JMP
+
+
+; Jumping to this location is like retskp. It assumes the instruction
+; after the call is a jmp addr.
+; here from: many places.
+rskp: pop h ;Get the return address.
+ inx h ;Increment by three.
+ inx h
+ inx h
+ pchl
+
+; Jumping here is the same as a ret. 'jmp r' is used after routines
+; that have skip returns, where the non-skip instruction must be 3 bytes.
+; here from: many places.
+r: ret
+
+; Pause-it routine. Informs the user to press any key to continue
+; and then waits for a key input. Called by the any routine
+; with more than, say, 20 lines of output.
+
+pausit: lxi d,anymes ; ask user to press any key to continue
+ call prtstr
+pausi1: call ckcon ; see if a key typed
+ ana a
+ jz pausi1 ; loop until a key has been pressed.
+
+ ret
+
+;
+; Open a file for reading (with inbuf). The filename is already
+; in fcb; upon return, the end of file flag is cleared and chrcnt
+; is set to zero, so inbuf will be called to get a buffer when we
+; next attempt to get a character.
+; called by: sinit, seof
+
+getfil: xra a
+ sta chrcnt ;Buffer is empty.
+ sta seccnt ;No sectors buffered.
+ sta eoflag ;Not the end of file.
+ sta endsts ;No EOF/error pending.
+ sta fcb+0CH ;Zero the extent.
+ sta fcb+0EH ;Must be zero for MAKEF or OPENF.
+ sta fcb+20H ;Zero the current record.
+ mvi c,openf ;Open the file.
+ lxi d,fcb
+ call bdos
+ ret
+
+; Get next sector. If necessary, read some more from disk.
+; preserves bc, de, hl
+; returns nonskip if EOF or error;
+; returns skip with chrcnt and bufpnt updated if success.
+; called by: gtchr, get1xc (from xmt/transmit)
+
+inbuf: lda eoflag ;Have we reached the end?
+ ora a
+ rnz ;Return if so.
+ push b
+ push d
+ push h
+inbuf1: lda seccnt ; Do we have any sectors left?
+ ora a
+ jz inbuf3 ; If not, go get some more.
+inbuf2: lhld nxtbuf ; Yes. Get address of next sector
+ shld bufpnt ; Update current buffer pointer
+ lxi b,bufsiz ; Get number of bytes in sector
+ dad b ; Update HL to point to next sector
+ shld nxtbuf ; Save for next time
+ dcr a ; Decrement count of buffered sectors
+ sta seccnt ; Put it back
+ mvi a,bufsiz-1 ; Number of bytes in buffer (pre-decremented)
+ sta chrcnt ; Store for our caller
+ pop h
+ pop d
+ pop b
+ jmp rskp ; Return success
+
+; We don't have any sectors buffered. If we've already hit an error or
+; EOF, return that status to the user.
+
+inbuf3: lda endsts ; Check status from previous read
+ ora a
+ jz inbuf4 ; It was OK. Get some more sectors.
+ sta eoflag ; End of file or error. Set the flag.
+ xra a
+ sta chrcnt ; Say no characters in buffer.
+ pop h
+ pop d
+ pop b
+ ret ; Return failure
+
+; Read sectors until we fill the buffer or get an error or EOF, then return
+; the first buffer to the user. (seccnt is zero)
+
+inbuf4: lhld bufadr ; Get address of big buffer
+ shld nxtbuf ; Store as next buffer address to give user
+inbuf5: shld bufpnt ; Store as next buffer address to read into
+ xchg ; Move buffer address to DE
+ mvi c,setdma ; Tell CP/M where to put the data
+ call bdos ; ...
+ mvi c,readf ; Read a record.
+ lxi d,fcb
+ call bdos
+ sta endsts ; Save ending status
+ ora a ; 00H => read O.K
+ jnz inbuf6 ; EOF/error: stop reading.
+ lxi h,seccnt ; Success. Get addr of sector count
+ inr m ; Bump sector count by one
+ lda bufsec ; Get max number of sectors in buffer
+ cmp m ; Are we there yet?
+ jz inbuf7 ; Yes, can't read any more.
+ lhld bufpnt ; No, try for another. Get buffer address,
+ lxi d,bufsiz ; and size of sector,
+ dad d ; giving next buffer address in HL
+ jmp inbuf5 ; Go read another sector.
+
+; We hit EOF or got an error. Put the DMA address back where it belongs,
+; then go see if we have any sectors (before the one that got the error)
+; to return to the caller. Nxtbuf points to the first good sector, if
+; any; seccnt contains the count of good sectors.
+
+inbuf6: call rstdma
+ jmp inbuf1 ; Go see if we have some data to return
+
+; We've filled the big buffer. Reset the DMA address, then go return a
+; sector to the caller. nxtbuf points to the beginning of the buffer;
+; seccnt contains the number of sectors successfully read (except that
+; if we've read 256 sectors, seccnt contains zero, so we can't just go
+; to inbuf1).
+
+inbuf7: call rstdma ;[pcc012]
+ lda seccnt ; Get sector count again.
+ jmp inbuf2 ; Return a sector.
+
+; IN1CHR - get a single character from the file. Taken code from old
+; TRANSMIT routine.
+in1chr:
+ lda eoflag ;EOF encountered?
+ ora a
+ rnz ; Yes, finish.
+ lxi d,cmdbuf ; Use comnd buffer as line buffer.
+ lhld bufpnt ; Get current buffer pointer.
+ lda chrcnt ; Get current byte count
+ mov b,a ; in B
+in1ch1: dcr b ; Assume there's a character there
+ jp in1ch2 ; If there was, proceed.
+ call inbuf ; There wasn't. Try for another buffer.
+ jmp in1che ; End of file.
+ lhld bufpnt ; Got another buffer. Get new pointer in HL
+ lda chrcnt ; and new byte count
+ mov b,a ; in B
+;[MF]The modification below was made 30-Jan-1991 per report from
+;[MF]Lance Tagliapietra from the University of Wisconsin at Platteville
+;[MF]The following instruction should not be executed as the character counter
+;[MF]has already been decremented by INBUF.
+; dcr b ; we are reading in a character, so less one
+in1ch2: mov a,b ; save new count
+ sta chrcnt
+ mov a,m ; Get a character from disk buffer.
+ inx h
+ shld bufpnt ; save new pointer
+ ani 7FH ; Mask 7 bits.
+ jz in1ch1 ; Skip nulls.
+ ret ; character in a
+
+
+in1che: mvi a,0ffh ; dubious about this one...
+ sta eoflag
+ ret ; set end of file flag...?????
+
+; ;[pcc012]
+; appfil - Create or append to an existing file. File name is in FCB.
+; Non-skip return if could not be done. Skip return with file
+; open and bufpnt pointing to end of file.
+; called by logopn
+appfil: xra a ;[pcc012] zero out stuff for open
+ sta fcb+0CH ;[pcc012] extent
+ sta fcb+0EH ;[pcc012] Must be zero for MAKEF or OPENF.
+ sta fcb+20H ;[pcc012] Zero the current record.
+ mvi c,openf ;[pcc012] Try to open the file
+ lxi d,fcb ;[pcc012]
+ call bdos ;[pcc012]
+ cpi 0FFH ;[pcc012] Did we find it?
+ jz makfi1 ;[pcc012] If not, go create it
+ mvi c,cflsz ;[pcc012] Compute the file size
+ lxi d,fcb ;[pcc012]
+ call bdos ;[pcc012]
+ lhld fcb+21H ;[pcc012] random record pointer
+ mov a,h ;[pcc012] See if zero length file
+ ora l ;[pcc012]
+ jz makfi2 ;[pcc012] set up pointers if null file
+ dcx h ;[pcc012] backup to last record written
+ shld fcb+21H ;[pcc012] store rec ptr back
+ lhld bufadr ;[pcc012] get buffer address
+ xchg ;[pcc012] to DE
+ mvi c,setdma ;[pcc012] set dma address
+ call bdos ;[pcc012] for read
+ mvi c,rrand ;[pcc012] read the last block
+ lxi d,fcb ;[pcc012]
+ call bdos ;[pcc012]
+ ora a ;[pcc012] check results
+ jnz rstdma ;[pcc012] reset dma and return if error
+ lhld bufadr ;[pcc012] get address again
+ lxi d,bufsiz ;[pcc012] and and size
+ mvi a,'Z'-40H ;[pcc012] control-Z for comparison
+appcz: cmp m ;[pcc012] Is this the EOF?
+ jz appxit ;[pcc012] Jump if yes
+ inx h ;[pcc012] no, bump
+ dcr e ;[pcc012] and grind
+ jnz appcz ;[pcc012] until find or buffer empty
+appxit: shld bufpnt ;[pcc012] store buffer pointer
+ dad d ;[pcc012] compute next buffer adr
+ shld nxtbuf ;[pcc012] and store
+ mov a,e ;[pcc012] updated chr count
+ sta chrcnt ;[pcc012]
+ xra a ;[pcc012] reset sector count
+ sta seccnt ;[pcc012]
+ call rstdma ;[pcc012] reset normal dma
+ jmp rskp ;[pcc012] and give good return
+
+; Create a file, deleting any previous version. The filename is in
+; fcb.
+; Returns nonskip if file could not be created.
+; If successful, takes skip return with bufpnt and chrcnt initialized
+; for output; buffers should be output via outbuf.
+; called by: gofil
+makfil: mvi c,delf ; delete the file if it exists.
+ lxi d,fcb
+ call bdos
+ xra a
+ sta fcb+0CH ; zero the extent.
+ sta fcb+0EH ; must be zero for MAKEF or OPENF.
+ sta fcb+20H ; zero the current record.
+;[pcc012] here from appfil above if file does not exist
+makfi1: mvi c,makef ;[pcc012] now create it.
+ lxi d,fcb
+ call bdos
+ cpi 0FFH ; is the disk full?
+ rz ; take error return if so.
+; success. set up pointers and counters for multisector buffering.
+;[pcc012] also here from appfil if found zero length file
+makfi2: lhld bufadr ;[pcc012] find beginning of buffer space.
+ shld bufpnt ; make it current buffer.
+ lxi d,bufsiz ; get sector size.
+ dad d ; find beginning of next buffer.
+ shld nxtbuf ; store for later.
+ mov a,e ; store buffer size
+ sta chrcnt ; for caller.
+ xra a
+ sta seccnt ; no sectors stored yet.
+ jmp rskp ; take success return.
+
+;[pcc012]
+; outadv - conditionally advance output buffer if disk write not needed.
+; preserves BC
+; skip return with with next output buffer set up
+; non-skip return if memory buffer full and must write to disk.
+; called by:logit
+
+outadv: push b ;[pcc012] save BC as advertised
+ lxi h,seccnt ;[pcc012] point to sectors buffered
+ inr m ;[pcc012] count this one
+ lda bufsec ;[pcc012] how many we can hold
+ cmp m ;[pcc012] check if full
+ jnz outbf2 ;[pcc012] continue if not
+ dcr m ;[pcc012] full, un-advance sector count
+ pop b ;[pcc012] restore bc
+ ret ;[pcc012] and give non-skip return
+
+; get a fresh output buffer, flushing big buffer if necessary.
+; returns nonskip if disk full.
+; if successful, returns skip with bufpnt and chrcnt updated. Note
+; that chrcnt holds one less than the buffer size.
+; preserves BC.
+; called by: ptchr,logwrt
+
+outbuf: push b
+ lxi h,seccnt ; count another buffered sector
+ inr m ; ...
+ lda bufsec ; get number of sectors we can hold
+ cmp m ; full?
+ jnz outbf2 ; if not, set up pointers and return
+ call outmbf ; flush the big buffer
+ jmp outbf9 ; disk error.
+;[pcc012] also here from outadv to advance buffer
+outbf2: lhld nxtbuf ; get pointer to fresh buffer
+ shld bufpnt ; store for caller
+ lxi d,bufsiz ; advance our pointer to next buffer
+ dad d
+ shld nxtbuf
+ mvi a,bufsiz-1 ; get buffer size (pre-decremented)
+ sta chrcnt ; store for caller
+ pop b
+ jmp rskp ; return success.
+
+outbf9: pop b ; clean up stack
+ ret ; and take error return.
+
+; flush incore output buffers.
+; returns nonskip if disk full.
+; if successful, returns skip with nxtbuf reset to start of buffer and
+; seccnt zero.
+; destroys all ac's.
+; called by: outbuf, clofil.
+
+outmbf: lhld bufadr ; get start of buffer
+ shld nxtbuf ; store for next fill cycle
+ shld bufpnt ; store for empty loop
+outmb2: lhld bufpnt ; get address of current sector
+ xchg ; into DE
+ lxi h,bufsiz ; advance HL to next sector
+ dad d ; ...
+ shld bufpnt ; and store for later
+ mvi c,setdma
+ call bdos ; point CP/M at current sector
+ lxi d,fcb
+ mvi c,writef
+ call bdos ; output the sector
+ ora a ; test for error (A non-zero)
+ jnz rstdma ;[pcc012] reset dma and take nonskip return if so
+ lxi h,seccnt
+ dcr m ; count down buffered sectors
+ jnz outmb2 ; loop if more saved
+ call rstdma ;[pcc012] restore normal dma
+ jmp rskp ; return success.
+
+; output current buffer, flush incore buffers, and close output file.
+; returns nonskip if disk full; skip if successful.
+; called by: rdata
+
+clofil:
+ lda chrcnt ; get the number of chars left in the buffer.
+ cpi bufsiz ; Virgin buffer?
+ jz clofl3 ; yes, don't output it.
+ lhld bufpnt ; get the buffer pointer.
+clofl1: dcr a ; lower the count.
+ jm clofl2 ; if full then stop.
+ mvi m,'Z'-100O ; put in a ^Z for EOF.
+ inx h ; point to the next space.
+ jmp clofl1
+
+clofl2: call outbuf ; output the last buffer.
+ jmp r ; give up if the disk is full.
+clofl3: lda seccnt ; any sectors buffered in memory?
+ ora a
+ jz clofl4 ; if not, don't try to flush.
+ call outmbf ; flush buffers
+ jmp r ; disk full.
+clofl4: mvi c,closf ; close up the file.
+ lxi d,fcb
+ call bdos
+ jmp rskp ; return success.
+
+
+; Reset DMA address to the default buffer
+; called from inbuf,appfil,outmbf
+rstdma: lxi d,buff ;[pcc012]
+ mvi c,setdma ;[pcc012]
+ jmp bdos ;[pcc012]
+
+; [8] Intercept BDOS calls to check for console input
+; This leads to simple trapping for input from disk rather than from the
+; keyboard, alowing commands to be stored in a TAKE file.
+; Printer is tested for readiness, and the second fuzzy clock is updated.
+bdos: ;call print ; print a character to the printer if needed
+ ;call clock ; update the clock
+ push psw ; we will need this register
+ lda takflg ; are we taking from a
+ ana a ; file or from command line
+ jz notake ; no, so do usual BDOS stuff
+ mov a,c ; get bdos function
+ cpi conin ; is it console in?
+ jz bd1in ; get a single character
+ cpi dconio ; direct console in or out?
+ jz bd1io ; test further for inpu or output
+ cpi rdstr ; read the console buffer?
+ jz bdcbuf ; then do it
+ cpi consta ; get the console status?
+ jz bdcst ; anything left in buffer?
+notake: pop psw ; else we have a kosher BDOS call
+ jmp 0005h ; Absolute address = BDOS entry point
+;
+bd1in: ; get a single character from take file
+ pop psw ; restore stack
+ call r1tchr ; read a single take character
+ ret ; and return. We dont expand tabs,
+ ; check for xon/off or backspaces.
+ ;Make sure the take file is error free?
+;
+bd1io: ;get or put a single character from/to console
+ mov a,e ; get e. If 0ffh then input else output
+ inr a ; if 0 then input
+ jnz notake ; its for output, so let notake restore stack
+ pop psw ; otherwise we do it
+ call r1tchr ; read a single take character
+ ret ; and return from out BDOS
+;
+bdcbuf: ; read a line of edited (?) input from the console
+ pop psw ; restore stack
+ inx d ; point to nc
+bdosc1: call r1tchr ; get a character
+ cpi cr ; if a cr then return
+ jz nomore
+ cpi lf ; ignore line feeds
+ jz bdosc1 ; so get another character
+ push psw ; we will want it later
+ mvi h,0
+ ldax d ; get nc, the no of characters in buffer
+ mov l,a ; now use as index from de+2
+ mvi h,0
+ inx d ; de is now de + 2
+ dad d
+ pop psw ; Told you we will want this
+ mov m,a
+ dcx d ; point again to nc
+ xchg ; make hl point to memory
+ inr m ; update pointer nc
+ xchg ; restore it
+ jmp bdosc1
+nomore: dcx d ; restore de to point to buffer
+ ret
+
+bdcst: ; get the console status. Returns a 00 if at eof
+ pop psw
+ push h ; now save de, hl for return
+ push d ;
+ lxi d,takdma ; make a point to next byte...
+ lhld takptr ; pointer from dma address. There will always
+ dad d ; be at least one byte, as the buffer is
+ mov a,m ; ...
+ pop d ; filled only if a read empties it.
+ pop h ; restore hl, de
+ cpi cntlz ; end of file?
+ mvi a,0ffh ; say there is
+ rnz ; if it is not a cntl z
+ jmp closet ; otherwise, close take file etc
+
+r1tchr: ; read a single character from the take file or command line
+ push h
+ push d ; save in case of return
+ lda takflg ; see if character is to come from file or line
+ ani 1 ; if bit zero set, from take file
+ jz r1lchr ; get character from the command line
+ lxi d,takdma
+ lhld takptr ; get next data byte
+ dad d
+ mov a,m
+ lhld takptr ; cos it's destroyed with dad
+ inx h
+ shld takptr ; update pointer
+ call p1tchr ; print it (so the user sees it)
+ push psw ; save the read data for a while
+ mov a,l ; if l = 0 then read another sector
+ ana a
+ jp r1tch1 ;[23] was jnz. jp => 128 byte sectors
+ call rnsect ;read next sector
+r1tch1: pop psw ; now, is this a cntl-z.. in whic case
+ pop d ; also these...
+ pop h
+ cpi lf ; skip if a line feed
+ jz r1tchr ;
+;[MF][31][30]Following lines commented out so semicolons are not considered
+;[MF][31][30]command separators and thus are considered part of the command
+;[MF][31][30]so commands like REMOTE DELETE *.*;* work correctly.
+; cpi semico ; see if its a semicolon
+; jnz r1tch2 ; no, ignore it
+; mvi a,cr ; else say its a cr (in case of command lines)
+r1tch2: cpi cntlz ; end of file??
+ rnz
+
+
+c1tchr: call closet ; close file etc, then
+ mvi a,cr ; fake a carriage return chr
+ ; ( => clears kermit comnd line)
+c1tch1: ret ; and hope that editing etc not required.
+
+r1lchr: ; read a single character from the command line
+ lxi d,cbuff ; point to buffer
+ lda cbptr ; get pointer for next character
+ mov l,a
+ lda cbuff ; get total number of characters there
+ cmp l ; ... less current character
+ jp r1lch1 ; if positive, we have more characters
+ lda takflg ; no more, so reset command line bit (bit 4)
+ ani 0efh
+ sta takflg
+ mvi a,cntlz ; fudge an end of file
+ push psw ; save for common exit (r1tch1)
+ jmp r1tch1
+;
+r1lch1: mov a,l ; get count back again
+ mvi h,0
+ dad d ; get offset to character
+ inr a
+ sta cbptr
+ mov a,m ; get next character
+ cpi semico ; if a semicolon, make it a carriage return
+ jnz r1lch2
+ mvi a,cr
+r1lch2: call p1tchr ; send a copy to the console
+ push psw ; save it for r1tch1
+ jmp r1tch1 ; common exit
+
+
+; rnsect - read the next take sector from disk to the take dma address
+; if there is no more then close the file too
+rnsect: push b
+ push d
+ push h ; save in case we need these later
+ mvi c,setdma
+ lxi d,takdma ; set a next read from disk
+ call bdos ; recursive...
+ mvi c,readf
+ lxi d,takfcb
+ call bdos
+ ana a
+ cnz closet ; if returned value not zero, assume eof
+ lxi h,0
+ shld takptr ; pointer restored
+ call rstdma ; reset the dma address for fussy routines (this one)
+ pop h
+ pop d
+ pop b
+ ret
+
+; closet - close the take file and set the take flag to 0 (ie no takes)
+;
+closet: lda takflg ; reset the take file bit (bit 0)
+ ani 0feh
+ sta takflg ; close the take file, and restore the flag
+ mvi c,closf
+ lxi d,takfcb
+ call bdos
+ call rstdma ; in case we did not do it above, reset dma
+ ret
+
+;
+; clock - is a 32 bit counter incremented every BDOS call. It serves as a
+; timer of sorts and allows a background clock to tick away..
+clock: push psw ; we need flags and hl
+ push h
+ lhld clkbit ; get the counter
+ inx h ;
+ shld clkbit
+ mov a,h
+ ora l ; do we need to update the next lot of clock bits?
+ jnz clockx
+ lhld clkbit+2 ; if carry up the top 16 bits
+ inx h
+ shld clkbit+2
+clockx: pop h
+ pop psw
+ ret
+
+; p1tchr - print a character in accumulator directly to the console
+; bypassing the bdos trap above.
+
+p1tchr: cpi lf ; if a lf ignore it
+ jz p1tchx
+ cpi cr ; ditto carriage returns
+ jz p1tchx
+ cpi cntlz ; control z
+ jz p1tchx ; then dont write it out
+ push psw ; we do not want to loose it, do we?
+ push b
+ push d
+ push h ; 'cos you never know what bdos does...
+ mov e,a
+ mvi c,conout ; direct console io
+ call 5 ; absolute address as we skip the trap
+ pop h
+ pop d
+ pop b ; ... and we need some of these regs.
+ pop psw ;
+p1tchx: ret ; and return
+
+
+
+; outprn - This routine sends charactes to the printer if the latter is ready,
+; or to a buffer if the printer is not ready. If the buffer is nearly
+; full, an XOFF is sent to the host, asking it to be quiet. The buffer
+; is emptied by a series of calls in the connect state only.
+; If the buffer is made nearly empty, then an XON is sent to the host.
+;
+outprn: mov a,e ; get the character to send back to a
+ sta prntmp ; we need all registers.
+ jmp outprx ; -testing-testing-testing- avoid buffer
+;
+outp0: call tstfree ; see how many spaces free
+ cpi 2 ; (free spaces in a on return)
+ jp outp1 ; enough free spaces, so keep going
+ call print ; else see if we can print summat
+ jmp outp0 ; and try again
+;
+outp1: cpi 4 ; common test - if three or less then send xoff
+ cm sndxoff
+outpr2: mov a,b ; inc ptr and check for wrap around
+ call wrapt
+ mov b,a ; input pointer to b
+ sta prnbuf+1 ; save the new pointer away
+ lxi h,prnbuf+2 ; point to first real data entry in buffer
+ call inchl ; add offset in a to hl
+ lda prntmp ; get th character to save away
+ mov m,a ; save the data away
+ ret
+
+; outprx - send character in a to the printer. (We have checked to see if
+; the printer is ready)
+; called by outprn, print
+outprx: mov e,a ; character has to be in e register
+ call outlpt ; send it to printer
+ ret ; assume we print it
+
+; TSTFREE - see how many free spacse there are in the buffer
+; - returns with free space in a, ip pointer in b, op pointer in c
+szecyc equ 127 ; 128 bytes in buffer (less for debugging)
+;
+tstfree:
+ lda prnbuf ; get output pointer
+ mov c,a ;.. to c
+ lda prnbuf+1 ; and input pointer ...
+ mov b,a ; ... to b
+;
+;
+; Now comes the tricky bit. We must establish whether there is less than
+; three characters left in the buffer. There are two conditions to test for
+; 1) the input pointer is a higher value than the output pointer
+; 2) the input pointer has been wrapped round and is less than the output pointer
+; ie
+; |-------|-------|---------------------------------------------|
+; Buffer |o/p ptr|i/p ptr| Buffer proper filling ---> |
+; |-------|-------|------|-------------|-----------|------------|
+; i/p2 o/p i/p1
+;
+; If ip = ip1 then if
+; (size of buffer - ip ptr + op ptr) < 3 send xoff
+; If ip = ip2 then if
+; (op ptr - input ptr ) < 3 send xoff
+;
+; First decide whice one applies
+
+ mov a,b ; get ip ptr
+ sub c ; see if op ptr > ip ptr (case 2)
+ jm outp2 ; yup, so do case two
+ mvi a,szecyc ; else do buffer - ip + op
+ sub b
+ add c
+ jmp outpx ; do common test
+outp2: mov a,c ; get op pointer
+ sub b ; less input pointer
+outpx: ret ; with free space in a
+;
+;
+;
+; print - get a character from the buffer and print it if the printer
+; is ready for it. If the buffer clears more than 3 spare characters
+; and an xoff has been sent, then send an xon again.
+print: push h ; save for rainy days
+ push d
+ push b
+ push psw ; .. as we may need flags etc....
+ lda initflg ; First check if the system has initialised
+ ana a
+ jz printx ; If system not set up then skip
+; nop
+; nop
+; nop ; debugging only...
+ call ckprtr ; check to see if printer is ready...
+ ana a ; not zero => ok
+ jz printx ; else skipit.
+; nop
+; nop
+; nop ; skip the jump for debugging
+ lxi h,prnbuf
+ mov a,m ; get input pointer
+ inx h ; test against output pointer
+ cmp m ; if = then buffer empty
+ jz printx ; so quit
+ dcx h ;pointer to output pointer
+ call wrapt ; check for wrap around
+ sta prnbuf ; save new pointer
+ inx h
+ inx h ;
+ call inchl ; add output pointer to hl
+ mov c,m ; get byte
+ lda hosths ; have we told host to be quiet?
+ cpi xoff ; if = xoff then we have
+ jnz print1 ; nope, so just print it..
+ push b ; save the character to print
+ call tstfree ; see how many free bytes in buffer
+ pop b
+ cpi 4 ; 3 characters left?
+ jz printx
+ push b
+ call sndxon ; send an xon to host and wake it up.
+ pop b
+print1: mov a,c ; we are gonna print a character, so ...
+ call outprx ; get it to a (as required by outprx) and print it
+printx:
+ pop psw
+ pop b
+ pop d
+ pop h ; restore regs.
+ ret
+
+;
+; Utilities for the cyclical buffer. Returns a 0ffh if printer ready,
+; else 0h. Called by outprn, print
+
+ckprtr:
+ call lptstat ; no registers saved
+; mvi a,0 ; FOR DEBUGGING PURPOSES
+; nop
+ ret
+;
+
+inchl: push psw ; we do maths through this register
+ add l
+ mov l,a
+ mvi a,0
+ adc h
+ mov h,a
+ pop psw ; hl = a + hl
+ ret
+
+; wrapt - checks the offset in a with the limits of the buffer.
+; returns next address or if wrap around then 0 (start of buffer)
+wrapt: push b
+ inr a
+ mov b,a ; save new a into b for now
+ mvi a,szecyc ; test for size of buffer
+ sub b
+ mov a,b
+ pop b ; restore bc regs again
+ rnz
+ xra a ; if wrap around, then reset pointer
+ ret ; return with next address pointer to in a
+
+; sndxoff - send an xoff to the host and save the xoff character in hosths
+; saves all regs. is called by logwrt, outprn
+sndxoff:
+ push psw
+ push b
+ push d
+ push h ; some calling routines may be sensitive...
+ lda floctl ; are we doing flow control?
+ ana a
+ jz sndxf ; no, so dont bother.
+ mvi a,xoff ;^S to stop the host while we write the buffer.
+ sta hosths ; save it so we know we have sent it
+ call setpar ; set correct parity...
+ mov e,a
+ call outmdm ; output it.
+ lxi d,ofsnt ; say we have sent an xoff
+ call prtstr
+sndxf: pop h
+ pop d
+ pop b
+ pop psw ; some routines touchy
+ ret
+ofsnt: db cr,lf,'[XOFF sent to host]',cr,lf,'$'
+
+; sndxon - send an xon to the host and clear the hosths flag. saves everything
+; called by logwrt, print
+sndxon: push psw
+ push b
+ push d
+ push h
+ lda floctl ; are we doing flow control?
+ ana a
+ jz sndxn
+ xra a
+ sta hosths ; no xoff to hos any more
+ mvi a,xon ;^Q to restart the host
+ call setpar ; set appropriate parity
+ mov e,a
+ call outmdm ; send it.
+ lxi d,onsnt
+ call prtstr ; say xon sent to host...
+sndxn: pop h
+ pop d
+ pop b
+ pop psw
+ ret ; shame we dont do a pushall/popall subroutine...
+onsnt: db cr,lf,'[XON sent to host]',cr,lf,'$'
+;
+; Routines to clear (or rather fill) TEMPnnn space with the data in A
+; and to shift it all along one (filltmp an shiftmp respectively)
+filltmp:
+ push b
+ push d
+ push h ; save all
+ lxi h,temp1
+ mvi b,10 ; ten locations to fill
+fillp: mov m,a
+ inx h
+ dcr b ; loop til all done
+ jnz fillp
+ pop h
+ pop d
+ pop b ; restore all
+ ret
+
+shiftmp:
+ push psw ; save all again
+ push b
+ push d
+ push h
+ lxi d,temp9
+ lxi h,temp10
+ mvi b,9 ; shift nine times
+shiftl: ldax d ; from tempx
+ mov m,a ; to tempx+1
+ dcx d
+ dcx h ; mover does not work as that increments
+ dcr b
+ jnz shiftl
+ pop h
+ pop d
+ pop b
+ pop psw
+ ret ; else all done
+
+; getun - get the user number to temp1 (lsd) and temp2 (msd)
+;
+getun: mvi a,0ffh ; tell nout to be quiet
+ sta nquiet
+ mvi c,usrcod
+ mvi e,0ffh ; get current user from bdos
+ call bdos
+ mov l,a ; put into hl
+ mvi h,0
+ call nout ; decimalise it (decimalise???)
+ xra a
+ sta nquiet ; let nout print again
+ ret
+
+; ckcon - Do a direct console IO (read) to see if there is any input
+; returns with a=0 (no input) or character (input received)
+; Assume that all regs may be destroy.
+ckcon: mvi e,0ffh ; direct console input
+ mvi c,dconio
+ call bdos
+ ret ; and return with wahtever returned in a
+
+
+
+;
+; subbc - Subtract the unsigned number in bc from the unsigned number
+; in HL with the answer in HL. Flags altered, all
+; other registers left intact.
+subbc: sta temp1 ; hl = hl - bc.. we need the accumulator
+ mov a,l
+ sub c
+ mov l,a
+ mov a,h
+ sbb b
+ mov h,a
+ lda temp1 ; restore loop counter but not flags
+ ret
+
+; P20LN - Routine to print a string at (DE) and count the number of
+; line feeds. Pause after 20 lines printed.
+p20ln: xra a ; clear the line counter
+ sta lincnt
+p20ln1: ldax d ; get character to print
+ inx d
+ cpi '$' ; if a dollar we have done
+ rz
+ push d
+ push psw ; save pointer and character to print
+ mov e,a
+ call outcon ; send character
+ pop psw
+ pop d ; restore pointers etc
+ cpi lf ; was that last character a line feed?
+ jnz p20ln1 ; no, so carry on
+ lda lincnt ; yup, so update counter
+ inr a
+ sta lincnt
+ cpi 20 ; 20 lines printed?
+ jnz p20ln1 ; not yet
+ push d ; we need DE
+; lxi d,anymes ; pause a while [MF]removed
+; call prtstr ; write the message [MF]
+;p20ln2: call ckcon ; wait for any input [MF]
+; ana a ;[MF]
+; jz p20ln2 ;[MF]
+ call pausit ;[MF] pause a while
+ pop d
+ jmp p20ln ; and continue
+
+
+; Little code to allow some expansion of code without changing
+; every futher address, only up to the end of this file.
+; TO BE REMOVED FOR RELEASE!
+
+; org ($+100h) AND 0FF00H
+
+; link to the data area (was part of CPSUTL.ASM)
+
+IF lasm
+ LINK CPSDAT
+ENDIF ;lasm
diff --git a/src/cpswld.asm b/src/cpswld.asm
new file mode 100644
index 0000000..8be6558
--- /dev/null
+++ b/src/cpswld.asm
@@ -0,0 +1,222 @@
+; CPSWLD.ASM
+; 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
+; 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.
+;
+; Multi-file access subroutine. Allows processing of multiple files
+; (i.e., *.ASM) from disk. This routine builds the proper name in the
+; FCB each time it is called. This command would be used in such pro-
+; grams such as modem transfer, tape save, etc. in which you want to
+; process single or multiple files.
+; Note that it will fail if more than 256 entries match the wildcard.
+;
+; revision history:
+; edit 4: June 20, 1986, by OBSchou. Added stuff at top and tail of routine
+; to support multiple FCBs. If the routine get to mfn01 (Search for next)
+; then the next file found gets its fcb added to the buffer. Once no
+; more files have been found, the mfflg3 flag is set non-zero.
+; The first thing to test on entry is whether a disk access
+; is needed. Either way, the routine should return the next file name
+; in the fcb, or return with the carry flag set if there are no more
+; files to do. Once there is a carry flag set for the return, all
+; temporary flags are reset. Get all that?
+;
+; edit 3: July 27, 1984
+; support LASM: remove exclamation points, link to CP4CMD.
+;
+; edit 2: June 7, 1984 (CJC)
+; formatting and documentation; add module version string; redo movfcb,
+; in preparation for moving DMA buffer (later...).
+;
+; edit 1: May, 1984 (CJC)
+; extracted from CPMBASE.M80 version 3.9; modifications are described
+; in the accompanying .UPD file.
+;
+wldver: db 'CPSWLD.ASM (4) 20-Jun-86$'
+
+; The FCB will be set up with the next name, ready to do normal
+; processing (OPEN, READ, etc.) when routine is called.
+;
+; Carry is set if no more names can be found
+;
+; MFFLG1 is count/switch [0 for first time thru, pos for all others]
+; MFFLG2 is counted down for each successive GETNEXT file call
+; MFFLG3 is set to the last remaining FCBs buffered once Search for next
+; file fails with files in the buffer.
+;
+; Technique used is to repeat SFIRST/SNEXT sequence N+1 times for each
+; successive call, till sequence fails. CP/M does NOT allow disk-handling
+; between SFIRST and SNEXT.
+; called by: send, seof, dir
+
+mfname: ora a ; clear carry
+ push b ;Save registers
+ push d
+ push h
+ jmp mfnam0 ; skip over the next bit (which is entered from elsewhere)
+
+;[4] Get the FCB counter and see if we have any fcbs already.
+mfnam1: lxi h,fcb0
+ shld xfcbptr ; reset the pointer if we are to return an FCB
+
+mfnam0: lda fcbcnt
+ ana a ; if none, then we may have to get some from disk
+ jz mfn00 ; see later on
+ lhld xfcbptr ; we have some, so give the next one to the user
+ lxi d,fcb ; move from (hl) to (de) for length bc
+ lxi b,12
+ call mover
+ xra a
+ sta fcbext ; clear fcb extents and such
+ sta fcbrno ; like record number
+ lhld xfcbptr ; point to next fcb
+ lxi d,fcblen
+ dad d ; yup
+ shld xfcbptr
+ lda fcbcnt
+ dcr a
+ sta fcbcnt ; decrease the number of fcbs we have
+ xra a ; clear carry
+ jmp mffix1 ; and exit as if were all done
+
+mfn00: lda mfflg3 ; no more FCBs for the user, any more on disk?
+ ana a
+ jnz mffix2 ; no, then set the carry flag to say so.
+ lxi h,fcb0 ; now reset the fcb pointers and counter
+ shld xfcbptr
+ xra a
+ sta fcbcnt
+;[4] end of this addition. See below as well.
+
+
+ mvi c,setdma ;Init DMA addr, FCB
+ lxi d,80H
+ call bdos
+ xra a ;A = 0
+ sta fcbext ;clear extension
+ lda mfflg1 ;find out if "second" call in row
+ ora a
+ jnz mfn01 ;Were here before
+ sta mfflg2
+ lxi h,fcb
+ lxi d,mfreq
+ lxi b,12
+ call mover ;.from FCB to MFREQ
+ mvi c,SFIRST ;Search first
+ lxi d,fcb
+ call bdos
+ jmp mfn02 ;and check results
+
+mfn01: dcr a
+ sta mfflg2 ;store down-counter
+ lxi h,mfreq ;SFIRST REQ name
+ lxi d,fcb
+ lxi b,12
+ call mover ;.from MFREQ to FCB
+ mvi c,sfirst ;Search first old one,we got it before
+ lxi d,fcb
+ call bdos ;no error's expected -we got that before
+mfn01a:
+ mvi c,snext ;Search next
+ call bdos
+mfn02: push psw
+ lda mfflg2 ;get "repeat file counter"
+ ora a
+ jz mfn02a ;if zero, check if SNEXT had ERROR
+ dcr a ;count down
+ sta mfflg2 ;store back
+ pop psw ;no error-check, we got it before
+ jmp mfn01a ;next SNEXT
+
+mfn02a: pop psw
+ ora a
+ jm mffi2a ;No (more) found
+ call movfcb ;move data to fcb
+ lda mfreq ;the original disk-designator
+ sta fcb ;back into fcb
+ lda mfflg1 ;get file-flag
+ inr a ;increment
+ sta mfflg1 ;and store for next go-around
+ mvi a,0 ;Setup FCB
+ sta fcbext ;clean up FCB for OPEN etc
+ sta fcbrno
+ lhld xfcbptr ;[4] like here
+ xchg
+ lxi h,fcb ;[4] from fcb space
+ lxi b,12
+ call mover
+ lhld xfcbptr ;[4] now lets update the pointers
+ lxi d,fcblen
+ dad d
+ shld xfcbptr ;[4] new pointer
+ lda fcbcnt ;[4] now the fcb counter
+ inr a
+ sta fcbcnt
+ cpi maxfcb ;[4] any more spare space?
+ jp mfnam1 ;[4] nope, so get first fcb and return
+ lxi d,fcb ; else restore the file to serach for
+ lxi h,mfreq
+ lxi b,12 ; copy the original fcb to fcb
+ call mover
+ jmp mfn01a ; and look for next match.
+
+mffix1: pop h ;restore registers
+ pop d
+ pop b
+ ret ;and return
+
+mffi2a:
+ sta mfflg3 ;[4] no more FCBs from disks to be had, but
+ lda fcbcnt ;[4]we have some in the buffer, havet we?
+ ana a
+ jnz mfnam1 ;[4] yes, so all's ok. Get an fcb and return,
+
+mffix2: xra a
+ sta mfflg3 ;[4] clear the new flag (=no more fcbs at all)
+ sta mfflg2 ;[4] may as well do the others, as we're not comming again
+ sta mfflg1 ;[4]
+ stc ;set carry
+ jmp mffix1 ;return with CARRY set
+
+; copy directory entry to FCB
+; called with A/ entry number in directory (0-3)
+; directory block in DMA buffer (buff)
+
+movfcb: add a
+ add a
+ add a
+ add a
+ add a ;* 32
+ mov c,a ; copy offset to bc
+ mvi b,0 ; (high byte is zero)
+ lxi h,buff ; get start of disk buffer
+ dad b ; calculate start of directory entry
+ lxi d,fcb
+ lxi b,12
+ call mover
+ ret
+
+; Data storage for MFNAME (multi-file access)
+mfreq: DS 12 ;Requested name
+mfflg1: DB 0 ;First time thru flag for MFNAME
+mfflg2: DB 0 ;Down counter for MFNAME
+mfflg3: DB 0 ;[4] Non zero if no more FCBs from disk,
+ ;[4] but we still have some in buffer
+;
+IF lasm
+ LINK CPSCMD
+ENDIF;lasm
+
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
diff --git a/src/cpxbbi.asm b/src/cpxbbi.asm
new file mode 100644
index 0000000..ffbdc14
--- /dev/null
+++ b/src/cpxbbi.asm
@@ -0,0 +1,618 @@
+IF NOT lasm
+.printx * CPXBBI.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.08
+;
+; 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 4, 7-Jan-1991 by MF. Added code to support the Ampro Little Board.
+; The code was contributed by Jay S. Rouman; 913 North Drive;
+; Mt. Pleasant, MI 48858 (voice (517)773-7887).
+; edit 3, 23 July by OBSchou to massage file to suit CPXCOM.ASM
+;
+; edit 2 23 May 1987 by C.J.MILES@UMRCC.
+; Reorganised file to be similar in structure to that
+; of the Amstrad sys-dep file. Added hangup in clear
+; screen options in CONNECT mode.
+;
+; edit 1 10 May 1987 by Chris Miles (C.J.MILES@UMRCC)
+; Removed Kaypro, Xerox and Big Board from CPXSYS.ASM
+; and grouped them into this file as CPXBBI.ASM.
+;
+;
+;
+; Original code broken off and modified by:
+;
+; Chris Miles
+; 344, Claremont Road,
+; Rusholme,
+; MANCHESTER,
+; M14 6WB.
+;
+; Tel: (061) 226 7839
+;
+
+;
+; *** MAIN CODE START ***
+;
+;
+; Keep module name, edit number, and last revision date in memory.
+
+sysedt: db 'CPXSYS.ASM (35) 01-Dec-86$'
+family: db 'CPXBBI.ASM (4) 7-Jan-1991$'
+
+
+; Assembly time message announcing which version we're building
+
+IF kpii
+.printx * Assembling Kaypro II KERMIT-80 *
+ENDIF
+
+IF xer820
+.printx * Assembling Xerox 820 KERMIT-80 *
+ENDIF
+
+IF bbII
+.printx * Assembling BigBoard II KERMIT-80 *
+ENDIF
+
+IF ampro
+.printx * Assembling Ampro Little Board KERMIT-80 *
+ENDIF
+
+z80 EQU TRUE ; They all use Z80s
+
+IF xer820
+defesc EQU ']'-100O ;The default escape character for Xerox
+ENDIF;xer820
+
+IF kpII
+defesc EQU '\'-100O ;The default escape character for Kaypro
+ENDIF;kpII
+
+; If one of the above, default to VT52-EMULATION ON.
+IF kpII OR xer820
+vtval EQU 1
+ENDIF;kpII OR xer820
+
+
+;
+; Specific machine hardware information
+;
+IF bbI
+mnport equ 04h ; Modem data port
+mnprts equ 06h ; Modem status port
+output equ 04h ; Transmit buffer empty
+input equ 01h ; Receive data available
+baudrt equ 00h ; Baud rate port for channel A
+ENDIF;bbI
+
+
+IF bbII
+mnport equ 80h ; Modem data port (SIO channel A)
+mnprts equ 81h ; Modem status port
+output equ 04h ; Transmit buffer empty
+input equ 01h ; Receive data available
+baudrt equ 89h ; Baud rate port for channel A
+ENDIF;bbII
+
+IF ampro
+mnport equ 88h ; Modem data port (SIO channel B)
+mnprts equ 8Ch ; Modem status port
+output equ 04h ; Transmit buffer empty
+input equ 01h ; Receive data available
+baudrt equ 50h ; Baud rate port for channel B
+ENDIF;ampro
+;
+
+sysxin: ;continuation of system initialisation code
+ lxi d,siotbl ; Load the address of the status able
+ mvi c,siolen ; Length of status table
+siolup: ; Loop back here for each command byte
+ ldax d ; Load the first byte into A
+ inx d ; Index the pointer
+ out mnprts ; Send it to the status port
+ dcr c ; Decrement the byte counter
+ jnz siolup ; Jump back for more commands
+ ret ; return from system-dependent routine
+
+; List of commands to set up SIO channel A for asynchronous operation.
+
+siotbl: DB 18H ; Channel reset
+ DB 18H ; another, in case register 0 wasn't selected
+ DB 04H ; Select register 4
+ DB 44H ; 1 stop bit, clock*16
+ DB 01H ; Select register 1
+ DB 00H ; No interrupts enabled
+ DB 03H ; Select register 3
+ DB 0C1H ; Rx enable, 8 bit Rx character
+ DB 05H ; Select register 5
+ DB 0EAH ; Tx enable, 8 bit Tx character,
+ ; raise DTR and RTS
+siolen equ $-siotbl ; length of command list
+
+
+;
+; sysexit - System-dependent termination processing
+; if we've changed anything, this is our last
+; chance to put it back.
+;
+sysexit:
+ ret
+
+;
+; syscon - System-dependent processing for start
+; of CONNECT command.
+;
+syscon:
+ lxi d,conmsg
+ call prtstr
+ ret
+
+conmsg: ; Messages printed when entering transparent (CONNECT) mode:
+ db cr,lf,'$'
+;
+; 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:
+ db cr,lf,'B Transmit a BREAK'
+ db cr,lf,'H Hangup using DTR'
+ db cr,lf,'W Wipe screen clear'
+ db '$'
+
+; 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 'B' ; send break ?
+ jz sendbr ; then jump to send break routine
+ cpi 'H' ; hang up ?
+ jz hangup ; then jump to hangup routine
+ cpi 'W' ; clear screen ?
+ jz clrtop ; then jump to clear screen routine
+ jmp rskp ; take skip return - command not recognized.
+
+;
+; Hangup and Break routines
+;
+hangup:
+ mvi d,0ah ; set up hangup bit mask
+ mvi e,255 ; time for hangup is 2 1/2 secs
+ jmp setbit ; skip Tx empty test
+
+sendbr:
+ mvi d,9ah ; set up break bit mask
+ mvi e,30 ; time for break is 300 ms
+
+sndbr1: mvi a,1 ; select Read Register 1
+ out mnprts
+ in mnprts ; read the contents
+ ani 1 ; test "all done" flag
+ jz sndbr1 ; loop until it's nonzero.
+;
+; Next, set the break or DTR bit on the SIO
+;
+setbit:
+ mvi a,5 ; select Write Register 5
+ out mnprts
+ mvi a,6ah ; Tx enable, 8 bit Tx character,
+ ora d ; OR with appropriate bit mask
+ out mnprts ;
+;
+; Now, delay for duration of hangup or break
+ mov a,e ; delay count
+ call delay
+;
+; Time's up. Put transmitter back in normal state and return.
+ mvi a,5 ; select Write Register 5
+ out mnprts
+ mvi a,0eah ; Tx enable, 8 bit Tx character,
+ out mnprts ;.
+ ret ; done.
+
+; 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
+
+;
+; sysbye - system-dependent processing for BYE command.
+;
+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:
+
+; Set the speed for bigboard II
+IF bbII
+ di ; don't let anything between the data bytes
+ mvi a,01000111b ; get the command byte (load time constant)
+ out baudrt ; output it to CTC
+ mov a,e ; Get the parsed value.
+ out baudrt ; Tell the baud rate generator.
+ ei ; end of critical section
+ ret
+ENDIF;bbII
+
+
+; Set the speed for bigboard I
+IF bbI
+ mov a,e ; get the parsed value
+ out baudrt ; Tell the baud rate generator.
+ ret
+ENDIF;bbI
+
+; set the speed for the Ampro Little Board
+if ampro
+ mvi e,3fh ; offset to port b ctc 3f hex bytes
+ call getbios
+ mvi a,47h ; counter mode,ctc reset,value follows
+ mov m,a ; store value
+ lda speed+1 ; get ctc divisor
+ inx h ; location of ctc divisor
+ mov m,a ; store new divisor
+;
+; set up wr4 clock divisor according to mspeed
+;
+ mvi e,50h ; offset to dart wr4
+ call getbios
+ mvi a,3fh ; mask for wr4 clock bits
+ ana m ; mask off bits
+ mov m,a ; and save to wr4
+ lda speed ; get clock flag
+ ora a ; set flags, zero = 300 bps
+ mvi a,80h ; x32 clock bit
+ jz lbps ; setup wr4 for 300 bps x32 clock
+;
+; set up wr4 value for 1200 bps x16 clock 'hl' has wr4 loc
+;
+hbps: mvi a,40h ; x16 clock
+;
+; setup wr4 value for 300 bps x32 clock 'hl' has wr4 loc
+;
+lbps: ora m ; set clock bits saving parity
+ mov m,a ; store new clock divisor to wr4 value
+;
+; initialize sio/dart
+;
+intsio: lxi h,intend
+ push h ; set up for return
+ mvi e,36h ; offset to ioinit
+ call getbios
+ pchl ; we pushed return address
+intend: ret
+
+;
+; return bios location in 'hl' called with offset in 'e'
+;
+getbios:
+ lhld 1 ; get bios location
+ mvi d,0 ; clear 'd'
+ dad d
+ ret
+;
+ENDIF;ampro
+
+;
+; 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 bbI
+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;bbI
+
+IF bbII
+spdtbl: db 8 ; 8 entries
+ db 04h,'1200$', 20h,20h
+ db 05h,'19200$', 02h,02h
+ db 04h,'2400$', 10h,10h
+ db 03h,'300$', 80h,80h
+ db 05h,'38400$', 01h,01h
+ db 04h,'4800$', 08h,08h
+ db 03h,'600$', 40h,40h
+ db 04h,'9600$', 04h,04h
+
+sphtbl: db cr,lf,' 300 600 1200 2400 4800 9600 19200 38400$'
+ENDIF;bbII
+
+
+IF ampro
+spdtbl: db 6 ; 6 entries
+ db 04h,'1200$', 1,104
+ db 04h,'2400$', 1,52
+ db 03h,'300$', 0,208
+ db 04h,'4800$', 1,26
+ db 03h,'600$', 1,208
+ db 04h,'9600$', 1,13
+
+sphtbl: db cr,lf,' 300 600 1200 2400 4800 9600$'
+ENDIF;ampro
+
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+;
+sysprt:
+ ret
+;
+
+prttbl equ 0 ; SET PORT is not supported
+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.
+; preserves BC, DE, HL.
+;
+selmdm:
+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:
+ 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
+
+
+;
+; get character from modem; return zero if none available.
+; destroys bc, de, hl.
+inpmdm:
+ 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.
+
+ 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 ; 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
+ 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.)
+;
+IF NOT (bbII OR ampro) ;[obs I think ]
+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
+ENDIF ; NOT bbII OR ampro
+
+;
+; delchr - make delete look like a backspace. Unless delete is a
+; printing character, we just need to print a backspace
+; (we'll output clrsp afterwards)
+delchr:
+
+IF bbI
+ lxi d,delstr
+ jmp prtstr
+ENDIF;bbI
+
+
+IF NOT bbI
+ mvi e,bs ;get a backspace
+ jmp outcon
+ENDIF;NOT bbI
+
+; 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 its a BigBoard or Ampro, we need a terminal, so link to CPXVDU.ASM
+IF bbII
+sysver: db 'Big Board II$'
+ENDIF;bbII
+
+IF ampro
+sysver: db 'Ampro Little Board$'
+ENDIF;ampro
+
+IF (bbII AND lasm) ; we need a terminal as well
+LINK CPXVDU.ASM
+ENDIF ;(bbII AND lasm)
+
+IF (ampro AND lasm) ; we need a terminal as well
+LINK CPXVDU.ASM
+ENDIF ;(ampro AND lasm)
+
+;If here, we are Kaypro or Xerox 820, or if from M80, we should skip
+; a few lines if Bigboard.
+
+IF kpii
+sysver:
+ttytyp: db 'Kaypro II$'
+outlin: db subt,cr,lf,tab,tab,'$'
+erascr: db subt,'$' ;Clear screen and home.
+eralin: db cr,18H,'$' ;Clear line.
+curldn: db esc,'=$' ;Cursor lead-in
+delstr: db bs,' ',bs,bs,'$' ; adjust for echoing delete character
+ttab: ;Table start location.
+ta: db 0BH,'$',0,0 ;Cursor up.
+tb: db 0AH,'$',0,0 ;Cursor down.
+tc: db 0CH,'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left
+te: db subt,'$',0,0 ;Clear display
+tf: db esc,'G$',0 ; Enter Graphics Mode (select Greek)
+tg: db esc,'A$',0 ; Exit Graphics mode (select ASCII)
+th: db 1EH,'$',0,0 ; Cursor home. [UTK016]
+ti: db esc,'E','$',0 ; Reverse linefeed. (insert line)
+tj: db 'W'-100O,'$',0,0 ; Clear to end of screen.
+tk: db 'X'-100O,'$',0,0 ; Clear to end of line.
+ENDIF ; kpii
+;
+
+IF xer820
+ttytyp:
+sysver: db 'Xerox 820$'
+outlin: db subt,cr,lf,tab,tab,'$'
+erascr: db subt,'$' ;Clear screen and home.
+eralin: db cr,18H,'$' ;Clear line.
+curldn: db esc,'=$' ;Cursor lead-in
+delstr: db bs,' ',bs,bs,'$' ; adjust for echoing delete character
+ttab: ;Table start location.
+ta: db 0BH,'$',0,0 ;Cursor up.
+tb: db 0AH,'$',0,0 ;Cursor down.
+tc: db 0CH,'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left
+te: db subt,'$',0,0 ;Clear display
+tf: db '$',0,0,0 ; Enter Graphics Mode (can't)
+tg: db '$',0,0,0 ; Exit Graphics mode (can't)
+th: db 1EH,'$',0,0 ; Cursor home. [UTK016]
+ti: db 0BH,'$',0,0 ; Reverse linefeed. (cursor up)
+tj: db 11H,'$',0,0 ; Clear to end of screen.
+tk: db 18H,'$',0,0 ; Clear to end of line.
+ENDIF ; xer820
+ovlend equ $ ; End of overlay
+
+ END
diff --git a/src/cpxbee.asm b/src/cpxbee.asm
new file mode 100644
index 0000000..7333c2a
--- /dev/null
+++ b/src/cpxbee.asm
@@ -0,0 +1,996 @@
+IF NOT lasm
+.printx * CPXBEE.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.09
+;
+; 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 1, 1st September 1990
+; Original version by Russell Lang <rjl@monu1.cc.monash.edu.au>
+; The 'microbee' is designed and manufactured in Australia
+; by Microbee Systems Ltd (previously Applied Technology).
+; The microprocessor is a Z80 at 3.375MHz.
+; The video screen is memory mapped from 0F000h to 0F7FFh,
+; with Programmable Characters 80-FF from 0F800h to 0FFFFh.
+; The serial and parallel ports are implemented using a Z80 PIO.
+; The early model microbees were ROM-Basic computers with up
+; to 32k of battery backed RAM. Later models dropped the
+; ROM-Basic and added disk drives and CP/M. The disk systems
+; include the 56k (64k) APC (5.25" drives), 64k Computer-In-A-Book
+; (3.5"), 128k Dynamic (5.25" or 3.5"), 256TC (3.5").
+;
+; This version of kermit was developed on a 56k APC.
+; It has been tested on 56k, 64k, 128k and 256k Microbees.
+;
+; The serial port is implemented in software NOT hardware.
+; A special transmit routine allows simultaneous receiving
+; for all speeds except 75/1200, 1200/75, 4800, 9600.
+; The receive routine is interrupt driven with a 2 kbyte buffer.
+; The 9600 bit/s speed is marginal on receive - if the transmitter
+; is slightly fast (more than about 1%), the serial routine will
+; not have enough time to put the character in the buffer before
+; the next character arrives.
+
+
+;
+; *** MAIN CODE START ***
+;
+;
+; Keep module name, edit number, and last revision date in memory.
+
+sysedt: db 'CPXSYS.ASM (35) 01-Dec-86$'
+family: db 'CPXBEE.ASM (1) 01-Sep-90$'
+
+
+; Assembly time message announcing which version we're building
+
+.printx * Assembling Microbee Kermit-80 *
+
+z80 EQU TRUE ; They all use Z80s
+
+defesc EQU ']'-100O ;The default escape character for Microbee
+
+vtval EQU 0 ; use default emulation which is adm3a superset
+
+;
+sysxin: ;continuation of system initialisation code
+ ; set up baud rate
+ lxi h,t300
+ shld speed
+ xchg
+ call setbaud
+ ; change the interrupt vector so that we intercept rs232 input
+ db 0EDh,57h ;ld a,i ;get old interrupt reg
+ sta oldint
+ mvi a,int ;new value
+ db 0EDh,47h ;ld i,a
+ ret ; return from system-dependent routine
+
+
+;
+; sysexit - System-dependent termination processing
+; if we've changed anything, this is our last
+; chance to put it back.
+;
+sysexit:
+ lda oldint ;restore old interrupt reg
+ db 0EDh,47h ;ld i,a
+ ret
+
+;
+; syscon - System-dependent processing for start
+; of CONNECT command.
+;
+syscon:
+ lxi d,conmsg
+ call prtstr
+ ret
+
+conmsg: ; Messages printed when entering transparent (CONNECT) mode:
+ db cr,lf,'$'
+;
+; 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:
+ db cr,lf,'B Transmit a BREAK (0.3s)'
+ db cr,lf,'L Transmit a LONG BREAK (1.8s)'
+ db cr,lf,'W Wipe screen clear'
+ db '$'
+
+; 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 'B' ; send break ?
+ jz sendbr ; then jump to send break routine
+ cpi 'L' ; long break ?
+ jz longbr ; then jump to long break routine
+ cpi 'W' ; clear screen ?
+ jz clrtop ; then jump to clear screen routine
+ jmp rskp ; take skip return - command not recognized.
+
+;
+; Break routines
+;
+longbr:
+ mvi e,180 ; time for long break is 1800 ms
+ jmp setbit
+
+sendbr:
+ mvi e,30 ; time for break is 300 ms
+
+setbit:
+ in portb
+ ani 0dfh ; mask with tx bit
+ out portb
+;
+; Now, delay for duration of hangup or break
+ mov a,e ; delay count
+ call delay
+;
+; Time's up. Put transmitter back in normal state and return.
+ in portb
+ ori 20h ; mask with tx bit
+ out portb
+ ret ; done.
+
+; 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
+
+;
+; sysbye - system-dependent processing for BYE command.
+;
+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:
+ call setbaud
+ ret
+
+;
+; 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 11 ;11 entries
+ db 03h,'110$'
+ dw t110
+ db 04h,'1200$'
+ dw t1200
+ db 07h,'1200/75$'
+ dw t1275
+ db 03h,'150$'
+ dw t150
+ db 04h,'2400$'
+ dw t2400
+ db 03h,'300$'
+ dw t300
+ db 04h,'4800$'
+ dw t4800
+ db 03h,'600$'
+ dw t600
+ db 02h,'75$'
+ dw t75
+ db 07h,'75/1200$'
+ dw t7512
+ db 04h,'9600$'
+ dw t9600
+
+sphtbl: db cr,lf,'75 75/1200 110 150 300 600 1200 1200/75'
+ db ' 2400 4800 9600$'
+
+
+;
+; This is the system-dependent SET PORT command.
+sysprt:
+ ret
+
+prttbl equ 0 ; SET PORT is not supported
+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.
+; preserves BC, DE, HL.
+;
+selmdm:
+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:
+;
+ push psw
+ push b
+ push d
+ push h
+ mov a,e
+ lxi h,outm2 ; return address
+ push h
+ lhld txcall
+ pchl ; send to rs232 port
+outm2: pop h
+ pop d
+ pop b
+ pop psw
+ ret
+
+
+;
+; get character from modem; return zero if none available.
+; bc, de, hl preserved.
+inpmdm:
+ call rsin ; get char if available
+ 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:
+ lda pflag
+ ret
+
+;
+; outlpt - output character in E to printer
+; console is selected.
+; preserves de.
+outlpt:
+ push d ; save DE in either case
+ ana a ; if A = 0 do nothing,
+ jz outlp1 ; [30] if a=0 do nothing
+ mov a,e
+ call parout
+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 clrsp afterwards)
+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
+clrtop: lxi d,erascr
+ jmp prtstr
+
+
+sysver: db 'Microbee$'
+outlin: db 1AH,cr,lf,tab,'$' ;(Clear screen, home cursor)
+erascr: db 1AH,'$' ;Clear screen and go home.
+eralin: db cr,esc,'T$' ;Clear line.
+delstr: db 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 ('L'-100O),'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left.
+te: db subt,'$',0,0 ;Clear screen.
+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.
+
+
+;Microbee software serial port routines
+porta equ 0
+portb equ 2
+
+
+; interrupt vectors
+; We change the Z80 Interrupt register to point to these vectors.
+; Instead of trying to identify a particular Microbee system,
+; we just put vectors here for all systems.
+;
+; known vectors are:
+; 48h : 56k (64k apc) - tested 19-Jun-1990
+; 48k : 64k - tested 01-Sep-1990
+; 50h : dreamdisk (3rd party disk for Microbee)
+; e0h : 128k - tested 19-Jun-1990
+; e0h : 256k - tested 01-Sep-1990
+
+ org ($ and 0ff00h) + 100h
+int equ $/256 ; byte for interrupt register
+
+ dw inta ; printer vector
+ dw intb ; rs232 vector
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+ dw inta
+ dw intb
+
+
+; tables for baud rates
+t75: db 124,13 ; full delay
+ db 55,7 ; semi delay
+ db 168,255 ; txrx delay
+ dw trout ; address of subroutine to transmit char
+t7512: db 124,13 ; 75R/1200T
+ db 55,7
+ db 194,1 ; txout delay
+ dw txout
+t110: db 129,9
+ db 55,5
+ db 5,217
+ dw trout
+t150: db 59,7
+ db 23,4
+ db 2,158
+ dw trout
+t300: db 26,4
+ db 134,2
+ db 3,75
+ dw trout
+t600: db 139,2
+ db 191,1
+ db 2,34
+ dw trout
+t1200: db 195,1
+ db 90,1
+ db 3,13
+ dw trout
+t1275: db 195,1 ; 1200R/75T
+ db 90,1
+ db 124,13
+ dw txout
+t2400: db 94,1
+ db 40,1
+ db 2,3
+ dw trout
+t4800: db 44,1
+ db 15,1
+ db 44,1
+ dw txout
+t9600: db 19,1
+ db 1,1
+ db 19,1
+ dw txout
+
+
+; copy table entries to locations used by serial routines
+setbaud:
+ lxi h,fulldel
+ mvi b,8
+setb2: ldax d
+ mov m,a
+ inx h
+ inx d
+ dcr b
+ jnz setb2
+ ret
+
+
+;transmit character in E
+; destroys all regs
+txout: mvi b,ntotal ;total number of bits to send
+ di
+ in portb ;c = portb with tx bit zeroed
+ ani 0dfh
+ mov c,a
+ ora a ;carry=0 (start bit)
+txout2: mov a,c ; 4T
+ jnc txout4 ;10T skip if space
+ ori 20h ; 3T (average) set mark
+txout4: out portb ;11T
+ lhld txrxdel ;16T
+txout6: dcr l ;delay
+ jnz txout6
+ dcr h
+ jnz txout6 ; 14*L + 14*H + 3584*(H-1)
+ stc ; 4T carry=1 (stop bit)
+ mov a,e ; 4T shift next bit to carry
+ rar ; 4T
+ mov e,a ; 4T
+ dcr b ; 4T
+ jnz txout2 ;10T
+ ;loop = 74T + (delay loop)
+ ei
+ ret
+
+
+;
+;transmit character in E
+;simultaneous receive char if necessary
+trout: mov a,e
+ mvi b,ndata
+ lxi h,0
+tro2: rrc ;shift tx char to hl
+ mov c,a
+ mov a,l
+ ral
+ mov l,a
+ mov a,h
+ ral
+ mov h,a
+ mov a,c ;recover
+ dcr b
+ jnz tro2
+tro10: mvi b,tqfudge ;adjust char in hl to align with
+ ;tx bit of portb
+tro12: stc ; pad out
+ mov a,l
+ ral
+ mov l,a
+ mov a,h
+ ral
+ mov h,a
+ dcr b
+ jnz tro12
+ mvi a,0ffh ;flag to say we are not receiving
+ sta trtemp ;save it
+ mvi d,tqbit ;total number of qtr bits to send
+ in portb ;b = portb with tx bit zeroed
+ ani 0dfh
+ mov b,a
+ mvi e,0 ;we are not receiving yet
+tro14: in portb
+ ori 8h ;test CTS
+ jz tro14 ;loop till Clear To Send
+ out 09h ;Color Wait OFF
+ di
+ call qbit
+ lda trtemp ;are we receiving
+ ora a
+ jnz tro22 ;skip if not
+ in portb ;is last bit a mark?
+ ori 10h
+ jz tro18 ;skip if mark (don't wait for stop)
+ lhld fulldel ;delay to stop bit
+tro16: dcr l
+ jnz tro16
+ dcr h
+ jnz tro16
+tro18: lhld wptr ; check buffer
+ xchg
+ lhld rptr
+ dcx d ; decrement queue pointer
+ mov a,d
+ ora e
+ jnz tro20 ; skip if no queue wrap around
+ lxi d,maxque-1 ; wrap around
+tro20: mov a,l ; sub hl,de
+ sub e
+ mov l,a
+ mov a,h
+ sbb d
+ mov h,a
+ ora l ; check for zero
+ jz tro22 ; skip if buffer full
+ xchg
+ shld wptr ; update queue
+ lxi d,rqueue
+ dad d
+ mov m,c ; put char in queue
+tro22: ei
+ ret ;ret
+
+
+; routine for quarter bit timing
+; for transmit and simultaneous receive
+; total execution time is 223T + L*14T + H*34T
+qbit: call txrx ;17T + 162T
+ lda txrxdel ;13T
+qbit2: dcr a ; 4T
+ jnz qbit2 ;10T
+ lda txrxdel+1 ;13T
+qbit4: dcr a ; 4T
+ nop ; 4T
+ nop ; 4T
+ nop ; 4T
+ nop ; 4T
+ nop ; 4T
+ jnz qbit4 ;10T
+ mov a,d ; 4T Check if still sending or receiving
+ ora e ; 4T
+ jnz qbit ;10T
+ ret
+
+
+;simultaneous transmit/receive
+;do next quarter bit
+; regs: b = portb with tx bit zeroed
+; c = character being received
+; d = number of qtr bits remaining to send
+; e = number of qtr bits remaining to receive (0 if not receiving)
+; hl = character being transmitted
+;this subroutine always executes in 162T (or 163T)
+txrx: mov a,d ; 4T qtr bits remaining to send
+ ora a ; 4T
+ jz txrx12 ;10T skip if no bits remaining (may be receiving)
+ ani 03h ; 7T a complete bit?
+ jnz txrx10 ;10T skip if not
+ dad h ;11T shift tx bit to bit 5 of h
+ mov a,h ; 4T
+ ani 20h ; 7T extract tx bit
+ ora b ; 4T combine with portb
+ out portb ;11T send it
+txrx2: dcr d ; 4T one less qtr bit to send
+ ;76T total
+;now receive part
+txrx4: mov a,e ; 4T qtr bits remaining to receive
+ ora a ; 4T
+ jz txrx16 ;10T skip if not receiving
+ ani 3h ; 7T a complete bit?
+ jnz txrx14 ;10T skip if not
+ in portb ;11T get input
+ ani 10h ; 7T extract rx bit
+ sui 1 ; 7T bit to carry
+ mov a,c ; 4T bit to c
+ rar ; 4T
+ mov c,a ; 4T
+txrx6: dcr e ; 4T one less qtr bit to receive
+txrx8: ret ;10T
+ ;86T total
+
+;come here if transmitting, but not a complete bit
+;delay to match up execution times
+txrx10:
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ori 00h ; 7T
+ jmp txrx2 ;10T
+
+;come here if not sending (but still receiving)
+;delay to match up execution times
+txrx12: ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ jmp txrx4 ;10T
+
+;come here if receiving (but not a complete bit)
+;delay to match up execution time
+txrx14: ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ori 00h ; 7T
+ jmp txrx6 ;10T
+
+;come here if not receiving
+txrx16: in portb ;11T check if start bit
+ ani 10h ; 7T
+ jz txrx18 ;10T skip if mark
+ mvi e,rqbit ; 7T get quarter bit count for receive
+ xra a ; 4T
+ sta trtemp ;13T store flag to say we are receiving
+ ori a ; 7T delay (should be 6T)
+ ret ;10T
+
+txrx18: ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ ora a ; 4T
+ jmp txrx8 ;10T
+
+
+
+
+; RS232 input interrupt routine
+; stores received character in queue
+; ;semi delay starts here
+intb: ;20T (approx.) for interrupt
+ push psw ;11T
+ push b ;11T
+ push d ;11T
+ push h ;11T
+ in portb ;11T
+ ani 10h ; 7T test input for start bit
+ jz intb16 ;10T skip if no start bit.
+ out 09h ;11T
+ lhld semidel ;16T half bit delay
+intb2: dcr l ; 4T
+ jnz intb2 ;10T inner loop 14T*L
+ dcr h ; 4T
+ jnz intb2 ;10T outer loop (14*H + 256*14*(H-1))T
+ mvi e,8 ; 6T number of data bits
+ ;semi delay ends here (125T + delay loop)
+ ;full delay starts here
+intb4: lhld fulldel ;16T full bit delay
+intb6: dcr l
+ jnz intb6
+ dcr h
+ jnz intb6 ; 14*L + 14*H + 3584*(H-1)
+ in portb ;11T test input
+ ani 10h ; 7T
+ sui 1 ; 7T input bit to carry
+ mov a,c ; 4T
+ rar ; 4T
+ mov c,a ; 4T and then to C
+ dcr e ; 4T bit count
+ jnz intb4 ;10T loop till all data bits collected
+ ;full delay ends here (67T + delay loop)
+ in portb
+ ani 10h
+ jz intb12 ; skip if mark
+ lhld fulldel ; wait for stop bit
+intb10: dcr l
+ jnz intb10
+ dcr h
+ jnz intb10
+intb12: lhld wptr ; check buffer
+ xchg
+ lhld rptr
+ dcx d ; decrement queue pointer
+ mov a,d
+ ora e
+ jnz intb14 ; skip if no queue wrap around
+ lxi d,maxque-1 ; wrap around
+intb14: mov a,l ; sub hl,de
+ sub e
+ mov l,a
+ mov a,h
+ sbb d
+ mov h,a
+ ora l ; check for zero
+ jz intb16 ; skip if buffer full
+ xchg
+ shld wptr ; update queue
+ lxi d,rqueue
+ dad d
+ mov m,c ; put char in queue
+intb16: pop h
+ pop d
+ pop b
+ pop psw
+ ei
+ db 0EDh,4Dh ;reti
+
+;
+; get char from serial port buffer.
+; exit: A=char or Z if no char
+rsin: push d
+ push h
+ lhld rptr
+ xchg
+ lhld wptr
+ mov a,l ;sub hl,de
+ sub e
+ mov l,a
+ mov a,h
+ sbb d
+ mov h,a
+ ora l ;check for zero
+ jnz rsi4 ;get char
+rsi2: pop h
+ pop d
+ ret
+
+rsi4: push psw
+ dcx d ; decrement queue pointer
+ mov a,d
+ ora e
+ jnz rsi6 ; skip if no queue wrap around
+ lxi d,maxque-1 ; wrap around
+rsi6: pop psw
+ xchg
+ shld rptr
+ lxi d,rqueue
+ dad d
+ mov e,m ;get char from queue
+ ori 0ffh ;set NZ
+ mov a,e
+ jmp rsi2
+
+; printer routines
+
+inta: sta ptemp
+ mvi a,0
+ sta pflag
+ lda ptemp
+ ei
+ db 0EDh,4Dh ;reti
+
+parout: push h
+ lxi h,pflag
+par2: db 0CBh,46h ;bit 0,(hl)
+ jnz par2
+ mvi m,0ffh
+ out porta
+ pop h
+ ret
+
+; data storage
+
+oldint: db 0 ; storage for old i reg
+trtemp: db 0
+ptemp: db 0 ;temp storage used by inta interrupt
+pflag: db 0 ;0ffh if waiting for printer. 00h if ready
+
+;receive queue pointers
+maxque equ 2048 ; receiver queue size
+rptr: dw maxque-1
+wptr: dw maxque-1
+
+;transmit
+ndata equ 8 ; 8 data bits
+nstrt equ 1 ; 1 start bit
+nstop equ 1 ; 1 stop bit
+ntotal equ nstrt+ndata+nstop
+rqbit equ 4*(nstrt+ndata) ;number of quarter bits to receive
+tqbit equ 4*(nstrt+ndata+nstop) ;number of quarter bits to transmit
+tqfudge equ 13-nstrt-ndata
+
+;H=0 or L=0 behave as 256
+;receive delays.
+fulldel: dw 0 ; 3584(H-1) + 14H + 14L + 67 cycles
+semidel: dw 0 ; 3584(H-1) + 14H + 14L + 125 cycles
+;1/4 bit transmit and simultaneous tx/rx delay 34H + 14L + 223 cycles
+;or full bit delay 3584(H-1) + 14H + 14L + 74 cycles
+txrxdel: dw 0 ;
+txcall: dw trout ; address of subroutine to transmit char
+
+; receiver queue
+rqueue: ds maxque
+
+
+ovlend equ $ ; End of overlay
+
+IF lasm
+ END
+ENDIF
diff --git a/src/cpxcif.asm b/src/cpxcif.asm
new file mode 100644
index 0000000..d4568c4
--- /dev/null
+++ b/src/cpxcif.asm
@@ -0,0 +1,746 @@
+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
+
diff --git a/src/cpxcom.asm b/src/cpxcom.asm
new file mode 100644
index 0000000..7c3034e
--- /dev/null
+++ b/src/cpxcom.asm
@@ -0,0 +1,486 @@
+IF NOT lasm
+.printx * CPXCOM.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 part common code required for most if not all
+; systems. Specifiacally, SYSINIT, INIADR, MOVER, and DELAY to name
+; the most important ones.
+;
+; revision history:
+;
+; edit 1, 21st July 1987 by OBSchou. Regretably, I have had to include
+; some system dependent IFs, mainly for CRT, TORCH and OSI. Inclusion
+; here means simpler family files later on. (Regrettably, the delay
+; loop for APMMDM differs too.)
+;
+; Set the fuzzy timeout value. Range is 1 (VERY short) through 0ffffH to zero
+; (maximum). The actual duration is a function of the loop length and the
+; processor speed. For now, we'll make it zero for everybody, but feel free
+; to change it for your system.
+; [OBS] make it a little less than max, say 1000H. More useful.
+fuzval EQU 1000H
+
+;
+; System-dependent initialization
+; Called once at program start.
+sysinit:
+;
+; [13] Had to move this call to here, as the prtstr routine needs this
+; before the config message is sent out. It has only been moved.
+;
+ call iniadr ;Initialize the BIOS addresses
+ mvi c,gtiob ;Get current I/O byte
+ call bdos ;From CP/M
+ sta coniob ;Remember where console is
+ mvi c,getvnm ; get the BDOS version number (e.g. 22H, 31H)
+ call bdos
+ mov a,l
+ sta bdosvr ; and store it away for future reference
+ lxi d,cfgmsg ; "configured for "
+ call prtstr
+ lxi d,sysver ; get configuration we're configured for
+ call prtstr ; print it.
+;
+; If we're set up to do special terminal handling, say what kind
+; of terminal we expect... (unless it's the generic 'crt')
+IF termin
+ lxi d,witmsg ; " with "
+ call prtstr
+ lxi d,ttytyp ; terminal type
+ call prtstr
+ENDIF;termin
+ call prcrlf ; print CR/LF
+;
+; now, to work...
+;
+; locate large buffer for multi-sector I/O
+; What we want to do here is find the ccp. Space between ovlend and the ccp
+; is available for buffering, except we don't want to use more than maxsec
+; buffers (if we use too many, the remote end could time out while we're
+; writing to disk). maxsec is system-dependent, but for now we'll just
+; use 8Kbytes. If you get retransmissions and other protocol errors after
+; transferring the first maxsec sectors, lower maxsec.
+
+maxsec EQU (8*1024)/bufsiz ; 8K / number of bytes per sector
+
+ lxi h,ovlend ; get start of buffer
+ shld bufadr ; store in linkage section
+ mvi a,maxsec ; get size of buffer, in sectors
+ sta bufsec ; store that, too.
+
+ call sysxin ; call system specific init code
+
+ ret ; return from system-dependent routine
+
+bdosvr: ds 1 ; space to save the BDOS version number
+IF NOT iobyt
+coniob: ds 1 ; space to save copy of IO byte
+ENDIF ;NOT iobyt
+;
+; This one is hopefully the last "improvement" in view of GENERIC
+;Kermit. It uses for Character-I/O the BIOS-routines ( instead of the
+;"normal" BDOS routines. What does it give us (hopefully) : More speed,
+;higher chance of success ( I/O byte implemented in BIOS [if at all]),
+;but no "extra" device handling - that's done by BDOS.
+;
+; How do we "get" the call-adresses? Location 0 has a JMP Warm-Boot
+;in CP/M which points into the second location of the BIOS JMP-Vector. The
+;next three locations of the JMP-Vector point to the CONSTAT,CONIN,CONOUT
+;BIOS-routines. CONOUT wants the character in C.
+;
+;- Bernie Eiben
+
+iniadr: lhld 1 ;get BIOS Warmstart-address
+ lxi d,3 ;next adress is CONSTAT in BIOS
+ dad d
+ shld bconst+1 ;stuff it into the call-instruction
+ lxi d,3 ;next adress is CONIN in BIOS
+ dad d
+ shld bconin+1 ;
+ lxi d,3 ;next adress is CONOUT in BIOS
+ dad d
+ shld bcnout+1
+ lxi d,3 ;next address is LIST in BIOS
+ dad d
+ shld blsout+1
+ lxi d,10*3 ; get printer status routine
+ dad d
+ shld bprtst
+ ret ;And return
+
+bconst: jmp $-$ ;Call BIOS directly (filled in by iniadr)
+
+bconin: jmp $-$ ;Call BIOS directly (filled in by iniadr)
+
+bcnout: jmp $-$ ;Call BIOS directly (filled in by iniadr)
+
+blsout: jmp $-$ ; ....
+
+bprtst: jmp $-$ ; Call BIOS directly for printer status
+
+IF NOT apmmdm ; Shame about this, but the Apple needs a different delay
+;
+;[cjc] Delay routine. Called with time (hundredths of seconds) in A.
+; The inner loop delays 1001 T-states, assuming no wait states are
+; inserted; this is repeated CPUSPD times, for a total delay of just
+; over 0.01 second. (CPUSPD should be set to the system clock rate,
+; in units of 100KHz: for an unmodified Kaypro II, that's 25 for
+; 2.5 MHz. Some enterprising soul could determine whether or not the
+; Kaypro actually inserts a wait state on instruction fetch (a common
+; practice); if so, the magic number at delay2 needs to be decreased.
+; (We also neglect to consider time spent at interrupt level).
+;
+; called by: sendbr
+; destroys BC
+
+delay: mvi c,cpuspd ; Number of times to wait 1000 T-states to
+ ; make .01 second delay
+delay2: mvi b,70 ; Number of times to execute inner loop to
+ ; make 1000 T-state delay
+delay3: dcr b ; 4 T-states (* 70 * cpuspd)
+ jnz delay3 ; 10 T-states (* 70 * cpuspd)
+ dcr c ; 4 T-states (* cpuspd)
+ jnz delay2 ; 10 T-states (* cpuspd)
+ ; total delay: ((14 * 70) + 14) * cpuspd
+ ; = 1001 * cpuspd
+ dcr a ; 4 T-states
+ jnz delay ; 10 T-states
+ ret ; grand total: ((1001 * cpuspd) + 14) * a
+ENDIF ; NOT apmmdm
+;
+;
+; Set up screen display for file transfer
+; called with kermit version in DE
+;
+sysscr: push d ; save version for a bit
+ lxi d,outlin ; clear screen, position cursor
+ call prtstr ; do it
+ pop d ; get Kermit's version
+IF NOT (osi OR crt) ; got cursor control?
+ call prtstr ; print it
+ mvi e,'[' ; open bracket
+ call outcon ; print it (close bracket is in outln2)
+ lxi d,sysver ; get name and version of system module
+ call prtstr
+ lxi d,outln2 ; yes, print field names
+ call prtstr
+ lda dbgflg ; is debugging enabled?
+ ora a
+ rz ; finished if no debugging
+ lxi d,outln3 ; set up debugging fields
+ call prtstr
+ENDIF;NOT (osi OR crt)
+ ret
+;
+; Calculate free space for current drive
+; returns value in HL
+sysspc:
+ lda bdosvr ;cpm3's alloc vect may be in another bank
+ cpi 30H ;cpm3 or later?
+ jm cp2spc ;no: use cp/m 2 algorithm
+ lda fcb ;If no drive, get
+ ora a ; logged in drive
+ jz dir180
+ dcr a ;FCB drive A=1 normalize to be A=0
+ jmp dir18a
+
+dir180: mvi c,rddrv
+ call bdos
+dir18a: mov e,a ;drive in e
+ mvi c,getfs ;get free space BDOS funct
+ call bdos ;returns free recs (3 bytes in buff..buff+2)
+ mvi b,3 ;conv recs to K by 3 bit shift
+dir18b: xra a ;clear carry
+ mvi c,3 ;for 3 bytes
+ lxi h,buff+3 ;point to addr + 1
+dir18c: dcx h ;point to less sig. byte
+ mov a,m ;get byte
+ rar ;carry -> A -> carry
+ mov m,a ;put back byte
+ dcr c ;for all bytes (carry not mod)
+ jnz dir18c
+ dcr b ;shift 1 bit 3 times
+ jnz dir18b
+ mov e,m ;get least sig byte
+ inx h
+ mov d,m ;get most sig byte
+ xchg ;get K free in HL
+ ret
+
+; the rest are CP/M 2.2 systems, so use the alloc vector
+cp2spc: mvi c,getalv ;Address of CP/M Allocation Vector
+ call bdos
+ xchg ;Get its length
+ lhld bmax
+ inx h
+ lxi b,0 ;Initialize Block count to zero
+dir19: push d ;Save allocation address
+ ldax d
+ mvi e,8 ;set to process 8 blocks
+dir20: ral ;Test bit
+ jc dir20a
+ inx b
+dir20a: mov d,a ;Save bits
+ dcx h
+ mov a,l
+ ora h
+ jz dir21 ;Quit if out of blocks
+ mov a,d ;Restore bits
+ dcr e ;count down 8 bits
+ jnz dir20 ;do another bit
+ pop d ;Bump to next count of Allocation Vector
+ inx d
+ jmp dir19 ;process it
+
+dir21: pop d ;Clear Allocation vector from stack
+ mov l,c ;Copy block to 'HL'
+ mov h,b
+ lda bshiftf ;Get Block Shift Factor
+ sui 3 ;Convert from records to thousands
+ rz ;Skip shifts if 1K blocks
+dir22: dad h ;Multiply blocks by 'K per Block'
+ dcr a
+ jnz dir22
+ ret
+
+; +----|----|----|----|----|----|----|...
+; 1 |
+; 2 | Kermit-80 v4.0 [system]
+; 3 |
+; 4 |Number of packets: ____
+; 5 |Number of retries: ____
+; 6 |File name: ____________
+; 7 |<error>...
+; 8 |<status>...
+; 9 |RPack: ___(if debugging)...
+; 10 |
+; 11 |SPack: ___(if debugging)...
+; 12 |
+; 13 |Kermit-80 A:> (when finished)
+;
+; For the PX-8, the display looks like:
+; 5 10 15 20 25 30 35 40 45 50 55
+; +----|----|----|----|----|----|----|----|----|----|----|----|----
+; 1 |Kermit-80 v4.05 [Epson PX-8] Number of retries: ____
+; 2 |Number of packets: ____ File name: ________.___
+; 3 |<error>...
+; 4 |<status>...
+; 5 |RPack: ___ (if debugging)...
+; 6 |
+; 7 |SPack: ___ (if debugging)...
+; 8 |
+; 9 |Kermit-80 A:> (when finished)
+;
+
+IF NOT px8 ; [29]
+nppos EQU 4*100h+20
+rtpos EQU 5*100h+20
+fnpos EQU 6*100h+12
+errlin EQU 7
+stlin EQU 8
+rplin EQU 9
+splin EQU 11
+prplin EQU 13
+ENDIF ; NOT px8
+
+IF px8
+nppos EQU 2*100h+20
+rtpos EQU 1*100h+59
+fnpos EQU 2*100h+51
+errlin EQU 3
+stlin EQU 4
+rplin EQU 5
+splin EQU 7
+prplin EQU 9
+ENDIF ; px8 [29]
+
+
+IF NOT (osi OR crt );[26]
+scrnp: lxi b,nppos
+ jmp csrpos
+
+scrnrt: lxi b,rtpos
+ jmp csrpos
+
+scrfln: lxi b,fnpos
+ call csrpos
+clreol:
+ lxi d,tk
+ jmp prtstr
+
+screrr: lxi b,errlin*100H+1
+ call csrpos
+ jmp clreol
+
+scrst: lxi b,stlin*100H+1
+ call csrpos
+ jmp clreol
+
+rppos: lxi b,rplin*100H+8
+ call csrpos
+ jmp clreol
+
+sppos: lxi b,splin*100H+8
+ call csrpos
+ jmp clreol
+
+; [29] Modify scrend to make the cursor line conditional on use of debugging
+; This means that in most cases the entire file transfer will fit on PX-8 lcd
+scrend: lda dbgflg
+ ora a
+ jz scr1nd
+ lxi b,prplin*100H+1 ; debugging in use [29]
+ jmp scr2nd
+scr1nd: lxi b,rplin*100H+1 ; no debugging
+scr2nd: call csrpos
+clreos: lxi d,tj
+ jmp prtstr
+; [29] and nop out the rest for now...
+;
+;scrend: lxi b,prplin*100H+1
+; call csrpos
+;clreos: lxi d,tj
+; jmp prtstr
+ENDIF;NOT (osi OR crt ) [26]
+
+
+IF osi OR crt ; no cursor control
+scrnp: mvi e,' '
+ jmp outcon
+
+scrnrt: mvi e,' '
+ call outcon
+ mvi e,'%'
+ jmp outcon
+
+scrfln:
+screrr:
+scrst:
+scrend: jmp prcrlf ;Print CR/LF [Toad Hall]
+
+rppos: lxi d,prpack
+ jmp prtstr
+
+sppos: lxi d,pspack
+ jmp prtstr
+ENDIF;osi OR crt
+
+; Some frequently-used routines (duplicates of those in CPSMIT):
+; prcrlf - output a CR/LF
+; prtstr - output string in DE
+; rskp - return, skipping over error return
+prcrlf: lxi d,crlf
+prtstr:
+; [17] added this to avoid prtstr.. emulate function 9 call.
+; Works on most machines.
+IF (torch OR px8 OR z80mu)
+;
+; Modified print string as the CP/N (for Nut) system traps control
+; characters in a function 9 call.. rot its cotton socks.
+ push h
+ push d
+ push b
+prtst1:
+ ldax d
+ inx d
+ cpi '$' ; if a dollar then end of string
+ jz prtst2
+ push d
+ mov e,a
+ mov c,a ; also to c if its via conout in BIOS
+ call outcon ; send it to the screen
+ pop d
+ jmp prtst1
+
+prtst2: pop b
+ pop d
+ pop h
+ ret ; regs restored.. just in case
+ENDIF ;(torch OR px8 OR z80mu)
+
+IF NOT (torch OR px8 or z80mu) ;ie any machine that can send ctrl chrs via dos call 9
+ PUSH H
+ PUSH D
+ push b
+ mvi c,9 ; Dos call 9 (print a string)
+ call bdos
+ pop b
+ POP D
+ POP H
+ ret ; all done for good machines
+ENDIF ;NOT (torch OR px8 OR z80mu)
+
+;
+; rskp - return to calling address + 3.
+rskp: pop h ; Get the return address
+ inx h ; Increment by three
+ inx h
+ inx h
+ pchl
+
+; Copy block of data
+; source in HL, destination in DE, byte count in BC
+; called by: cpxsys, mfname
+;
+mover:
+;IF NOT z80 ; 8080's have to do it the hard way
+;OBS assume its an 8080 for now - this will work on Z80s anyway.
+ mov a,m
+ stax d
+ inx h
+ inx d
+ dcx b
+ mov a,b
+ ora c
+ jnz mover
+;ENDIF;NOT z80
+;IF z80
+; db 0EDh,0B0h ; Z80 LDIR instruction
+;ENDIF;z80
+ ret
+
+;
+; Miscellaneous messages
+;
+crlf: db cr,lf,'$'
+cfgmsg: db 'configured for $'
+witmsg: db ' with $' ; Its included if we get here ('with terminal')
+
+IF NOT (osi OR crt OR px8) ; [29] got cursor control?
+outln2: db ']',cr,lf,cr,lf,'Number of packets:'
+ db cr,lf,'Number of retries:'
+ db cr,lf,'File name:$'
+ENDIF;NOT (osi OR crt OR px8)
+
+IF px8 ; [29]
+outln2: db '] Number of retries:', cr, lf
+ db 'Number of packets: File name:$'
+ENDIF ; px8 [29]
+
+IF NOT (osi OR crt) ; [29]
+outln3: db cr,lf,cr,lf ; debugging messages
+ db cr,lf,'Rpack:'
+ db cr,lf ; Blank line in case of long packet
+ db cr,lf,'Spack:$'
+ENDIF ; NOT (osi OR crt) [29]
+
+IF lasm
+LINK CPXSWT.ASM
+ENDIF ;lasm
+
diff --git a/src/cpxgni.asm b/src/cpxgni.asm
new file mode 100644
index 0000000..615103f
--- /dev/null
+++ b/src/cpxgni.asm
@@ -0,0 +1,440 @@
+; CPXGNI.ASM
+; 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 various
+; Genie 3 CPM kermit
+;
+; This has the Family name of CPXGNI.ASM.
+;
+; revision history (last edit first)
+; edit 3: 27 October, a987 by OBSchou. Massaged file to suit V4.09 structure.
+;
+; Edit 2: Aug 27 1987 GDS Put in code for BREAK and fillited out
+; a lot of unnecessary IF's
+;
+;Edit 1: Nov. 28, 1986 Geof Smith Clinical Research centre Harrow UK.
+
+.printx * Assembling for Eaca Genie 3 *
+;
+drtime EQU 05H ;Default receive time out interval.
+;
+; the basics...
+;
+mnport EQU 0E8H
+mnprts EQU 0EDH
+output EQU 20H
+input EQU 01H
+lctrl EQU 0EBH
+divlsb EQU 0E8H
+divmsb EQU 0E9H
+z80 EQU TRUE
+brkval EQU 40H
+
+defesc EQU ']'-100O ;The default escape character.
+
+
+;Select initial setting for VT-52 emulation flag.
+
+; default to VT52-EMULATION ON.
+;
+vtval EQU 1
+;
+;
+
+; Family is the string used in VERSION to say which of several
+; smaller overlay files are used. These are (will be) derived from
+; the huge CP4SYS.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 'CPXGNI.ASM (3) 27-Oct-87$' ; Used for family versions....
+
+
+
+;
+; System-dependent initialization
+; Called once at program start.
+sysxin:
+;
+ ;Set up 9600 bd, 8bit words, no parity 1stop bit
+
+ mvi a,83H ;enable DLAB by setting bit 7
+ out lctrl ;and outputting to control port
+ mvi a,14H ;get word = 20 decimal
+ out divlsb ;and put it out
+ mvi a,00H ;as two separate
+ out divmsb ;bytes
+ lda pstore ;get parity etc
+ out lctrl ;do it resetting DLAB at same time
+
+ 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
+
+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:
+
+ db cr,lf,'B Transmit a BREAK'
+
+ 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 'B' ; send break?
+ jz sendbr ; yes, go do it. return nonskip when through.
+
+ jmp rskp ; take skip return - command not recognized.
+
+
+;-------------------------------------------------------------------------------
+sendbr:
+;
+; Ensure that the transmitter has finished sending buffered chars
+sndbr1: in mnprts ; get UART status
+ ani output ; everything sent?
+ jz sndbr1 ; no, wait a bit more
+;
+; Begin sending a break by setting bit in UART command register
+ mvi a,brkval ; SBreak,
+ out lctrl
+;
+; Wait for 250 milliseconds (using hundredths second delay routine)
+ mvi a,25
+ call delay
+;
+; Resume normal operation by clearing the SendBreak command bit
+ lda pstore ;and restoring value from parity store
+ out mnprts
+;
+ ret ;done
+
+;
+;
+
+;
+; 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 modem in E
+; with parity set as appropriate.
+; return with accumulator = 0 do do nothing,
+; <> 0 to send char in E.
+mdmflt: mov a,e ; get character to a
+ 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:
+
+ ;Set up baud rate 8bit words, no parity 1stop bit
+ mvi a,83H ;enable DLAB by setting bit 7
+ out lctrl ;and outputting to control port
+ mov a,d ;get LSB
+ out divlsb ;and put it out
+ mov a,e ;get MSB
+ out divmsb ;output it as well
+ lda pstore ;get parity etc
+ out lctrl ;do it resetting DLAB at same time
+ ret
+
+pstore: db 03H ;Default value for parity word length and stop bits
+
+spdtbl: db 11h ;17 entries
+ db 03h,'110$', 06H,0D1H
+ db 04h,'1200$', 00H,0A0H
+ db 05h,'134.5$', 05H,94H
+ db 03h,'150$', 05H,00H
+ db 04h,'1800$', 00H,6BH
+ db 05h,'19200$', 00H,0AH
+ db 04h,'2000$', 00H,60H
+ db 04h,'2400$', 00H,50H
+ db 03h,'300$', 02H,80H
+ db 04h,'3600$', 00H,35H
+ db 05h,'38400$', 00H,05H
+ db 04h,'4800$', 00H,28H
+ db 02h,'50$', 0FH,00H
+ db 03h,'600$', 01H,40H
+ db 04h,'7200$', 00H,1BH
+ db 02h,'75$', 0AH,00H
+ db 04h,'9600$', 00H,14H
+
+sphtbl: db cr,lf,' 50 75 110 134.5 150 300 600 1200'
+ db cr,lf,' 1800 2000 2400 3600 4800 7200 9600 19200 38400$'
+
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+sysprt:
+
+ ret
+;
+prttbl equ 0 ; SET PORT not supported
+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:
+
+ 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
+
+;--------------------------------------------------------------------------
+;
+; get character from modem; return zero if none available.
+; for IOBYT systems, the modem port has already been selected.
+; destroys bc, de, hl.
+inpmdm:
+;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.
+ 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:
+ 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
+ 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:
+
+ mvi e,bs ;get a backspace
+ jmp 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
+
+;[2] I see no real saving in having all screens in separate file and
+;therefore have included screen definition here and commented out
+;the link to VDU file
+;
+;Specific definitions for the Genie III screen
+;
+sysver: db 'Eaca Genie III$'
+outlin: db 1aH,cr,lf,' $'
+erascr: db 1AH,'$'
+eralin: db cr,18H,'$'
+curldn: db esc,'=$'
+ttab:
+ta: db 0BH,'$',0,0 ;Cursor up
+tb: db 0AH,'$',0,0 ;Cursor down
+tc: db 0CH,'$',0,0 ;Cursor right
+td: db 08H,'$',0,0 ;Cursor left
+te: db 1AH,'$',0,0 ;Clear display
+tf: db esc,'R$',0 ;Reverse on
+tg: db esc,'S$',0 ;Reverse off
+th: db 1EH,'$',0,0 ;Cursor home
+ti: db 0BH,'$',0,0 ;Reverse linefeed
+tj: db 19H,'$',0,0 ;Clear to end of screen
+tk: db 18H,'$',0,0 ;Clear to end of line
+
+ovlend equ $ ;End of overlay
+
+END
+
+
+
+
+
diff --git a/src/cpxhea.asm b/src/cpxhea.asm
new file mode 100644
index 0000000..e78d9df
--- /dev/null
+++ b/src/cpxhea.asm
@@ -0,0 +1,921 @@
+IF NOT lasm
+.printx * CPXHEA.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
+; specific to the Heath/Zenith H89 and Z100, the Telcon Zorba,
+; and the OEM ScreenTyper. All but the latter use VT52 (or a
+; replica thereof) for screen output; the ScreenTyper uses the
+; same serial port chip as the H89 (an Intel 8250).
+;
+; revision history:
+;
+; Edit 4, 31-Aug-1989 by Mike Freeman, 301 N.E. 107th Street; Vancouver wa
+; 98685 USA; Telephone (206)574-8221: Added Baud-rate Selection and
+; Break-sending ability for the Telcon Zorba portable.
+;
+; edit 3, 22 July, 1987 by OBSchou to massage code to conform to new set
+; of overlay files (stripping out common code to CPXCOM.ASM)
+;
+; edit 2 by OBSchou to add in old Kermit-80 V3.5 heath-8 code, formerly
+; in CPM directory. Entry from CP/M file:
+;
+; This file contains an upgrade to the CPMBASE.M80 KERMIT
+; to allow setting and display of baud rates, a bug fix in
+; telnet, and an extension of the HELP to show GET (which works
+; in this release, on the H8). Look for the new symbol "h8quad"
+; (for the heath quad i/o board that it uses) in the conditionals.
+; Note that the Heath H8 is NOT the same machine as the H89. The H89
+; code does not run 'as is' on the H8, and does NOT initialize the
+; UART. Also there was a bug in the telnet section that is fixed
+; here, though I expect that it has already been found and fixed
+; by now - this is from the DECUS FALL 83 tape. The comments were
+; stripped out of this file to make it small enough for my H8 to
+; assemble, however, I have put the first section back in to make
+; it easier for you to identify. Thanks for a nice product to use
+; and work on. Major insertions are heavily commented, edit as needed.
+;
+; This modification done by John Mealing, InteCom Inc, 601 Intecom Dr.,
+; Allen, TX 75002 (214)797-9141, x-2493, 5 Nov 84.
+;
+; [OBSchou notes: This is the header, and the bugs in telnet are
+; unknown. telnet routine has been substantially changed anyway with
+; 4.08-4.09 revision. As for the major insertions: they probably went
+; with the 4.xx re-write. I am unable to test this version: can
+; anyone else do so??]
+;
+;
+; edit 01 5th Mar 1987 by M J Carter, Nottingham Uni [majoc]
+; Split off from CPXSYS.ASM, in order to install support for
+; the OEM ScreenTyper. I can't test anything other than the
+; ScreenTyper as I haven't the hardware. Any offers?
+; Thanks are due to Paul Bartlett of John Elmer
+; Electronics Ltd, who provided me with his modified sources
+; for (a slightly antiquated) CP/M 4.05 Kermit on which this
+; is based.
+;
+; Keep module name, edit number, and last revision date in memory.
+;sysedt: db 'CPXSYS.ASM (35) 01-Dec-86 $'
+; [majoc 870305] Now in CPXFRK. I'll have to consult on this ...
+;
+;
+;
+; 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 heath
+.printx * Assembling KERMIT-80 for the Heath/Zenith 89 *
+ENDIF
+
+IF h8quad
+.printx * Assembling KERMIT-80 for the Heath-8 with Quad IO board *
+ENDIF
+
+IF z100
+.printx * Assembling KERMIT-80 for the Heath/Zenith Z100 *
+ENDIF
+
+IF telcon
+.printx * Assembling KERMIT-80 for the Telcon Zorba *
+ENDIF
+
+IF scntpr
+.printx * Assembling KERMIT-80 for the OEM ScreenTyper *
+ENDIF
+;
+
+;
+
+IF heath
+mnport EQU 330O ;Modem data port
+ENDIF ; heath
+
+IF h8quad
+mnport EQU 330O ;all port addresses can be set by user -
+mnprts EQU mnport + 05 ; in octal cause heath wrote documents that
+output EQU 20H ; way -- relative addressing on the UART
+input EQU 01H ; registers, just to be nice
+baudls EQU mnport ;ls baud divisor latch when DALB set
+baudms EQU mnport + 1 ;ms baud divisor latch when DALB set
+linctl EQU mnport + 3 ;line control register
+modctl EQU mnport + 4 ;MODEM control register
+dalbon EQU 80H ;enables speed selection
+linset EQU 03H ;force hardware 8 bit, even parity
+;
+; The line control register (linctl) is bit mapped as follows:
+; bit # function value
+; 0,1 select word size 00 -> 5 bit, 10 -> 7 bit
+; 01 -> 6 bit, 11 -> 8 bit
+; 2 select stop bits 0 -> 1 stop bit, 1 -> 1 1/2 for 5 bit,
+; 1 -> 2 for 6 bit words
+; 3 parity enable 0 -> no parity, 1 -> parity as set by 4
+; 4 Even parity select 0 -> Odd parity, 1 -> Even parity
+; 5 Stick parity 1 -> Parity of bit 4 is inverted
+; 6 Break control 1 -> output forced to spacing (break)
+; 7 DALB 1 -> access divisor latches to set baud rate
+;
+; The value in linset is loaded into linctl when KERMIT comes up.
+;
+ms300 EQU 001O ;set for 300 baud as default
+ls300 EQU 200O
+rtsoff EQU 20O ;direct control of modem lines
+rtson EQU 11O
+z80 EQU FALSE ;[2] or is it?
+ENDIF ;h8quad
+
+IF scntpr
+mnport EQU 8 ;Modem data port
+ENDIF ; scntpr
+IF heath OR scntpr
+
+; Definitions for the 8250 ACE
+
+acerbr EQU 0 ; ACE Receiver Buffer Register offset (R/O) (DLAB = 0)
+acethr EQU 0 ; ACE Transmitter Holding Register offset (W/O)
+acedll EQU 0 ; ACE Divisor Latch (Low) (DLAB = 1)
+acedlh EQU 1 ; ACE Divisor Latch (High) (DLAB = 1)
+aceier EQU 1 ; ACE Interrupt Enable Register (DLAB = 0)
+aceiir EQU 2 ; ACE Interrupt Identification Register
+acelcr EQU 3 ; ACE Line Control Register
+acemcr EQU 4 ; ACE Modem Control Register
+acelsr EQU 5 ; ACE Line Status Register offset
+acemsr EQU 6 ; ACE Modem Status Register
+
+ace8bw EQU 00000011b ; 8 bit words
+acesb EQU 01000000b ; set break
+acedla EQU 10000000b ; divisor latch access
+acedtr EQU 00000001b ; data terminal ready
+aceloo EQU 00010000b ; loopback mode
+acedr EQU 00000001b ; data ready
+acethe EQU 00100000b ; transmitter holding register empty
+
+;mnport EQU 330O ;Modem data port
+; [35a: majoc 870305] Shifted up above joint IF, to save nesting.
+mnprts EQU mnport+acelsr ;Modem status port
+output EQU acethe ;Transmitter empty
+input EQU acedr ;Input data available
+z80 EQU TRUE ;H89 uses the Z80
+ENDIF;heath OR scntpr
+
+IF z100
+mnport EQU 0ECH ;Modem data port
+mnprts EQU 0EDH ;Modem status port
+output EQU 01H ;Transmitter empty
+input EQU 02H ;Input data available
+z80 EQU FALSE ;[hh] this one's an 8085.
+ENDIF;z100
+
+
+IF telcon
+MNPORT EQU 20H ;Modem data port
+MNPRTS EQU 21H ;Modem status port
+OUTPUT EQU 01H ;Transmitter empty
+INPUT EQU 02H ;Input data available
+BRPORT EQU 00H ;8254-2 Baud Rate Generator Timer for Port A
+COMMND EQU 03H ;8254-2 Timer Control Port
+z80 EQU TRUE ;[MF]A real Z80
+ENDIF;telcon
+;
+
+IF telcon
+defesc EQU ']'-100O ;The default escape character.
+ENDIF;telcon
+
+IF heath OR h8quad OR z100 OR scntpr
+defesc EQU '\'-100O ;The default is Control \ -- it's easier B.E.
+ENDIF;heath OR h8quad OR z100 OR scntpr
+
+; Select initial setting for VT-52 emulation flag.
+IF (heath OR h8quad OR z100 OR telcon)
+vtval EQU 0 ; we don't need VT52 emulation
+ENDIF;heath OR h8quad OR z100 OR telcon OR vt52 [OBS question - ok for h8quad?]
+; If none of the above, default to VT52-EMULATION ON.
+IF scntpr
+vtval EQU 1 ; we do VT52 emulation
+ENDIF;scntpr
+
+
+;
+; 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 'CPXHEA.ASM (4) 31-Aug-1989$' ; Used for family versions....
+
+;
+sysxin: ; continuation of initialisation code
+IF heath OR scntpr
+;
+; System dependent startup for H89 and OEM ScreenTyper
+;
+
+ call mdmofl ; keep the line safe from garbage
+
+; First, tell Kermit the modem port's current speed
+ in mnport+acelcr
+ ori acedla
+ out mnport+acelcr ; access the ACE's divisor latch
+ in mnport+acedll ; get the low byte
+ sta speed
+ in mnport+acedlh ; and the high byte
+ sta speed+1
+
+; Now set up the port for Kermit
+ mvi a,ace8bw ; 8 data bits, 1 stop bit, no parity
+ out mnport+acelcr
+ in mnport+acemcr
+ ori acedtr ; raise DTR (just in case)
+ out mnport+acemcr
+ call mdmonl ; and put the ACE back on line
+ ret
+
+; Take the ACE off line before modifying its state
+mdmofl:
+ in mnport+aceier ; save the ACE's interrupt state
+ sta iersav
+ xra a
+ out mnport+aceier ; and disable ACE interrupts
+ in mnport+acemcr ; now put the ACE in loopback mode
+ ori aceloo
+ out mnport+acemcr
+ ret
+
+; Put the ACE back on line
+mdmonl:
+ in mnport ; flush left-over garbage in the receive buffer
+ mvi a,7 ; wait about 2 300-baud character times
+ call delay
+ in mnport ; and flush more garbage
+ in mnport+acemcr ; take the ACE out of loopback mode
+ ani 0FFH-aceloo
+ out mnport+acemcr
+ lda iersav
+ out mnport+aceier ; and restore the ACE's interrupt state
+ ret
+
+iersav: ds 1
+ENDIF;heath OR scntpr
+
+IF h8quad
+h8init: lxi d,180h ; [2] set up for 300 baud
+h8baud: mvi a,rtsoff ;disable modem for now
+ out modctl
+ mvi a,dalbon ;set for UART speed programming
+ out linctl
+ mov a,d ; [2] get ms bits for rate
+ out baudms
+ mov a,e ; [2] get ls bits for rate
+ out baudls
+ mvi a,linset ;force 8 bit, no parity and clear dalb
+ out linctl
+ in mnport ;clear the recieve side
+ mvi a,rtson ;get ready
+ out modctl ;modem is on and ready to go
+ENDIF ;h8quad
+
+ 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
+
+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:
+IF heath OR scntpr OR telcon;[4]
+ lxi d,inhlps ; we got options...
+ call prtstr ; print them.
+ENDIF;heath OR scntpr OR telcon
+
+ ret
+
+
+;additional, system-dependent help for transparent mode
+; (two-character escape sequences)
+inhlps:
+IF heath OR scntpr OR telcon;[4]
+ db cr,lf,'B Transmit a BREAK'
+ENDIF;heath OR scntpr OR telcon
+
+IF heath OR scntpr
+ db cr,lf,'D Drop the line'
+ENDIF;heath OR scntpr
+
+ 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 heath OR scntpr
+ cpi 'D' ; drop line?
+ jnz intc00 ; no: try next function character
+
+mdmdrp: in mnport+acemcr ; (we also get here from sysbye)
+ ani 0FFH-acedtr
+ out mnport+acemcr ; yes: drop DTR
+ mvi a,50 ; for half a second
+ call delay
+ in mnport+acemcr
+ ori acedtr
+ out mnport+acemcr ; and then restore it
+ ret
+intc00:
+ENDIF;heath OR scntpr
+
+IF heath OR scntpr OR telcon;[4]
+ cpi 'B' ; send break?
+ jz sendbr ; yes, go do it. return nonskip when through.
+ENDIF;heath OR scntpr OR telcon
+ jmp rskp ; take skip return - command not recognized.
+
+
+;
+IF heath OR scntpr
+;
+; Send BREAK on H89 or ScreenTyper
+;
+sendbr: in mnport+acelcr
+ ori acesb
+ out mnport+acelcr ; set ACE break condition
+ mvi a,30
+ call delay ; wait 300 milliseconds
+ in mnport+acelcr
+ ani 0FFH-acesb
+ out mnport+acelcr ; and clear ACE break condition
+ ret
+
+ENDIF;heath OR scntpr
+;
+IF telcon ;[4]
+;
+; Send break on Telcon Zorba
+;
+sendbr: mvi a,3fH ;DTR normal, break on
+ out mnprts ;Set break on
+ mvi a,30 ;Wait 300 ms
+ call delay ;...
+ mvi a,37h ;DTR normal, tx, rx enabled
+ out mnprts ;Restore normal condition
+ ret ;and return
+;
+ENDIF ;telcon
+
+;
+;
+; 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, scntpr, and lobo, hang up the phone.
+sysbye:
+IF heath OR scntpr
+ call mdmdrp ; Sleazy but effective
+ENDIF;heath OR scntpr
+
+ 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 heath OR scntpr
+;
+; Set speed for H89
+;
+ call mdmofl ; keep the line safe from garbage
+ in mnport+acelcr
+ ori acedla
+ out mnport+acelcr ; access the ACE's divisor latch
+ mov a,e ; low byte of speed is in E
+ out mnport+acedll ; set the low byte
+ mov a,d ; high byte of speed is in D
+ out mnport+acedlh ; set the high byte
+ in mnport+acelcr
+ ani 0FFH-acedla
+ out mnport+acelcr ; de-access the ACE's divisor latch
+ call mdmonl ; and put the ACE back on line
+ENDIF;heath OR scntpr
+
+IF h8quad ;[2][obs] A bit of guesswork this. Enter with date in de
+ call h8baud ; [2] routine is in initialisation bit
+ENDIF ; h8quad[2]
+;
+IF telcon ;[4]
+ MVI A,36H ;Set square wave
+ OUT COMMND ;...
+ MOV A,E ;Get LSB of Baud rate
+ OUT BRPORT ;Send to generator
+ MOV A,D ;Get msb of baud rate
+ OUT BRPORT ;Send to Baud rate generator
+ENDIF ;telcon
+;
+ ret
+
+;
+;
+; 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 heath
+;
+; Speed selection table for H89 (OK, so I got a little carried away...)
+;
+
+spdtbl: db 19 ; 19 entries
+ db 3,'110$'
+ dw 1047
+ db 4,'1200$'
+ dw 96
+ db 5,'134.5$'
+ dw 857
+ db 4,'1800$'
+ dw 64
+ db 5,'19200$'
+ dw 6
+ db 3,'200$'
+ dw 576
+ db 4,'2400$'
+ dw 48
+ db 3,'300$'
+ dw 384
+ db 4,'3600$'
+ dw 32
+ db 5,'38400$'
+ dw 3
+ db 3,'450$'
+ dw 256
+ db 4,'4800$'
+ dw 24
+ db 2,'50$'
+ dw 2304
+ db 5,'56000$'
+ dw 2
+ db 3,'600$'
+ dw 192
+ db 4,'7200$'
+ dw 16
+ db 2,'75$'
+ dw 1536
+ db 3,'900$'
+ dw 128
+ db 4,'9600$'
+ dw 12
+
+sphtbl: db cr,lf
+ db ' 50 75 110 134.5 200 300 450 600 900 1200'
+ db cr,lf,' 1800 2400 3600 4800 7200 9600 19200 38400 56000$'
+ENDIF;heath
+
+IF h8quad
+spdtbl: db 6 ;[2] 6 entries
+ db 3,'300$', 1,80h ; divisor for 300 baud
+ db 3,'600$', 0,0c0h
+ db 4,'1200$', 0,60h
+ db 4,'2400$', 0,30h
+ db 4,'4800$', 0,18h
+ db 4,'9600$', 0,0ch
+;
+; The strings to display the speed selected from the table above
+;
+sphtbl: db cr,lf,' 300 600 1200 2400 4800 9600$'
+ENDIF ;h8quad
+
+IF scntpr
+; [35a: majoc 870305]
+;
+; Speed selection table for ScreenTyper
+;
+
+spdtbl: db 14 ; 14 entries
+ db 3,'110$'
+ dw 470H
+ db 4,'1200$'
+ dw 68H
+ db 5,'134.5$'
+ dw 3a1H
+ db 4,'1800$'
+ dw 45H
+ db 5,'19200$' ; This was in PB's table, but not in the
+ dw 7H ; accompanying text string. Oversight?
+; db 3,'200$'
+; dw 576
+ db 4,'2400$'
+ dw 34H
+ db 3,'300$'
+ dw 1a1H
+ db 4,'3600$'
+ dw 23H
+; db 5,'38400$'
+; dw 3
+; db 3,'450$'
+; dw 256
+ db 4,'4800$'
+ dw 1aH
+ db 2,'50$'
+ dw 964H
+; db 5,'56000$'
+; dw 2
+ db 3,'600$'
+ dw 0d0H
+ db 4,'7200$'
+ dw 11H
+ db 2,'75$'
+ dw 683H
+; db 3,'900$'
+; dw 128
+ db 4,'9600$'
+ dw 0dH
+
+sphtbl: db cr,lf,' 50 75 110 134.5 300 600 1200'
+ db cr,lf,' 1800 2400 3600 4800 7200 9600 (19200?)$'
+ENDIF;scntpr
+;
+IF telcon ;[4]
+;
+; Speed selection tables for the Telcon Zorba (I overdid it, also)
+;
+; **NOTE** that when Kermit is first executed, the baud rate is
+; unknown to Kermit, having been set by CP/M upon cold-boot, SETUP.COM,
+; another communications program, etc. The easiest way to insure that
+; the baud rate is known upon Kermit start-up is to set it
+; in KERMIT.INI.
+;
+spdtbl: db 20 ;[4]Number of entries (some of these
+ ;speeds are *weird* but the Zorba
+ ;supports them so I'll put them in
+ db 3,'110$'
+ dw 4545
+ db 4,'1200$'
+ dw 417
+ db 5,'134.5$'
+ dw 3717
+ db 3,'150$'
+ dw 3333
+ db 4,'1760$'
+ dw 284
+ db 4,'1800$'
+ dw 278
+ db 5,'19200$'
+ dw 26
+ db 3,'200$'
+ dw 2500
+ db 4,'2000$'
+ dw 250
+ db 4,'2400$'
+ dw 208
+ db 3,'300$'
+ dw 1667
+ db 4,'3520$'
+ dw 142
+ db 4,'3600$'
+ dw 139
+ db 4,'4800$'
+ dw 104
+ db 2,'50$'
+ dw 10000
+ db 3,'600$'
+ dw 833
+ db 4,'62.5$'
+ dw 8000
+ db 4,'7200$'
+ dw 69
+ db 2,'75$'
+ dw 6667
+ db 4,'9600$'
+ dw 52
+;
+; Help table
+;
+sphtbl: db cr,lf
+ db ' 50 62.5 75 110 134.5 150 200 300 600 1200'
+ db cr,lf,' 1760 1800 2000 2400 3520 3600 4800 7200'
+ db cr,lf,' 9600 19200$'
+;
+ENDIF ;Telcon
+
+; 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 z100
+spdtbl equ 0 ; SET BAUD not supported.
+sphtbl equ 0
+ENDIF;z100
+;
+;
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+sysprt:
+ ret
+;
+prttbl equ 0 ; SET PORT is not supported
+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:
+IF NOT iobyt
+ mvi c,dconio ;Direct console I/O BDOS call.
+ mvi e,0FFH ;Input.
+ call BDOS
+ENDIF;NOT 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
+ 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
+
+;
+;
+; 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 NOT iobyt ;[2] this routine not in submitted file, so I guess
+ ; guess this is what it is supposed to do.
+ in mnprts ; input status port
+ ani input ; anything t read in?
+ rz ; nope
+ in mnport ; else read in the data
+ ret ; return with character in A
+ENDIF ; NOT iobyte [2]
+
+;
+; 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:
+ call bprtst ; 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
+
+IF NOT iobyt
+ mvi c,lstout
+ call bdos ;Char to printer
+ENDIF;NOT 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.)
+;
+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:
+ mvi e,bs ;get a backspace
+ jmp 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 telcon
+sysver: db 'Telcon Zorba$'
+ENDIF;telcon
+
+IF heath
+sysver: db 'Heath/Zenith 89$'
+ENDIF;heath
+
+IF h8quad
+sysver: db 'Heath H8 with quad I/O card$'
+ENDIF
+
+IF z100
+sysver: db 'Heath/Zenith Z-100 CP/M$'
+ENDIF;z100
+
+IF scntpr
+; [35a: majoc 870305]
+sysver: db 'OEM ScreenTyper: 4MHz Z80 running OS/M$'
+ENDIF;scntpr
+
+IF heath OR h8quad OR z100 OR telcon
+outlin: db esc,'H',esc,'J',cr,lf,tab,tab,'$'
+erascr: db esc,'H',esc,'J$' ;Clear screen and go home.
+eralin: db cr,esc,'K$' ;Clear line.
+curldn: db esc,'Y$' ;cursor leadin
+ttab: ;Table start location.
+ta: db esc,'A$',0 ;Cursor up.
+tb: db esc,'B$',0 ;Cursor down.
+tc: db esc,'C$',0 ;Cursor right.
+td: db esc,'D$',0 ;Cursor left
+te: db esc,'E$',0 ;Clear display
+tf: db esc,'F$',0 ;Enter Graphics Mode
+tg: db esc,'G$',0 ;Exit Graphics mode
+th: db esc,'H$',0 ;Cursor home.
+ti: db esc,'I$',0 ;Reverse linefeed.
+tj: db esc,'J$',0 ;Clear to end of screen.
+tk: db esc,'K$',0 ;Clear to end of line.
+ENDIF;heath OR h8quad OR z100 OR telcon
+;
+
+IF scntpr ; [35a: majoc 870305]
+outlin: db 1aH, cr, lf, '$'
+erascr: db 1aH, '$' ;Clear screen and go home.
+eralin: db cr,esc,'*$' ;Clear line.
+curldn: db esc,'=$' ;cursor leadin
+ttab: ;Table start location.
+ta: db 1eH,'$',0,0 ;Cursor up.
+tb: db 1fH,'$',0,0 ;Cursor down.
+tc: db 1cH,'$',0,0 ;Cursor right.
+td: db 1dH,'$',0,0 ;Cursor left
+te: db 1aH,'$',0,0 ;Clear display
+tf: db 0,0,0,0 ;(Can't)Enter Graphics Mode
+tg: db 0,0,0,0 ;(Can't)Exit Graphics mode
+th: db 15H,'$',0,0 ;Cursor home.
+ti: db 1eH,'$',0,0 ;Reverse linefeed.
+tj: db esc,'%$',0 ;Clear to end of screen.
+tk: db esc,'*$',0 ;Clear to end of line.
+ENDIF;scntpr
+
+ovlend EQU $ ; End of overlay
+ END ; Phew ... [majoc 870305]
diff --git a/src/cpxlnk.asm b/src/cpxlnk.asm
new file mode 100644
index 0000000..30dd080
--- /dev/null
+++ b/src/cpxlnk.asm
@@ -0,0 +1,206 @@
+; CPXLNK.ASM
+; 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
+; 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 describes the areas used to communicate between KERMIT
+; and the customizing overlay. It is included by the overlay.
+; This file should be changed only to reflect changes in the
+; system-independent portion of Kermit (enhancements, I hope).
+;
+; revision history:
+;edit 8, 14-Sep-1990 by MF. Added variable "incflg" to hold incomplete-
+; file status for SET INCOMPLETE-FILES command.
+; edit 7: 8 April, 1987 by OBSchou. Added a new entry EXTERN to leap off to
+; code written by the user to emulate any terminal they want. All
+; characters are sent here in stead of conout during connect state.
+; In due course, Ill trap all prtstrs and dconio as well.
+;
+; edit 6: May 30, 1986 by OBSchou. Added two more entries to the link area:
+; first to point to a "family" string giving the family name of the
+; system. If the older CP4SYS.ASM still has the code, then the
+; string is null. Secondly, a JMP to give printer status (should be
+; a BIOS function). If 0 then printer is ready, if 0ffh then printer
+; busy. This makes version 4.07 incompatable with 4.05
+;
+; edit 5: February 6, 1985
+; Added a storage variable, "PORT", for the port-in-use value
+; required for the port status routine (same purpose as SPEED).
+; Also moved the printer copy flag (PRNFLG:) into the commun-
+; ications storage area so machine dependant overlay can access it.
+; [Hal Hostetler]
+; Also, replace assembly-time conditional "ffussy" with run-time
+; switch (CJC).
+;
+; edit 4: August 21, 1984 (CJC)
+; Define a use for the third word of the linkage section: it points
+; to the version string for CP4SYS.ASM. Add flsmdm, to flush comm line
+; on startup. Add bufadr and bufsec for multiple-sector buffer support.
+; Shift the entry section up two bytes so we can exit cleanly from DDT.
+;
+; edit 3: August 3, 1984 (CJC)
+; put "mover" in CP4SYS, so we can do a Z80 block move if so inclined.
+;
+; edit 2: July 10, 1984 (CJC)
+; integrate Toad Hall changes for LASM compatibility: CP4LNK is linked
+; by CP4DEF, and links CP4SYS.
+;
+; edit 1: May, 1984 (CJC)
+; extracted from CPMBASE.M80 version 3.9; modifications are described
+; in the accompanying .UPD file.
+;
+
+; Define the entry section. These addresses contain jumps to
+; useful routines in KERMIT. To show we know what we're doing,
+; we store the length of this section (entsiz) in our linkage
+; section. I didn't use ORG and DS because I don't want zeroes
+; generated for all the space between here and the actual start
+; of cp4sys.
+entry equ 105H ; start of entry section
+kermit equ entry+0 ; reentry address
+nout equ entry+3 ; output HL in decimal
+entsiz equ 2*3 ; 2 entries, so far.
+;
+; End of entry section.
+;
+; Linkage section. This block (through the definition of lnksiz)
+; is used by Kermit to reach the routines and data in the overlay.
+; The section length is stored at the beginning of the overlay
+; area so Kermit can verify that the overlay section is (a) present,
+; (b) in the right place, and (c) the same size as (and therefore
+; presumably the same as) the linkage section Kermit is expecting.
+;
+ ASEG
+ ORG OVLADR
+;
+lnkflg: dw lnksiz ; linkage information for consistency check.
+ dw entsiz ; length of entry table, for same.
+ dw swtver ; address of switcher. CPXSYS now a family
+ dw family ;*NEW* for V4.08. Address of the family string
+;
+; hooks for system-dependent routines:
+;
+; Input/output routines.
+;
+ jmp selmdm ; select modem for I/O
+ jmp outmdm ; output character in E to modem
+ jmp inpmdm ; read character from modem. return character or 0 in A.
+ jmp flsmdm ; flush pending input from modem
+ jmp selcon ; select console for I/O
+ jmp outcon ; output character in E to console
+ jmp inpcon ; read char from console. return character or 0 in A
+ jmp outlpt ; output character in E to printer
+ jmp lptstat ;*NEW* get the status for the printer.
+ ; 0=>ok, 0ffh=> not ok
+ jmp 0 ;*NEW for 4.09* Terminal Emulation code (optional)
+ ; If terminal is set to EXTERNAL and this address
+ ; has been filled, then user uses their own code.
+xbdos: jmp 0 ;*NEW* Address of the BDOS trap in the independent
+ ; code. Use this enty for BDOS calls if you want
+ ; the printer handler to work properly.
+
+; screen formatting routines
+ jmp clrlin ; erase current line
+ jmp clrspc ; erase current position (after backspace)
+ jmp delchr ; make delete look like backspace
+ jmp clrtop ; erase screen and go home
+;
+; these routines are called to display a field on the screen.
+ jmp scrend ; move to prompt field
+ jmp screrr ; move to error message field
+ jmp scrfln ; move to filename field
+ jmp scrnp ; move to packet count field
+ jmp scrnrt ; move to retry count field
+ jmp scrst ; move to status field
+ jmp rppos ; move to receive packet field (debug)
+ jmp sppos ; move to send packet field (debug)
+;
+ jmp sysinit ; program initialization
+ jmp sysexit ; program termination
+ jmp syscon ; remote session initialization
+ jmp syscls ; return to local command level
+ jmp sysinh ; help text for interrupt (escape) extensions
+ jmp sysint ; interrupt (escape) extensions, including break
+ jmp sysflt ; filter for incoming characters.
+ ; called with character in E.
+ jmp sysbye ; terminate remote session
+ jmp sysspd ; baud rate change routine.
+ ; called with value from table in DE
+ jmp sysprt ; port change routine.
+ ; called with value from table in HL
+ jmp sysscr ; screen setup for file transfer
+ ; called with Kermit's version string in DE
+ jmp csrpos ; move cursor to row B, column C
+ jmp sysspc ; calculate free space for current drive
+ jmp mover ; do block move
+ jmp prtstr ; *** NEW *** Link from system indep equivalent
+;
+; Local parameter values
+;
+pttab: dw ttab ; points to local equivalents to VT52 escape sequences
+spdtab: dw spdtbl ; address of baud rate command table, or zero
+spdhlp: dw sphtbl ; address of baud rate help table, or zero
+prttab: dw prttbl ; address of port command table, or zero
+prthlp: dw prhtbl ; address of port help table, or zero
+timout: dw fuzval ; Fuzzy timeout.
+vtflg: db vtval ; VT52 emulation flag
+escchr: db defesc ; Storage for the escape character.
+speed: dw 0FFFFH ; storage for the baud rate (initially unknown)
+port: dw 0FFFFH ; storage for port value (initially unknown) [hh]
+prnflg: db 0 ; printer copy flag [hh]
+dbgflg: db 0 ; debugging flag
+ecoflg: db 0 ; Local echo flag (default off).
+flwflg: db 1 ; File warning flag (default on).
+ibmflg: db 0 ; IBM flag (default off).
+cpmflg: db 0 ;[bt] file-mode flag (default is DEFAULT)
+incflg: db 0 ;[MF]incomplete-file flag (default is DISCARD)
+parity: db defpar ; Parity.
+spsiz: db dspsiz ; Send packet size.
+rpsiz: db drpsiz ; Receive packet size.
+stime: db dstime ; Send time out.
+rtime: db drtime ; Receive time out.
+spad: db dspad ; Send padding.
+rpad: db drpad ; Receive padding.
+spadch: db dspadc ; Send padding char.
+rpadch: db drpadc ; Receive padding char.
+seol: db dseol ; Send EOL char.
+reol: db dreol ; Receive EOL char.
+squote: db dsquot ; Send quote char.
+rquote: db drquot ; Receive quote char.
+chktyp: db dschkt ; Checksum type desired
+tacflg: ; TACtrap status:
+IF tac
+ db tacval ; when non-zero, is current TAC intercept character;
+ENDIF;tac
+IF NOT tac
+ db 0 ; when zero, TACtrap is off.
+ENDIF;tac
+tacchr: db tacval ; Desired TAC intercept character (even when off)
+bufadr: dw buff ; Address of possibly multi-sector buffer for I/O
+bufsec: db 1 ; Number of sectors big buffer can hold (0 means 256)
+ffussy: db 1 ; if nonzero, don't permit <>.,;?*[] in CP/M filespec.
+; space used by directory command; here because space calculation is
+; (operating) system-dependent
+bmax: ds 2 ; highest block number on drive
+bmask: ds 1 ; (records/block)-1
+bshiftf: ds 1 ; number of shifts to multiply by rec/block
+nnams: ds 1 ; counter for filenames per line
+
+lnksiz equ $-lnkflg ; length of linkage section, for consistency check.
+
+IF lasm ; If we're assembling with LASM,
+ LINK CPXCOM ; get the next section.
+ENDIF;lasm
diff --git a/src/cpxmrl.asm b/src/cpxmrl.asm
new file mode 100644
index 0000000..31d6849
--- /dev/null
+++ b/src/cpxmrl.asm
@@ -0,0 +1,454 @@
+IF NOT lasm
+.printx * CPXMRL.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.
+;
+; CPXMRL.ASM created 16 July, 1987 from submitted code by William Rose.
+;
+; Kermit system dependent file for Rair Black Box (British Telecom
+; Merlin, ICL PC etc) originally submitted by William Rose, and
+; modified by OBSchou to work with the Kermit-80 V4.08 and later
+; files. Wills original overlay file a stripped down CPXSYS.ASM
+; file.
+;
+; KERSYS.ASM - version 0.6A dated 17 Jun 87.
+;
+; Cutdown CP4SYS.ASM for Telecom Merlin M2215 only. (ICL PC, Rair Black Box)
+;
+; This uses TTY1: only, and cannot alter it's parameters. It resets the
+; interrupt flag to prevent use of the buffer, and is generally a kludge.
+; However it runs at 4800 baud, and tidying the code might get 9600.
+;
+; Revision History (Last entry first)
+;
+; edit 2, 22 July by OBSchou to massage frile to fit with CPXCOM.ASM
+;
+; edit 1, 17 July by OBSchou for Will Rose, to make file suitable for V4.08
+; overlay etc.
+;
+; Keep module name, edit number, and last revision date in memory.
+;
+family: db 'CPXMRL.ASM (2) 22-Jun-87 $' ; Telecom Merlin added
+
+;
+; Assembly time message to let me know I'm building the right version.
+;
+
+IF m2215
+ .printx * Assembling Kermit-80 for Merlin M2215 *
+ENDIF
+
+IF m2215 ;equates removed because interrupts stopped port access
+;iobase equ 14h ; base address of TTY1
+;mnport equ iobase ; rx and tx data ports
+;mnprts equ iobase+1 ; status port
+;mnmode equ iobase+2 ; mode port
+;mncmd equ iobase+3 ; PCI command port
+;txrdy equ 1 ; tx ready bit set if free
+;output equ txrdy
+;rxrdy equ 2 ; RX ready bit
+;input equ rxrdy
+z80 equ false ; For Merlin M2215
+ENDIF
+
+
+sysxin: ; Continue system initialisation fro sysinit
+
+IF FALSE ; unable to penetrate the 8085 interrupts
+ in mncmd ; clear command register counter
+ mvi a,4eh ; 0100$1110 - 1 stop bit, 8 data bits,
+ ; / by 16 counter
+ out mnmode
+ mvi a,30h+7 ; 0011$0000 - select internal rate generator
+ ; use 1200 baud by default
+ out mnmode
+ mvi a,27h ; 0010$0111 - enable tx and rx, RTS and DTR low
+ out mncmd
+ mvi h, 12
+ mvi l, 12
+ shld speed ; to show its been set up
+
+ENDIF
+
+ ret
+
+porbuf: ds 3 ; original port settings
+
+;
+; system-dependent KERMIT 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
+
+conmsg: ; Messages printed when entering transparent (CONNECT) mode:
+
+ db '$'
+
+;
+; 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:
+ ; still can't pentrate interrupts
+ ret
+
+; Additional, system-dependent help for transparent mode
+; (two-character escape sequences)
+;
+inhlps:
+
+IF m2215
+ db cr, lf, 'B Transmit a BREAK'
+ENDIF
+
+ db '$' ; string 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: seqence was not recognized
+;
+sysint: ani 137O ; convert lower case to upper, for testing...
+
+IF FALSE ; as always
+ cpi 'B' ; send break ?
+ jz sendbr
+ENDIF
+ jmp rskp ; take skip return - command not recognised
+
+; Actual commands
+
+IF FALSE ;as always
+sendbr:
+ in mnprts
+ ani 04h ; make sure shift reg is clear
+ jz sendbr
+
+ mvi a,2fh ; set for a break
+ out mncmd
+ mvi a,100 ; wait a bit
+ call delay
+ mvi a,27h ; restore mode
+ out mncmd
+
+ ret
+ENDIF
+
+ ret
+
+;
+; 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
+; 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 ; get character to test
+ ret
+
+;
+; prtflt - printer filter
+; 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 ; get character to test
+
+IF FALSE ; strip out lf from printer stream
+ ani 7fh ; make sure it is parity less
+ cpi lf ; is it a line feed?
+ rnz ; no, print it
+; xra a ; yes, don't.
+
+ENDIF
+
+ ret
+
+;
+; system-dependent processing for BYE command.
+;
+sysbye:
+ ret
+
+;
+; This is the system-dependent command to change the baud rate.
+; DE contains the two-byte value from the baud rate table; both
+; bytes of this value are also stored in 'speed'.
+;
+sysspd:
+
+IF FALSE ; as always
+ in mncmd ; clear register counter
+ mvi a,4eh ; set for 1 stop, 8 data bits
+ out mnmode ; save in mode 1 port
+ mvi a,30h ; set bits for rate etc..
+ add e ; add baud rate (bits 0 - 3)
+ out mnmode ; set mode port 2
+ mvi a,27h ; set tx/rx ready, RTS CTS active
+ out mncmd
+ ret
+ENDIF
+ ret ; if routine not supported
+;
+; 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 bytes or 1 word, ab)
+; the data byte a is return in A and E, and b in D
+; only byte 'a' is the key for the table
+
+IF FALSE ; as always
+spdtbl: db 16 ; sixteen entries for PCI
+ db 3,'110$', 2,2
+ db 4,'1200$', 7,7
+ db 3,'134$', 3,3
+ db 3,'150$', 4,4
+ db 4,'1800$', 8,8
+ db 5,'19200$', 15,15
+ db 4,'2000$', 9,9
+ db 4,'2400$', 10,10
+ db 3,'300$', 5,5
+ db 4,'3600$', 11,11
+ db 4,'4800$', 12,12
+ db 2,'50$', 0,0
+ db 3,'600$', 6,6
+ db 4,'7200$', 13,13
+ db 2,'75$', 1,1
+ db 4,'9600$', 14,14
+
+sphtbl: db ' 50 75 110 134 150 300 600 1200 '
+ db cr,lf,'1800 2000 2400 3600 4800 7200 9600 19200$'
+ENDIF
+
+IF m2215
+spdtbl equ 0 ; routine unsupported
+sphtbl equ 0
+ENDIF
+
+;
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+;
+sysprt:
+
+IF m2215
+prttbl equ 0 ; SET PORT is not supported
+prhtbl equ 0 ; Merlin M2215 could, I suppose
+ENDIF
+
+;
+; 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 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:
+ call 0f55dh ;CONST BIOS vector
+ ora a ;set flags
+ rz
+ call 0f56eh ;CONIN BIOS vector
+ ret
+
+;
+; Output character in E to the console.
+; destroys bc, de, hl
+;
+outcon:
+ mov c, e
+ call 0f57fh ;CONOUT BIOS vector
+ 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 m2215
+ push psw
+ push h
+ push d
+ push b
+
+ mov c, e
+ mvi a, 1 ; ie: tty1:
+ mov d, a
+ call 0f6a2h ;PUN BIOS vector
+
+ pop b
+ pop d
+ pop h
+ pop psw
+ENDIF
+
+ ret
+
+;
+; for IOBYT systems, the modem port has already been selected.
+; destroys bc, de, hl.
+;
+inpmdm:
+
+IF m2215
+ ; check status
+ lda 0fa32h ; ie. tty1:
+ ora a
+ rz
+
+ mvi a, 1 ; RDR BIOS vector
+ mov d, a
+ call 0f651h
+; ani 7fh
+
+ push a
+ di
+ mvi a, 0
+ sta 0fa32h ; remove interrupt flag
+ sta 0f2d3h ; zero buffer counter
+ lda 0f2d4h
+ sta 0f2d5h
+ ei
+ nop
+ pop a
+
+ ret
+ENDIF
+
+;
+; 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 ; if a=0 do nothing
+
+outlp1: pop d ; restore saved register pair
+ ret
+
+; 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)
+delchr:
+
+ mvi e,bs ;get a backspace
+ jmp 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 m2215
+sysver: db 'BT Merlin M2215, port TTY1:, settings unchanged.$'
+ENDIF
+
+tstmsg: db 'Test message',cr,lf,'$'
+
+IF lasm
+LINK CPXVDU.ASM ; link to the Terminal definition tables
+ENDIF ;lasm
diff --git a/src/cpxnor.asm b/src/cpxnor.asm
new file mode 100644
index 0000000..2648060
--- /dev/null
+++ b/src/cpxnor.asm
@@ -0,0 +1,587 @@
+IF NOT LASM
+.printx * CPXNOR.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 various
+; NorthStar KERMITs. This has the Family name of CPXNOR.ASM.
+;
+; revision history (last edit first)
+;
+;edit 4, 16-Jan-1991 by MF. Fixed a bug in OUTCON wherein the final RET
+; was missing (bug reported by David P. Arnot of Scottish
+; Agricultural College).
+;edit 3, 12-Oct-1990 by MF. Added a semicolon before the comment
+; beginning "Family is the string so we don't get errors
+; edit 2, 23 July, 1987 by OBSchou to massage file to suit CPXCOM.ASM.
+;
+; edit 1: 1 June, 1986 by OBSchou, Loughborogh University, UK.
+; Hived off northstar and Comart system dependent modules from
+; CPXSYS.ASM. This assembles ok, but I cannot test it. Any comments?
+
+
+IF norths
+.printx * Assembling for NorthStar Horizon with HSIO-4 board *
+ENDIF;norths
+
+IF horizon ;[25]
+.printx * Assembling KERMIT-80 for the NorthStar Horizon *
+ENDIF;horizon
+
+IF advant ;[22]
+.printx * Assembling kermit-80 for North Star Advantage *
+ENDIF ;[22]
+
+IF basicns ;[29]
+.printx * Assembling KERMIT-80 for the Northstar Horizon using printer port *
+ENDIF ;basicns [29]
+
+IF comart
+.printx * Assembling KERMIT-80 for Comart Communicator *
+ENDIF ; comart
+
+; the basics...
+IF norths ;The basic Northstar Horizon BIOS does not access ports 2-5
+port0d equ 02h ;Port 0 data (console)
+port0s equ 03h ;Port 0 status
+port1d equ 04h ;Port 1 data (printer)
+port1s equ 05h ;Port 1 status
+
+port2b equ 10h ;Port 2 baud
+port2i equ 11h ;Port 2 interrupt mask
+port2d equ 12h ;Port 2 data
+port2s equ 13h ;Port 2 status
+
+port3b equ 14h ;Port 3 baud
+port3i equ 15h ;Port 3 interrupt mask
+port3d equ 16h ;Port 3 data
+port3s equ 17h ;Port 3 status
+
+port4b equ 18h ;Port 4 baud
+port4i equ 19h ;Port 4 interrupt mask
+port4d equ 1Ah ;Port 4 data
+port4s equ 1Bh ;Port 4 status
+
+port5b equ 1Ch ;Port 5 baud
+port5i equ 1Dh ;Port 5 interrupt mask
+port5d equ 1Eh ;Port 5 data
+port5s equ 1Fh ;Port 5 status
+
+NS19K2 EQU 00H ;19.2 kilobaud
+NS9600 EQU 01H ;9600 baud
+NS4800 EQU 02H ;4800 baud
+NS2400 EQU 03H ;2400 baud
+NS1200 EQU 04H ;1200 baud
+NS0600 EQU 05H ; 600 baud
+NS0300 EQU 06H ; 300 baud
+NS0110 EQU 07H ; 110 baud
+;; Set to use port 5 at 1200 baud
+mnport equ port5d ;Data port
+mnprts equ port5s ;Status port
+baudrt equ port5b ;Baud rate port
+baudini equ ns1200 ;Initial baud rate
+output EQU 1 ;Bit of UART status for transmitter ready
+input EQU 2 ;Bit of UART status for receiver ready
+z80 EQU TRUE ;This one's a Z80.
+ENDIF;norths
+
+IF basicns ;[29]
+mnport equ 04h ;printer port data
+mnprts equ 05h ; printer port status
+output equ 1 ;transmitter ready
+input equ 2 ;receiver ready
+z80 equ FALSE ; not important
+ENDIF ;basicns [29]
+
+IF horizon ;[25]
+mnport EQU 004H ;Modem data port
+mnprts EQU 005H ;Modem status port
+output EQU 01H ;Transmitter empty
+input EQU 02H ;Input data available
+TxEmpty EQU 04h ;Transmitter empty
+;Note: Needs terminal definition (vt100, vt52, tvi925, adm3a or crt above)
+z80 EQU TRUE ;This one's a Z80.
+ENDIF;horizon
+
+IF advant ;[22]
+vtval EQU 1 ; we do emulation of VT52s
+slot EQU 1 ;SIO card slot
+mnport EQU (6-slot)*16 ;Modem data port
+mnprts EQU mnport+1 ;Modem status port
+baudrt EQU mnport+8 ;Baud rate register
+output EQU 01H ;Transmitter buffer empty
+input EQU 02H ;Input data available
+TxEmpty EQU 04h ;Transmitter empty flag
+z80 EQU TRUE
+ENDIF;[22] advant
+
+IF comart ;[25]
+mnport EQU 002H ;Modem data port
+mnprts EQU 003H ;Modem status port
+output EQU 01H ;Transmitter empty
+input EQU 02H ;Input data available
+TxEmpty EQU 04h ;Transmitter empty
+;Note: Needs terminal definition (vt100, vt52, tvi925, adm3a or crt above)
+z80 EQU TRUE ;This one's a Z80.
+ENDIF;comart
+
+
+IF advant
+defesc EQU '\'-100O
+ENDIF;advant
+
+;
+; 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 CP4SYS.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 'CPXNOR.ASM (4) 16-Jan-1991$' ; Used for family versions....
+
+
+
+sysxin: ; continuation of system dependent initialisation code
+IF advant ;[22]
+ mvi a,40h
+ out mnprts ; Reset USART
+ lxi h,7070h ; Default to 1200 baud
+ shld speed ; store current speed
+ xchg
+ call sysspd ; set default baud rate
+ mvi a,4Eh ; Set UART mode to async 16x clock, 8 data
+ out mnprts ; bits, no parity, and 1 stop bit
+ mvi a,37h ; Set command to Tx enable, DTR on, Rx enable,
+ out mnprts ; break off, error reset, and RTS on
+ENDIF;[22] advant
+
+IF norths
+ mvi a,baudini ;Get initial speed
+ out baudrt
+ sta speed ;save for status display
+ sta speed+1
+ENDIF;norths
+
+IF comart OR horizon ;[25]
+; The PD8251/PD8251A is reset by three successive 00 Hex or two
+; successive 80 Hex command instructions followed by a software
+; reset command instruction (40 Hex).
+ mvi a,80h ; Send UART reset
+ out mnprts
+ mvi a,80h
+ out mnprts
+ mvi a,40h
+ out mnprts
+ mvi a,4Eh ; Set UART mode to async 16x clock, 8 data
+ out mnprts ; bits, no parity, and 1 stop bit
+ mvi a,37h ; Set command to Tx enable, DTR on, Rx enable,
+ out mnprts ; break off, error reset, and RTS on
+ENDIF;comart OR horizon
+
+
+ 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
+
+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:
+IF advant OR comart OR horizon ; some more
+ lxi d,inhlps ; we got options...
+ call prtstr ; print them.
+ENDIF;[22] advant OR comart OR horizon [29]
+
+ 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 advant OR comart OR horizon ; ... some more
+ db cr,lf,'B Transmit a BREAK'
+ENDIF;[22] advant OR comart OR horizon
+
+ 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 advant OR comart OR horizon ; [22] [25] ... some more
+ cpi 'B' ; send break?
+ jz sendbr ; yes, go do it. return nonskip when through.
+ENDIF;advant OR comart OR horizon [32]
+
+ jmp rskp ; take skip return - command not recognized.
+
+
+;
+
+IF advant OR comart OR horizon ;[lmj]
+sendbr:
+;
+; Ensure that the transmitter has finished sending buffered chars
+sndbr1: in mnprts ; get UART status
+ ani TxEmpty ; everything sent?
+ jz sndbr1 ; no, wait a bit more
+;
+; Begin sending a break by setting bit in UART command register
+ mvi a,3Fh ; Set TxEna, DTR, RxEna, SBreak, ErrRst, RTS
+ out 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
+ out mnprts
+;
+ ret ;done
+ENDIF;advant OR comart OR horizon
+
+;
+
+;
+; 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
+IF advant ;[22]
+ cpi 'D'-100O ;Control-D's reset video
+ rnz ; if not control-D, it's ok.
+ xra a ; don't allow control-D out.
+ENDIF;[22] advant
+ 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 norths OR advant ;
+ mov a,e ; get the parsed value
+ out baudrt ; Tell the baud rate generator.
+ ret
+ENDIF;norths OR advant
+
+IF advant ;[22]
+spdtbl: db 6 ; 6 entries
+ db 04,'1200$', 70h,70h
+ db 04,'2400$', 78h,78h
+ db 03,'300$', 40h,40h
+ db 04,'4800$', 7Ch,7Ch
+ db 03,'600$', 60h,60h
+ db 04,'9600$', 7Eh,7Eh
+
+sphtbl: db cr,lf,' 300 600 1200 2400 4800 9600$'
+ENDIF;[22] advant
+
+
+IF norths
+spdtbl: db 8 ; 8 entries
+ db 3,'110$', 07H,07H
+ db 4,'1200$', 04H,04H
+ db 5,'19200$', 00H,00H
+ db 4,'2400$', 03H,03H
+ db 3,'300$', 06H,06H
+ db 4,'4800$', 02H,02H
+ db 3,'600$', 05H,05H
+ db 4,'9600$', 01H,01H
+
+
+sphtbl: db cr,lf
+ db ' 110 300 600 12000 2400 4800 9600 19200$'
+ENDIF;norths
+
+; 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 NOT (advant OR norths)
+spdtbl EQU 0 ;[hh] SET BAUD not supported.
+sphtbl EQU 0 ;[hh] ran out of room above...
+ENDIF ;NOT (advant OR norths)
+;
+;
+
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+sysprt:
+ ret
+
+prttbl equ 0 ; SET PORT not supported
+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:
+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 ;[MF]per David P. Arnot
+;
+
+;
+; outmdm - output a char from E to the modem.
+; the parity bit has been set as necessary.
+; returns nonskip; bc, de, hl preserved.
+outmdm:
+ 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
+;
+
+;
+; get character from modem; return zero if none available.
+; for IOBYT systems, the modem port has already been selected.
+; destroys bc, de, hl.
+inpmdm:
+;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.
+ 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 ; 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
+ ret
+IF advant ; all others require terminals
+;
+
+;
+; 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
+ENDIF ;advant
+
+;
+; 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:
+IF advant ;[22]
+ ret
+ENDIF;advant
+IF NOT (advant );[22]
+ mvi e,bs ;get a backspace
+ jmp outcon
+ENDIF;NOT (advant) [22]
+
+; 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 norths
+sysver: db 'Northstar Horizon$'
+ENDIF;norths
+
+IF basicns ;[29]
+sysver: db 'Northstar using printer port$'
+ENDIF ;basicns [29]
+
+IF comart ;[25]
+sysver: db 'Comart Communicator$'
+ENDIF;comart
+
+IF horizon ;[25]
+sysver: db 'Northstar Horizon$'
+ENDIF;horizon
+
+IF advant ;[22]
+sysver: db 'North Star Advantage$'
+outlin: db 04H,cr,lf,tab,'$'
+erascr: db 04H,'$' ;Clear screen and go home.
+eralin: db cr,0EH,'$' ;Clear line.
+curldn: db esc,'=$' ;cursor leadin
+ttab: ;Table start location.
+ta: db 0BH,'$',0,0 ;Cursor up.
+tb: db 0AH,'$',0,0 ;Cursor down.
+tc: db 0CH,'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left
+te: db 04H,'$',0,0 ;Clear display
+tf: db 12H,'$',0,0 ;Enter Graphics Mode
+tg: db 13H,'$',0,0 ;Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home.
+ti: db 0BH,'$',0,0 ;Reverse linefeed.
+tj: db 0FH,'$',0,0 ;Clear to end of screen.
+tk: db 0EH,'$',0,0 ;Clear to end of line.
+ENDIF;[22] advant
+IF lasm AND (NOT advant)
+LINK CPXVDU.ASM
+ENDIF ;lasm - m80 will INCLUDE CPXVDU.ASM
+
+IF lasm ; here if not a terminal selected and in LASM
+ovlend equ $
+ END
+ENDIF ;lasm
diff --git a/src/cpxpcw.asm b/src/cpxpcw.asm
new file mode 100644
index 0000000..554fd61
--- /dev/null
+++ b/src/cpxpcw.asm
@@ -0,0 +1,912 @@
+IF NOT lasm
+.printx * CPXPCW.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.08
+;
+; 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.
+;
+; This file contains the system-dependent code and data for KERMIT
+; on the Amstrad range of personal computers.
+;
+;
+; Revision history:
+;
+;edit 9, 22-Jan-1991 by MF. Added "sysinit" code at "init04" from Kermit
+; version 4.08 which had been left out of version 4.09 to reserve
+; space for the Amstrad's I/O buffers. Amstrad Kermit now stores
+; files correctly (version 4.09 had garbled files). Again,
+; this fix comes from Mr. D. P. Arnot of the Scottish Agricultural
+; College in the UK.
+;edit 8, 16-Jan-1991 by MF. Added a "bs" left out of "delstr" per
+; instruction from David P. Arnot of Scottish Agricultural
+; College, Auchincruive, Ayr, UK.
+; E-mail: <D.P.Arnot@edinburgh.ac.uk>
+; edit 7, 22 July 1987 by OBSchou to massage code to fit with CPXCOM.ASM
+; Had to rename bcnout to bcnot as the former label clashed with
+; one of the same name in CPXCOM.ASM. Sorry, folks.
+;
+; edit 6, 14th July, 1987 by OBSchou for Phillip Wade, Hull University
+; Computer Centre. Change to delchr routine for PCW machines,
+; as character 127 decimal is a printing character on
+; the Amstrad PCW. The routine has been replaced
+; by a bs,space,bs,bs string. (OBS Comment - why a total of THREE bs?)
+;
+; edit 5 9 May 1987 by C.J.MILES@UK.AC.UMRCC
+; Hangup phone and clear screen options added to
+; terminal mode.
+;
+; edit 4 23 March 1987 by C.J.MILES@UK.AC.UMRCC
+; Use direct input drom SIO for CPC machines instead
+; of using BDOS. Improvement reduces time for file
+; transfer to 65% of time used by BDOS method.
+; Add reverse Prestel baud rate.
+;
+; edit 3 20 March 1987 by Chris Miles (C.J.MILES@UK.AC.UMRCC)
+; (Greater Manchester Archaeological Unit, Manchester Univ.).
+; Added support for Amstrad CPC CP/M Plus machines,
+; Added 31250 baud rate option,
+; Bug fixed in sending BREAK,
+; Bug fixed in 1200/75 baud setup
+; Machine and CP/M version checks added.
+;
+; edit 2 11 Febuary, 1987 by OBSchou for Ian Young.
+; Changes to the send break routine to change two lines of code from
+; ori 018h ; send break, Tx enable
+; and ori 0008h ; Tx enable
+;
+; to ori 01ah ; send break, Tx enable, RTS
+; and ori 00ah ; Tx enable, RTS
+;
+; This is a bug fix to hopefully keep RTS actve during breaks.
+;
+; [Ed. (OBSchou) 21/1/87.
+; This file linked FROM cpxsys.asm, so do NOT rename this
+; file. The diffculty of needing a HUGE CPXSYS.ASM file on your floppy
+; only to act as a switcher remains, but hopefully will be better in
+; the future. If you ARE stuck, then rename this CPXSYS.ASM but add the
+; label SYSEDT: to the FAMILY label. A bit messy.]
+;
+;
+; The "author" of this system-dependent file is:
+;
+; Ian A. Young
+; Lattice Logic Ltd
+; 9 Wemyss Place
+; Edinburgh
+;
+; Some other addresses:
+;
+; ian@latlog.uucp
+; ...seismo!mcvax!ukc!latlog!ian
+; or c/o OBSchou@uk.ac.lut.multics
+;
+; ... although much of the code concerned was written by others.
+;
+
+
+; Keep module name, edit number, and last revision date in memory.
+
+;sysedt: db 'CPXSYS.ASM (36) 20-Mar-87$'
+family: db 'CPXPCW.ASM (9) 22-Jan-1991$'
+
+
+;
+; Assembly-time message announcing which version we are building
+;
+
+IF pcw
+.printx * Assembling Amstrad PCW Kermit-80 *
+ENDIF
+
+IF cpc
+.printx * Assembling Amstrad CPC Kermit-80 *
+ENDIF
+
+;
+; Miscellany of parameter settings
+;
+z80 EQU TRUE ; all Amstrads have a Z80.
+defesc EQU '\'-100O ; The default escape character.
+vtval EQU 0 ; we don't need VT52 emulation
+
+;
+; Amstrad CPC machines use 16 bit I/O address decoding and therefore
+; the Z80 instructions OUT (C),A and IN A,(C) must be defined.
+;
+outc EQU 79edh ; IN A,(C)
+inpc EQU 78edh ; OUT (C),A
+
+;
+; hardware information
+;
+; There is a Z80-DART (Mostek/SGS 8470) at I/O addresses E0..E3 (PCW)
+; and FADC..FADD (CPC), and a 8253 programmable divider running it at
+; E4..E7 (PCW) and FBDC..FBDF (CPC)
+;
+
+input EQU 01h ; input data available
+output EQU 04h ; output buffer ready
+
+IF pcw
+mnport EQU 0E0h ; data register for SIO
+mnprts EQU 0E1h ; control register for SIO
+ctc0 EQU 0E4h ; 8253 load counter 0
+ctc1 EQU 0E5h ; 8253 load counter 1
+ctcmod EQU 0E7h ; 8253 write mode word
+ENDIF
+
+IF cpc
+mnport EQU 0FADCh ; data register for SIO
+mnprts EQU 0FADDh ; control register for SIO
+ctc0 EQU 0FBDCh ; 8253 load counter 0
+ctc1 EQU 0FBDDh ; 8253 load counter 1
+ctcmod EQU 0FBDFh ; 8253 write mode word
+ENDIF
+
+;
+; SIO input buffering
+;
+siosz EQU 4096 ; size of SIO input buffer
+siomsk EQU 4095 ; mask for wrapping buffer round
+
+;
+; Extended BIOS jump-block addresses; reached through USERF
+;
+sainit EQU 00B6h ; initialise SIO
+sabaud EQU 00B9h ; set baud rate
+saparm EQU 00BCh ; fetch SIO parameters
+teask EQU 00BFh ; find out cursor position
+cdvers EQU 00E3h ; get version numbers
+cdinfo EQU 00E6h ; get BIOS system information
+
+;
+; System-dependent initialization
+; Called once at program start.
+sysxin: ; continuation of system initialzation
+;
+; check for correct CP/M version
+;
+ mvi c,12 ; get CP/M version BDOS call
+ call bdos
+ mov a,l ; check if CP/M Plus
+ cpi 31h
+ jz init08
+ lxi d,wrong2 ; point to error message
+ call prtstr
+ mvi c,0 ; warm boot
+ call bdos
+;
+init08: ;[OBS] Moved the Cinfigured for message out as
+ ;[OBS] it is in CPXCOM.ASM
+;
+; get addresses of BIOS routines
+;
+; BIOS USERF is used to get to extended BIOS routines
+;
+ lhld 1 ; warm boot vector
+ lxi d,87 ; offset to USERF vector
+ dad d ; DE now has USERF vector address
+ shld userf+1 ; ready for jumping to...
+;
+; BIOS routines for fast character I/O
+;
+ lhld 1 ; warm boot vector (#1)
+ lxi d,3
+ dad d ; next is #2, CONST
+ shld bcnst+1
+ dad d ; next is #3, CONIN
+ shld bcnin+1
+ dad d ; next is #4, CONOUT
+ shld bcnot+1 ;[obs] Was bcnout, but this conflicts
+ ;[obs] with a label in CPXCOM.ASM
+ dad d ; next is #5, LIST
+ shld blist+1
+ dad d ; next is #6, AUXOUT
+ dad d ; next is #7, AUXIN
+ shld baxin+1
+ lhld 1 ; warm boot vector again
+ lxi d,002Ah ; offset to LISTST (#15)
+ dad d
+ shld lptstat+1
+ lhld 1 ; warm boot vector again
+ lxi d,0033h ; offset to AUXIST (#18)
+ dad d
+ shld baxist+1
+;
+; check if running on correct Amstrad
+;
+ call userf
+ dw cdvers
+IF pcw
+ cpi 0
+ENDIF
+IF cpc
+ cpi 1
+ENDIF
+ jnz init06
+ lxi d,wrong1 ; point to error message
+ call prtstr
+ mvi c,0
+ call bdos
+;
+; verify presence of SIO board by asking the BIOS.
+;
+init06: call userf ; C gets 00 if not fitted
+ dw cdinfo
+ xra a ; a <- 0
+ ora c ; zero => no serial port
+ jnz init03 ; non-zero => OK
+ lxi d,nosio ; snooty message...
+ call prtstr
+ mvi c,0 ; warm boot out of here
+ call bdos
+init03:
+;
+; find initial baud rate and other information
+;
+ call userf ; gives B=rx baud, C=tx baud, D=stop bits,
+ ; E=parity, H=rx bits, L=tx bits.
+ dw saparm ; get SIO parameters
+ push h ; save bit settings
+ mov a,b ; if TX and RX speeds same, they are OK
+ cmp c
+ jz init01
+ cpi 8 ; rx=1200?
+ jnz init02 ; no, can't be Prestel
+ mov a,c
+ cpi 2 ; tx=75?
+ jnz init02 ; no, can't be Prestel
+ lxi b,0 ; otherwise 1200/75 comes out as 0s.
+init01: push b ; assign value to SPEED
+ pop h
+ shld speed
+init02: ; here if we leave it as is
+ pop h ; get bit settings
+ mov a,l ; no of TX data bits set
+ sui 5 ; make into 00, 01, 10, 11.
+ rrc
+ rrc
+ rrc
+ sta txbits ; we may need it later
+;
+; set handshake mode: there are two parts to this, interrupts and
+; hardware handshake. The MODE byte used by the firmware expresses
+; this combination as -(int*2 + hand*1). Thus, both options on would
+; be (-3) or 0FDh.
+;
+; Here, we set the interrupt part of the mode on; it helps the BIOS cope.
+; Unfortunately, >sigh<, according to Soft971, this will only work
+; if you have BIOS V1.4 or higher. I have no idea what would happen
+; if we tried random hanshake mode flags with lower versions, so we
+; just skip over if it would be dangerous...
+;
+ call userf ; fetch all parameters
+ dw saparm
+ sta orgmode ; remember original mode for later
+
+ call userf ; get BIOS version to B,C
+ dw cdvers
+ mov a,b ; BIOS major version number (eg 1)
+ ora a ; if zero, too low...
+ jz init04
+ cpi 1 ; if not 1, definitely OK
+ jnz init05
+ mov a,c ; otherwise, its 1.X; want >= 4
+ cpi 4
+ jm init04 ; <4 => too low
+
+init05: call userf ; get the original flags back
+ dw saparm
+ xri 0FFh ; make mode into bit mask
+ inr a
+ ori 2 ; set interrupt mode
+ xri 0FFh ; turn back into mode value
+ inr a
+ call userf ; feed change back to BIOS
+ dw sainit
+init04: ; come here if not setting mode
+
+; Locate large buffers for multi-sector I/O and SIO input buffering.
+; Space above ovlend is available for buffers; we have pretty well the machine
+; to ourselves in an Amstrad PCW because they all gave 61K TPAs. We don't even
+; bother to perform any checking.
+; We don't want to use more than maxsec for disk buffers because
+; if we use too many, the remote end could time out while we're
+; writing to disk. maxsec is system-dependent, but for now we'll just
+; use 8Kbytes. If you get retransmissions and other protocol errors after
+; transferring the first maxsec sectors, lower maxsec.
+;
+maxsec EQU (8*1024)/bufsiz ; 8K / number of bytes per sector
+
+ lxi h,ovlend+siosz ; get start of buffer
+ shld bufadr ; store in linkage section
+ mvi a,maxsec ; get size of buffer, in sectors
+ sta bufsec ; store that, too.
+
+
+ ret ; return from system-dependent routine
+
+;
+; message complaining about wrong Amstrad machine
+;
+wrong1: db 'Error - This Kermit will only run on the Amstrad '
+IF pcw
+ db 'PCW 8256/8512'
+ENDIF
+IF cpc
+ db 'CPC 464/664/6128'
+ENDIF
+ db cr,lf,'$'
+;
+; message complaining about version of CP/M being used
+;
+wrong2: db 'Error - Incorrect CP/M version, needs CP/M 3.x'
+ db cr,lf,'$'
+;
+; message complaining of no SIO board
+;
+nosio: db 'Error - No SIO option fitted to this machine'
+ db cr, lf, '$'
+
+;
+; jumps to BIOS character I/O routines.
+; Addresses filled in by initialisation code above.
+;
+bcnst: jmp $-$ ; console status
+bcnin: jmp $-$ ; console input
+bcnot: jmp $-$ ; console output [obs - was bcnout]
+blist: jmp $-$ ; printer output
+baxin: jmp $-$ ; aux port input
+baxist: jmp $-$ ; aux port status
+lptstat:jmp $-$ ; printer status
+
+;
+; Other BIOS routines
+;
+userf: jmp $-$ ; call extended BIOS function
+
+;
+; saved value of some original parameters
+;
+orgmode:ds 1
+txbits: ds 1
+
+;
+; system-dependent termination processing
+; If we've changed anything, this is our last chance to put it back.
+sysexit:
+ call userf ; fetch firmware parameters
+ dw saparm
+ lda orgmode ; replace with original mode
+ call userf ; inform BIOS
+ dw sainit
+ ret
+
+;
+; system-dependent processing for start of CONNECT command
+;
+syscon:
+ lxi d,conmsg ; how to get escape char message
+ call prtstr
+ ret
+
+conmsg: ; Messages printed when entering transparent (CONNECT) mode:
+IF pcw
+ db '(Use boxed minus key next to space bar to generate a Control-\)'
+ENDIF
+ db cr,lf,'$'
+
+;
+; 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:
+ db cr,lf,'B Transmit a BREAK'
+ db cr,lf,'H Hangup using DTR'
+ db cr,lf,'W Wipe screen clear'
+ 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 'B' ; send break ?
+ jz sendbr ; yes, go do it. return nonskip when through.
+ cpi 'H' ; hang up ?
+ jz hangup
+ cpi 'W' ; clear screen ?
+ jz clrtop
+ jmp rskp ; take skip return - command not recognized.
+
+;
+; Hangup (drop DTR) and Break send routine
+;
+
+hangup:
+ mvi d,0ah ; set up hangup bit mask
+ mvi e,255 ; time for hangup is 2 1/2 secs
+ jmp setbit ; skip Tx empty test
+
+sendbr:
+ mvi d,9ah ; set up break bit mask
+ mvi e,30 ; time for break is 300 ms
+
+sndbr1: mvi a,1 ; select Read Register 1
+
+IF pcw ; allow 8 bit I/O instructions
+ out mnprts
+ in mnprts ; read the contents
+ENDIF
+
+IF cpc ; use 16 bit I/O instructions
+ lxi b,mnprts
+ dw outc ; OUT (C),A
+ dw inpc ; IN A,(C)
+ENDIF
+
+ ani 1 ; test "all done" flag
+ jz sndbr1 ; loop until it's nonzero.
+;
+; Next, set the break or hangup bit on the SIO.
+;
+setbit:
+ mvi a,5 ; select Write Register 5
+IF pcw
+ out mnprts
+ENDIF
+IF cpc
+ dw outc ; OUT (C),A
+ENDIF
+ lda txbits ; get txbits (already in correct bit positions)
+ ora d ; send break, Tx Enable, RTS
+IF pcw
+ out mnprts
+ENDIF
+IF cpc
+ dw outc ; OUT (C),A
+ENDIF
+
+;
+; Now, delay for duration of hangup or break
+;
+ mov a,e ; delay count
+ call delay
+;
+; Time's up. Put transmitter back in normal state and return.
+;
+ mvi a,5 ; select Write Register 5
+IF pcw
+ out mnprts
+ENDIF
+IF cpc
+ lxi b,mnprts
+ dw outc ; OUT (C),A
+ENDIF
+ lda txbits ; get txbits again
+ ori 8ah ; Reset break, Tx Enable, RTS
+IF pcw
+ out mnprts
+ENDIF
+IF cpc
+ dw outc ; OUT (C),A
+ENDIF
+ ret ; done.
+
+;
+; 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
+;
+; system-dependent processing for BYE command.
+;
+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:
+ push d ; move to HL for firmware
+ pop h
+ mov a,h ; if h=0 then Prestel rates
+ ora a
+ jnz spd01 ; if not 1200/75 then skip
+ lxi h,0802H ; else set 1200/75 into HL
+ jmp spd03 ; jump to normal setup
+
+spd01: cpi 11h ; if h=11h then reverse Prestel
+ jnz spd02 ; if not 75/1200 then skip
+ lxi h,0208h ; else set 75/1200 into HL
+ jmp spd03 ; jump to normal setup
+
+spd02: cpi 10h ; if h=10h then 31250 baud
+ jnz spd03 ; if not 31250 then skip to normal setup
+ mvi a,36h ; set 8253 for mode 2 binary count
+ lxi b,ctcmod ; output to CTC mode register
+ dw outc
+ lxi b,ctc0 ; select transmit clock
+ mov a,4 ; timer value for 31250 (04h)
+ dw outc
+ mov a,0 ; timer value for 31250 (04h)
+ dw outc
+ lxi b,ctc0 ; select receive clock
+ mov a,4 ; timer value for 31250 (04h)
+ dw outc
+ mov a,0 ; timer value for 31250 (04h)
+ dw outc
+ ret
+
+spd03: call userf ; set whatever we have now...
+ dw sabaud ; using BIOS routine
+ ret
+
+;
+; 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)
+;
+spdtbl: db 12h ;18 entries
+ db 03h,'110$', 03h,03h
+ db 04h,'1200$', 08h,08h
+ db 07h,'1200/75$', 00h,00h ; real values faked up when required
+ db 05h,'134.5$', 04h,04h
+ db 03h,'150$', 05h,05h
+ db 04h,'1800$', 09h,09h
+ db 05h,'19200$', 0fh,0fh
+ db 04h,'2400$', 0ah,0ah
+ db 03h,'300$', 06h,06h
+ db 05h,'31250$',10h,10h ; flag to direct setup routine
+ db 04h,'3600$', 0bh,0bh
+ db 04h,'4800$', 0ch,0ch
+ db 02h,'50$', 01h,01h
+ db 03h,'600$', 07h,07h
+ db 04h,'7200$', 0dh,0dh
+ db 02h,'75$', 02h,02h
+ db 07h,'75/1200$',11h,11h ; real values faked up when required
+ db 04h,'9600$', 0eh,0eh
+
+sphtbl: db cr,lf,lf
+ db 'Normal rates: 50 75 110 134.5 150 300 600'
+ db cr,lf
+ db ' 1200 1800 2400 3600 4800 7200 9600 19200'
+ db cr,lf,lf
+ db 'High speed : 31250 (only between Amstrads)'
+ db cr,lf,lf
+ db 'Split rates : 1200/75 (Rx=1200, Tx= 75)'
+ db cr,lf
+ db ' 75/1200 (Rx= 75, Tx=1200)'
+ db cr,lf,'$'
+
+;
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+;
+sysprt:
+ ret
+
+prttbl equ 0 ; SET PORT is not supported
+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.
+; preserves bc, de, hl.
+;
+selmdm:
+selcon:
+ ret
+
+;
+; Get character from console, or return zero.
+; result is returned in A. destroys bc, de, hl.
+;
+inpcon:
+ call bcnst ; get console status
+ ora a ; anything there?
+ rz ; no, forget it
+ jmp bcnin ; yes, get the character
+
+;
+; Output character in E to the console.
+; destroys bc, de, hl
+;
+outcon:
+ mov a,e ; TAB?
+ cpi tab
+ jz out001
+ mov c,e ; set correct arg register
+ jmp bcnot ; output to console via BIOS [obs was bcnout]
+
+;
+; perform tab expansion ourselves
+;
+out001: call userf ; get column in L
+ dw teask
+ mov a,l ; a <- column 0..n
+ ani 7 ; column 0..7
+ xri 0FFh ; not(col 0..7)
+ adi 9 ; a is 8-(colf7)
+out002: ora a ; any left?
+ rz ; return if not
+ dcr a ; one less now, anyhow
+ push psw ; save over BIOS call (just in case)
+ mvi c,' ' ; print one space
+ call bcnot ;[obs was bcnout]
+ call suck ; in case any stuff coming in
+ pop psw ; fetch count back
+ jmp out002 ; and go round again
+
+;
+; 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 cpc
+ push b ; save BC for CPC 16 bit I/O
+ENDIF
+outmd1:
+ call xsuck ; keep checking for incoming characters
+IF pcw
+ in mnprts ; get the output done flag.
+ENDIF
+IF cpc
+ lxi b,mnprts
+ dw inpc ; IN A,(C)
+ENDIF
+ ani output ; is it set?
+ jz outmd1 ; if not, loop until it is.
+ mov a,e
+IF pcw
+ out mnport ; output it.
+ENDIF
+IF cpc
+ lxi b,mnport
+ dw outc ; OUT (C),A
+ pop b ; restore BC
+ENDIF
+ ret
+
+;
+; get character from modem; return zero if none available.
+; destroys bc, de, hl.
+;
+inpmdm:
+ call suck ; get any characters pending
+ lhld sioct ; count of chars in buffer
+ mov a,h ; or together to get result
+ ora l
+ rz ; not got any, return now
+
+ dcx h ; down count
+ shld sioct
+
+ lhld siord ; read pointer
+ mov c,m ; fetch character ** NB TO C FOR NOW **
+
+ lxi d,1-ovlend ; bump pointer, subtract base
+ dad d
+ mov a,h ; mask high byte of offset
+ ani siomsk/256
+ mov h,a
+ lxi d,ovlend ; add in base again
+ dad d
+ shld siord
+
+ mov a,c ; get to proper register
+ 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.
+
+;
+; SIO input buffer handling. The buffer pointers are held as pointers into
+; the buffer. The read pointer
+; is to the next unused character, the write pointer to the next unused space.
+;
+siord: dw ovlend ; next char to read
+siowr: dw ovlend ; next char to write
+sioct: dw 0 ; number in buffer
+
+xsuck: push d ; save regs version of suck
+ push b
+ push h
+ call suck
+ pop h
+ pop b
+ pop d
+ ret
+
+;
+; suck
+;
+; this routine is called whenever it would be possible that some
+; characters might be available in the SIO device; they are all
+; transferred (there may be up to 4 pending) to the buffer.
+;
+; all registers are destroyed
+;
+suck:
+IF pcw
+ call baxist ; check input status via BDOS
+ ora a ; check if zero
+ENDIF
+IF cpc
+ lxi b,mnprts ; get input status directly
+ dw inpc ; IN A,(C)
+ ani input ; mask for Rx ready
+ENDIF
+ rz ; return if no
+
+IF pcw
+ call baxin ; fetch character via BDOS
+ENDIF
+IF cpc
+ lxi b,mnport ; fetch character directly from SIO
+ dw inpc ; IN A,(C)
+ENDIF
+
+ lhld siowr ; write pointer
+ mov m,a ; put character
+
+ lxi d,1-ovlend ; take off base, bump pointer
+ dad d
+ mov a,h ; top byte of offset
+ ani siomsk/256 ; masked off
+ mov h,a
+ lxi d,ovlend ; add on base again
+ dad d
+ shld siowr ; replace pointer
+
+ lhld sioct ; bump count in buffer
+ inx h
+ shld sioct
+
+ jmp suck ; go round in case any more
+
+;
+; outlpt - output character in E to printer
+; console is selected.
+; preserves de.
+outlpt:
+ push d ; save DE in either case
+ mov c,e ; correct arg register
+ call blist
+ 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.)
+; or (row) and (column)
+;
+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:
+IF pcw ;[6] OBS for Phillip Wade
+ lxi d,delstr ;[5] send a string rather than a single character
+ call prtstr
+
+delstr: db bs,' ',bs,'$' ;[OBS] Was bs,space,bs,bs
+ENDIF ;pcw
+
+ mvi e,bs ;get a backspace
+ jmp 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 pcw
+sysver: db 'Amstrad PCW with SIO option$'
+ENDIF
+IF cpc
+sysver: db 'Amstrad CPC with CP/M Plus$'
+ENDIF
+
+outlin: db esc,'H',esc,'J',cr,lf,' $'
+
+erascr: db esc,'H',esc,'J$' ;Clear screen and go home.
+eralin: db cr,esc,'K$' ;Clear line.
+curldn: db esc,'Y$' ;cursor leadin
+ttab: ;Table start location.
+ta: db esc,'A$',0 ;Cursor up.
+tb: db esc,'B$',0 ;Cursor down.
+tc: db esc,'C$',0 ;Cursor right.
+td: db esc,'D$',0 ;Cursor left
+te: db esc,'E$',0 ;Clear display
+tf: db '$',0,0,0 ;Enter Graphics Mode
+tg: db '$',0,0,0 ;Exit Graphics mode
+th: db esc,'H$',0 ;Cursor home.
+ti: db esc,'I$',0 ;Reverse linefeed.
+tj: db esc,'J$',0 ;Clear to end of screen.
+tk: db esc,'K$',0 ;Clear to end of line.
+
+ovlend equ $ ; End of overlay
+
+ END
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
diff --git a/src/cpxsb.asm b/src/cpxsb.asm
new file mode 100644
index 0000000..3beefe7
--- /dev/null
+++ b/src/cpxsb.asm
@@ -0,0 +1,696 @@
+IF NOT lasm
+.printx * CPXSB.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 created 16 July, 1987 by OBSchou from code submitted
+; by William Rose for the Micromint SB180 systems (as featured in
+; BYTE magazine, 1986). This file has been modified to fit in with
+; Kermit-80 V4.08 etc. His file KERSYS.ASM is a stripped down version
+; of CPXSYS.ASM (formerly CP4SYS.ASM).
+;
+; revision history:
+; KERSYS.ASM - version 0.8 dated 13 Jul 87.
+;
+; Cutdown CP4SYS.ASM for SB-180/Ampro 230.
+;
+;
+; While this is a single CPU version (to ease editing) the assembler
+; conditionals have been kept to identify machine specific code.
+;
+; Note that the baud setting routine also sets parity, but this does not
+; change the parity given by Kermit's 'stat' command. I assume that the
+; main body of the program does its own parity check.
+;
+; Revision history (last entry first)
+;
+; edit 2, 22 July by OBSchou to massage file to fit with CPXCOM.ASM.
+;
+; edit 1, 15 July, 1987 by OBSchou for William Rose who submitted
+; the code for Kermit-80 V 4.05. Modified code as appropriate
+; for 4.08 compatability.
+;
+
+delfac EQU 150 ; Delay factor in SB-180 input loop - a fudge
+
+;
+; Keep module name, edit number, and last revision date in memory.
+;
+;sysedt: db 'KERSYS.ASM (03) 12-FEB-87 $' ; last SB-180 revision
+;sysedt: db 'KERSYS.ASM (04) 12-APR-87 $' ; Telecom Merlin added
+;sysedt: db 'KERSYS.ASM (5) 9-May-87 $' ; Minor tidying
+;sysedt: db 'KERSYS.ASM (6A) 17-Jun-87 $' ; BT Merlin M2215 only
+;sysedt: db 'KERSYS.ASM (7) 19-Jun-87 $' ; SB-180 only
+;sysedt: db 'KERSYS.ASM (8) 13-Jul-87 $' ; 6/9 MHz version
+family: db 'CPXSB.ASM (2) 22-Jul-87$' ; First entry for V4.08/9
+
+;
+; Assembly time message to let me know I'm building the right version.
+;
+
+IF sb180
+.printx * Assembling Kermit-80 for Micromint SB-180 *
+ENDIF
+
+
+IF sb180
+mnctrla EQU 000H ;Modem control port - CNTLA0
+mnctrlb EQU 002H ;Modem control port - CNTLB0
+mnstat EQU 004H ;Modem status port - STAT0
+mntxdat EQU 006H ;Modem output port - TDR0
+mnrddat EQU 008H ;Modem input port - RDR0
+output EQU 002H ;Transmit data register empty mask - TDRE
+input EQU 080H ;Receive data register full mask - RDRF
+z80 EQU TRUE ;This one's an HD64180, but Z80 will do
+ENDIF
+
+
+sysxin: ; continuation of system initialisation from sysinit
+
+IF sb180
+ lxi h, porbuf ; park the original settings
+ db 0EDh, 038h, mnctrla ; HD64180 code IN0 g,(m)
+ mov m, a
+ inx h
+ db 0EDh, 038h, mnctrlb
+ mov m, a
+ inx h
+ db 0EDh, 038h, mnstat
+ mov m, a
+ENDIF
+ ; re-initialise for KERMIT
+IF sb6
+ mvi h, 08h ; 0000$1001 - 9600 baud, (even) parity
+ mvi l, 08h ; 'speed' is two bytes
+ENDIF
+
+IF sb9
+ mvi h, 21h ; 0010$0001 - 9600 baud, (even) parity
+ mvi l, 21h ; 'speed' is two bytes
+ENDIF
+
+IF sb180
+ shld speed
+ lxi h, parind
+ mvi m, 8 ; index for 8 bits, no parity, 2 stop
+ call setpor
+ENDIF
+
+ ret
+
+porbuf: ds 3 ; original port settings
+
+;
+; system-dependent KERMIT termination processing
+; If we've changed anything, this is our last chance to put it back.
+;
+sysexit:
+
+IF sb180
+ lxi h, porbuf
+ mov a, m ; output parity
+ db 0EDh, 039h, mnctrla ; HD64180 code OUT0 (m),g
+ inx h
+ mov a, m ; output baud rate
+ db 0EDh, 039h, mnctrlb
+ inx h
+ mov a, m ; output to clear error flags
+ db 0EDh, 039h, mnstat
+ ; read twice to reset DCD0 ?
+ db 0EDh, 038h, mnstat
+ db 0EDh, 038h, mnstat
+ENDIF
+
+ ret
+
+;
+; system-dependent processing for start of CONNECT command
+;
+syscon:
+ ret
+
+conmsg: ; Messages printed when entering transparent (CONNECT) mode:
+
+ db '$'
+
+;
+; 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 sb180
+ lxi d, inhlps
+ call prtstr
+ENDIF
+
+ ret
+
+; Additional, system-dependent help for transparent mode
+; (two-character escape sequences)
+inhlps:
+
+IF sb180
+ db cr, lf, 'V Cycle port parameters'
+ENDIF
+
+ db '$' ; string 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: seqence was not recognized
+;
+sysint:
+; ani 137O ; convert lower case to upper, for testing...
+ ; does this work?
+IF sb180
+ cpi 'V' ; cycle port ?
+ jz pcycl
+ cpi 'v'
+ jz pcycl
+ENDIF
+
+ jmp rskp ; take skip return - command not recognised
+
+; Actual commands
+
+IF sb180
+pcycl:
+ lxi h, parind ; increment parval, modulo 12
+ mov a, m
+ adi 1
+ cpi 13
+ jnz pcy1
+ mvi a, 1
+pcy1: mov m, a ; update the storage
+ ; get index of name in parstr
+ ora a ; clear flags
+ dcr a
+ rlc
+ rlc
+ mov c, a
+ mvi b, 0
+ lxi h, parstr
+ inx h
+ dad b
+ push h
+ lxi d, cgmsg1
+ call prtstr
+ pop d
+ call prtstr
+ lxi d, cgmsg2
+ call prtstr
+ call setpor ; reset the port
+
+ ret
+
+cgmsg1: db '<$'
+cgmsg2: db '>$'
+ENDIF
+
+ ret
+
+;
+; Delay routine. Called with time (hundredths of seconds) in A.
+; The inner loop delays 1001 T-states, assuming no wait states are
+; inserted; this is repeated CPUSPD times, for a total delay of just
+; over 0.01 second. (CPUSPD should be set to the system clock rate,
+; in units of 100KHz: for an unmodified Kaypro II, that's 25 for
+; 2.5 MHz. Some enterprising soul could determine whether or not the
+; Kaypro actually inserts a wait state on instruction fetch (a common
+; practice); if so, the magic number at delay2 needs to be decreased.
+; (We also neglect to consider time spent at interrupt level).
+;
+; called by: sendbr
+; destroys BC
+;
+;delay: mvi c,cpuspd ; Number of times to wait 1000 T-states to
+; ; make .01 second delay
+;delay2: mvi b,70 ; Number of times to execute inner loop to
+; ; make 1000 T-state delay
+;delay3: dcr b ; 4 T-states (* 70 * cpuspd)
+; jnz delay3 ; 10 T-states (* 70 * cpuspd)
+; dcr c ; 4 T-states (* cpuspd)
+; jnz delay2 ; 10 T-states (* cpuspd)
+; ; total delay: ((14 * 70) + 14) * cpuspd
+; ; = 1001 * cpuspd
+; dcr a ; 4 T-states
+; jnz delay ; 10 T-states
+;
+; ret ; grand total: ((1001 * cpuspd) + 14) * a
+
+;
+; 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
+; 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 ; get character to test
+ ret
+
+;
+; prtflt - printer filter
+; 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 ; get character to test
+
+IF FALSE ; strip out lf from printer stream
+ ani 7fh ; make sure it is parity less
+ cpi lf ; is it a line feed?
+ rnz ; no, print it
+; xra a ; yes, don't.
+
+ENDIF
+
+ ret
+
+;
+; system-dependent processing for BYE command.
+;
+sysbye:
+ ret
+
+;
+; This is the system-dependent command to change the baud rate.
+; DE contains the two-byte value from the baud rate table; both
+; bytes of this value are also stored in 'speed'.
+;
+sysspd:
+
+IF sb180
+ lxi d, prtmsg ; ask for variables
+ call prtstr
+
+ lxi d, tbuf ; get suitable string
+ mvi c, 10
+ call bdos
+
+ lxi h, tbuf1
+ mov a, m
+ ora a
+ jz setpor ; leave unchanged if string zero length
+
+ cpi 3 ; check given length
+ jnz spd1 ; error - wrong length
+ inx h
+ inx h
+ mov a, m
+ ani 137O ; convert parity code to upper case
+ mov m, a
+
+ lxi d, tbuf1 ; get index of given parameter
+ lxi h, parstr
+ call sposn
+ ora a
+ jnz spd2 ; or fall through if error
+spd1: lxi d, invmsg ; invalid input - try again
+ call prtstr
+ jmp sysspd
+
+spd2: adi 3 ; get index to parval table
+ rrc ; by dividing by 4
+ rrc
+ ani 15 ; mask out high bits
+ lxi h, parind
+ mov m, a ; and store it
+ call setpor ; set up port iaw index and speed bytes
+
+ ret
+
+prtmsg: db cr,lf,'Enter bit/char, parity, and stop bits required.'
+ db cr,lf,'(Bit 7/8 Parity N/O/E Stop 1/2 - CR same) : $'
+invmsg: db cr,lf,'Invalid parameters$'
+
+parind: db 8 ; default <8N2> index
+parstr: db 48,'7N1$7N2$7O1$7O2$7E1$7E2$'
+ db '8N1$8N2$8O1$8O2$8E1$8E2$'
+parval: db 0,1,16+2,16+3,2,3
+ db 4,5,16+6,16+7,6,7
+tbuf db 6
+tbuf1 db 3,'8N2','$$$$'
+
+;
+; Set up the port using the table index in parind and the speed byte
+;
+setpor:
+ lxi h, parind
+ mov a, m
+ dcr a
+ lxi h, parval ; table base
+ mvi b, 0
+ mov c, a
+ dad b ; HL points at parameter value
+ mov a, m
+ mov b, a ; park parval
+
+ ani 16 ; the parity switch bit
+ lxi h, speed
+ add m ; this is now the baud rate byte
+ mov c, a ; park it
+
+ mov a, b ; sort out the parameter byte
+ ani 7 ; b/p/s only wanted
+ adi 96 ; RE, TE enable
+ db 0EDh,039h,mnctrla ; output parity etc.
+ mov a, c
+ db 0EDh,039h,mnctrlb ; output baud rate
+ mvi a, 0
+ db 0EDh,039h,mnstat ; clear status
+ db 0EDh,038h,mnstat ; read twice to reset DCD0
+ db 0EDh,038h,mnstat
+ ret
+
+;
+; Find substring position - Leventhal page 293, modified
+; enter with subtring in DE and string in HL
+; returns index in A or 0 for failure
+;
+sposn:
+ mov a, m ; exit if either string length zero
+ ora a
+ jz notfnd
+ sta slen
+ mov b, a
+ inx h
+ shld string
+ xchg
+ mov a, m
+ ora a
+ jz notfnd
+ sta sublen
+ mov c, a
+ inx h
+ shld substg
+ mov a, b
+
+; no of searches = stringlen - substrlen + 1
+; if substr longer than string quit immediately
+
+ sub c
+ jc notfnd
+ inr a
+ mov c, a
+ xra a
+ sta index
+
+; search until remaining string shorter than substring
+
+slp1: lxi h, index
+ inr m
+ lda sublen
+ mov b, a
+ lhld substg
+ xchg
+ lhld string
+
+; try to match substring starting at index
+
+cmplp: ldax d
+ cmp m
+ jnz slp2
+ dcr b
+ jz found
+ inx h
+ inx d
+ jmp cmplp
+
+; arrive here if match fails
+
+slp2: dcr c
+ jz notfnd
+ lhld string
+ inx h
+ shld string
+ jmp slp1
+
+; found, return index
+
+found: lda index
+ ret
+
+; not found, return zero
+
+notfnd: sub a
+ ret
+
+string: ds 2
+substg: ds 2
+slen: ds 1
+sublen: ds 1
+index: ds 1
+ENDIF
+
+ ret
+
+;
+; 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 bytes or 1 word, ab)
+; the data byte a is return in A and E, and b in D
+; only byte 'a' is the key for the table
+
+IF sb6
+spdtbl: db 9 ; 9 entries
+ db 04h,'1200$', 0Bh,0Bh
+ db 03h,'150$', 0Eh,0Eh
+ db 05h,'19200$', 01h,01h
+ db 04h,'2400$', 0Ah,0Ah
+ db 03h,'300$', 0Dh,0Dh
+ db 05h,'38400$', 00h,00h
+ db 04h,'4800$', 09h,09h
+ db 03h,'600$', 0Ch,0Ch
+ db 04h,'9600$', 08h,08h
+
+sphtbl: db cr,lf
+ db ' 150 300 600 1200 2400 4800 9600 19200 38400$'
+ENDIF
+
+IF sb9
+spdtbl: db 7 ; 7 entries
+ db 04h,'1200$', 24h,24h
+ db 05h,'19200$', 20h,20h
+ db 04h,'2400$', 23h,23h
+ db 03h,'300$', 26h,26h
+ db 04h,'4800$', 22h,22h
+ db 03h,'600$', 25h,25h
+ db 04h,'9600$', 21h,21h
+
+sphtbl: db cr,lf
+ db ' 300 600 1200 2400 4800 9600 19200$'
+ENDIF
+
+
+;
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+;
+sysprt:
+ ret
+
+IF sb180
+prttbl EQU 0 ; SET PORT is not supported
+prhtbl EQU 0
+ENDIF
+
+;
+; 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 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 sb180
+ db 0EDh,038h,mnstat
+ ani output ; check status
+ jz outmdm ; wait until port is available
+ mov a, e
+ db 0EDh,039h,mntxdat ; transmit
+ENDIF
+
+ 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:
+
+IF sb180
+ lxi h, delfac ; loops to give delay
+inpm1: db 0EDh,038h,mnstat
+ ani input ; check status
+ jz inpm2
+ db 0EDh,038h,mnrddat ; get a byte
+ ret
+
+inpm2: dcx h ; no data
+ mov h, a
+ ora l
+ jnz inpm1 ; still tries left
+ ret ; with zero in A
+ENDIF
+
+ 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:
+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 ; if a=0 do nothing
+
+outlp1: pop d ; restore saved register pair
+ ret
+
+; 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)
+delchr:
+
+ mvi e,bs ;get a backspace
+ jmp 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 sb180
+sysver: db 'MicroMint SB 180 '
+ENDIF
+
+IF sb6
+ db ' (6 MHz)'
+ENDIF
+
+IF sb9
+ db ' (9 MHz)'
+ENDIF
+ db '$'
+
+IF lasm
+LINK CPXVDU.ASM ; get terminal defs etc
+ENDIF ;lasm
diff --git a/src/cpxswt.asm b/src/cpxswt.asm
new file mode 100644
index 0000000..32b0d11
--- /dev/null
+++ b/src/cpxswt.asm
@@ -0,0 +1,294 @@
+IF NOT lasm
+.printx * CPXSWT.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 is a simple family or system file switcher, selecting
+; one of several family files, or selectin CPXSYS.ASM (now modified)
+; if a family file does not exist.
+;
+;
+; revision history:
+;
+;edit 10, 7-Jan-1991 by MF. Added code by Jay S. Rouman to support the
+; Ampro Little Board (see CPXBBI.ASM) and PRINTX for the HP-125.
+; edit 9, 1st September 1990 by Russell Lang, rjl@monu1.cc.monash.edu.au.
+; Added Microbee support.
+; edit 8, 2 December by OBSchou. Added Z80MU "system" to allow kermit-80
+; debugging on a PC!
+;
+; edit 7, 27 October, 1987 by OBSchou. Added bits for Sanyo, Compupro,
+; Genie and TRS-80 M4.
+;
+; edit 6, 16 July, 1987 for Will Rose, who has submitted code for
+; Micromint SB180 (6 and 9 Mhz) and a BT Merlin (alias RAIR)
+;
+; edit 5, 15 July, 1987 by OBSchou for David Moore, who has submitted
+; code for a Teletek SYSTEMASTER and for ADM22 terminals.
+;
+; edit 4, 14 July 1987 by OBSchou for JA Shearwood of Birmingham University,
+; Chris Miles of Manchester University. Added a Cifer family file
+; for John, and added a BigBoard-Kaypro-Xerox family file for Chris
+; Finally, added in new family file for Heath, telcon, z100 and scntpr
+; systems for Martin Carter of Nottingham University.
+;
+; edit 3, 6 April, 1986 by OBSchou.
+; Added in switching for NCR Desision Mate V and Amstrad CPC 664/6128
+; systems.
+;
+; edit 2, March 16, 1987 by OBSchou.
+; added in support for m80 macro assembler.
+;
+; edit 1 28 January, 1987 by OBSchou.
+; Take out the series of printx etx and selection of systems and
+; leave this with only the system dep. code for systems without
+; a family file. Hopefully, this file will go alltogether in time.
+;
+; Keep module name, edit number, and last revision date in memory.
+swtver: db 'CPXSWT.ASM (10) 7-Jan-1991 $'
+;
+; 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 (torfam AND lasm)
+;Link to the module with the code for Superbrains, Torch, Cifer and pci2651
+LINK CPXTOR.ASM ; also NCR DMV systems
+ENDIF;(torfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (ciffam AND LASM)
+; Link to the Cifer family file. (Cifer code previously on CPXTOR.ASM)
+LINK CPXCIF.ASM ; Cifer family file
+ENDIF ;(ciffam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (appfam AND lasm) ;[33] apple frogs as a separate family..
+; Link to the APPLE family...
+LINK CPXAPP.ASM
+ENDIF ;(appfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (norfam AND lasm); Link to the Northstar family (and Comart)
+; Link to the NorthStar family file
+LINK CPXNOR.ASM
+ENDIF; (norfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (pcwfam AND lasm) ;[35] Amstrad PCW 8256/8512 or CPC systems
+; Link to the Amstrad PCW family
+LINK CPXPCW.ASM
+ENDIF ;(cpwfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (bbifam AND lasm) ;Bigboard, Kaypro and Xerox 820 file
+; Link to the Bigboard family
+.printx * Linking to the BigBoard family *
+LINK CPXBBI.ASM
+ENDIF ;(bbifam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (heafam AND lasm) ; heath, z100, telcon, and scntpr systems
+; Link to the Heath-telcon-screentyper family
+.printx * Linking to the Heath-telcon-screentyper family *
+LINK CPXHEA.ASM
+ENDIF ;(heafam) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (sbfam AND lasm)
+; Link to the SB180 Family file
+,printx * Linking to the SB180 Family file *
+LINK CPXSB.ASM
+ENDIF ; (sbfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (m2215 AND lasm)
+; Link to the RAIR/ BT Merlin code
+.printx * Linking to the Merlin/Rair code *
+LINK CPXMRL.ASM
+ENDIF ; (m2215 AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (sanfam AND lasm)
+; Link to the Sanyo code
+.printx * linking to the sanyo code *
+LINK CPXSYO.ASM
+ENDIF ; (sanfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (comfam AND lasm)
+; Link to the compupro code
+.printx * linking to the Compupro code *
+LINK CPXPRO.ASM
+ENDIF ; (comfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (genfam AND lasm)
+; Link to the Genie family code
+.printx * linking to the Genie code *
+LINK CPXGNI.ASM
+ENDIF ; (genfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (trsfam AND lasm)
+; Link to the TRS-80 family file
+.printx * linking to the TRS family file*
+LINK CPXTM4.ASM
+ENDIF ; (trsfam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (z80fam AND lasm)
+; Link to the Z80MU family file
+.printx * linking to the Z80MU family file*
+LINK CPXZ80.ASM
+ENDIF ; (z80fam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+IF (beefam AND lasm)
+; Link to the Microbee family file
+.printx * linking to the Microbee family file *
+LINK CPXBEE.ASM
+ENDIF ; (beefam AND lasm) - m80 use: INCLUDE from CPXTYP.ASM
+
+
+; If we have come here, we are assembling the CPXSYS.ASM file
+
+IF robin
+.printx * Assembling KERMIT-80 for the DEC VT180 *
+ENDIF
+
+IF vector
+.printx * Assembling KERMIT-80 for the Vector Graphics *
+ENDIF
+
+IF osi
+.printx * Assembling KERMIT-80 for the Ohio Scientific *
+ENDIF
+
+IF heath
+.printx * Assembling KERMIT-80 for the Heath/Zenith 89 *
+ENDIF
+
+IF z100
+.printx * Assembling KERMIT-80 for the Heath/Zenith Z100 *
+ENDIF
+
+IF trs80
+.printx * Assembling KERMIT-80 for the TRS-80 II *
+ENDIF
+
+IF osbrn1
+.printx * Assembling KERMIT-80 for the Osborne 1 *
+ENDIF
+
+IF telcon
+.printx * Assembling KERMIT-80 for the Telcon Zorba *
+ENDIF
+
+IF dmII
+.printx * Assembling KERMIT-80 for the DECmate II *
+ENDIF
+
+IF gener
+.printx * Assembling Generic KERMIT-80 *
+ENDIF
+
+IF cpm3
+.printx * Assembling Generic KERMIT-80 for CP/M 3.0 *
+ENDIF
+
+IF hp125
+.printx * Assembling Kermit-80 for the HP-125 Series 100 *
+ENDIF ;hp125
+
+IF kpii
+.printx * Assembling Kaypro II KERMIT-80 *
+ENDIF
+
+IF xer820 ;[pcc001]
+.printx * Assembling Xerox 820 KERMIT-80 *
+ENDIF ;[pcc001]
+
+IF bbII
+.printx * Assembling BigBoard II KERMIT-80 *
+ENDIF
+
+IF ampro
+.printx * Assembling Ampro Little Board KERMIT-80 *
+ENDIF
+
+IF mdI
+.printx * Assembling for Morrow Decision I *
+ENDIF ;mdI [Toad Hall]
+
+IF mmdI
+.printx * Assembling for Morrow Micro Decision I *
+ENDIF ;mmdI
+
+IF mikko
+.printx * Assembling MikroMikko Kermit-80 *
+ENDIF
+
+IF delphi ;[7]
+.printx * Assembling Digicomp Delphi 100 Kermit-80 *
+ENDIF ;[7]
+
+IF cpt85xx
+.printx * Assembling CPT-85xx (under CompuPak CP/M) Kermit-80 *
+ENDIF
+
+IF cmemco ;[25]
+.printx * Assembling KERMIT-80 for the Cromemco (TU-ART) *
+ENDIF;cmemco
+
+IF bbc ;[22]
+.printx * Assembling Kermit-80 for BBC with Z80 co-processor *
+ENDIF ;[22]
+
+IF rm380z ;[22]
+.printx * Assembling Kermit-80 for Research Machines 380Z *
+ENDIF ;[22]
+
+IF px8 ;[29]
+.printx * Assembling Kermit-80 for Epson PX-8 *
+ENDIF ;px8 [29]
+
+IF mmate ;[29]
+.printx * Assembling KERMIT-80 for the PMC MicroMate *
+ENDIF ;mmate [29]
+
+IF disc ;[29]
+.printx * Assembling KERMIT-80 for the A. C. E. Discovery *
+ENDIF ;disc [29]
+
+IF s1008 ;[29]
+.printx * Assembling KERMIT-80 for the MicroSales s1008 *
+ENDIF ;s1008 [29]
+
+IF access ;[29]
+.printx * Assembling Kermit-80 for the ACCESS-MATRIX computer *
+ENDIF ;access [29]
+
+IF lobo ;[hh]
+.printx * Assembling Kermit-80 for the Lobo MAX-80 *
+ENDIF;lobo [hh]
+
+IF teletek
+.printx * Assembling Kermit-80 for the Teletek *
+ENDIF ;teletek
+
+;
+;
+; If here, we have not linked to a family, so link to CPXSYS.ASM
+IF lasm
+ LINK CPXSYS.ASM
+ENDIF ;lasm
+;
+; If we are using m80, then the CPXSYS.ASM file will be INCLUDED from CPXTYP
+;
+
+
+
diff --git a/src/cpxsy2.asm b/src/cpxsy2.asm
new file mode 100644
index 0000000..a420d37
--- /dev/null
+++ b/src/cpxsy2.asm
@@ -0,0 +1,1364 @@
+IF NOT lasm
+.printx * CPXSY2.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:
+;
+;
+; 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 px8 ; [29]
+ push d
+ call rsclose ; baud rate can only be set on opening rs232
+ pop d
+ mov a, e
+ sta px8blk+4 ; set param block
+ call rsopen ; to set rate
+ ret
+ENDIF ; px8 [29]
+
+; Set the speed for the Osborne I
+IF osbrn1
+ mvi a,osbin1 ;Reset the ACIA
+ call osstst ;Write the control port
+osbs1: inr c ;Waiting loop
+ jnz osbs1
+ mov a,e ; get the specified speed
+ jmp osstst ;Write the control reg.
+ENDIF;osbrn1
+
+;[hh] set the speed for a lobo MAX-80
+IF lobo
+ mov a,e ;[hh] get the parsed value
+setbd: sta baudrt ;[hh] and send it to the baud rate port
+ ret ;[hh]
+ENDIF;lobo
+
+; Set the speed for bigboard I or the delphi or the CPT-85xx
+; or Cromemco (TU-ART)
+IF delphi OR cpt85xx OR cmemco OR mmate ;[22] [29]
+ mov a,e ; get the parsed value
+ out baudrt ; Tell the baud rate generator.
+ ret
+ENDIF;delphi OR cpt85xx OR cmemco OR mmate [22] [29]
+
+;[22] Set the speed for Acorn BBC
+IF bbc
+ mov l,e
+ mvi a,7 ;Set receive baud rate
+ call osbyte ;*FX7,?e
+ mov l,e
+ mvi a,8 ;Set transmit baud rate
+ call osbyte ;*FX8,?e
+ ret
+ENDIF;[22] bbc
+
+;[22] Set speed for RM 380Z
+IF rm380z
+ mvi a,4 ;device type (SI/O4) in A
+ rst 6 ; EMT
+ db 29h ; SETLST
+ ret
+ENDIF;[22] rm380z
+
+; Set the speed for MicroMikko. DE is baud rate multiplier
+IF mikko
+ di
+ lxi h,txclk
+ mov m,d ;LSB first (swapped in memory)
+ mov m,e ;MSB last
+ lxi h,rxclk
+ mov m,d
+ mov m,e
+ mvi b,0 ;"modifier" for 1 stop bit
+ mvi a,2 ;Test MSB of speed >2 (110 bps or less)
+ cmp e
+ jp miksp1
+ mvi b,00001000B ;"modifier" for 2 stop bits
+miksp1: mvi a,4 ;Select SIO Reg 4
+ lxi h,sioac
+ mov m,a
+ mvi a,sion4 ;Get values
+ ora b ;Add modifier
+ mov m,a ;Set value (stop bits)
+ ei
+ ret
+ENDIF;mikko
+
+
+; Set the speed for the Decision I
+IF mdI
+ call selmdm ;Let's be absolutely sure, huh?
+ mvi a,dlab+wls1+wls0+stb ;Set data latch access bit
+ out lcr ;Out to Line Control Register
+ lhld speed ;Load baudrate multiplier
+ xchg
+ mov a,d ;Get low order byte for baud rate
+ out dlm ;Out to the MSB divisor port
+ mov a,e ;...and the high order byte
+ out dll ;Out to the LSB divisor port
+ mvi a,wls1+wls0+stb ;Enable Divisor Access Latch
+ out lcr ;Out to ACE Line Control Register
+ xra a ;Clear A
+ out ier ;Set no interrupts
+ out lsr ;Clear status
+ in msr ;Clear Modem Status Register
+ in lsr ;Clear Line Status Register
+ in rbr ;Clear Receiver Buffers
+ in rbr
+ ret
+ENDIF ;mdI [Toad Hall]
+
+IF teletek
+ di
+ mov a,e ; first speed byte
+ out baudrt
+ mov a,d ; second speed byte
+ out baudrt
+ ei
+ ret
+ENDIF ;teletek
+
+IF access ;[29]
+ mov a,e ;Get the parsed time constant
+;The following code is derived from the Access initialization code
+ sta savspd ;Save the time constant
+ mvi a,14h ;Code for 'monitor' to set channel A baudrate
+ call monitor
+ lda savspd ;Get the time constant
+ call monitor ; and send it to the CRT
+ ret
+savspd: ds 1
+monitor: ;Routine to do CRT functions
+ out 90h ;Output the data to the CRT
+ mvi a,1 ;Set DRDY true
+ out 23h
+mon1: in 0a0h ;Wait for CACK* true
+ rlc
+ jc mon1
+ in 80h ;Read the input data latch
+ push psw ;Save the input data
+ xra a ;Set DRDY false
+ out 23h
+mon2: in 0a0h ;Wait for CACK* false
+ rlc
+ jc mon2
+ pop psw
+ sta 0ee02h ;Save the input data
+ ret
+ENDIF;access [29]
+
+
+IF disc ;[29]
+; Assuming that parsing of value from speed table puts low order
+; byte of time constant in the e register and high byte in d.
+ mvi a,12 ;Register 12
+ out mnprts
+ mov a,e ;Low order byte of time constant
+ out mnprts
+ mvi a,13 ;Register 13
+ out mnprts
+ mov a,d ;High order byte of time constant
+ out mnprts
+ mvi a,14 ;Register 14
+ out mnprts
+ mvi a,3 ;Enable baud rate generator
+ out mnprts
+ mvi a,11 ;Register 11
+ out mnprts
+ mvi a,52h ;no Xtal, tclk=rclk=/trxc out=br gen
+ out mnprts
+ ret
+ENDIF;disc [29]
+; 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 delphi OR lobo ;[hh]
+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;delphi OR lobo ;[hh]
+
+IF cpt85xx
+spdtbl: db 15 ; 15 entries
+ db 03,'110$', 03h,03h
+ db 04,'1200$', 09h,09h
+ db 05,'134.5$', 04h,04h
+ db 03,'150$', 05h,05h
+ db 04,'1800$', 0Ah,0Ah
+ db 04,'2400$', 0Bh,0Bh
+ db 03,'300$', 06h,06h
+ db 04,'3600$', 0Ch,0Ch
+ db 04,'4800$', 0Dh,0Dh
+ db 02,'50$', 01h,01h
+ db 03,'600$', 07h,07h
+ db 04,'7200$', 0Eh,0Eh
+ db 02,'75$', 02h,02h
+ db 03,'900$', 08h,08h
+ db 04,'9600$', 0Fh,0Fh
+
+sphtbl: db cr,lf,' 50 75 110 134.5 150 300 600 900'
+ db cr,lf,' 1200 1800 2400 3600 4800 7200 9600$'
+ENDIF;cpt85xx
+
+IF bbc ;[22]
+spdtbl: db 8 ; 8 entries
+ db 04,'1200$', 04h,04h
+ db 03,'150$', 02h,02h
+ db 05,'19200$', 08h,08h
+ db 04,'2400$', 05h,05h
+ db 03,'300$', 03h,03h
+ db 04,'4800$', 06h,06h
+ db 02,'75$', 01h,01h
+ db 04,'9600$', 07h,07h
+
+sphtbl: db cr,lf,' 75 150 300 1200 2400 4800 9600 19200$'
+ENDIF;[22] bbc
+
+IF rm380z ;[22]
+spdtbl: db 7 ; 7 entries
+ db 03,'110$', 00h,00h
+ db 04,'1200$', 03h,03h
+ db 04,'2400$', 04h,04h
+ db 03,'300$', 01h,01h
+ db 04,'4800$', 05h,05h
+ db 03,'600$', 02h,02h
+ db 04,'9600$', 06h,06h
+
+sphtbl: db cr,lf,' 110 300 600 1200 2400 4800 9600$'
+ENDIF;[22] rm380z
+
+IF px8 ; [29]
+spdtbl: db 9 ; 9 entries
+ db 03,'110$', 02h,02h
+ db 04,'1200$', 0ah,0ah
+ db 03,'150$', 04h,04h
+ db 05,'19200$', 0fh,0fh
+ db 04,'2400$', 0ch,0ch
+ db 03,'300$', 06h,06h
+ db 04,'4800$', 0dh,0dh
+ db 03,'600$', 08h,08h
+ db 04,'9600$', 0eh,0eh
+sphtbl: db cr, lf
+ db ' 100 150 300 600 1200 2400 4800 9600 19200$'
+ENDIF ; px8 [29]
+
+IF mikko
+spdtbl: db 9h ;9 entries
+ db 03h,'110$'
+ dw 0369h
+ db 04h,'1200$'
+ dw 0050h
+ db 03h,'150$'
+ dw 0280h
+ db 04h,'2400$'
+ dw 0028h
+ db 03h,'300$'
+ dw 0140h
+ db 04h,'4800$'
+ dw 0014h
+ db 03h,'600$'
+ dw 00A0H
+ db 02h,'75$'
+ dw 0500h
+ db 04h,'9600$'
+ dw 000ah
+
+sphtbl: db cr,lf,' 75 110 150 300 600 1200 2400 4800 9600$'
+ENDIF;mikko
+
+IF osbrn1
+spdtbl: db 02h ;2 entries
+ db 04h,'1200$', OSBI12,OSBI12
+ db 03h,'300$', OSBI03,OSBI03
+
+sphtbl: db cr,lf,' 300',cr,lf,' 1200$'
+ENDIF;osbrn1
+
+
+IF mdI
+spdtbl: db 0dh ; 13 entries
+ db 03h, '110$'
+ dw 1047
+ db 04h, '1200$'
+ dw 96
+ db 03h, '150$'
+ dw 768
+ db 05h,'19200$'
+ dw 6
+ db 04h, '2400$'
+ dw 48
+ db 03h, '300$'
+ dw 384
+ db 05h,'38400$'
+ dw 3
+ db 03h, '450$'
+ dw 288
+ db 04h, '4800$'
+ dw 24
+ db 05h,'56000$'
+ dw 2
+ db 03h, '600$'
+ dw 192
+ db 02h, '75$'
+ dw 1536
+ db 04h, '9600$'
+ dw 12
+
+sphtbl: db cr,lf,' 75 110 150 300 450 600 1200'
+ db cr,lf,' 2400 4800 9600 19200 38400 56000$'
+
+;(Lord knows what you'll be communicating with at 56000 baud, but the
+;Multi-I/O board literature says it'll do it, so what the heck....
+;might as well throw it in here just to show off...sure hope the
+;port don't melt...)
+
+ENDIF ;mdI [Toad Hall]
+
+IF cmemco ;[25]
+spdtbl: db 7 ; 7 entries
+ db 3,'110$', 01H,01H
+ db 4,'1200$', 88H,88H
+ db 3,'150$', 82H,82H
+ db 4,'2400$', 90H,90H
+ db 3,'300$', 84H,84H
+ db 4,'4800$', 0A0H,0A0H
+ db 4,'9600$', 0C0H,0C0H
+
+sphtbl: db cr,lf
+ db ' 110 150 300 1200 2400 4800 9600$'
+ENDIF;cmemco
+
+IF access ;Similar to bbI with different values [29]
+spdtbl: db 6h ;6 entries
+ db 04h,'1200$', 28h,28h
+ db 04h,'2400$', 14h,14h
+ db 03h,'300$', 0a0h,0a0h
+ db 04h,'4800$', 0ah,0ah
+ db 03h,'600$', 50h,50h
+ db 04h,'9600$', 5,5
+
+sphtbl: db cr,lf,' 300 600 1200 2400 4800 9600$'
+ENDIF;access [29]
+
+IF mmate ;[29]
+spdtbl: db 10h ;16 entries
+ db 03h,'110$', 0e2h,0e2h
+ db 04h,'1200$', 0e7h,0e7h
+ db 05h,'134.5$', 0e3h,0e3h
+ db 03h,'150$', 0e4h,0e4h
+ db 04h,'1800$', 0e8h,0e8h
+ db 05h,'19200$', 0efh,0efh
+ db 04h,'2000$', 0e9h,0e9h
+ db 04h,'2400$', 0eah,0eah
+ db 03h,'300$', 0e5h,0e5h
+ db 04h,'3600$', 0ebh,0ebh
+ db 04h,'4800$', 0ech,0ech
+ db 02h,'50$', 0e0h,0e0h
+ db 03h,'600$', 0e6h,0e6h
+ db 04h,'7200$', 0edh,0edh
+ db 02h,'75$', 0e1h,0e1h
+ db 04h,'9600$', 0eeh,0eeh
+
+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;mmate [29]
+
+IF disc ;[29]
+; Similar to mikko table but with different time constant values
+spdtbl: db 9h ;9 entries
+ db 03h,'110$'
+ dw 1134
+ db 04h,'1200$'
+ dw 102h
+ db 03h,'150$'
+ dw 831
+ db 04h,'2400$'
+ dw 50
+ db 03h,'300$'
+ dw 415
+ db 04h,'4800$'
+ dw 24
+ db 03h,'600$'
+ dw 206
+ db 02h,'75$'
+ dw 1665
+ db 04h,'9600$'
+ dw 11
+
+sphtbl: db cr,lf,' 75 110 150 300 600 1200 2400 4800 9600$'
+ENDIF;disc [29]
+
+IF teletek
+spdtbl: db 7 ; 7 entries
+ db 4, '1200$', 47h,40h
+ db 5,'19200$', 47h,04h
+ db 4, '2400$', 47h,20h
+ db 3, '300$', 47h,00h
+ db 4, '4800$', 47h,10h
+ db 3, '600$', 47h,80h
+ db 4, '9600$', 47h,08h
+
+sphtbl: db cr,lf
+ db ' 300 600 1200 2400 4800 9600 19200$'
+ENDIF ;teletk
+
+
+; 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 robin OR gener OR dmII OR vector OR trs80;[32]
+spdtbl equ 0 ; SET BAUD not supported.
+sphtbl equ 0
+ENDIF;robin OR gener OR dmII OR vector OR trs80
+;
+IF mmdI OR osi OR cpm3 OR S1008 ; [29]
+spdtbl EQU 0 ;[hh] SET BAUD not supported.
+sphtbl EQU 0 ;[hh] ran out of room above...
+ENDIF;mmdI OR osi OR cpm3 OR S1008 [29]
+;
+IF hp125 ;[MF]
+spdtbl equ 0 ; SET BAUD not supported.
+sphtbl equ 0
+ENDIF;hp125 [MF]
+;
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+sysprt:
+IF lobo ;[hh]
+ mov a,l ;[hh] get the data port value and store at
+ sta outmd3+1 ;[hh] the two places we use...
+ sta inpmd2+1 ;[hh] MNPORT in the overlay
+ sta port ;[hh] inform program of the change in ports
+ inr a ;[hh] status port = data port + 1 in the Lobo
+ sta outmd1+1 ;[hh] store it at the three places...
+ sta inpmd1+1 ;[hh] we use MNPRTS...
+ sta outctl+1 ;[hh] in the overlay
+ mov a,h ;[hh] now get the baud rate port value
+ sta getbd+1 ;[hh] store it in the two places we use...
+ sta setbd+1 ;[hh] BAUDRT in the overlay
+ sta port+1 ;[hh] don't need to, but keeps it consistant
+getbd: lda baudrt ;[hh] get baud rate value from port
+ sta speed ;[hh] tell STAT. baud rate for each port
+ ;[hh] is independant of the other
+ENDIF ;lobo
+
+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
+
+IF iobyt AND robin
+ inx h ;Point at next entry
+ mov a,m ;Get the hardware address for the port
+ sta prtadr ;Store it
+ENDIF;iobyt AND robin
+;
+IF hp125 ;[MF]
+ push psw
+ push b
+ push d
+ push h
+ xchg ;Put port connect sequence address in DE
+ call prtstr ;Connect proper port
+ pop h
+ pop d
+ pop b
+ pop psw
+ENDIF;hp125 [MF]
+;
+ ret
+;
+; Port tables for Lobo MAX-80
+IF lobo ;[hh]
+; help text
+prhtbl: db cr,lf,'RS-232 port A or B$'
+;
+; command table
+prttbl: db 02H ;[hh] two entries
+ db 01H,'A$',0E4H,0D0H
+ db 01H,'B$',0E6H,0D4H
+ENDIF ;lobo
+;
+; 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
+
+;
+; Port tables for DECmate II or MicroMikko or Acorn BBC
+;
+IF dmII OR mikko OR bbc ;[22]
+; help text
+prhtbl: db cr,lf,'COMMUNICATIONS port$'
+
+; command table
+prttbl: db 01H ;Only one port known at this point
+ db 0EH,'COMMUNICATIONS$'
+ dw comptb ;address of info
+
+; port entry table
+; table entries are:
+; db iobyte-value, BDOS output function, reserved
+comptb: db batio,punout,0
+
+ENDIF;[22] dmII OR mikko OR bbc
+;
+; Port tables for Robin
+;
+IF robin
+; help text
+prhtbl: db cr,lf,'COMMUNICATIONS port'
+ db cr,lf,'GENERAL purpose port'
+ db cr,lf,'PRINTER port$'
+
+; command table
+prttbl: db 03H ;Three entries
+ db 0EH,'COMMUNICATIONS$'
+ dw comptb
+ db 07H,'GENERAL$'
+ dw gppptb
+ db 07H,'PRINTER$'
+ dw prnptb
+
+; port entry table
+; table entries are:
+; db iobyte-value, BDOS output function, hardware port address
+; (control/status)
+;
+;At present, the hardware port address is only used for sending a break.
+comptb: db batio,punout,comtst
+gppptb: db gppio,conout,gentst
+prnptb: db lptio,conout,prntst
+
+prtadr: db comtst ;space for current hardware port address
+ENDIF;robin
+
+IF iobyt
+prtfun: db punout ;Function to use for output to comm port
+prtiob: db batio ;I/O byte to use for communicating
+coniob: db defio ;I/O byte to use for console
+ENDIF;iobyt
+;
+IF hp125 ;[MF]
+; Help table
+prhtbl: db cr,lf,'Communications port'
+ db cr,lf,'Printer port$'
+; command table
+prttbl: db 02H ;2 entries
+ db 0eH,'COMMUNICATIONS$'
+ dw mapon1
+ db 07H,'PRINTER$'
+ dw mapon2
+;Port table entries are the addresses of the escape sequences to connect
+;the ports.
+;
+ENDIF;hp125 [MF]
+
+IF NOT (iobyt OR lobo OR hp125) ;[hh] [MF]
+prttbl equ 0 ; SET PORT is not supported
+prhtbl equ 0
+ENDIF;NOT iobyt OR lobo OR hp125 [MF]
+;
+; 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
+
+IF mdI
+ lda group
+ ori mdmgrp ;Mask modem serial port
+ out grpsel
+ENDIF;mdI [Toad Hall]
+
+ ret
+
+selcon:
+IF iobyt
+ lda coniob ;Set up for output to go to the console port
+ sta iobyte ;Switch directly
+ENDIF;iobyt
+
+IF mdI
+ lda group
+ ori congrp ;Mask console serial port (1)
+ out grpsel
+ENDIF;mdI [Toad Hall]
+
+ 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 rm380z ;[22]
+ mov a,e
+ cpi cr ;cr produces cr + lf
+ jnz outcn1
+ mvi e,'N'-100O ;Control-N produces cr only
+outcn1: ;continue
+ENDIF;[22] rm380z
+
+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 osi OR lobo ;[hh]
+ 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;osi OR lobo
+
+IF osbrn1
+ call osldst ;Read the status port
+ ani output ;Loop till ready.
+ jz outmdm
+ mov a,e
+ jmp osstda ;Write to the data port
+ENDIF;osbrn1
+
+IF px8 ; [29]
+ push h
+ push b
+ push d
+outmd1: call rsoutst ; get the output status
+ ora a
+ jz outmd1 ; check if output enabled
+ pop d
+ mov c, e ; char in C
+ push d
+ call rsput
+ pop d
+ pop b
+ pop h
+ ret
+ENDIF; px8 [29]
+
+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 cpm3 OR hp125 ;[MF]
+ push h
+ push b
+ mvi c,auxout ;Output to the aux output device
+ call bdos
+ pop b
+ pop h
+ ret
+ENDIF;cpm3 OR hp125 [MF]
+
+; org $+100h AND 0FF00h ; get rid of phase error
+
+;
+; 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 cpm3
+ 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;cpm3
+;
+IF hp125 ;[MF]
+ lxi b,70ffh ;SEt subfunction to get RDR (auxin) status
+ call bdos ;is char at RDR?
+ ora a ;something there?
+ rz ;no
+ mvi c,auxin
+ call bdos ;read char from RDR
+ENDIF;hp125 [MF]
+
+IF osi OR lobo ;[hh]
+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;osi OR lobo
+
+IF osbrn1
+ call osldst ;Read the status port
+ ani input ;Something there?
+ rz ;Nope
+ call osldda ;Read the data port
+ENDIF;osbrn1
+
+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 px8 ; [29]
+ call rserst ; check error status
+ ani 64h ; this assumes 'not open' cannot occur
+ jnz inpmd1 ; error has occurred!
+ call rsinst ; any chars outstanding?
+ ora a
+ rz ; exit if none
+ call rsget ; get char in A
+ ret
+; return the 'no char outstanding' indication on error
+inpmd1: mvi a, 0
+ENDIF; px8 [29]
+
+ 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:
+IF iobyt ;[33]
+ call bprtst ;
+call bprtst ; get status
+ENDIF ;iobyt[33]
+IF NOT iobyt ;[33]
+ xra a ; assume it is ok.. this may not be necessary
+ENDIF ;iobyt [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 iobyt
+ 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 NOT (robin OR dmII OR osi OR vector OR termin OR hp125)
+ ;[MF] Terminals code in CPXVDU
+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
+ENDIF;NOT (robin OR dmII OR osi OR vector OR termin OR hp125)[MF]
+;
+;
+;
+; csrpos for ANSI terminals
+;
+IF robin OR dmII
+csrpos: push b ; save coordinates
+ lxi d,curldn ; get cursor leadin sequence
+ call prtstr ; print it
+ pop h ; peek at coordinates
+ push h ; then save away again
+ mov l,h ; l = row
+ mvi h,0 ; hl = row
+ call nout ; output in decimal
+ mvi e,';' ; follow with semicolon
+ call outcon ; print it
+ pop h ; restore column
+ mvi h,0 ; hl = column
+ call nout
+ mvi e,'H' ; terminate with 'move cursor' command
+ jmp outcon ; output it and return
+ENDIF;robin OR dmII
+;
+; csrpos for the HP-125 [MF]
+;
+IF hp125 ;[MF]
+csrpos: dcr b ;HP-125 uses zero-based addressing
+ dcr c ;...
+ push b ; save coordinates
+ lxi d,curldn ; get cursor leadin sequence
+ call prtstr ; print it
+ pop h ; peek at coordinates
+ push h ; then save away again
+ mov l,h ; l = row
+ mvi h,0 ; hl = row
+ call nout ; output in decimal
+ mvi e,'R'+20h ;Say it was a row
+ call outcon ; print it
+ pop h ; restore column
+ mvi h,0 ; hl = column
+ call nout
+ mvi e,'C' ; terminate with 'move cursor' command
+ jmp outcon ; output it and return
+ENDIF;hp125 [MF]
+;
+; csrpos for the Vector General. It's weird.
+;
+IF vector
+csrpos: dcr b ; vector uses zero-based addressing?
+ dcr c
+ push b ; save coordinates
+ mvi e,esc ; print an escape
+ call outcon
+ pop d ; peek at coordinates
+ push d
+ call outcon ; output column
+ pop d
+ mov e,d ; get row
+ jmp outcon ; output and return
+ENDIF;vector
+
+IF osi ; systems without cursor positioning
+csrpos: ret ; dummy routine referenced by linkage section
+ENDIF;osi
+
+
+;
+; 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:
+
+IF vector OR osbrn1 OR lobo
+ lxi d,delstr
+ jmp prtstr
+ENDIF ;vector OR osbrn1 OR lobo
+
+IF bbc OR rm380z ;[22]
+ ret
+ENDIF;bbc OR rm380z
+
+IF NOT (vector OR osbrn1 OR bbc OR rm380z);[22]
+ mvi e,bs ;get a backspace
+ jmp outcon
+ENDIF;NOT (vector OR osbrn1 OR bbc OR rm380z [22]
+
+; 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 robin
+sysver: db 'VT180 Robin$'
+ENDIF;robin
+
+IF dmII
+sysver: db 'DECmate II CP/M-80$'
+ENDIF;dmII
+
+IF delphi ; [7] new system
+sysver: db 'Digicomp Delphi 100$'
+endif;delphi
+
+IF access
+sysver: db 'Actrix CP/M$'
+endif;
+
+IF teletek
+sysver: db 'Teletek SYSTEMASTER CP/M-80$'
+ENDIF ;teletek
+
+IF cpt85xx
+sysver: db 'CPT-85xx under CompuPak CP/M$'
+ENDIF;cpt85xx
+
+IF mdI
+sysver: db 'Morrow Decision I$'
+ENDIF;mdI [Toad Hall]
+
+IF mmdI
+sysver: db 'MicroDecision I$'
+ENDIF;mmdI
+
+IF osi
+sysver: db 'Ohio Scientific$'
+ENDIF;osi
+
+IF mmate ;[29]
+sysver: db 'PMC Micromate using port I/O$'
+ENDIF;mmate [29]
+
+IF disc ;[29]
+sysver: db 'Discovery using 83U board port B$'
+ENDIF ;disc [29]
+
+IF s1008 ;[29]
+sysver: db 'U. S. MicroSales using printer port$'
+ENDIF ;s1008 [29]
+
+IF cmemco ;[25]
+sysver: db 'Cromemco (TU-ART)$'
+ENDIF;cmemco
+;
+IF robin OR dmII
+; Note that we cannot support Graphics Mode or the H19 erase-screen command
+; (<esc>E), because the sequences are more than three bytes.
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+vtval EQU 0 ; we probably don't want VT52 emulation
+outlin: db esc,3CH,esc,'[H',esc,'[J',cr,lf,tab,tab,'$'
+erascr: db esc,'[H',esc,'[J$' ;Clear screen and go home.
+eralin: db cr,esc,'[K$' ;Clear line.
+curldn: db esc,'[$' ; Cursor leadin
+ttab:
+ta: db esc,'[A$' ; Cursor up.
+tb: db esc,'[B$' ; Cursor down.
+tc: db esc,'[C$' ; Cursor right.
+td: db esc,'[D$' ; Cursor left
+te: db '$',0,0,0 ; (can't) Clear display
+tf: db '$',0,0,0 ; (don't) Enter Graphics Mode
+tg: db '$',0,0,0 ; (don't) Exit Graphics mode
+th: db esc,'[H$' ; Cursor home.
+ti: db esc,'M$',0 ; Reverse linefeed.
+tj: db esc,'[J$' ; Clear to end of screen.
+tk: db esc,'[K$' ; Clear to end of line.
+ENDIF;robin OR dmII
+
+IF mikko
+sysver: db 'MikroMikko$'
+outlin: db subt,cr,lf,tab,'$'
+erascr: db subt,'$' ;Clear screen and go home.
+eralin: db cr,1CH,'$' ;Clear line.
+curldn: db esc,'=$' ;cursor leadin
+ttab: ;Table start location.
+ta: db 0BH,'$',0,0 ;Cursor up.
+tb: db 0AH,'$',0,0 ;Cursor down.
+tc: db 0CH,'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left
+te: db subt,'$',0,0 ;Clear display
+tf: db '$',0,0,0 ;(can't) Enter Graphics Mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home.
+ti: db '$',0,0,0 ;(can't) Reverse linefeed.
+tj: db 1cH,'$',0,0 ;Clear to end of screen.
+tk: db 1cH,'$',0,0 ;Clear to end of line.
+ENDIF;mikko
+;
+IF bbc ;[22]
+sysver: db 'BBC (Z80)$'
+outlin: db 0CH,esc,'=',21H,30H,'$'
+erascr: db 0CH,'$' ;Clear screen and go home.
+eralin: db cr,esc,'@$' ;Clear line.
+curldn: db esc,'=$' ;cursor leadin
+ttab: ;Table start location.
+ta: db 0BH,'$',0,0 ;Cursor up.
+tb: db 0AH,'$',0,0 ;Cursor down.
+tc: db tab,'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left
+te: db 0CH,'$',0,0 ;Clear display
+tf: db '$',0,0,0 ;(can't) Enter Graphics Mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home.
+ti: db '$',0,0,0 ;(can't) Reverse linefeed.
+tj: db esc,'?$',0,0 ;Clear to end of screen.
+tk: db esc,'@$',0,0 ;Clear to end of line.
+ENDIF;[22] bbc
+;
+IF rm380z ;[22]
+sysver: db 'Research Machines 380Z$'
+outlin: db 1FH,cr,tab,'$'
+erascr: db 1FH,'$' ;Clear screen and go home.
+eralin: db 0EH,19H,'$' ;Clear line.
+curldn: db 16H,'$' ;cursor leadin
+ttab: ;Table start location.
+ta: db 0BH,'$',0,0 ;Cursor up.
+tb: db 0AH,'$',0,0 ;Cursor down.
+tc: db 18H,'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left
+te: db 1FH,'$',0,0 ;Clear display
+tf: db '$',0,0,0 ;(can't) Enter Graphics Mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1DH,'$',0,0 ;Cursor home.
+ti: db '$',0,0,0 ;(can't) Reverse linefeed.
+tj: db 1EH,'$',0,0 ;Clear to end of screen.
+tk: db 19H,'$',0,0 ;Clear to end of line.
+ENDIF;[22] rm380z
+
+IF lobo ;[hh]
+sysver: db 'Lobo MAX-80$'
+outlin: db esc,'*',cr,lf,tab,tab,'$'
+erascr: db esc,'*$' ;[hh] clear screen and home cursor
+eralin: db cr,esc,'R$' ;[hh] clear line
+curldn: db esc,'=$' ;[hh] cursor lead-in string
+delstr: db bs,' ',bs,bs,'$' ;[hh] ??adjust for echoing delete
+ttab: ;[hh] table start location
+ta: db 0BH,'$',0,0 ;[hh] cursor up
+tb: db 0AH,'$',0,0 ;[hh] cursor down
+tc: db 0CH,'$',0,0 ;[hh] cursor right
+td: db 08H,'$',0,0 ;[hh] cursor left
+te: db esc,'*$',0 ;[hh] clear display (homes cursor)
+tf: db '$',0,0,0 ;[hh] (can't) enter graphics mode
+tg: db '$',0,0,0 ;[hh] (can't) exit graphics mode
+th: db 01EH,'$',0,0 ;[hh] home cursor
+ti: db esc,'E$',0 ;[hh] reverse linefeed (insert line)
+tj: db esc,'Y$',0 ;[hh] clear to end of screen
+tk: db esc,'T$',0 ;[hh] clear to end of line
+ENDIF ;lobo
+
+IF px8 ; [29]
+sysver: db 'Epson PX-8$'
+outlin: db esc,'*$'
+erascr: db esc,'*$' ; clear screen and home
+eralin: db cr,esc,'T$' ; clear line
+curldn: db esc,'=$' ; cursor lead in
+ttab: ; table start location
+ta: db 30,'$',0,0 ; cursor up
+tb: db 31,'$',0,0 ; cursor down
+tc: db 28,'$',0,0 ; cursor right
+td: db 29,'$',0,0 ; cursor left
+te: db esc,'*$',0 ; clear display
+tf: db '$',0,0,0 ; can't enter graphics graphics mode
+tg: db '$',0,0,0 ; can't exit graphics mode
+th: db 11,'$',0,0 ; home cursor
+ti: db 30,'$',0,0 ; reverse linefeed
+tj: db esc,'Y$',0 ; erase to end of screen
+tk: db esc,'T$',0 ; erase to end of line
+ENDIF ; px8 [29]
+
+;
+IF osbrn1
+sysver: db 'Osborne 1$'
+outlin: db 1AH,cr,lf,tab,'$' ;(Clear screen, home cursor)
+erascr: db 1AH,'$' ;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 ('L'-100O),'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left.
+te: db subt,'$',0,0 ;Clear screen.
+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,'T$',0 ;(can't) Clear to end of screen.
+tk: db esc,'T$',0 ;Clear to end of line.
+ENDIF;osbrn1
+;
+IF vector
+sysver: db 'Vector Graphics$'
+outlin: db ('D'-100O),cr,lf,tab,tab,'$'
+erascr: db ('D'-100O),'$' ;Clear screen and go home.
+eralin: db cr,('Q'-100O),'$' ;Clear line.
+delstr: db bs,' ',bs,bs,'$' ; adjust for echoing delete character
+ttab: ;Table start location.
+ta: db ('U'-100O),'$',0,0 ;Cursor up.
+tb: db 12O,'$',0,0 ;Cursor down.
+tc: db ('Z'-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 ('B'-100O),'$',0,0 ;Cursor home.
+ti: db ('U'-100O),'$',0,0 ;Reverse linefeed.
+tj: db ('P'-100O),'$',0,0 ;Clear to end of screen.
+tk: db ('Q'-100O),'$',0,0 ;Clear to end of line.
+ENDIF;vector
+
+IF trs80lb
+sysver: db 'TRS-80 II Lifeboat CP/M$'
+outlin: db esc,':',cr,lf,tab,tab,'$'
+erascr: db esc,':$' ;Clear screen and go home.
+eralin: db cr,esc,'T$' ;Clear line.
+curldn: db esc,'=$' ;Cursor lead-in
+ttab: ;Table start location.
+ta: db 0BH,'$',0,0 ;Cursor up.
+tb: db 0AH,'$',0,0 ;Cursor down.
+tc: db 0CH,'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left
+te: db esc,':$',0 ;Clear display
+tf: db '$',0,0,0 ;(can't) Enter Graphics Mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home.
+ti: db 0BH,'$',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;trs80lb
+;
+IF trs80pt
+sysver: db 'TRS-80 II P+T CP/M$'
+outlin: db 0CH,cr,lf,tab,tab,'$'
+erascr: db 0CH,'$' ;Clear screen and go home.
+eralin: db cr,01H,'$' ;Clear line.
+curldn: db esc,'Y$' ;Cursor lead-in
+ttab: ;Table start location ;Must be 4 bytes each
+ta: db 1EH,'$',0,0 ;Cursor up.
+tb: db 1FH,'$',0,0 ;Cursor down.
+tc: db 1DH,'$',0,0 ;Cursor right.
+td: db 1CH,'$',0,0 ;Cursor left
+te: db 0CH,'$',0,0 ;Clear display
+tf: db 11H,'$',0,0 ;Enter Graphics Mode
+tg: db 14H,'$',0,0 ;Exit Graphics mode
+th: db 06H,'$',0,0 ;Cursor home.
+ti: db 1EH,'$',0,0 ;Reverse linefeed.
+tj: db 02H,'$',0,0 ;Clear to end of screen.
+tk: db 01H,'$',0,0 ;Clear to end of line.
+ENDIF;trs80pt
+
+IF osi
+outlin: db cr,lf,'Starting ...$'
+erascr equ crlf ;"Home & clear" (best we can do).
+eralin: db '^U',cr,lf,'$' ;Clear line.
+prpack: db cr,lf,'RPack: $'
+pspack: db cr,lf,'SPack: $'
+ttab equ 0 ; no VT52 table
+ENDIF;osi
+;
+IF hp125 ;[MF]
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+vtval EQU 0 ; we probably don't want VT52 emulation
+;
+sysver: db 'HP-125 Series 100$'
+;
+outlin: db esc,'H',esc,'J',cr,lf,tab,tab,'$'
+erascr: db esc,'H',esc,'J$' ;Clear screen and go home.
+eralin: db cr,esc,'K$' ;Clear line.
+curldn: db esc,'&a$' ;Cursor leadin
+ttab: ;Table start location.
+ta: db esc,'A$',0 ;Cursor up.
+tb: db esc,'B$',0 ;Cursor down.
+tc: db esc,'C$',0 ;Cursor right.
+td: db esc,'D$',0 ;Cursor left
+te: db esc,'J$',0 ;Clear display
+tf: db '$',0,0,0 ;[hh] (can't) enter graphics mode
+tg: db '$',0,0,0 ;[hh] (can't) exit graphics mode
+th: db esc,'H$',0 ;Cursor home.
+ti: db esc,'M$',0 ;Reverse linefeed.
+tj: db esc,'J$',0 ;Clear to end of screen.
+tk: db esc,'K$',0 ;Clear to end of line.
+;
+;
+; Escape sequences to map CP/M Reader/Punch to Data Comm input/output,
+; respectively and to turn off these mappings
+;
+mapon1: db esc,'&i10s18d9M'
+ db esc,'&i2s25d9M'
+ db esc,'&i10s16d2M'
+ db esc,'&i0s25d2M$';Esc. sequences to turn off DAtacomm2/turn
+ ;on Data Comm 1
+mapon2: db esc,'&i10s16d9M'
+ db esc,'&i0s25d9M'
+ db esc,'&i10s18d2M'
+ db esc,'&i2s25d2M$';Esc. sequences to turn off Datacomm1/turn
+ ;on Datacomm 2
+mapoff: db esc,'&i0s25d9M'
+ db esc,'&i10s16d9M'
+ db esc,'&i2s25d9M'
+ db esc,'&i10s18d9M$'
+;
+readin: call $-$ ;Read character into b
+ mov a,b ;Get 8-bit character
+ ret ;and return
+;
+jbuf: db 7 ;bios dispatch table vector argument block
+ db 0 ;to read RDR routine address
+ db 0c3h ;...
+ dw 0 ;...
+;
+ENDIF;hp125 ;[MF]
+
+IF lasm and termin ; if no terminal, no need to link
+LINK CPXVDU.ASM
+ENDIF ; lasm and termin
+
+ovlend EQU $
+
+IF lasm
+ END ; If m80 then this ignored
+ENDIF ; lasm
diff --git a/src/cpxsyo.asm b/src/cpxsyo.asm
new file mode 100644
index 0000000..5b1cb0e
--- /dev/null
+++ b/src/cpxsyo.asm
@@ -0,0 +1,389 @@
+IF NOT lasm
+.printx * CPXSYO.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 Sanyo MBC 1100
+; systems, and has been extracted from the CPMSYO.ASM code (kermit
+; version 3.5)
+;
+; revision history:
+;
+; edit 1, 27 October, 1987, by OBSchou. Extracted Sanyo code from CPMSYO.ASM
+; and massaged fort CP/M kermit V4.09
+;
+; Keep module name, edit number, and last revision date in memory.
+family: db 'CPXSYO.ASM (1) 27-Oct-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 sanyo
+.printx * Assembling Kermit-80 for Sanyo MBC 1100 *
+ENDIF
+
+iobyte EQU 03H ;Location of I/O byte
+
+if sanyo
+baudrt EQU 0DAH ;BAUD RATE MEMORY LOCATION
+MNPORT EQU 0DCH ;COMMUNICATIONS PORT
+MNPRTS EQU 0DDH ;COMMUNICATIONS PORT STATUS
+OUTPUT EQU 01H ;OUTPUT READY BIT
+INPUT EQU 02H ;INPUT READY BIT
+ENDIF;SANYO
+
+defesc EQU '\'-100O ;The default escape character.
+
+; Select initial setting for VT-52 emulation flag.
+vtval EQU 1
+
+
+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 '$' ;[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...
+ ret
+
+; 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:
+ ret
+
+;
+
+; 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 sanyo
+spdtbl EQU 0 ; No speed table for the Sanyo
+sphtbl EQU 0 ; ditto help for speed.
+
+; 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 tot he Sanyo...
+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:
+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
+
+;
+
+;
+; 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 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
+ 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:
+ 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
+ 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
+ENDIF;NOT (robin OR dmII OR osi OR vector OR termin)
+
+ ret ; Can the Sany do cursor opsitioning??
+
+;
+;
+; 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 SANYO
+outlin: DB ESC,'E',ESC,'H',CR,LF,TAB ;WHATEVER
+sysver: DB 'KERMIT-80 V3.9 [SANYO MBC-1100]',CR,LF,'$' ;VERSION HEADING
+DELSTR: DB ESC,'K','$' ;WHATS A STRING?
+eralin: DB ESC,'P','$' ;CLEAR SPACE
+;CLRLIN: DB ESC,'K','$' ;CLEAR LINE
+erascr: DB ESC,'E',ESC,'H','$' ;CLEAR SCREEN AND CURSOR HOME
+curldn: db esc,'=','$',0 ;cursor lead in
+;SCRNP: DB ESC,'=',24H,25H,'$' ;SPOT FOR SCREEN PACKETS
+;SCRNRT: DB ESC,'=',25H,25H,'$' ;SPOT FOR # OF RETRIES
+;SCRFLN: DB ESC,'=',26H,25H,'$' ;SPOT FOR FILE NAME
+;SCRST: DB ESC,'=',28H,25H,'$' ;SPOT FOR STATUS
+;SCREND: DB ESC,'=',2AH,25H,'$' ;SPOT FOR PROMPT
+;SCRERR: DB ESC,'=',2DH,25H,'$' ;SPOT FOR ERRORS
+ttab: ;NO TRANSLATION TABLE
+ta: DB ESC,'A',0,0 ;CURSOR UP
+tb: DB ESC,'B',0,0 ;CURSOR DOWN
+tc: DB ESC,'D',0,0 ;CURSOR RIGHT
+td: DB ESC,'C',0,0 ;CURSOR LEFT
+te: DB ESC,'E',0,0 ;CLEAR SCREEN
+tf: DB 0,0,0,0 ;WHAT???
+tg: DB 0,0,0,0 ;WHAT???
+th: DB ESC,'H',0,0 ;CURSOR HOME
+ti: DB ESC,'A',ESC,'C',0,0 ;REVERSE LINEFEED??
+tj: DB ESC,'J',0,0 ;CLEAR TO END OF SCREEN
+tk: DB ESC,'K',0,0 ;CLEAR TO END OF LINE
+ENDIF;SANYO
+
+ovlend equ $ ; End of overlay
+
+ END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/cpxsys.asm b/src/cpxsys.asm
new file mode 100644
index 0000000..0b179b9
--- /dev/null
+++ b/src/cpxsys.asm
@@ -0,0 +1,1386 @@
+IF NOT lasm
+.printx * CPXSYS.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 40, 28-Aug-89 by Mike Freeman of Bonneville Power Administration,
+; P.O. Box 491, Vancouver WA 98666 USA, Telephone (206)690-2307:
+; Home address: 301 N.E. 107th Street; Vancouver, WA 98685 USA
+; Home telephone: (206)574-8221
+; added support for Hewlett-Packard HP-125 Business Assistant computer
+; running a HP-modified CP/M Version 2.2; communications on
+; DAta Comm 1 or Data Comm 2 (8th-bit quoting must be used on
+; Data Comm 2 to transfer binary files as Data Comm 2 only supports
+; a 7-bit data path); printer cannot be used with communications on
+; Data Comm 2 (the printer port).
+; edit 39, 4 August, 1987b by OBSchou for Charles Lasner re. DECMATE II
+; fixes to set xon/off control off for the duration of Kermit-80.
+;
+; His header reads:
+;
+; IBM mode restore program
+;
+; This routine must be run after using CP4DMF (and KERMIT-80) to restore
+; the normal handling of XON/XOFF; the user may also elect to cold-boot
+; the DECMATE instead.
+;
+; acknowledgments and limitations.
+;
+; This program is based on DECMATE specific implementation details
+; provided by Walt Lamia of DEC. It is of course, specific to DECMATE
+; implementations of CP/M-80 for DECMATE II, III, III-plus, etc.
+;
+; usage consists of merely:
+;
+; CP4DMF run xon/xoff disable program
+; KERMIT80 then run kermit
+; <KERMIT-80 commands used normally here, including SET IBM ON>
+; CP4DMU run this program to restore normal XON
+;
+; unless CP4DMU is run following KERMIT-80, the normal handling of
+; XON/XOFF provided by KERMIT-80 will not work (cold boot is another
+; alternative).
+;
+; [Note - These edits now included in the init/de-init code]
+;
+; edit 38, 23 July, 1987 by OBSchou. Moved out commonly used code
+; to CPXCOM.ASM, and adjusted this (ond other family) files accordingly.
+; Also filtered out code now in other family files.
+;
+; edit 37 , 15 July 1987 by OBSchou for David Moore, who has submitted
+; code for Teletek SYSTEMASTER (teletek) and for an ADM 22 terminal.
+;
+; edit 36 28 Jan 87 by OBSchou.
+; Removed the printx etc and should only have this file if a system
+; does not have a family file.
+;
+; edit 35 1st Dec 1986 by OBSchou. Added test for Amstrad PCW range (PCW)
+; Links to CPXPCW.ASM, which was submitted by Ian Young, Lattice
+; Logic Systems.
+;
+; edit 34 20 August by OBSchou for Brian Robertson, Aberdeen University:
+; I have discovered a bug in my code for the BBC/Z80 version of Kermit.
+; At startup the transmitter baud rate is read from the serial ULA.
+; The TX and RX baud rates are then reset to this value and the
+; value is stored in location 'baud:' for the STATUS (or SHOW)
+; command. That is how it is supposed to work ! Unfortunately
+; my code at present "misreads" the initial TX baud rate - there
+; is some bit manipulation that needs to be done to extract the
+; correct value.
+;
+; edit 33 30-May-86 OBSchou. Added two new enties to the overly. One for
+; printer status and the other for the address of the family of
+; computer using the overlay. If it is still in CPXSYS.ASM then it
+; is a dollar only.
+;
+;edit 32, 27 May, 1986 by OBSchou Loughborough University for
+; B Robertson, Aberdeen Univ. Computing Centre. Any mistakes my fault.
+; Add support for APPLE II with serial cards based on the 6850 ACIA.
+; Mod 380Z support to allow both MDS (5 1/4" discs) and FDS (8" discs)
+; configurations.
+;
+; edit 31, 22 April, 1986, OBSchou.
+; Kermit version 4.06 starts here. All previous edits have been
+; put aside (leave in a BWR file?). Hived off some definitions
+; to the CPSDEF.ASM file as that is where they belong.
+; Start on splitting off individual
+; systems from this huge file. It is done using the LINK facility
+; LASM. We link to a collection of systems under CPXxxx.ASM.
+; I have started with the systems I know, the Torch, Cifer and
+; pci2651. These will all be held under CPXTOR.ASM
+;
+;
+; Keep module name, edit number, and last revision date in memory.
+family: db 'CPXSYS.ASM (40) 28-Aug-89 $' ; now a family...
+;
+
+
+; Processor speed in units of 100KHz
+; for cpt85xx, advance, apple,bbc,px8 & rm380z timing loop [12]
+IF rm380z
+cpuspd SET 40 ; 4.0 MHz CPU
+ENDIF; rm380z
+
+IF disc OR mmate OR s1008 OR access
+cpuspd SET 40 ; 4.0 MHz CPU
+ENDIF ;disc OR mmate OR s1008 OR access
+
+IF bbc ;[9]
+cpuspd SET 60 ; BBC with 6Mhz Z80
+ENDIF;bbc
+
+
+; the basics...
+
+IF gener
+batio EQU 056H ;I/O byte CON=BAT,LIST=CRT,READER=RDR,PUNCH=PTP
+defio EQU 095H ;I/O byte CON=CRT,LIST=LPT,READER=RDR,PUNCH=PTP
+crtio equ 01010101B ; use CRT: device
+ptrio equ 01010110B ; use PTR: device
+ttyio equ 00000000B ; use TTY: device
+uc1io equ 01010111B ; use UC1: device
+ur1io equ 01101010B ; use UR1: device
+ur2io equ 01111110B ; use UR2: device
+ENDIF;gener
+
+IF robin
+batio EQU 056H ;I/O byte CON=BAT,LIST=CRT,READER=RDR,PUNCH=PTP
+defio EQU 095H ;I/O byte CON=CRT,LIST=LPT,READER=RDR,PUNCH=PTP
+lptio EQU 054H ;I/O byte CON=TTY,LIST=CRT,READER=PTR,PUNCH=PTP
+gppio EQU 057H ;I/O byte CON=UC1,LIST=CRT,READER=RDR,PUNCH=PTP
+ENDIF;robin
+
+
+IF dmII OR bbc ;[22]
+batio EQU 042H ;I/O byte CON=BAT,LIST=CRT,READER=RDR
+defio EQU 081H ;I/O byte CON=CRT,LIST=LPT,READER=RDR
+ENDIF;dmII
+
+IF mikko
+batio EQU 10110010B ; I/O byte console => serial line
+defio EQU 10000001B ; I/O byte console => CRT and Keyboard
+ENDIF;mikko
+;
+IF lobo ;[hh]
+mnport EQU 0F7E4H ;Modem data port A
+mnprts EQU 0F7E5H ;Modem status/conrtol port A
+baudrt EQU 0F7D0H ;Baud rate port A
+output EQU 04H ;Transmit buffer empty
+input EQU 01H ;Receive data available
+z80 SET TRUE ;a good z80, here
+ENDIF;lobo
+
+IF osi
+mnport EQU 0CF01H ;Modem data port
+mnprts EQU 0CF00H ;Modem status port
+output EQU 02H ;Transmitter empty
+input EQU 01H ;Input data available
+z80 SET FALSE ;I don't know...
+ENDIF;osi
+
+IF vector
+mnport EQU 04H ;Modem data port
+mnprts EQU 05H ;Modem status port
+output EQU 01H ;Transmitter empty
+input EQU 02H ;Input data available
+z80 SET FALSE ;I don't know...
+ENDIF;vector
+
+IF delphi ;[7]
+mnport EQU 22H ;[7] Modem data port
+mnprts EQU 23H ;[7] Modem status port
+output EQU 01H ;[7] Transmitter empty
+input EQU 02H ;[7] Input data available
+baudrt equ 29h ;[7] Baud rate port for channel 2 (default)
+z80 SET true ;[7] We're using the z80 side of the dual processor
+ENDIF;[7] delphi
+
+IF trs80
+;NEEDS display definition (e.g. trs80lb or trs80pt)
+mnport EQU 0F4H ;Modem data port (0F5H for port B)
+mnprts EQU 0F6H ;Modem status port (0F7H for port B)
+output EQU 04H ;Transmitter empty
+input EQU 01H ;Input data available
+z80 SET TRUE ;[hh] All TRS-80's but the CoCo
+ENDIF;trs80
+
+IF teletek
+mnport EQU 00H ;Modem data port (02 for port B (console))
+mnprts EQU 01H ;Modem status port (03 for port B (console))
+baudrt EQU 08H ;ctc0 control port (09 for port B (console))
+output EQU 04H ;Transmitter empty
+input EQU 01H ;Input data available
+z80 SET TRUE ;All Teleteks
+ENDIF;teletek
+
+IF osbrn1
+;Osborne 1 uses 6850 ACIA, but memory mapped. Derived from Apple.
+BAUDRT EQU 0EFC1H ;Memory location where baud rates are stored.
+OSTOP EQU 4000H ;Where we move OSMOVE to at startup
+OSPORT EQU 2A01H ;Communications Port.
+OSPRTS EQU 2A00H ;Communications Port Status.
+OUTPUT EQU 02H ;Output Buffer Empty.
+INPUT EQU 01H ;Input Register Full.
+OSBIN1 EQU 57H ;First Init Character for 6850 ACIA (Reset)
+;(I would have thought 03, but prom code writes 57 there)
+OSBI12 EQU 55H ;Second Init Character for ACIA (8-bits, 1200)
+OSBI03 EQU 56H ;Second init char. for ACIA (8 bits, 300)
+;(don't ask.. I don't know why SETUP writes 55 and 56 either)
+z80 SET TRUE ;[hh] a z80 here, also
+ENDIF;osbrn1
+
+IF robin
+;Those definitions below that are commented out are just for information
+;***** NOT generally found in distributed documentation ****
+
+;pbausl EQU 90H ;The Baud-Rate register.
+prntst EQU 49H ;Printer
+;prndat EQU 48H
+contst EQU 41H ;Console
+;condat EQU 40H
+gentst EQU 51H ;General port.
+;gendat EQU 50H
+comtst EQU 59H ;COMM-Port
+;comdat EQU 58H
+;output EQU 01H ;Output ready bit.
+;input EQU 02H ;Input ready bit.
+z80 SET TRUE ; This one's a Z80.
+ENDIF;robin
+
+IF s1008 ;[29]
+mnport equ 00 ;printer port data
+mnprts equ 01 ;printer port status
+output equ 4 ;transmitter ready
+input equ 2 ;receiver ready
+z80 equ FALSE ;not important
+ENDIF;s1008 [29]
+
+IF mmate ;[29]
+mnport EQU 89H ;MODEM data port
+mnprts EQU 8BH ;MODEM status/control port
+output EQU 04H ;Transmit buffer empty, ready to send
+input EQU 01H ;Receive data available
+baudrt EQU 93H ;MODEM baud rate port
+ ;NOTE - also used for console
+z80 SET TRUE
+ENDIF;mmate [29]
+
+IF disc ;[29]
+mnport EQU 05 ;Discovery 83U port B data
+mnprts EQU 04 ;Discovery 83U port B status/command
+output EQU 04 ;Transmit buffer empty
+input EQU 01 ;Receiver ready
+z80 SET TRUE
+ENDIF;disc [29]
+
+IF cmemco ;[25]
+tuart EQU 020H ;TU-ART address
+mnport EQU tuart+1 ;Modem data port
+mnprts EQU tuart ;Modem status port
+output EQU 080H ;Transmitter empty
+input EQU 040H ;Input data available
+baudrt EQU tuart ;Baud rate port
+;Note: Needs terminal definition
+z80 SET TRUE ;This one's a Z80.
+ENDIF;cmemco
+
+IF cpt85xx
+baudrt EQU 4Ch ; Baud rate generater (National MM5307)
+mnport EQU 4Bh ; Comm port data register (Intel 8251)
+mnprts EQU 4Ah ; Comm port command/status register
+output EQU 01h ; Transmitter buffer empty flag
+input EQU 02h ; Reciver buffer full flag
+TxEmpty EQU 04h ; Transmitter empty flag
+z80 SET FALSE ; It's really an 8080 [or 8085 ... same thing]
+ENDIF;cpt85xx
+
+IF mmdI ;Morrow MicroDecision - the single-board one
+mnport EQU 0FEH ;Morrow Printer UART data port
+mnprts EQU 0FFH ;Morrow Printer UART command/status
+output EQU 01H ;Output ready bit.
+input EQU 02H ;Input ready bit.
+;Note: Needs terminal definition
+z80 SET FALSE ;I don't know...
+ENDIF;mmdI
+
+IF bbc ;[22]
+osbyte EQU 0FFF4H ; OS entry point
+osword EQU 0FFF1H ; " " "
+term EQU 0FFC8H ;Terminal mode OS entry
+z80 SET TRUE
+ENDIF;[22] bbc
+
+;Two types of 380Z system
+IF rm380zm ;[27] MDS - 5 1/4" discs
+mnport EQU 0C8H ;Modem data port
+mnprts EQU 0C9H ;Modem status port
+ENDIF;[32] rm380zm
+
+IF rm380zf ;[32] FDS - 8" discs
+mnport EQU 0E8H ;Modem data port
+mnprts EQU 0E9H ;Modem status port
+ENDIF;[32] rm380zf
+
+IF rm380z ;[32] Common to both systems
+output EQU 01H ;Transmitter buffer empty
+input EQU 02H ;Input data available
+TxEmpty EQU 04h ;Transmitter empty flag
+z80 SET TRUE
+ENDIF;[22] rm380z
+
+IF px8 ; [29]
+z80 SET TRUE
+mnprts EQU 0dh ; used in sending a break
+ENDIF ;px8 [29]
+
+IF mdI ;Morrow Decision I - the big sucker
+mnport equ 48H ; Modem data port.
+mnprts equ 4DH ; Modem status port.
+output equ 20H ; Transmitter empty.
+input equ 1 ; Input data available.
+mbase equ 48H ; Base address of Multi I/O port
+ ; selector area.
+grpsel equ 4FH ; Group select port.
+rbr equ 48H ; Read Data Buffer.
+group equ 1 ; Multi I/O Group byte for serial ports.
+congrp equ 1 ; Serial Port 1 for console
+mdmgrp equ 3 ; Serial Port 3 for modem.
+
+; Following are needed for baud rate changes...[Toad Hall]
+
+dlm equ 49H ; Baud Rate Divisor (Most Sig Bit)
+dll equ 48H ; Baud Rate Divisor (Least Sig Bit)
+ier equ 49H ; Interrupt Enable Register
+lcr equ 4BH ; Line Control Register
+lsr equ 4DH ; Line Status Register
+msr equ 4EH ; Modem Status Register
+dlab equ 80H ; Divisor Latch Access Bit
+wls0 equ 1 ; Word Length Select Bit 0
+wls1 equ 2 ; Word Length Select Bit 1 for 8 bit word
+stb equ 4 ; Stop bit count - 2 stop bits
+imask equ 0 ; Interrupt mask (all disabled)
+z80 SET TRUE ; This one's a Z80.
+ENDIF ;mdI NOTE: needs terminal definition. [Toad Hall]
+
+IF mikko
+sioac EQU 0FF12H ;SIO channel A register(s) address
+sioo3 EQU 01000001B ;SIO Write Reg. 3 original setup (?)
+ ;RX 7 bits,synch mode bits 0,RX enable
+sion3 EQU 11001111B ;SIO Write Reg. 3 KERMIT setup
+ ;RX 8 bits,synch mode bits 0,RX enable
+sioo4 EQU 01001111B ;SIO Write Reg. 4 original setup (?)
+ ;X16 clock,8 bit synch(ignored),
+ ;2stop bits,par even(on)
+sion4 EQU 01000100B ;SIO Write Reg. 4 KERMIT setup
+ ;X16 clock,8 bit synch(ignored),
+ ;1stop bit,par off
+sioo5 EQU 10101010B ;SIO Write Reg. 5 original setup (?)
+ ;DTR,TX 7 bits,TX enable,RTS
+sion5 EQU 11101010B ;SIO Write Reg. 5 KERMIT setup
+ ;DTR,TX 8 bits,TX enable,RTS
+txclk EQU 0FF30H ;Baud rate generator (CTC) for transmitter
+rxclk EQU 0FF31H ;Baud rate generator (CTC) for receiver
+chmask EQU 0F1F2H ;Mask byte address for SIO ch. A reception
+z80 SET TRUE ;It's got a SIO and a CTC, it must be a Z80
+ENDIF;mikko
+
+
+IF access ;[29]
+mnport EQU 40H ;Modem data port A
+mnprts EQU 42H ;Modem status/conrtol port A
+output EQU 04H ;Transmit buffer empty
+input EQU 01H ;Receive data available
+z80 SET TRUE ;a good z80, here
+ENDIF;access [29]
+
+
+IF robin OR dmII
+z80 SET TRUE ; This one's a Z80
+ENDIF;robin OR dmII
+
+IF hp125 ;[MF]
+z80 SET TRUE ;HP-125 uses a Z80
+ENDIF;hp125 [MF]
+
+IF gener OR cpm3 ; To be truly generic, we must assume 8080.
+z80 SET FALSE
+ENDIF;gener OR cpm3
+;
+IF osi
+defesc EQU ']'-100O ;The default escape character.
+ENDIF; osi
+
+IF vector
+defesc EQU '~' ;Vector can't type ']'.
+ENDIF;vector
+
+IF mikko OR osbrn1 OR lobo
+defesc EQU '\'-100O ;The default is Control \ -- it's easier B.E.
+ENDIF;mikko OR osbrn1 OR lobo
+
+IF cpt85xx
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+ENDIF;cpt85xx
+
+IF bbc OR rm380z OR px8 OR access OR S1008 ;[22] [29]
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+ENDIF ;bbc OR rm380z OR px8 OR access OR s1008[29]
+
+IF trs80
+defesc EQU '_'-100O ;CTRL-_ (Down-arrow on TRS-80 keyboard)
+ENDIF;trs80
+
+; Select initial setting for VT-52 emulation flag.
+
+IF vt52 ; If console looks like (or is) VT52
+vtval EQU 0 ; we don't need VT52 emulation
+ENDIF;vt52
+
+; If none of the above, default to VT52-EMULATION ON.
+IF NOT (crt OR vt52 OR robin OR dmII OR vt100 OR hp125);[MF]
+vtval EQU 1
+ENDIF;NOT (crt OR vt52 OR robin OR dmII OR vt100 OR hp125)[MF]
+
+
+; sysxin - system dependent initialisation code, called from SYSINIT
+;
+sysxin:
+
+IF dmII
+; edit added by OBSchou for C. Lasner. If this dont work, tell me whats
+; wrong, as I have no DMII or IBM to play with
+;
+; IBM mode fixup program
+;
+; This routine must be run before attempting to use KERMIT-80 with half
+; duplex KERMIT implementations such as CMS-KERMIT, as the 6120 processor
+; will otherwise "swallow" the XON character.
+;
+; acknowledgments and limitations.
+;
+; This program is based on DECMATE specific implementation details
+; provided by Walt Lamia of DEC. It is of course, specific to DECMATE
+; implementations of CP/M-80 for DECMATE II, III, III-plus, etc.
+;
+; usage consists of merely:
+;
+; CP4DMF run this program
+; KERMIT80 then run kermit
+; <KERMIT-80 commands used normally here, including SET IBM ON>
+; CP4DMU run companion program to restore normal XON
+;
+; unless CP4DMU is run following KERMIT-80, the normal handling of
+; XON/XOFF provided by KERMIT-80 will not work (cold boot is another
+; alternative).
+;
+; CP4DMF.ASM
+;
+; last edit: 12-jun-87 20:00:00 Charles J. Lasner (CJL)
+
+;oboff equ 3fh ; offset of outbyt routine for 6120
+;prtctl equ 02h ; port control
+nocoxon equ 001h ; turn off comm. output XON
+
+ lxi b,(nocoxon * 100h) + prtctl ; c/prtctl, b/no out. xon
+ call outbyt
+ ret ; and return
+
+;outbyt has been catered for (in break routine)
+ENDIF ;dmII
+
+IF osbrn1 ;(Note now no longer needs code > 4000h as it is already there
+; lxi d,ostop ;where we're moving it to
+; lxi h,osmove ;what we're moving
+; mvi b,osmct ;How many bytes we're moving
+; call mover
+ lda baudrt ; Find out what speed is current
+ ani 1
+ mvi a,osbi03 ; assume 300 baud
+ jz osstr1
+ mvi a,osbi12 ; nope, it's 1200.
+osstr1: sta speed ; save initial speed
+ sta speed+1 ; as 16 bits, to match speed table entries
+ mov d,a
+ mov e,a ; get initial speed in DE
+ call sysspd ;set up parity etc.
+ENDIF;osbrn1
+
+IF cpt85xx
+ mvi a,80h ; Send UART reset [force idle] by setting
+ out baudrt ; bit 7 of baud rate I/O port
+ lxi H,0f0fh ; Clear reset and default to 9600 baud [23]
+ shld speed ; store current speed
+ xchg
+ call sysspd ; set default baud rate
+ mvi a,4Eh ; Set UART mode to async 16x clock, 8 data
+ out mnprts ; bits, no parity, and 1 stop bit
+ mvi a,37h ; Set command to Tx enable, DTR on, Rx enable,
+ out mnprts ; break off, error reset, and RTS on
+ENDIF ; cpt85x
+
+IF bbc ;[22]
+ lxi d,modstr ; Set MODE 3
+ call prtstr
+ mvi a,1 ; Set terminal mode on
+ call term
+ mvi a,0F2H ; Read current transmit speed
+ lxi h,0FF00H ; .. 3 lsb of ULA register
+ call osbyte ; FX242,0,255
+ mov a,l
+ ani 7 ; Mask of 3 lsb
+;
+; Edit of July 22, 1986 by B Robertson, Aberdeen Univ. Computing Centre.
+; Correct bug in sysinit for BBC - reads the initial baud rate at
+; start up incorrectly.
+;
+;
+ rar ; Reverse order of 3 lsb
+ rar ; Bit2 now in bit0
+ jnc binit1 ;
+ ori 2 ; Restore bit1
+binit1: ana a ; Set sign bit as appropriate
+ jp binit2 ;
+ ori 4 ; Bit0 now in bit2
+binit2: ani 7 ; Mask off unwanted bits
+; End of Edit
+
+ xri 7 ; Stored as 2's complement
+ inr a
+ sta speed ; Store 16 bit value
+ sta speed+1
+ mov e,a ; Ensure RX and TX speeds are the same
+ call sysspd
+ENDIF;[22] bbc
+
+IF rm380z ;[22]
+ mvi e,11h ;Output ctrl-Q to clear autopaging
+ call outcon
+ENDIF;[22] rm380z
+
+
+IF lobo ;[hh]
+ lxi d,siotbl ;[hh] address of status table
+ mvi c,siolen ;[hh] length of the table
+siolup: ;[hh] loop here for each command byte
+ ldax d ;[hh] load first byte into A
+ inx d ;[hh] index pointer to next bute
+ sta mnprts ;[hh] send it to status port A
+ sta mnprts+2 ;[hh] and to status port B
+ dcr c ;[hh] decrement the counter
+ jnz siolup ;[hh] loop back for more commands
+ mvi a,05H ;[hh] value for 300 baud
+ sta baudrt ;[hh] starting default for port A
+ sta baudrt+4 ;[hh] and for port B
+ sta speed ;[hh] tell program they're set
+ mvi a,0E4H ;[hh] value for port A
+ sta port ;[hh] tell program we've set this, too
+ mvi a,0D0H ;[hh] port A baud rate value
+ sta port+1 ;[hh] save this as well, for consistancy
+ENDIF ;lobo
+
+IF mikko
+ lxi d,mintbl ;Address of KERMIT Reg values (what)
+ mvi c,minlen ;Length of table (how many)
+ lxi h,sioac ;Send data to ch. A SIO registers (to where)
+ call movmik
+ mvi a,0FFH ;Set ch. A mask to use all bits
+ sta chmask
+ENDIF;mikko
+
+IF mdI
+ lxi h,96 ;Default 1200 baud modem port speed
+ shld speed ;Store as modem port speed
+ call sysspd ;Initialize the port
+ENDIF;mdI [Toad Hall]
+
+IF cmemco ;[25]
+ mvi a,01h ; Reset TU-ART
+ out tuart+2
+ mvi a,90h ; Set default baud rate (2400), and 1 stop bit
+ out tuart
+ sta speed ; save for status display
+ sta speed+1
+ENDIF;cmemco
+
+IF delphi ;[7]
+;
+; shove the default baud rate (1200) in to the Delphi port address
+; for the baud rate generator on port 2, the default port; save this
+; value so we can tell what speed is selected.
+;
+ mvi a,07h ;[7] get value for 1200 baud
+ out baudrt ;[7] set it for port 2
+ sta speed ;[7] save for status display
+ sta speed+1
+ENDIF;[7] delphi
+
+IF px8 ; [29]
+ lda 0f6a9h ; get baud rate value set by CONFIG
+ sta px8blk+4 ; put into parameter block
+ mov h, a ; initialise global speed indicator
+ mov l, a
+ shld speed
+ lhld 6 ; base of CP/M
+; buffer starts at ovlend+8192, immediately after sector buffer
+; We must also allow (800h) for the CCP as Kermit exits with a RET
+ lxi d, ovlend+8192+800h ; calc buffer length
+ ora a ; clear carry
+ db 0edh, 52h ; sbc hl, de
+ shld px8blk+2
+ call rsopen
+ENDIF ; px8 [29]
+
+IF disc ;[29]
+;Initialization sequence for Discovery 83U port B
+;Sets port to 9600 baud, 8 data bits, 1 stop bit, no parity
+ mvi a,12 ;Register 12
+ out mnprts
+ mvi a,11 ;Low byte of time constant for 9600
+ out mnprts
+ mvi a,13 ;Register 13
+ out mnprts
+ mvi a,0 ;High byte of time constant for 9600
+ out mnprts
+ mvi a,14 ;Register 14
+ out mnprts
+ mvi a,3 ;Enable baud rate generator
+ out mnprts
+ mvi a,11 ;Register 11
+ out mnprts
+ mvi a,52h ;No Xtal, tclk=rclk=/trxc out=br gen
+ out mnprts
+ mvi a,4 ;Register 4
+ out mnprts
+ mvi a,44h ;16x clock, 1 stop, no parity
+ out mnprts
+ mvi a,3 ;Register 3
+ out mnprts
+ mvi a,71h ;rx 8 bit/ch, autoenable, rx enable
+ out mnprts
+ mvi a,5 ;Register 5
+ out mnprts
+ mvi a,0eah ;tx 8 bit/ch, tx enable, rts
+ out mnprts
+ENDIF;disc [29]
+;
+;
+IF mikko ;currently for MIKROMIKKO only
+; copy command block into memory-mapped SIO.
+movmik: di ;disable interrupts
+movmk1: ldax d ;Get a register value
+ mov m,a ;Output it
+ inx d ;Next value
+ dcr c ;Decrement counter
+ jnz movmk1 ;Repeat until done
+ ei
+ ret
+ENDIF;mikko
+
+;
+IF osbrn1
+osmove:
+osflag equ 0EF08H ;Osborne 1 Bank-2 flag
+;
+; return modem status in A
+;
+OSLDST:
+ DI
+ OUT 0
+ LDA osprts ;Read the status port
+ OUT 1
+ EI
+ ret
+;
+; set modem status from A
+;
+OSSTST:
+ DI
+ OUT 0
+ STA osprts ;Write the control port
+ jmp osstex
+;
+; read character from modem into A
+;
+OSLDDA:
+ DI
+ OUT 0
+ LDA osport
+ OUT 1
+ EI
+ ret
+;
+; output character in A to modem
+;
+OSSTDA:
+ DI
+ OUT 0
+ STA osport
+osstex:
+ OUT 1
+ mvi a,1
+ sta osflag
+ EI
+ ret
+ENDIF;osbrn1
+
+IF lobo
+; List of commands to set up SIO channel A for asynchronous operation.
+siotbl: DB 18H ; Channel reset
+ DB 18H ; another, in case register 0 wasn't selected
+ DB 04H ; Select register 4
+ DB 44H ; 1 stop bit, clock*16
+ DB 01H ; Select register 1
+ DB 00H ; No interrupts enabled
+ DB 03H ; Select register 3
+ DB 0C1H ; Rx enable, 8 bit Rx character
+ DB 05H ; Select register 5
+ DB 0EAH ; Tx enable, 8 bit Tx character,
+ ; raise DTR and RTS
+siolen equ $-siotbl ; length of command list
+ENDIF;lobo
+
+IF mikko
+; command list to set SIO chip back to normal state
+miotbl: db 3 ;reg. 3
+ db sioo3
+ db 5 ;reg. 5
+ db sioo5
+ db 4 ;reg. 4
+ db sioo4
+ db 0 ;reselect reg. 0
+miolen equ $-miotbl ;MikroMikko SIO table length (original values)
+
+; command list to set up SIO chip for operation with Kermit
+mintbl: db 3 ;reg. 3
+ db sion3
+ db 5 ;reg. 5
+ db sion5
+ db 4 ;reg. 4
+ db sion4
+ db 0 ;reselect reg. 0
+minlen equ $-mintbl ;MikroMikko SIO table length (KERMIT values)
+ENDIF;mikko
+
+
+IF bbc ;[22]
+modstr: db 16h,03h,'$' ; String to put screen into MODE 3
+ENDIF
+
+IF px8 ; [29]
+rsget: mvi b, 50h
+ jmp rsiox
+rsinst: mvi b, 30h
+ jmp rsiox
+rsput: mvi b, 60h
+ jmp rsiox
+rsoutst:mvi b, 40h
+ jmp rsiox
+rserst: mvi b, 90h
+ jmp rsiox
+rsopen: lxi h, px8blk ; copy px8blk to px8prm
+ lxi d, px8prm
+ lxi b, 9
+ call mover
+ mvi b, 10h ; open code
+ jmp rsiox
+rsclose:mvi b, 20h ; close code
+rsiox: lxi h, px8prm
+ lxi d, 51h ; offset into BIOS jump table
+ push h
+ lhld 1 ; start of BIOS
+ dad d
+ xthl ; entry point on stack, px8prm addr in hl
+ ret ; jump indirect
+
+px8prm: dw 0, 0
+ db 0, 0, 0, 0, 0 ; the param area is overwritten in rsopen
+px8blk: dw ovlend+8192 ; buffer address
+ dw 0 ; buffer size - overwritten
+ db 0 ; baud rate - overwritten
+ db 3 ; 8 bits/char
+ db 0 ; no parity, it is done internally
+ db 1 ; 1 stop bit
+ db 0cfh ; special bits - activate xon/xoff
+; The documentation suggests that the xon/xoff bit is bit 4, i.e the pattern
+; should be 0efh, but the top bit is omitted from the diagram. I will try
+; clearing both bit 4 and bit 5.
+ENDIF ; px8 [29]
+
+IF hp125 ;[MF]
+ lxi b,73ffh ;Prepare Data Comm 1 to
+ call bdos ;Transfer eight-bit data
+ lxi d,jbuf ;Point to bios jump-table vector
+ lxi b,7effh ;Set up special subfunction code to
+ call bdos ;Get rdr routine address
+ lhld jbuf+3 ;Remember this address
+ shld readin+1 ;for our eight-bit rdr routine
+ mvi a,1 ;We want to write into the bios jump table
+ sta jbuf+1 ;...
+ lxi h,readin ;Point to our rdr routine (all 8 bits)
+ shld jbuf+3 ;as new RDR routine
+ lxi d,jbuf ;Point to jump vector argument block
+ lxi b,7effh ;Set subfunction code to
+ call bdos ;Substitute our rdr routine in dispatch table
+ lxi h,mapon1 ;Make Data Comm 1 the default port
+ shld port ;at program-start
+ xchg ;Put in DE
+ call prtstr ;Print escape sequences to connect
+ ;DAta Comm 1 to rdr/punch
+ENDIF ;hp125 [MF]
+
+ ret ; end of sysxin
+
+;
+; system-dependent termination processing
+; If we've changed anything, this is our last chance to put it back.
+sysexit:
+
+IF dmII
+; Edited by OBSchou for Charles Lasner. His bug fix now in Kermit-80:
+;
+; IBM mode restore program
+;
+; This routine must be run after using CP4DMF (and KERMIT-80) to restore
+; the normal handling of XON/XOFF; the user may also elect to cold-boot
+; the DECMATE instead.
+;
+; acknowledgments and limitations.
+;
+; This program is based on DECMATE specific implementation details
+; provided by Walt Lamia of DEC. It is of course, specific to DECMATE
+; implementations of CP/M-80 for DECMATE II, III, III-plus, etc.
+;
+; usage consists of merely:
+;
+; CP4DMF run xon/xoff disable program
+; KERMIT80 then run kermit
+; <KERMIT-80 commands used normally here, including SET IBM ON>
+; CP4DMU run this program to restore normal XON
+;
+; unless CP4DMU is run following KERMIT-80, the normal handling of
+; XON/XOFF provided by KERMIT-80 will not work (cold boot is another
+; alternative).
+;
+; CP4DMF.ASM
+;
+; last edit: 12-jun-87 20:00:00 Charles J. Lasner (CJL)
+;
+coxon equ 000h ; enable comm. output XON
+;oboff equ 3fh ; offset of outbyt routine for 6120
+;prtctl equ 02h ; port control
+
+
+ lxi b,(coxon * 100h) + prtctl ; c/prtctl, b/with out. xon
+ call outbyt ;[OBS] declared elswhere
+ ret ; and return
+
+ENDIF ;dmII
+
+IF mikko
+ lxi d,miotbl ;Load the adress of original reg values
+ mvi c,miolen ;Length of table
+ lxi h,sioac ;Send data to ch A SIO registers
+ call movmik
+ mvi a,07FH ;Set ch A mask to use just 7 bits
+ sta chmask
+ENDIF;mikko
+
+IF teletek
+;Note - This code was handwritten onto the lising I was sent, with the
+; comment that David had just thought of the code, so it was
+; not on the listing. If you have problems I suggest you
+; comment out these few lines.
+;Bertil Schou.
+;
+ di
+ mvi a,47h ; reset baud rate to 9600
+ out baudrt
+ mvi a,08h
+ out baudrt
+ ei
+ENDIF ;teletek
+
+IF cpt85xx
+ mvi a,80h ; Reset (force idle) the 8251 UART via bit 7
+ out baudrt ; of the baud rate generater port
+ mvi a,00h ; and turn off the baud rate generater
+ out baudrt
+ENDIF;cpt85xx
+
+IF bbc ;[22]
+ mvi a,0 ; Turn off terminal mode
+ call term
+ENDIF;[22] bbc
+
+IF px8 ;[29]
+ call rsclose
+ENDIF ;px8 [29]
+
+IF hp125 ;[MF]
+ lxi b,74ffh ;Set subfunction code to
+ call bdos ;Reset Data Comm 1 for 7-bit data
+ lhld readin+1 ;Get original rdr routine address
+ shld jbuf+3 ;and store in jump vector
+ lxi d,jbuf ;Point to jump vector
+ lxi b,7effh ;Set subfunction code to
+ call bdos ;Put original rdr routine back in bios
+ ;dispatch table
+ lxi d,mapoff ;Point to escape sequences to
+ call prtstr ;Turn off Data Comm 1/2 mappings
+ENDIF ;hp125 [MF]
+
+ ret
+
+;
+; system-dependent processing for start of CONNECT command
+;
+syscon:
+IF robin OR trs80 OR cpt85xx ;For Robin/TRS80/CPT-85xx, add some more info
+ lxi d,conmsg ; about obscure key combinations
+ call prtstr
+ENDIF;robin OR trs80 OR cpt85xx
+
+IF osbrn1 ;*** This is Software dependent ***
+ lhld 1 ;Modify back-arrow code to DELETE
+ mvi l,0 ;Get BIOS-start address
+ lxi d,85H ;Adress for key-code = XX85H
+ dad d
+ mov e,m ;Get it in DE
+ inx h
+ mov d,m
+ xchg ;Memory pointer to HL
+ mvi m,del ;modify the code
+ENDIF;osbrn1
+ ret
+
+conmsg: ; Messages printed when entering transparent (CONNECT) mode:
+IF robin ; for Robin, control-S key is hidden
+ db ' (Type Left Arrow to send CTRL-S)',cr,lf,'$'
+ENDIF;robin
+IF trs80 ; for TRS-80, the preferred escape key is hidden
+ db ' (Control-_ is the Down-Arrow key on the TRS-80 keyboard)'
+ db cr,lf,'$'
+ENDIF;trs80
+IF cpt85xx ; for CPT-85xx, some graphics map "funny" to keyboard in CP/M
+ db ' (Use CODE + SHIFT + 1/2 key to generate a Control-\)'
+ db cr,lf,'$'
+ENDIF;cpt85xx
+;
+; syscls - system-dependent close routine
+; called when exiting transparent session.
+;
+syscls:
+IF osbrn1
+ lhld 1 ;Modify back-arrow code to BACKSPACE
+ mvi l,0 ;Get BIOS address
+ lxi d,85H ;Address for key-code =XX85H
+ dad d
+ mov e,m ;Get it in DE
+ inx h
+ mov d,m
+ xchg ;Address to HL
+ mvi m,bs ;Modify code
+ENDIF;osbrn1
+ ret
+;
+; sysinh - help for system-dependent special functions.
+; called in response to <escape>?, after listing all the
+; system-independent escape sequences.
+;
+sysinh:
+IF robin OR dmII OR cpt85xx OR lobo
+ lxi d,inhlps ; we got options...
+ call prtstr ; print them.
+ENDIF;robin OR dmII OR cpt85xx OR lobo
+
+IF bbc OR rm380z ; some more
+ lxi d,inhlps ; we got options...
+ call prtstr ; print them.
+ENDIF;[22] bbc OR rm380z
+
+IF px8 OR access OR mmate OR disc ;and more...
+ lxi d,inhlps ; we got options...
+ call prtstr ; print them.
+ENDIF ;px8 OR access OR mmate OR disc
+
+ ret
+
+
+;additional, system-dependent help for transparent mode
+; (two-character escape sequences)
+inhlps:
+
+IF robin OR dmII OR cpt85xx OR lobo
+ db cr,lf,'B Transmit a BREAK'
+ENDIF;robin OR dmII OR cpt85xx OR lobo
+
+IF bbc OR rm380z
+ db cr,lf,'B Transmit a BREAK'
+ENDIF;bbc OR rm380z
+
+IF px8 OR access OR mmate
+ db cr,lf,'B Transmit a BREAK'
+ENDIF ;px8 OR access OR mmate
+
+IF disc ;[29] [32]
+ db cr,lf,'B Transmit a 300ms BREAK'
+ db cr,lf,'L Transmit a 5 second BREAK'
+ENDIF;disc [29]
+
+IF lobo
+ db cr,lf,'D Drop the line'
+ENDIF;lobo
+
+ 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 robin OR dmII OR cpt85xx OR lobo
+ cpi 'B' ; send break?
+ jz sendbr ; yes, go do it. return nonskip when through.
+ENDIF;robin OR dmII OR cpt85xx OR lobo
+
+IF bbc OR rm380z ; [22] [25] ... some more
+ cpi 'B' ; send break?
+ jz sendbr ; yes, go do it. return nonskip when through.
+ENDIF; bbc OR rm380z
+
+IF px8 OR access OR mmate ;[28] [29] and anothers
+ cpi 'B' ; send break?
+ jz sendbr ; yes, go do it. return nonskip when through.
+ENDIF ; px8 OR access OR mmate [28] [29]
+
+IF lobo ;[hh]
+ cpi 'D' ;[hh] disconnect?
+ jz discon ;[hh] yes, go do it. nonskip return when done.
+ENDIF ;lobo
+
+IF disc ;[29]
+ cpi 'B' ;Send short break?
+ jz sendbr
+ cpi 'L' ;Send long break?
+ jz sendlbr
+ENDIF;disc [29]
+
+ jmp rskp ; take skip return - command not recognized.
+
+
+;
+IF robin ;Definitions & code to send a BREAK (ungenerically, no other way).
+
+comctl equ 59h ;VT180 communications port
+crtctl equ 41h ;VT180 crt port
+
+;VT180 serial port command bits
+
+txe equ 1 ;transmit enable
+dtr equ 2 ;dtr on
+rxe equ 4 ;rx enable
+sndbrk equ 8
+rerr equ 10h ;reset error
+rts equ 20h ;RTS on
+reset equ 40h ;port reset
+
+;Send a break to the communications port.
+;
+
+sendbr: lxi h,38500 ;250 ms(?)
+ lda prtadr ;Get address of selected port
+ mov c,a ;Into C
+ mvi a,sndbrk+dtr
+; OUT C,A ;Want to send to port addressed by C
+ db 0EDH,079H ;Op code for above instruction
+sndbr1: dcx h ;timing loop...
+ mov a,l
+ ora h
+ jnz sndbr1 ;...until over
+ lda prtadr ;Get the address for the port
+ mov c,a ;Into C
+ mvi a,txe+dtr+rxe+rerr+rts ;enable tr/rc, dtr, reset error
+; out c,a ;Z-80 only instruction
+ db 0EDH,079H ;Op code for above instruction
+ out contst ;reset ports
+ ret
+ENDIF;robin
+;
+IF dmII ;[jd] this added to send break on DECmate
+
+; DECmate command codes for 6120 I/O processor
+oboff equ 3fh ; offset of outbyt routine for 6120
+prtctl equ 02h ; port control
+brdat equ 06h ; data to tell 6120 to send a break
+brdur equ 30 ; duration, 30 = 300 ms.
+
+sendbr: lxi b,(brdat * 100h) + prtctl ; c/prtctl, b/brdat
+ call outbyt
+ lxi b,brdur*100h ; b/duration, c/0
+; fall through into outbyt
+
+outbyt: lhld 1 ; get warm boot address
+ lxi d,oboff ; offset of outbyt routine
+ dad d ; compute address
+ pchl ; branch there (a callret)
+
+ENDIF;dmII
+;
+IF access OR mmate ;[cjc] send break on Kaypro [29]
+; Officially, a "break" is 300 milliseconds of "space" (idle line is
+; "mark"). (or maybe 200 milliseconds; I forget.) The timing isn't
+; usually that critical, but we'll make an attempt, at least. Sending
+; too long a break can cause some modems to hang up.
+
+sendbr:
+; First, make sure the transmitter is really empty. (The SIO sets
+; "transmitter buffer empty" when it can accept another character;
+; the previous character is still being shifted onto the line.
+; Another status bit, "all done", is set to indicate that the
+; transmitter is really idle.
+sndbr1: mvi a,1 ; select Read Register 1
+ out mnprts
+ in mnprts ; read the contents
+ ani 1 ; test "all done" flag
+ jz sndbr1 ; loop until it's nonzero.
+;
+; Next, set the "send break" bit to start the transmitter spacing.
+ mvi a,5 ; select Write Register 5
+ out mnprts
+ mvi a,0FAH ; Tx enable, 8 bit Tx character, Send Break,
+ out mnprts ; DTR and RTS on.
+;
+; Now, delay for 30 hundredths of a second
+ mvi a,30 ; delay count
+ call delay
+;
+; Time's up. Put transmitter back in normal state (data byte is the
+; same as the one in siotbl: for Write Register 5) and return.
+ mvi a,5 ; select Write Register 5
+ out mnprts
+ mvi a,0EAH ; Tx enable, 8 bit Tx character,
+ out mnprts ; DTR and RTS on.
+ ret ; done.
+ENDIF;access OR mmate [29]
+
+IF lobo ;[hh] This routine sends a break tone or disconnects a modem
+; (those that respond to it) by setting the DTR line low
+; for 300 ms.
+;
+sendbr: mvi a,05H ;[hh] write register 5
+ call outctl ;[hh] send it to control port
+ mvi a,0FAH ;[hh] value to send break tone
+ jmp sndbr1 ;[hh]
+;
+discon: mvi a,05H ;[hh] write register 5
+ call outctl ;[hh] send it to the control port
+ mvi a,06AH ;[hh] DTR off and break tone on
+sndbr1: call outctl ;[hh] send to control port
+ mvi a,30 ;[hh] delay count for 300 ms.
+ call delay ;[hh] wait a while...
+ mvi a,05H ;[hh] write register 5
+ call outctl ;[hh] get it's attention
+ mvi a,0EAH ;[hh] normal 8 bits, DTR on, RTS on, etc.
+ call outctl ;[hh] restore SIO
+ ret
+;
+outctl: sta mnprts ;[hh]
+ ret
+ENDIF ;lobo
+;
+IF cpt85xx OR rm380z ;[lmj] [22] [25]
+sendbr:
+;
+; Ensure that the transmitter has finished sending buffered chars
+sndbr1: in mnprts ; get UART status
+ ani TxEmpty ; everything sent?
+ jz sndbr1 ; no, wait a bit more
+;
+; Begin sending a break by setting bit in UART command register
+ mvi a,3Fh ; Set TxEna, DTR, RxEna, SBreak, ErrRst, RTS
+ out 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
+ out mnprts
+;
+ ret ;done
+ENDIF;cpt85xx OR rm380z
+
+IF px8 ; [29]
+sendbr: mvi a, 3fh ; set break bit
+ out mnprts
+ mvi a, 25
+ call delay ; wait 250 msec
+ mvi a, 37h ; clear break bit
+ out mnprts
+ ret
+ENDIF ; px8 [29]
+
+;
+IF bbc ;[22]
+sendbr:
+;
+; Ensure that the transmitter has finished sending buffered chars
+sndbr1: mvi a,96h ; get ACIA status
+ mvi l,8
+ call osbyte ; *FX150,8
+ mov a,h
+ ani 2 ; everything sent?
+ jz sndbr1 ; no, wait a bit more
+;
+; Disable centisecond clock (system VIA) which interferes with break
+ lxi h,0FE4Eh ; system VIA interrupt enable register
+ mvi a,40H ; disable timer 1
+ call wrtiom ; write to I/O processor memory
+;
+; Begin sending a break by setting bit in ACIA control register
+ mvi a,9Ch
+ lxi h,9F60h ; Set Rxint, Txint, Break, RTS
+ call osbyte ; *FX 156,96,159
+;
+; Wait for 250 milliseconds (using hundredths second delay routine)
+ mvi a,25
+ call delay
+;
+; Resume normal operation by returning old control byte
+ mvi a,9Ch
+ mvi h,0 ;Set TxEna, DTR, RxEna, ErrRst, RTS
+ call osbyte ; *FX 156,oldvalue,0
+;
+; Enable centisecond clock (system VIA)
+ lxi h,0FE4Eh ; system VIA interrupt enable register
+ mvi a,0C0H ; enable timer 1
+ call wrtiom ; write to I/O processor memory
+;
+ ret ;done
+;
+; Routine to write byte in A to I/O processor memory address
+; given by HL
+wrtiom:
+ shld parblk ; store address to parameter block
+ sta parblk+4 ; store data
+ lxi h,parblk ; load hl with address of param block
+ mvi a,6 ; write I/O processor memory
+ call osword ; go do it
+ ret
+;
+parblk: DS 5 ; reserve space for parameter block
+ENDIF;bbc [22]
+;
+IF disc ;[29]
+; This is almost an exact copy of the bbI sendbr routine.
+; Modifications to include a long break have been made.
+;
+; Officially, a "break" is 300 milliseconds of "space" (idle line is
+; "mark"). (or maybe 200 milliseconds; I forget.) The timing isn't
+; usually that critical, but we'll make an attempt, at least. Sending
+; too long a break can cause some modems to hang up.
+
+sendlbr:
+ push d ;save d, this may not be necessary, but safe
+ mvi d,17 ;do short break 17 times (approx. 5 sec.)
+ jmp sndbr1
+sendbr:
+ push d
+ mvi d,1 ;On short break, do only once
+; First, make sure the transmitter is really empty. (The SIO sets
+; "transmitter buffer empty" when it can accept another character;
+; the previous character is still being shifted onto the line.
+; Another status bit, "all done", is set to indicate that the
+; transmitter is really idle.
+sndbr1: mvi a,1 ; select Read Register 1
+ out mnprts
+ in mnprts ; read the contents
+ ani 1 ; test "all done" flag
+ jz sndbr1 ; loop until it's nonzero.
+;
+; Next, set the "send break" bit to start the transmitter spacing.
+ mvi a,5 ; select Write Register 5
+ out mnprts
+ mvi a,0FAH ; Tx enable, 8 bit Tx character, Send Break,
+ out mnprts ; DTR and RTS on.
+;
+; Now, delay for 30*d hundredths of a second
+sendbr2:
+ mvi a,30 ; delay count
+ call delay
+; The following has been added to allow doing .03 delay d times
+ dcr d ; decrement # of times to do loop
+ jnz sendbr2 ; if not done, do again
+ pop d ; reload d
+;
+; Time's up. Put transmitter back in normal state (data byte is the
+; same as the one in siotbl: for Write Register 5) and return.
+ mvi a,5 ; select Write Register 5
+ out mnprts
+ mvi a,0EAH ; Tx enable, 8 bit Tx character,
+ out mnprts ; DTR and RTS on.
+ ret ; done.
+ENDIF ;disc [29]
+
+
+;
+; 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
+IF mikko
+ cpi 'O'-100O ;Control-O's lock keyboard
+ rnz ; if not control-O, it's ok.
+ xra a ; don't allow control-O out.
+ENDIF;mikko
+
+ 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 lobo, hang up the phone.
+sysbye:
+IF lobo ;[hh]
+ call discon ;[hh] force modem to hang up
+ENDIF;lobo
+ ret
+
+IF lasm
+ LINK CPXSY2.ASM ; If m80 then this ignored
+ENDIF ; lasm
diff --git a/src/cpxtm4.asm b/src/cpxtm4.asm
new file mode 100644
index 0000000..bb933ee
--- /dev/null
+++ b/src/cpxtm4.asm
@@ -0,0 +1,490 @@
+;CPXTM4.ASM
+; 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 various
+; Tandy Model 4 running under Montezuma Micro CPM
+;
+; This has the Family name of CPXTM4.ASM.
+;
+; revision history (last edit first)
+;
+; edit 5, 8-Feb-1991 by Lance Tagliapietra of the University of Wisconsin-
+; Platteville. Corrected error in the VT52 translation table for
+; clearing from the cursor to the end of the line.
+;
+; edit 4, 27 October, 1987 by OBSchou. Massaged into format suitable
+; for overlay version 4.09
+;
+; Edit 3: Sept 5 1987 GDS Transformed code from Genie III to Tandy Model 4
+;
+; Edit 2: Aug 27 1987 GDS Put in code for BREAK and fillited out
+; a lot of unnecessary IF's
+;
+;Edit 1: Nov. 28, 1986 Geof Smith Clinical Research centre Harrow UK.
+
+
+.printx * Assembling for Tandy Model 4*
+;
+drtime EQU 05H ;Default receive time out interval.
+;
+; the basics...
+;
+mnport EQU 0EBH
+mnprts EQU 0EAH
+output EQU 40H
+input EQU 80H
+lctrl EQU 0E8H
+baudpt EQU 0E9H
+z80 EQU TRUE
+brkval EQU 0H
+inout EQU TRUE
+
+defesc EQU 'X'-100O ;The default escape character.
+
+
+;Select initial setting for VT-52 emulation flag.
+
+; default to VT52-EMULATION ON.
+;
+vtval EQU 1
+;
+;
+
+
+
+
+
+
+
+
+
+; Family is the string used in VERSION to say which of several
+; smaller overlay files are used. These are (will be) derived from
+; the huge CP4SYS.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 'CPXTM4.ASM (5) 8-Feb-91$' ; Used for family versions....
+
+
+;
+; System-dependent initialization
+; Called once at program start.
+sysxin:
+;
+ ;Set up 9600 bd, 8bit words, no parity 1stop bit
+
+ mvi a,0EEH ;Get byte for desired baud (9600 = CC) and
+ out baudpt ;and put it out of baud port
+ out lctrl ;latch control port with anything
+ lda pstore ;get parity etc and put it out of
+ out mnprts ;port
+ 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
+
+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:
+
+ db cr,lf,'B Transmit a BREAK'
+
+ 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 'B' ; send break?
+ jz sendbr ; yes, go do it. return nonskip when through.
+
+ jmp rskp ; take skip return - command not recognized.
+
+
+;-------------------------------------------------------------------------------
+sendbr:
+;
+; Ensure that the transmitter has finished sending buffered chars
+sndbr1: in mnprts ; get UART status
+ ani output ; everything sent?
+ jz sndbr1 ; no, wait a bit more
+;
+; Begin sending a break by setting bit in UART command register
+ mvi a,brkval ; SBreak,
+ out lctrl
+ out mnprts
+;
+
+; Wait for 250 milliseconds (using hundredths second delay routine)
+ mvi a,25
+ call delay
+;
+; Resume normal operation by clearing the SendBreak command bit
+ lda pstore ;get parity etc value
+ out lctrl ;latch control port
+ out mnprts ;and set values
+;
+ ret ;done
+
+;
+;
+
+
+
+
+
+
+
+
+
+;
+; 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 modem in E
+; with parity set as appropriate.
+; return with accumulator = 0 do do nothing,
+; <> 0 to send char in E.
+mdmflt: mov a,e
+ 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:
+ ;Set up baud rate 8bit words, no parity 1stop bit
+
+ mov a,e ;get get speed into a
+ out baudpt ;output it as well
+ lda pstore ;get parity etc
+ out lctrl ;do it resetting DLAB at same time
+ out mnprts
+ ret
+
+pstore: db 6CH ;Default value for parity word length and stop bits
+
+spdtbl: db 10h ;17 entries
+ db 03h,'110$', 22H,22H
+ db 04h,'1200$', 77H,77H
+ db 05h,'134.5$', 33H,33H
+ db 03h,'150$', 44H,44H
+ db 04h,'1800$', 88H,88H
+ db 05h,'19200$', 0FFH,0FFH
+ db 04h,'2000$', 99H,99H
+ db 04h,'2400$', 0AAH,0AAH
+ db 03h,'300$', 55H,55H
+ db 04h,'3600$', 0BBH,0BBH
+ db 04h,'4800$', 0CCH,0CCH
+ db 02h,'50$', 00H,00H
+ db 03h,'600$', 66H,66H
+ db 04h,'7200$', 0DDH,0DDH
+ db 02h,'75$', 11H,11H
+ db 04h,'9600$', 0EEH,0EEH
+
+sphtbl: db cr,lf,' 50 75 110 134.5 150 300 600 1200'
+ db cr,lf,' 1800 2000 2400 3600 4800 7200 9600 19200 $'
+
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+sysprt:
+ ret
+;
+prttbl equ 0 ; SET PORT not supported
+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:
+
+ 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
+
+;--------------------------------------------------------------------------
+;
+; get character from modem; return zero if none available.
+; for IOBYT systems, the modem port has already been selected.
+; destroys bc, de, hl.
+inpmdm:
+;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.
+ 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:
+ 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
+ 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:
+
+ mvi e,bs ;get a backspace
+ jmp 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
+
+;[2] I see no real saving in having all screens in separate file and
+;therefore have included screen definition here and commented out
+;the link to VDU file
+;
+;
+;Specific definitions for the Model IV screen
+;
+sysver: db 'Tandy Model IV$'
+outlin: db 1aH,cr,lf,' $'
+erascr: db 1AH,'$'
+eralin: db cr,15H,'$'
+curldn: db esc,'=$'
+ttab:
+ta: db 0BH,'$',0,0 ;Cursor up
+tb: db 0AH,'$',0,0 ;Cursor down
+tc: db 0CH,'$',0,0 ;Cursor right
+td: db 08H,'$',0,0 ;Cursor left
+te: db 1AH,'$',0,0 ;Clear display
+tf: db 0FH,'$',0,0 ;Reverse on
+tg: db 0EH,'$',0,0 ;Reverse off
+th: db 1EH,'$',0,0 ;Cursor home
+ti: db 0BH,'$',0,0 ;Reverse linefeed
+tj: db 19H,'$',0,0 ;Clear to end of screen
+tk: db 15H,'$',0,0 ;Clear to end of line
+
+ovlend equ $ ;End of overlay
+
+ END
diff --git a/src/cpxtor.asm b/src/cpxtor.asm
new file mode 100644
index 0000000..51b653a
--- /dev/null
+++ b/src/cpxtor.asm
@@ -0,0 +1,1229 @@
+IF NOT lasm
+.printx * CPXTOR.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 Torch, Superbrains,
+; PCI2651 (Loughborough 8" Standard CP/M system) and Cifer computers.
+;
+; This is the first attempt to break the huge CPXSYS.ASM file
+; into smaller system dependent files. To start with I will bunch
+; several micros to one class.
+;
+; Please name system dependent files in the form CPXxxx.ASM where
+; xxx is a three letter abbrev. for the system you are adding.
+;
+; revision history:
+;
+;edit 5, 10-Jan-1991 by MF. Removed references to assembly switch ker09.
+; edit 4, 21 July, 1987 by OBSchou. Removed routines no in CPXCOM.ASM
+;
+; edit 3, 8 April, 1987 by OBSchou. Moved the VDU declarations for the
+; Torch, superbrain and Cifer from CPXVDU.ASM. Also added code to
+; see if the MCP/CCCP ROM versions on the Torch is less or grater than
+; 1. Less than 1 => poor screen control. Finally adjusted the
+; positioning of the filename to cope with a user number and drive
+; in the filename field
+;
+;
+; edit 2, 20 March, 1987 by C.J.MILES@UK.AC.UMRCC. Added support for
+; NCR Decision Mate V (2651 USART)
+;
+; edit 1, 22 April, 1986, OBSchou. Start on splitting off individual
+; systems from this huge file. It is done using the LINK facility
+; LASM. We link to a collection of systems under CPXxxx.ASM.
+; I have started with the systems I know, the Torch, Cifer and
+; pci2651. These will all be held under CPXTOR.ASM
+;
+;
+; Keep module name, edit number, and last revision date in memory.
+family: db 'CPXTOR.ASM (5) 10-Jan-1991 $'
+;
+; 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 ncrdmv
+.printx * Assembling KERMIT-80 for the N.C.R. Decision Mate V *
+ENDIF
+
+IF brain
+.printx * Assembling KERMIT-80 for the Intertec Superbrain *
+ENDIF
+
+IF brainm
+.printx * With main port selected
+ENDIF
+IF braina
+.printx * With Aux port
+ENDIF
+
+IF pci2651 ;
+.printx * assembling Kermit-80 for 2651 PCI as comms device *
+ENDIF
+
+IF torch
+.printx * Assembling Kermit-80 for Torch Unicorn 5 *
+ENDIF
+; *******This should be in the original CPXSYS.ASM file
+;
+;=========================================================================
+; 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
+
+
+; [13] modifed to use either main or aux port. Should really
+; be selected by set port, but this is urgent, so no frills
+IF brain
+baudst EQU 60H ;
+baudrt EQU 0EF00H ;Memory location where baud rates are stored.
+output EQU 01H ;Transmitter ready
+input EQU 02H ;Input data available
+TxEmpty EQU 04h ;Transmitter empty
+z80 SET TRUE ;I don't know...
+ENDIF;brain
+IF brainm ; Superbrain and main ports
+mnport EQU 58H ;Modem data port
+mnprts EQU 59H ;Modem status port
+ENDIF ;brainm
+IF braina ; Superbrain and aux port
+mnport EQU 40H ;Modem data port
+mnprts EQU 41H ;Modem status port
+ENDIF ;braina [13]
+
+IF ncrdmv
+iobase equ 70h ; base address of PCI device
+modrx equ 70h ; Rx data port
+mnprts equ 71h ; status port
+mnmodr equ 72h ; mode register read
+mncmdr equ 73h ; command register read
+modtx equ 74h ; Tx data port
+mnmodw equ 76h ; mode register write
+mncmdw equ 77h ; command register write
+txrdy equ 1
+output equ txrdy
+rxrdy equ 2
+input equ rxrdy
+baudini equ 0ah ; initial baud to 2400
+z80 SET true
+cpuspd SET 40
+ENDIF
+
+IF pci2651 ;[28]
+iobase equ 04h ; base address of PCI device
+mnport equ iobase ; rx and tx data ports
+mnprts equ iobase+1 ; status port
+mnmode equ iobase+2 ; mode port
+mncmd equ iobase+3 ; PCI command port
+
+txrdy equ 1 ; tx ready bit set if free
+output equ txrdy
+rxrdy equ 2 ; RX ready bit
+input equ rxrdy
+baudini equ 7 ; 7 => 1200 baud by default
+z80 SET true ; For Ithica intersystems it is
+cpuspd SET 40 ; and running at four megs
+ENDIF ;[28]
+
+IF torch ;[13]
+z80 SET TRUE
+; [32] baudini removed as now read current baud rate
+; settings from base processor.
+
+;baudini equ 707h ; Initial Baud rate = 1200 baud
+ ; Entry to be of form x0xh where x is
+ ; the value x in the FX 7,x and FX 8,x
+ ; funtion calls. 4= 1200 baud, 7 = 9600
+ ; 2 = 300 baud.
+ENDIF
+
+IF brain OR torch
+defesc EQU ']'-100O ;The default escape character.
+ENDIF;brain OR torch
+
+; If none of the above, default to VT52-EMULATION ON.
+IF NOT crt
+vtval EQU 1
+ENDIF;NOT crt
+
+
+sysxin:
+
+IF brainm ;[25]
+ lda baudrt ; fetch current baud rate
+ ani 0F0H ; extract left nibble
+ rrc ; shift right 4 places
+ rrc
+ rrc
+ rrc
+ sta speed ; store as comm port speed
+ sta speed+1 ; (16 bits, to match speed table entries)
+ENDIF;brainm
+
+IF braina ;[25]
+ lda baudrt ; fetch current baud rate
+ ani 00FH ; extract right nibble
+ sta speed ; store as comm port speed
+ sta speed+1 ; (16 bits, to match speed table entries)
+ENDIF;braina
+
+IF torch ; [13] [32]
+ push h
+ mvi a,0f2h ; nick code from BBC initialisation
+ lxi h,0ff00h
+ call osbyte ; Read current speed setting
+ mov a,l
+ ani 7
+ xri 7 ; Store as two's complement
+ inr a
+ sta speed
+ sta speed+1
+ mov e,a
+ call sysspd ; Make sure they are both the same!
+ mvi a,15 ; Flush all internal buffers [32]
+ mvi l,0
+; call osbyte
+ mvi a,3
+ lxi h,0100h ; *FX 3,0,1 Enable RS423
+ call osbyte
+ mvi a,2 ; Select keyboard, Enable RS423 input
+ mvi l,2
+ call osbyte
+ mvi a,5 ; Select serial printer [32]
+ mvi l,2
+ call osbyte ; [30]
+ mvi a,6 ; Must be able to send LF [30]
+ mvi l,0
+ call osbyte ; [30]
+ mvi a,202 ; FX 202,255 set lower case on
+ mvi l,255
+ call osbyte
+ pop h
+
+; Now see what version of MCP CCP roms. Assume >1, else copy a few of the
+; older Torch VDU declares over the new ones.
+;
+; lda 0ffffh ; Address 0ffffh has single byte Version no.
+; push psw ; save for a rainy day
+; ani 0F0h ; get ms digit of MCP version
+; rra ; move right 4 places
+; rra
+; rra
+; rra
+; ani 0fh
+; adi 30h ; make it a number
+; sta mcpver
+; pop psw ; its raining...
+; push psw ; ... its pouring...
+; ani 0fh ; get ls digit
+; adi 30h ; make it ascii number
+; sta mcpver+2
+; pop psw ; restore psw
+; cpi 10h ; Version 1.00 or less?
+; jp init2 ; yes, so skip next bit
+; lxi h,ooutli ; from old string table
+; lxi d,ttab ; to new ttab
+; lxi b,60 ; 60 bytes to move
+; call mover
+init2:
+
+IF ncrdmv
+ mvi a,00 ; clear out command register
+ out mncmdw
+ mvi a,4eh ; 1 stop bit, 8 data bits, / by 16 counter
+ out mnmodw
+ mvi a,70h+baudini ; baud rate and select internal rate gen.
+ out mnmodw
+ mvi a,27h ; enable tx and rx, RTS and DTR low
+ out mncmdw
+ENDIF ; ncrdmv
+
+IF pci2651 ;[28]
+ in mncmd ; clearw command reg counter
+ mvi a,4eh ; 1 stop bit, 8 data bits, / by 16 counter
+ out mnmode
+ mvi a,30h+baudini ; baud rate and select internal rate gen.
+ out mnmode
+ mvi a,27h ; enable tx and rx, RTS and DTR low
+ out mncmd
+ENDIF ; pci2651 [28]
+
+ 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
+
+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:
+IF torch OR brain OR pci2651 OR ncrdmv
+ lxi d,inhlps ; we got options...
+ call prtstr ; print them.
+ENDIF;torch OR brain OR pci2651 OR ncrdmv
+
+ 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 pci2651 OR brain OR torch OR ncrdmv
+ db cr,lf,'B Transmit a BREAK'
+ENDIF ;pci2651 OR brain OR torch OR ncrdmv
+
+IF torch ; added this simply to debug the escape cokebottle D for the apple
+ db cr,lf,'D Disconnect the modem (Test purposes only)'
+ENDIF;Torch
+
+ 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 brain OR pci2651 OR torch OR ncrdmv
+ cpi 'B' ; send break?
+ jz sendbr ; yes, go do it. return nonskip when through.
+ENDIF ;brain OR pci2651 OR torch OR ncrdmv
+
+IF Torch; added bit for doing a D...
+ cpi 'D' ;drop the line...
+ jz dropln
+ENDIF ;torch
+
+ jmp rskp ; take skip return - command not recognized.
+
+
+IF torch
+dropln: lxi d,dropm ; tell user line is dropped..
+ call prtstr
+ xra a ; destroy A
+ ret
+dropm: db bell,cr,lf,'Testing line dropped ',cr,lf,bell
+ db '$'
+ENDIF ;torch and dropping them there lines..
+
+;
+
+IF brain
+sendbr:
+;
+; Ensure that the transmitter has finished sending buffered chars
+sndbr1: in mnprts ; get UART status
+ ani TxEmpty ; everything sent?
+ jz sndbr1 ; no, wait a bit more
+;
+; Begin sending a break by setting bit in UART command register
+ mvi a,3Fh ; Set TxEna, DTR, RxEna, SBreak, ErrRst, RTS
+ out 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
+ out mnprts
+;
+ ret ;done
+ENDIF;brain
+
+IF torch ; [18] [27] [30] [32]
+; Send a break.
+;
+; [30] Dumping of 6502 code not yet used, but may be for later versions of
+; the Torch CCCP Rom in the BBC. This works, so I leave it for now.
+
+sendbr:
+ push h ;save for a monsoon
+ mvi a,0e8h
+ lxi h,0 ; turn interrupts off
+ call osbyte
+ push h
+;
+ mvi a,9ch ; OSBYTE call 9c is read/write 6850 cntl prt
+ lxi h,0077h ; H = 6502 Y reg, L = 6502 X reg
+ call osbyte ; returned new val. = (old value AND Y)XOR X
+ push h ; save it for return
+;
+ mvi a,30
+ call delay ; do a delay
+;
+; now clear rx register
+;
+ mvi a,96h ; do a read sheila address 08h
+ mvi l,8
+ mvi h,0
+ call osbyte ; read sheila 08h = 6850 rx reg
+;
+; restore 6850 regs...
+;
+ pop h ; restore previous cntl reg
+ ; old x reg in l, so leave it there
+; mov l,h
+ mvi h,0
+ mvi a,9ch ; write previous value to 6850
+ call osbyte
+;
+; and Beebs interrupt mask
+;
+ pop h ; get interrupt mask
+ ; Once again, old X in L so leave it alone
+; mov l,h
+ mvi h,0
+ mvi a,0e8h
+ call osbyte ; restore interrupts mask
+;
+ pop h
+ ret ; its raining again, so exit
+ENDIF ; torch [18] [32]
+
+IF ncrdmv
+sendbr: in mnprts ; get status
+ ani 04h ; make sure shift register is empty
+ jz sendbr
+
+ mvi a,2fh ; force a break
+ out mncmdw
+ mvi a,100 ; set delay period
+ call delay
+ mvi a,27h ; restore command register
+ out mncmdw
+ ret
+ENDIF ; ncrdmv
+
+IF pci2651 ;[28]
+sendbr: in mnprts
+ ani 04h ; make sure shift reg is clear
+ jz sendbr
+
+ mvi a,2fh ; set foe a break
+ out mncmd
+ mvi a,100 ; wait a bit
+ call delay
+ mvi a,27h ; restore mode
+ out mncmd
+ ret
+ENDIF ;pci2651 [28]
+
+;
+; 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
+IF torch ;[30] map del to bs,space,bs
+ ani 7fh ; strip parity
+ cpi 7fh ; is it the delete character
+ rnz ; no, then a <> 0 so print it
+ mvi e,bs ; else load a backspace
+ call outmdm ; little recursion...
+ mvi e,' ' ; then a space
+ call outmdm ; backspace, space, now another...
+ mvi e,bs ; backspace
+ call outmdm ;
+ xra a ; clear a => on return do nowt.
+ENDIF ;torch [30]
+ 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
+IF torch ; strip out lf from printer stream
+ ani 7fh ; make sure it is parity less
+ cpi lf ; is it a line feed?
+ rnz ; no, print it
+; xra a ; yes, don't.
+
+ENDIF ;torch [30]
+ 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:
+
+; Set the speed for the Brain (Main Port)
+IF brainm ;[25]
+ lda baudrt ;Get the present baud rates.
+ ani 0fH ;turn off the left
+ mov d,a ;Set it aside.
+ mov a,e ;Get the new baud rate.
+ rlc ;Shift left 4 places.
+ rlc
+ rlc
+ rlc
+ ora d ; combine with the old baud rate
+ sta baudrt ;Store the new baud rates.
+ out baudst ;Set the baud rates.
+ ret
+ENDIF;brainm
+
+; Set the speed for the Brain (Aux Port)
+IF braina ;[25]
+ lda baudrt ;Get the present baud rates.
+ ani 0f0H ;turn off the right
+ ora e ; combine with the new baud rate
+ sta baudrt ;Store the new baud rates.
+ out baudst ;Set the baud rates.
+ ret
+ENDIF;braina
+
+If torch ; Set speed for Torch [14] [32]
+ mvi a,7 ; Osbyte call to set rx rate
+ mov l,e
+ call osbyte ;
+ mvi a,8 ; set up for tx rate to be set
+ mov l,e
+ call osbyte
+ ret ; and now, all rates should be different
+
+ENDIF ;torch [14] [32]
+
+IF ncrdmv ; Set baud rate for NCR Decision Mate V
+ mvi a,00 ; clear command register
+ out mncmdw
+ mvi a,4eh ; set for 1 stop, 8 data bits
+ out mnmodw ; save in mode 1 port
+ mvi a,70h ; set bits for rate etc..
+ add e ; add baud rate (bits 0 - 3)
+ out mnmodw ; set mode port 2
+ mvi a,27h ; set tx/rx ready, RTS CTS active
+ out mncmdw
+ ret
+ENDIF ; ncrdmv
+
+
+IF pci2651 ; Set baud for PCI [28]
+ in mncmd ; Clear register counter
+ mvi a,4eh ; set for 1 stop, 8 data bits
+ out mnmode ; save in mode 1 port
+ mvi a,30h ; set bits for rate etc..
+ add e ; add baud rate (bits 0 - 3)
+ out mnmode ; set mode port 2
+ mvi a,27h ; set tx/rx ready, RTS CTS active
+ out mncmd
+ ret
+ENDIF ;pci2651 [28]
+
+;
+; 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 brain OR pci2651 OR ncrdmv
+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;brain OR pci2651 OR ncrdmv
+
+IF torch ;[17]
+spdtbl: db 8 ; 8 entries
+ db 4,'1200$', 4,4
+ db 3,'150$', 2,2
+ db 5,'19200$', 8,8
+ db 4,'2400$', 5,5
+ db 3,'300$', 3,3
+ db 4,'4800$', 6,6
+ db 2,'75$', 1,1
+ db 4,'9600$', 7,7
+
+sphtbl: db cr,lf,' 75 150 300 1200 2400 4800 9600 19200$'
+ENDIF;torch [17]
+
+
+; 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 iobyt
+prtfun: db punout ;Function to use for output to comm port
+prtiob: db batio ;I/O byte to use for communicating
+coniob: db defio ;I/O byte to use for console
+ENDIF;iobyt
+
+IF NOT iobyt
+prttbl equ 0 ; SET PORT is not supported
+prhtbl equ 0
+ENDIF;NOT iobyt
+;
+;
+; 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 AND NOT ncrdmv
+ 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 AND NOT ncrdmv
+
+IF inout AND ncrdmv
+ in mnprts ;Get the output done flag
+ ani output ;Set ?
+ jz outmdm ;Loop until it is
+ mov a,e
+ out modtx ;output char
+ ret
+ENDIF;inout AND ncrdmv
+
+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 torch ; [32] [13] Torch stuff. Requires some bit bashing
+ ; via the BBC host computer (io computer)
+ ; see also decription of osbyte later on
+outdat:
+ lda prinuse ; get the printer in use flag
+ ana a ; if set, then must use traditional osbyte,
+ jnz outda2 ; else...
+ push b
+ push h ; Preserve registers [32]
+ call tx
+ db 1 ; MCP send to printer command
+ mov c,e ; Byte to send is in E [32]
+ call txbyte
+ pop h
+ pop b
+ ret
+
+outda2: ; Preserve registers [32]
+ push h
+ mvi a,138 ; Osbyte insert byte into buffer
+ mvi l,2
+ mov h,e ; get the byte to be sent s-l-o-w-l-y
+ call osbyte
+ pop h ; Restore registers and exit
+ ret
+
+ENDIF ;[13]
+
+;
+;
+; 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 AND NOT ncrdmv
+;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 AND NOT ncrdmv
+
+IF inout AND ncrdmv
+ in mnprts ;Get input port status
+ ani input ;Mask input RDY bit
+ rz ;return if no char
+ in modrx ;get the char
+ENDIF;inout AND ncrdmv
+IF torch ; [32] [13] torch input
+indat:
+ push h
+ mvi a,128
+ lxi h,0fffeh ; Read buffer status
+ call osbyte
+ mov a,h ; HL has number of characters
+ ora l ; in the buffer
+ jz indatq ; None, so skip fetch
+ mvi a,145 ; Get character from input buffer [32]
+ lxi h,1
+ call osbyte ; Result returned in 'Y', rather H
+ mov a,h
+indatq:
+ pop h
+ ani 7fh
+ ret ; rx data in A
+ENDIF ;torch [13] [32]
+
+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 torch
+ mvi a,80h ; read chars remaining in printer buffer
+ mvi l,252 ; do osbyte 80H, X=252 (printer buffer)
+ mvi h,0ffh
+ call osbyte
+ mov a,h
+ cpi 10 ; 10 characters left?
+ mvi a,0 ; if pos, yes r better
+ rp
+ mvi a,0ffh
+ ret
+ENDIF ;torch
+
+IF torch
+ mvi a,5 ; got to select the real printer (par. port)
+ mvi l,1 ; ie FX 5,1
+ call osbyte
+ENDIF ;torch
+
+IF iobyte ;[33]
+ call bprtst ; get status
+ENDIF ;iobyte[33]
+
+IF torch
+ push psw
+ mvi a,5 ; restore serial line = printer
+ mvi l,2 ; ie FX 5,2
+ call osbyte
+ pop psw ; return with code in a
+ENDIF ;torch
+
+
+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 torch ;[30] Must set printer routed to par port
+ mvi a,5 ; fx 5,1 (parallel port selected for printer)
+ mvi l,1 ; Modified for new osbyte form [32]
+ call osbyte
+ENDIF ;torch [30]
+
+IF NOT iobyt
+ mvi c,lstout
+ call bdos ;Char to printer
+ENDIF;NOT iobyt
+IF iobyt
+ mov c,e
+ call blsout
+ENDIF;iobyt
+IF torch ; re-route printer to serial port => faster tx bytes to line [30]
+ mvi a,5 ; Modified for new Osbyte form [32]
+ mvi l,2 ;fx 5,2
+ call osbyte
+ mvi a,6
+ mvi l,0 ;fx 6,0
+ call osbyte
+ENDIF ;torch [30]
+
+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 brain
+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
+ENDIF;brain
+;
+;
+IF torch
+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 0ffh ; NULL is column one
+ mov e,a
+ push h
+ call outcon ; output row
+ pop h
+ mov a,h ; [obs] get row
+ adi 0ffh ; NULL (ie decrement) is row one
+ mov e,a
+ jmp outcon ; output it and return
+ENDIF;torch
+;
+;
+; 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:
+
+
+IF NOT torch ;[22]
+ mvi e,bs ;get a backspace
+ jmp outcon
+ENDIF;NOT torch
+
+; 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 torch ;[13]
+;
+; OSBYTE call from Torch to BBC Base Processor.
+;
+; A register has osbyte type
+; H register has equivalent Y register of 6502
+; L register has equivalent X register of 6502
+;
+; Results (X and Y) are returned in HL respectively
+;
+;
+
+usrimm equ 0ffc0h ; MCP user function [32]
+tx equ 0ffc3h ; tx routine to talk to base board proc.
+rx equ 0ffc6h ; rx ditto
+txbyte equ 0ffc9h ; send C to base processor [32]
+
+osbyte: ; Osbyte rewritten [32]
+ push b ; Keep these
+ mov b,a ; Local copy - use in a moment
+ call usrimm ; MCP osbyte function
+ db 15
+ mov c,b ; Osbyte function
+ call txbyte
+ mov c,l ; 6502 X register
+ call txbyte
+ mov c,h ; 6502 Y register
+ call txbyte
+ call rx ; fetch results
+ mov l,a ; X returned
+ sta xx ; save just in case...
+ call rx
+ mov h,a ; Y returned
+ sta yy
+ mov a,b ; return A as called
+ pop b
+ ret
+
+xx: db 0
+yy: db 0 ; temporary space
+
+prinuse:db 0 ; 0=> fast tx, <>0 => slow tx to serial pt. [30]
+
+ENDIF ;torch [13]
+
+IF pci2651 ; whatever version
+sysver: db 'Ithaca Intersystems S100$'
+ENDIF ;pci2651
+
+IF ncrdmv ; whatever version
+sysver: db 'NCR DecisionMate V$'
+ENDIF ;ncrdmv
+
+IF torch ; whatever version
+ttytyp:
+sysver: db 'Torch Unicorn 5 '
+ db '$' ; stop here for now, otherwise say..
+ db ' MCP version '
+ db '1.00 $' ; or whatever...
+ENDIF ;torch
+
+; Assume MCP - CCCP ROMS greater than 1
+;mcpver: db 'x.x $'
+;outlin: db esc,'*',cr,lf,tab,'$'
+;eralin: db cr,esc,'&$' ;Clear to end of line.
+;erascr: db esc,'*$' ;Clear screen and go home.
+;curldn: db esc,'=$' ;Cursor lead-in
+;ttab: ;Table start location.
+;ta:
+ db esc,'!$',0 ;Cursor up.
+;tb: db 0ah,'$',0,0 ;Cursor down.
+;tc: db esc,'+$',0 ;Cursor right.
+;td: db 08h,'$',0,0 ;Cursor left.
+;te: db esc,'*$',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,'>$',0 ;Cursor home.
+;ti: db '$',0,0,0 ;(Can't) reverse linefeed
+;tj: db esc,'%$',0 ; Clear to end of screen
+;tk: db esc,'&$',0 ; Clear to end of line.
+
+
+;Older message for MCP - CCCP verstion less than 1
+;ooutli: db 0ch,cr,lf,tab,tab,'$';
+;oerali: db '$',0,0,0 ;Clear to end of line.
+;oerasc: db 0ch,'$',0 ;Clear screen and go home.
+;ocurld: db 1fh,'$',0 ;Cursor lead-in
+;ottab: ;Table start location.
+; db 0bh,'$',0,0 ;Cursor up.
+; db 0ah,'$',0,0 ;Cursor down.
+; db 09h,'$',0,0 ;Cursor right.
+; db 08h,'$',0,0 ;Cursor left.
+; db 0ch,'$',0,0 ;Clear screen and home cursor
+; db '$',0,0,0 ;(can't) Enter Graphics mode
+; db '$',0,0,0 ;(can't) Exit Graphics mode
+; db 1eh,'$',0,0 ;Cursor home.
+; db 0bh,'$',0,0 ;reverse linfeed
+; db '$',0,0,0 ;(Can't) Clear to end of screen
+; db '$',0,0,0 ;(Can't) Clear to end of line.
+;
+;Specials
+;spac15: db ' '
+; db bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,'$';
+;spac80: db cr
+; db ' '
+; db ' '
+; db bs,cr,'$' ;80 spaces, bs and then back to line start
+;
+
+IF torch ; Should be IF ker08 AND torch...
+ db '$' ; to terminate the ID string
+outlin: db 0ch,cr,lf,tab,tab,'$'
+eralin: db '$',0,0,0 ;Clear to end of line.
+erascr: db 0ch,'$',0 ;Clear screen and go home.
+curldn: db 1fh,'$',0 ;Cursor lead-in
+ttab: ;Table start location.
+ta: db 0bh,'$',0,0 ;Cursor up.
+tb: db 0ah,'$',0,0 ;Cursor down.
+tc: db 09h,'$',0,0 ;Cursor right.
+td: db 08h,'$',0,0 ;Cursor left.
+te: db 0ch,'$',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 1eh,'$',0,0 ;Cursor home.
+ti: db 0bh,'$',0,0 ;reverse linfeed
+tj: db '$',0,0,0 ;(Can't) Clear to end of screen
+tk: db '$',0,0,0 ;(Can't) Clear to end of line.
+
+;Specials
+spac15: db ' '
+ db bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,'$';
+spac80: db cr
+ db ' '
+ db ' '
+ db bs,cr,'$' ;80 spaces, bs and then back to line start
+
+ENDIF;ker08 AND torch [13]
+
+IF brain
+sysver: db 'Intertec SuperBrain$'
+outlin: db ('A'-100O),esc,'~k',cr,lf,tab,tab,'$'
+erascr: db ('A'-100O),esc,'~k$' ;Clear screen and go home.
+eralin: db cr,esc,'~K$' ;Clear line.
+curldn: db esc,'Y$' ; leadin for cursor positioning
+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 ('A'-100O),'$',0,0 ;Cursor home.
+ti: db ('K'-100O),'$',0,0 ;Reverse linefeed.
+tj: db esc,'~k$',0 ;Clear to end of screen.
+tk: db esc,'~K$',0 ;Clear to end of line.
+ENDIF;brain
+
+IF lasm and not termin ; we dont want CPXVDU
+ovlend equ $ ;Overlay end - start buffer
+ end
+ENDIF ;lasm and not termin
+
+IF lasm; we want a terminal
+LINK CPXVDU.ASM
+ENDIF ;lasm
+
diff --git a/src/cpxtyp.asm b/src/cpxtyp.asm
new file mode 100644
index 0000000..28b65b3
--- /dev/null
+++ b/src/cpxtyp.asm
@@ -0,0 +1,722 @@
+; CPXTYP.ASM
+; 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 is the header file for building the system-dependent overlay
+; for KERMIT. It contains the definitions used to select the target
+; system, and collects (via INCLUDE or LINK directives) the remaining
+; code. If the target system is one of the supported systems
+; described below, then this is the only file that needs to be
+; edited.
+;
+; revision history:
+;
+;edit 34, 10-Jan-1991 by MF. Put in "terminal required" notation for
+; more machines that need terminals.
+;edit 33, 9-Jan-1991 by MF. Put in "terminal required" notation for Access
+; Matrix and eliminated an extra "sysfam set FALSE" when torfam set TRUE
+;edit 32, 7-Jan-1991 by MF. Added code by Jay. S. Rouman to support the
+; Ampro Little Board (see CPXBBI.ASM).
+; Also put in a couple of missing .printx's
+;edit 31, 2-Nov-1990 by MF. Moved overlay address to 7000H.
+;edit 30, 14-Sep-1990 by MF. Added INCOMPLETE-FILE flag for SET
+; INCOMPLETE-FILE
+;edit 29, 11-Sep-1990 by MF. Moved overlay address for version 4.10.
+; to 6C00H.
+; edit 28, 1st September 1990 by Russell Lang, rjl@monu1.cc.monash.edu.au
+; Added support for MicroBee (CPXBEE.ASM).
+;
+; edit 27, 28-Aug-89 by Mike Freeman, Bonneville Power Administration,
+; P.O. Box 491, Vancouver WA 98666 USA: add support for Hewlett-
+; Packard HP-125 "Business Assistant" computer using a HP-modified
+ ;CP/M Version 2.2.
+;
+; edit 26, 2 December, by OBSchou. Added code for CP/M-80 Kermit to
+; run on an IBM-PC under Z80MU. Perverse?? No, its to allow testing
+; of independent code on a PC running CP/M kermit.
+;
+; edit 25, 27 October, 1987 by OBSchou. Merged in Sanyo, CompuPro, Genie
+; and TRS Model 4 code, and added four new families.
+; CPXSYO.ASM for the Sanyo, CPXPRO.ASM for the Compupro,
+; CPXTRS.ASM for the TRS-80 Model 4, CPXGNI.ASM for the Genie.
+; Many thanks to G. Smith for these latter two systems. Also
+; added the WYSE 100 Terminal type to the VDU table.
+;
+; edit 24, 17 July, 1987 by OBSchou. Added (hopefully) code from
+; CP/M Kermit 3.5 (WOW) for the Heath 8. (h8quad) The actual code
+; has been put into the CPXHEA.ASM family file, but I do not actually
+; *KNOW* if this new version works. Anyone willing to test it out??
+;
+; edit 23 16 July, 1987 for for Will Rose:
+; edit of 15 Jan 1987 by C W Rose
+; Added code for Micromint SB180 and Ampro 230 terminal.
+;
+; edit of 10 Apr 87 by C W Rose
+; Amended code for pci2651 to handle Telecom Merlin M2215.
+; (8085 at 5 MHz, 2651 USART, port TTY1:, Ampro 230 terminal equivalent).
+;
+; edit of 13 Jul 1987 by C W Rose
+; Added Micromint SB180 with 6/9 MHz. option.
+;
+; edit 22, 15th July, 1987 by OBSchou for David Moore.
+; David submitted a paper copy of Kermit 4.05 overlay for a Teletek
+; system: I have (hopefully) correctly appended his code. He also
+; send in the code for ADM 22 terminals.
+;
+; edit 21, 14 July, 1986 by OBSchou for John Shearwood of Birmingham
+; University. His edits:
+; edit of Apr 7th, 1987 by JA Shearwood. Added entry for Cifer Aux port
+; edit of Mar 24 1987 by JA Shearwood, Birmingham. Added code for Cifer
+; 1886 with CP/M Plus
+;
+; Also added in code from Chris Miles:
+; edit of 19 May 26, 1987 by C.J.MILES@UMRCC.
+; Kaypro II, Xerox 820 and Big Board II code seperated
+; from CPXSYS.ASM and put in a new family file called
+; CPXBBI.ASM.
+;
+; Finally added code from MJ Carter of Nottingham University:
+; edit 16a of 5th Mar 1987 by M J Carter, Nottingham Uni [majoc], to add
+; entry for OEM ScreenTyper (scntpr). See also CPXFRK.ASM ("fork"),
+; the tail end of CPXLNK.ASM, and the Heath-Zenith family file
+; CPXHEA.ASM (heath, z100, telcon, and scntpr).
+;
+; [Note: Martins CPXFRK is another version of CPXSWT.ASM]
+;
+;
+; edit 20, 21 May 1987 by OBSchou for Colin Burns of the Institute
+; of Neurological Sciences, Glasgow. Added flag for Hazeltine 1500
+; VDU (h1500)
+;
+; edit 19, 6th April, 1987 by OBSchou.
+; Added in EQUs for Amstrad 664 and 6128 machines (CPC) and NCR
+; Decsision mate V, bot sets of code submitted by Chris Miles of
+; Manchester University. NCR code is similar to the PCI2651 code, so
+; NCRDMV chains to CPXTOR.ASM. CPC cahins to the modified CPXPCW file
+; as submitted by Chris. *** NOTE *** All Amstrad versions require
+; CP/M 3, so the 664 version must both have the system upgraded to
+; CP/M 3 and have an aditional RAM pack. All Amstrad systems require
+; a serial interface.
+;
+; edit 18, 30 March, 1986. OBSchou.
+; * * * Here Begineth kermit-80 Version 4.09 * * *
+;
+; Biggest change is the overlay address has been moved (again) to 6000h
+; and the files have all been diced into families. M80 (almost) back
+; in, though I have found some bugs. Will worry about those later.
+; CPXSYS.ASM (CP4SYS.ASM in V4.05) now is a family file as well.
+;
+; Comments and all that would be much appreciated.
+;
+; Bertil Schou,
+; The Computer Centre,
+; Loughborough University of Technology,
+; Loughborough
+; Leicestershire, LE11 3TU
+; Great Britain
+;
+; tel (0509) 222313
+; E-Mail (Janet) OBSchou at LOUGHBOROUGH.MULTICS
+;
+;
+; edit 17, March 15, by OBSchou to add in support for M80 Macro Assembler.
+; Now its a little messy using the M80 Assembler,asn we have family files
+; and how are we gonna tell M80 what files to use?
+; Sort of Simple: we generate a set of EQUs that only INCLUDE the family
+; file being assembled. I hope.
+;
+; edit 16 Dec 1st, 1986 by OBSchou. Added entry for Amstrad PCW range (PCW)
+; Code in Family file CPXPCW.ASM, submitted by Ian Young of Lattice
+; Logic Systems.
+;
+; Edit 15 June 20 1986. Had to chand org address to 5000h to give room for
+; multi-fcb space for DIR command and other additions in the system
+; indepentent part. This starts Kermit-80 version 4.08...
+;
+; Edit 14: March 20, 1986 by OBSchou Loughborough University for
+; B Robertson, Aberdeen Univ. Computing Centre.
+; Add support for APPLE II with serial cards based on the 6850 ACIA.
+; Mod 380Z support to allow both MDS (5 1/4" discs) and FDS (8" discs)
+; configurations. Any mistakes on this merge all my fault (OBSchou)
+;
+; edit 13 22 April, 1986 by OBSchou Loughborough University
+; Changed org address to 4000h to allow for mods to the system
+; independent part for kermit version 4.06
+;
+; edit 12 5 Febuary, 1986 by OBSchou
+; merged in conditionals for Epson PX8 (px8). Code from Tony Addyman
+; Salford University, England.
+; Added code from other contibutors for Basic Northstar (basicns),
+; Access-Matrix (access), US Micro Sales s1008 (s1008),
+; Micro Mate (mmate), A.C.E. Discovery (disc).
+; These I cannot test: please send comments back if these are buggy.
+;
+; edit 11 29 January 1985 by OBSchou @ multics.lut.ac.uk
+; added in code for 2651 USART for use with CP/M and a VDU
+;
+; edit 10: 21 November, 1985 by ajcole @ leeds.ai
+; Merged in support for the following:
+; North Star Horizon without SIO-4 (horizon)
+; Comart Communicator (comart)
+; Cromemco TU-ART interface (cmemco)
+; TVI912/920 VDUs (tvi912)
+;
+; edit 9 24 October by OBSchou. Merged code from B Robertson from
+; Aberdeen University. He writes:
+; September 20, 1985 by B Robertson, Aberdeen Univ. Computing Centre.
+; Add support for Research Machines 380Z, North Star Advantage, Acorn
+; BBC with Z80 co-processor and APPLE II with Mountain Computers CPS
+; Multifunction card.
+;
+; edit 8: 11 October, 1985 by OBSchou
+; tidied up code around Superbrain main/aux port business
+;
+; edit 7: 11 June, 1985 by O B Schou, Loughborough University of Tech.
+; Loughborough, Leics, England.
+; Added code for Torch (Second processor to BBC-B) and Cifer 1886
+; Hopefully this code will work with Torchpacks, and Cifer 26xx
+; and 28xx series computers. Edits marked by OBS
+;
+; edit 6: 9-Feb-85 by CJC
+; Merge Northstar Horizon, Lobo MAX, and Xerox 820 changes:
+; 13-Dec-84 Add Northstar Horizon with SIO-4 board, port 5 at 1200 [CSM]
+; 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
+;
+;pcc001 27-Dec-84 vjc modules: cp4sys,cp4typ
+; Add conditional for Xerox 820. I thought at first I could
+; live with the kaypro conditional, but it's enough of a pain
+; that I added it back in. The clear-to-end-of-screen char
+; is different, breaking many programs in VT52 mode, and the
+; default escape char control-\, is not at all obvious how
+; to type on the 820 keyboard. If you muddle through the
+; key translation table, it turns out to be control-comma.
+; Rather than OR xer820 all the occurances of kpII conditionals
+; I added a bbI conditional for all common code for the big
+; board I based machines that is automatically turned on by
+; either kpII or xer820. This will also make it easier in
+; the future if another flavor of bigboard is added.
+;
+;pcc010 2-Jan-85 vjc modules:cp4pkt,cp4typ
+; Control-C during send or recieve clobbers some of the screen
+; and doesn't look nice. Position the cursor to end of screen
+; before returning to main loop.
+;
+;pcc013 8-Jan-85 vjc modules:cp4mit,cp4utl,cp4typ
+; Replace CLOSE command to cancel session logging to SET
+; LOGGING ON/OFF. This seems to fit in with the command
+; structure better. Default the log file to KERMIT.LOG
+; incase no previous LOG command. Logging is also enabled
+; by LOG command, as before.
+;
+; edit 5: October 13, 1984 by L M Jones, JCC, for New York Botanical Garden
+; Add support for CPT-85xx series of word processors when running CP/M.
+;
+; edit 4: August 29, 1984 by Bdale Garbee @ CMU
+; Add support for Digicomp Delphi 100 and Netronics Smartvid terminal.
+;
+; edit 3: July 27, 1984 (CJC)
+; Shuffle files around for easier assembly by both M80 and LASM.
+;
+; edit 2: June 4, 1984 [Toad Hall]
+; Added Morrow Decision I (the big S100 bus sucker, not the
+; little single motherboard one); added Toad Hall TACTrap to deal
+; with those working through a TAC and its intercept character.
+;
+; edit 1: May, 1984 (CJC)
+; extracted from CPMBASE.M80 version 3.9; modifications are described
+; in the accompanying .UPD file.
+;
+
+FALSE EQU 0
+TRUE EQU NOT FALSE
+
+;
+; Assembler type. Define the appropriate one TRUE, the rest FALSE. (We can't
+; use ASM, because it cannot handle multiple input files)
+mac80 EQU FALSE ; For assembly via MAC80 cross-assembler.
+m80 EQU FALSE ; For assembly via Microsoft's M80.
+lasm EQU TRUE ; For assembly via LASM, a public-domain
+ ; assembler.
+;
+; Address at which the overlay should be loaded. This will not
+; change often (no more than once per version of KERMIT); it should
+; be updated when a new version of KERMIT is released.
+;
+
+ovladr EQU 7000H ; [18] address = 6c00h for Kermit v4.10
+ ;[MF]...
+
+cpsker EQU FALSE ; building the system-dependent part...
+
+; SET some options to FALSE, then SET them TRUE if needed
+iobyt SET FALSE ;assume we dont want IOBYTE..
+inout SET FALSE ;... or IN/OUT code
+termin SET FALSE ; we are not using a terminal
+; Also set the CPU speed to a default 2.0 Mhz
+cpuspd SET 20 ; default to 2 Mhz, in case we dont know
+; Assume kit is Z80 based, and set z80 false for non z80 systems.
+;z80 SET TRUE
+
+;Which CP/M system hardware are we building KERMIT-80 for?
+;One of the following should be TRUE, the rest FALSE:
+;
+;We have basically three "classes" of systems:
+
+;Systems supporting the IO-redirection via I/O-Byte
+
+bbc EQU FALSE ;[9] Acorn BBC model B
+;added code by JAS
+cifer2 EQU FALSE ; Cifer 1886 using io byte flipping [OBS]
+cifer3 EQU FALSE ; Cifer 1886 with CP/M Plus [JAS]
+ ; (Not IOBYTE but easier to keep together)
+cifaux EQU FALSE ; One of above Cifers using AUX port else VL port
+dmII EQU FALSE ;"Generic" KERMIT-80 for DECMATE II.
+gener EQU FALSE ;"Generic" Kermit-80, CP/M calls only.
+ ; (terminal required)
+mikko EQU FALSE ;"Generic" KERMIT-80 for MikroMikko
+robin EQU FALSE ;DEC VT180 = Generic + VT100 screen control
+
+;.. \and Systems supporting direct IN / OUT handling of ports
+advant EQU FALSE ;[10] North Star Advantage
+access EQU FALSE ; Access Matrix .. uses port J5 [12]
+ ; (terminal required) [MF]
+ampro EQU FALSE ; Ampro Little Board (terminal required)
+basicns EQU FALSE ; Basic Northstar using printer port (CRT req.)
+bbII EQU FALSE ;BigBoard II (terminal required)
+brainm EQU FALSE ;Select Superbrain Main port **[obs]
+braina EQU FALSE ;Select Superbrain AUX port **[obs]
+comart EQU FALSE ;[10] Comart Communicator
+ ; (terminal required)
+compro EQU FALSE ;Compupro Interfacer 4 (or 3) [gv]
+ ; (terminal required) [MF]
+cpt85xx EQU FALSE ;CPT-85xx word processor w/CPM (set ADM3A TRUE)
+cmemco EQU FALSE ;[10] Cromemco (TU-ART) (terminal required)
+delphi EQU FALSE ;Digicomp Delphi 100 (terminal required)
+disc EQU FALSE ; Action Computer Enterprises "Discovery"
+ ; Port B on an 83U user board (CRT required)
+genie EQU FALSE ;Eaca Genie III
+h8quad EQU FALSE ;[24] Entry for heath-8. NOT same as H-89
+heath EQU FALSE ;For Heath/Zenith H89.
+kpII EQU FALSE ;Kaypro-II
+horizon EQU FALSE ;[10] North Star Horizon (mother-board)
+ ; (terminal required)
+m2215 EQU FALSE ; BT Merlin [23] - uses 2651, Terminal rqd
+mmate EQU FALSE ; PMC - 101 MicroMate (Crt required)
+mmdI EQU FALSE ;Morrow Micro Decision I (terminal required)
+mdI EQU FALSE ;Morrow Decision I (the big sucker)
+ ; (terminal required) [Toad Hall]
+ncrdmv EQU FALSE ; NCR Desision Mate V. (2651 USART) (Term rqd.)
+norths EQU FALSE ;[CSM] NorthStar Horizon with HSIO-4 board
+ ; (terminal required)
+pci2651 EQU FALSE ; CP/M with 2651 USART. Needs VDU. [11]
+rm380zm EQU FALSE ;[14] Research Machines 380Z MDS (5.25" discs)
+rm380zf EQU FALSE ;[14] Research Machines 380Z FDS (8" discs)
+s1008 EQU FALSE ; US Micro Sales s1008 (Terminal required)
+sb6 EQU FALSE ; SB180 6/9 MHz cpu speed conditionals -
+sb9 EQU FALSE ; set one of these to TRUE, - it will
+ ; automatically set sb180 TRUE
+ ; (terminal reqd for Sb-180 systems)
+scntpr EQU FALSE ; [majoc 870305] For OEM ScreenTyper
+sanyo EQU FALSE ;For sanyo mbc-1100 series
+telcon EQU FALSE ;For TELCON Zorba portable
+teletek EQU FALSE ; Teletek SYSTEMASTER (terminal rqd)
+trs80lb EQU FALSE ;For Lifeboat 2.25C CP/M Display
+trs80pt EQU FALSE ;For Pickles + Trout CP/M Display
+trsm4 EQU FALSE ;TRS80 Model 4 under Montezuma Micro CPM 2.2
+vector EQU FALSE ;For Vector Graphics.
+xer820 EQU FALSE ;[pcc001] Xerox 820
+z100 EQU FALSE ;For Z-100 under CP/M-85.
+
+;.. and Systems doing neither...
+apmmdm EQU FALSE ;jb Micromodem II in slot 2
+ap6551 EQU FALSE ;jb apple with 6551 ACIA in serial interface
+ap6850 EQU FALSE ;[14] Apple with 6850 ACIA in serial interface
+ ;[14] e.g PACT, SSM AIO, Aristocard
+apcps EQU FALSE ;[9] Apple with CP multifunction card
+cpc EQU FALSE ; Amstrad CPC CP/M Plus computers
+cpm3 EQU FALSE ;"Generic" Kermit-80 for CP/M 3.0 (CP/M Plus)
+ ; (terminal required)
+lobo EQU FALSE ;Lobo Max-80
+osi EQU FALSE ;For Ohio Scientific.
+osbrn1 EQU FALSE ;For Osborne 1
+pcw EQU FALSE ; Amstrad PCW 8256/8512 computers
+px8 EQU FALSE ;[12] For Epson PX-8
+torch EQU FALSE ;[obs] Torch does comms via Beeb as IO processor
+z80mu EQU FALSE ; CP/M-80 Kermit under z80mu emulator on PC
+hp125 EQU FALSE ;[MF]HP-125 Business Assistant, 8-bit data
+ ; path thru Data Comm 1, 7-bit data path
+ ; thru Data Comm 2 (requires 8th-bit quoting
+ ; for binary transfers on Data Comm 2)
+ ; set VT52 TRUE
+mbee EQU FALSE ; Microbee Systems - Microbee
+
+;.. and for Micros, like the MDI, which have "terminals of choice", you must
+;select one of these in addition to selecting the micro itself.
+;Also select a terminal for "gener" and "cpm3": use "crt" for the TRUE generic.
+crt EQU FALSE ;Basic CRT, no cursor positioning
+adm3a EQU FALSE ;Adm3a Display (or CPT built-in display)
+adm22 EQU FALSE ;ADM 22 terminal
+h1500 EQU FALSE ;Hazeltine 1500
+smrtvd EQU FALSE ;Netronics Smartvid terminal.
+soroq EQU FALSE ;Soroq IQ-120.. this a guess [OBS]
+am230 EQU FALSE ;Ampro 230 [13]
+tvi912 EQU FALSE ;[10] TVI912/920
+tvi925 EQU FALSE ;TVI925 Display
+ ; (works for Freedom 100 also) [Toad Hall]
+vt52 EQU FALSE ;VT52 or equivalent (or H19)
+vt100 EQU FALSE ;VT100 or equivalent
+wyse EQU FALSE ;Wyse 100 terminal
+;
+; Several systems are basically the same, with very slight variations,
+; so use common code. List these sysems below
+;
+cifer EQU cifer2 OR cifer3 ; DO NOT TOUCH THIS LINE
+brain EQU brainm OR braina ;For Intertec SuperBrain. **[obs]
+;
+; flag 380Z system if either selected
+;
+rm380z EQU rm380zm OR rm380zf ;[14]
+;
+trs80 EQU trs80lb OR trs80pt ; if either, flag TRS-80 system.
+bbI EQU kpII OR xer820 ;[pcc001] flag for bigboard I
+sb180 EQU sb6 OR sb9 ; Micromint SB180 (BYTE Oct 85)
+;
+; flag apple system if either selected
+;
+apple EQU apmmdm OR ap6551 OR ap6850 OR apcps
+;
+; also set termin(al) TRUE if any terminal selected (crt included)
+termin SET crt OR adm3a OR adm22 OR h1500 OR smrtvd OR am230
+termin SET termin OR tvi912 OR tvi925 OR vt52 OR vt100
+termin SET termin OR wyse OR soroq
+
+; Now set iobyt or inout TRUE for those systems doing so
+; IOBYTE systems...
+IF robin OR dmII OR gener OR mikko OR cifer2 OR bbc;[**obs]
+iobyt SET TRUE ;Short conditional for above
+ENDIF;robin OR dmII OR gener OR cifer2 OR bbc
+
+; INOUT systems...
+IF brain OR vector OR sanyo or compro
+inout SET TRUE ;Short conditional for above
+ENDIF;brain OR vector OR sanyo OR compro
+
+IF heath OR h8quad OR z100 OR trs80 OR telcon OR bbI
+inout SET TRUE ;Short conditional for above
+ENDIF;heath OR h8quad OR z100 OR trs80 OR telcon OR bbI
+
+IF bbII OR mmdI OR mdI OR delphi OR cpt85xx OR norths ;running out of room
+inout SET TRUE ;Short conditional for above
+ENDIF;bbII OR mmdI OR mdI OR delphi OR cpt85xx OR norths
+
+IF advant OR rm380z OR comart OR horizon OR cmemco ;[9] [10] more room here
+inout SET TRUE ;Short conditional for above
+ENDIF;advant OR rm380z OR comart OR horizon OR cmemco
+
+IF pci2651 OR m2215 OR sb180 OR ncrdmv OR teletek;[11] and even more room
+inout SET TRUE ;Short conditional for above
+ENDIF ;pci2651 OR m2215 OR sb180 OR ncrdmv OR teletek [11]
+
+IF access OR basicns OR s1008 OR mmate OR disc ; [12]
+inout SET TRUE ;Short conditional for above
+ENDIF ; access OR basicns OR s1008 OR mmate OR disc [12]
+
+IF genie OR trsm4 OR ampro
+inout SET TRUE ;Short conditional for above
+ENDIF ; genie OR trsm4 OR ampro
+
+
+; Toad Hall TAC Trap: If you're going through a TAC, it will
+; cough on its Intercept Character (usually a @ (* - 40H)). Sending it
+; twice forces the TAC to recognize it as a valid ASCII character,
+; and it'll send only one on to the host. If you've SET the TACTrap
+; to OFF, it will be a null character, and nothing will happen. If you
+; set it on, it will be your selected TAC intercept character (or will
+; default to the common intercept char, '@'.
+; If you never expect to have to work through such a beastie, just set
+; TAC to false and forget all this mess. [Toad Hall]
+
+tac EQU FALSE ; gonna work through a TAC?
+tacval EQU '@' ;Typical TAC intercept character
+
+; Processor speed in units of 100KHz
+; for bbII, kpII, cpt85xx, advance, apple,bbc,px8 & rm380z timing loop [12]
+; We have to set these before CPXCOM to make sure we update the CPU speed.
+
+; The following systems I have no idea of cpu speed. Can anyone oblige??
+; robin, dmII, mikko, vector, heath, h8quad, z100, scntpr
+; trs80 (both), telcon, mmdI, mdI, delphi, ncrdmv,
+; cromemco, teletek, osi, lobo
+
+IF z80mu
+cpuspd SET 2 ; a PC is about 200khz Z80 equivalent
+ENDIF; z80mu
+
+IF apple OR cpt85xx OR px8 OR heath OR h8quad ;[9] [12] What rate is heath?
+cpuspd SET 20 ; Apple Softcard, CPT-85xx: 2.0 MHz
+ ; ('cause of integral video?)
+ENDIF; apple OR cpt85xx OR px8 OR heath OR h8quad [12]
+
+IF kpII OR xer820 OR scntpr OR osbrn1 ;[9] What speed is scntpr??
+cpuspd SET 25 ; original Kaypro II,Xerox 820: 2.5 MHz
+ENDIF;kpII OR xer820 OR scntpr OR osbrn1
+
+IF PCW or CPC
+cpuspd SET 33 ; all 4MHz but insterted wait states
+ ; reduce to an effective 3.3 MHz.
+ENDIF ;pcw OR cpc
+
+IF brain OR advant OR bbII OR torch OR z100 OR genie OR trsm4
+cpuspd SET 40 ; 4.0 MHz CPU
+ENDIF; brain OR advant OR bbII OR torch OR z100 OR genie OR trsm4
+
+IF cifer OR rm380z OR comart OR horizon OR norths
+cpuspd SET 40 ; 4.0 MHz CPU
+ENDIF; cifer OR rm380z OR comart OR horizon OR norths
+
+IF disc OR mmate OR s1008 OR access OR basicns ;[29] This is a guess.. Most are 4Mhz
+cpuspd SET 40 ; 4.0 MHz CPU
+ENDIF ;disc OR mmate OR s1008 OR access OR basicns [29]
+
+IF m2215
+cpuspd SET 50 ; BT Merlin Rair Black Box is 8085 at 5 Mhz
+ENDIF ;m2215
+
+IF bbc or sb6
+cpuspd SET 60 ; BBC or SB-180 with 6Mhz Z80/61480
+ENDIF;bbc OR sb6
+
+IF sb9
+cpuspd SET 90 ; SB-180 with 9 Mhz clock
+ENDIF;sb9
+
+IF hp125 OR telcon
+cpuspd SET 40 ;[MF]HP125 or TELCON
+ENDIF;hp125 OR telcon
+
+IF mbee
+cpuspd SET 33 ; Microbee has 3.375MHz Z80
+ENDIF; mbee
+
+; Set Z80 flag FALSE for non Z80 or unknown CPU systems
+IF FALSE ; assume all systems are not z80 based
+;z80 SET FALSE
+ENDIF ;FALSE
+
+; Now, lets see what family we are assembling for. Reset all
+; family file to FALSE
+
+torfam SET FALSE ; not Torch family file
+ciffam SET FALSE ; not Cifer kit
+appfam SET FALSE ; not Apples
+norfam SET FALSE ; not North Star kit
+pcwfam SET FALSE ; not Amstrad PCW kit
+bbifam SET FALSE ; not the BBI family
+heafam SET FALSE ; not Heath, Z100, telcon,or screentyper
+sbfam SET FALSE ; not an SB180 system
+merfam SET FALSE ; not a BT Merlin system
+sanfam SET FALSE ; not a Sanyo
+comfam SET FALSE ; not a compupro
+genfam SET FALSE ; not a genie
+trsfam SET FALSE ; not a trs-80 Model 4
+z80fam SET FALSE ; not z80mu system
+beefam SET FALSE ; not a Microbee system
+sysfam SET TRUE ; ... but assume the worst, and its in
+ ; the CPXSYS.ASM file
+
+
+IF (torch OR pci2651 OR ncrdmv OR brain) ;[15]
+torfam SET TRUE ; we are to use the Torch family file
+.printx * torfam set TRUE *
+;(Yeah, I know, there are more than Torch systems in it)
+ENDIF ;(torch OR pci2651 OR ncrdmv OR brain) [15]
+
+IF (cifer)
+ciffam SET TRUE ; we are to use the cifer family file
+.printx * ciffam set TRUE *
+ENDIF ;cifer
+
+IF apple ;[15]
+appfam SET TRUE ; apples
+.printx * appfam set TRUE *
+ENDIF ;apple [15]
+
+IF (horizon OR basicns OR norths OR advant OR comart) ;[15]
+norfam SET TRUE ; north star kit
+.printx * norfam set TRUE *
+ENDIF ;(horizon OR basicns OR norths OR advant OR comart) [15]
+
+IF (pcw OR cpc) ;[15]
+pcwfam SET TRUE ; Amstrad PCW kit
+.printx * pcwfam set TRUE *
+ENDIF ;pcw OR cpc [15]
+
+IF (kpII OR xer820 OR bbII OR ampro)
+bbifam SET TRUE ; The Bigboard, Kaypro, Xerox and Ampro family
+.printx * bbifam set TRUE *
+ENDIF ;(kpII or xer820 OR bbII OR ampro)
+
+IF (heath OR h8quad OR telcon OR z100 OR scntpr)
+heafam SET TRUE ; Doing Heath, z100, telcon, or screentyper
+.printx * heafam set TRUE *
+ENDIF ;(heath OR h8quad OR telcon OR z100 OR scntpr)
+
+IF sb180
+sbfam SET TRUE ; doing an SB180 system
+.printx * sbfam set TRUE *
+ENDIF ; sb180
+
+IF m2215
+merfam SET TRUE ; doing a BT Merlin system
+.printx * merfam set TRUE *
+ENDIF ; m2215
+
+IF sanyo
+sanfam SET TRUE ; doing a Sanyo MBC-1100 system
+.printx * sanfam set TRUE *
+ENDIF ; sanyo
+
+IF compro
+comfam SET TRUE ; doing a Compupro system
+.printx * comfam set TRUE *
+ENDIF ; compro
+
+IF genie
+genfam SET TRUE ; doing a Genie system
+.printx * genfam set TRUE *
+ENDIF ; genie
+
+IF trsm4
+trsfam SET TRUE ; doing a TRS-80 M4 system
+.printx * trsfam set TRUE *
+ENDIF ; trs4m
+
+IF z80mu
+z80fam SET TRUE ; doing a z80mu emulation
+.printx * z80fam set TRUE *
+ENDIF ; z80mu
+
+IF mbee
+beefam SET TRUE ; doing a Microbee system
+.printx * beefam set TRUE *
+ENDIF ; mbee
+
+; Now, if none of the above, then its the older CPXSYS.ASM file we want
+
+IF (torfam OR ciffam OR appfam OR norfam OR sanfam OR comfam) AND sysfam
+sysfam SET FALSE ; Were not doing the CPXSYS.ASM file
+.printx * sysfam set FALSE *
+ENDIF ; (torfam OR ciffam OR appfam OR norfam OR sanfam OR comfam) AND sysfam
+
+IF (pcwfam OR bbifam OR heafam OR sbfam OR merfam) AND sysfam
+sysfam SET FALSE ; Were not doing the CPXSYS.ASM file
+.printx * sysfam set FALSE *
+ENDIF ; (pcwfam OR bbifam OR heafam OR sbfam OR merfam) AND sysfam
+
+IF (genfam OR trsfam OR z80fam OR beefam) AND sysfam
+sysfam SET FALSE ; Were not doing the CPXSYS.ASM file
+.printx * sysfam set FALSE *
+ENDIF ; (genfam OR trsfam OR z80fam OR mbeefam) AND sysfam
+
+IF sysfam
+.printx * sysfam set TRUE *
+ENDIF
+
+IF lasm
+ LINK CPSDEF ; Use the system independent declares
+ENDIF;lasm [Toad Hall]
+
+; If we're still here, must be M80 or MAC80. Collect the rest of
+; the sources.
+.sfcond
+
+
+ INCLUDE CPSDEF.ASM ; common definitions
+ INCLUDE CPXLNK.ASM ; linkage area description
+ INCLUDE CPXCOM.ASM ; include common code
+ INCLUDE CPXSWT.ASM ; this wont do much, but will announce machine
+
+IF torfam ;[15]
+ INCLUDE CPXTOR.ASM ; we are assembling for Torch, Cifer etc
+ENDIF ;torfam [15]
+
+IF ciffam
+ INCLUDE CPXCIF.ASM ; we are assembling for a Cifer
+ENDIF ;ciffam
+
+IF appfam ;[15]
+ INCLUDE CPXAPP.ASM ; we are assembling for an apple
+ENDIF ;appfam [15]
+
+IF norfam ;[15]
+ INCLUDE CPXNOR.ASM ; we are assembling a NortStar machine
+ENDIF ;norfam [15]
+
+IF pcwfam ;[15]
+ INCLUDE CPXPCW.ASM ; we are assembling for the Amstrad PCW machine
+ENDIF ;pcwfam [15]
+
+IF bbifam
+ INCLUDE CPXBBI.ASM ; assembling for BigBoard, Kaypro, Xerox
+ ; & Ampro Little Board
+ENDIF ;bbifam
+
+IF sysfam ;[15]
+ INCLUDE CPXSYS.ASM ; system-dependent code and tables (Part 1)
+ INCLUDE CPXSY2.ASM ; system-dependent code and tables (Part 2)
+ENDIF ;sysfam [15]
+
+IF heafam
+ INCLUDE CPXHEA.ASM
+ENDIF ;heafam
+
+IF m2215
+ INCLUDE CPXMRL.ASM
+ENDIF ;m2215
+
+IF sbfam
+ INCLUDE CPXSB.ASM
+ENDIF ;sbfam
+
+IF sanfam
+ INCLUDE CPXSYO.ASM
+ENDIF ;sanfam
+
+IF comfam
+ INCLUDE CPXPRO.ASM
+ENDIF ;comfam
+
+IF genfam
+ INCLUDE CPXGNI.ASM
+ENDIF ;genfam
+
+IF trsfam
+ INCLUDE CPXTM4.ASM
+ENDIF ;trsfam
+
+IF z80fam
+ INCLUDE CPXZ80.ASM
+ENDIF ;z80fam
+
+IF beefam
+ INCLUDE CPXBEE.ASM
+ENDIF ;beefam
+
+IF termin ; any terminal selected?
+ INCLUDE CPXVDU.ASM ;[15] Just in case we need a VDU...
+ENDIF ;termin
+ END
diff --git a/src/cpxvdu.asm b/src/cpxvdu.asm
new file mode 100644
index 0000000..332fd8f
--- /dev/null
+++ b/src/cpxvdu.asm
@@ -0,0 +1,462 @@
+IF NOT lasm
+.printx * CPXVDU.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
+; 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.
+;
+;edit 6, 12-Oct-1990 by MF. Added a semicolon to the comment "If we
+; need cursor ..." so it isn't seen as an undefined symbol
+; edit 5, 20 July by OBSchou. Put in the cursor positioning code for
+; all the terminal supported, and moved the vtval EQUs and defesc EQUs
+; here if the system requires andn external terminal. If the system
+; has a 'built in' terminal (ie own scrteen driver) you will not come
+; to this file, so you must declare these three lables etc in your
+; own code.
+; This will allow only those systems requiring a terminal to require
+; CPXVDU.ASM during assembly.
+;
+; edit 4, 16 July, 1987 by OBSchou for will Rose.
+; Added code for Ampro 230 terminal
+;
+; edit 3, 15 July, 1987 by OBSchou for David Moore. Added adm22 terminal
+; codes.
+;
+; edit 2 21 May, 1987 by OBSchou. Added in definitions for Hazeltine 1500
+; submitted by Colin Burns of the Institute of Neurological Sciences
+; in Glasgow.
+; edit 1 ??? date. Split the terminal codes off from the CPXSYS.ASM file
+;
+vduver: db 'CPXVDU.ASM (6) 12-Oct-1990 $' ;file, edit version,, date.
+
+
+; First, print out what terminal (if any) we are assembling for
+
+IF crt
+.printx * generic CRT selected *
+ENDIF
+
+IF adm3a
+.printx * ADM3A selected *
+ENDIF
+
+IF adm22
+.printx * ADM22 selected *
+ENDIF
+
+IF smrtvd ;[7]
+.printx * Netronics Smartvid-80 selected *
+ENDIF ;[7]
+
+IF tvi912
+.printx * TVI912/920 selected *
+ENDIF
+
+IF tvi925
+.printx * TVI925 selected *
+ENDIF
+
+IF vt52
+.printx * VT52 selected *
+ENDIF
+
+IF vt100
+.printx * VT100 selected *
+ENDIF
+
+IF am230
+.printx * Ampro 230 terminal selected *
+ENDIF
+
+IF wyse
+.printx * Wyse 100 terminal selected *
+ENDIF
+;
+
+;
+; If we need cursor positioning, here is the code to do it
+;
+; 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 NOT (vt100 OR crt OR h1500)
+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
+ENDIF;NOT (vt100 OR crt OR h1500)
+;
+;
+;
+;
+; csrpos for ANSI terminals
+;
+IF vt100
+csrpos: push b ; save coordinates
+ lxi d,curldn ; get cursor leadin sequence
+ call prtstr ; print it
+ pop h ; peek at coordinates
+ push h ; then save away again
+ mov l,h ; l = row
+ mvi h,0 ; hl = row
+ call nout ; output in decimal
+ mvi e,';' ; follow with semicolon
+ call outcon ; print it
+ pop h ; restore column
+ mvi h,0 ; hl = column
+ call nout
+ mvi e,'H' ; terminate with 'move cursor' command
+ jmp outcon ; output it and return
+ENDIF;vt100
+
+;Definition for Hazeltine 1500 does things a little strange.
+;
+IF h1500
+csrpos: push b ; save coordinates
+ lxi d,curldn ; get cursor leadin sequence
+ call prtstr ; print it
+ pop h ; restore coordinates
+ mov a,l ; get col
+ nop
+ nop
+; adi (' '-1) ; space is row one
+ mov e,a
+ push h
+ call outcon ; output row
+ pop h
+ mov a,h ; get row
+ adi (' '-1) ; space is column one
+ mov e,a
+ jmp outcon ; output it and return
+ENDIF; h1500
+
+
+IF crt ; systems without cursor positioning
+csrpos: ret ; dummy routine referenced by linkage section
+ENDIF;crt
+;
+;
+;
+; Now for the rest of CPXVDU.ASM
+;
+;
+;
+IF crt ;Set flags etc for systems with CRT selected
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+vtval EQU 0FFH ; we can't support VT52 emulation
+ttytyp: db 'Generic (Dumb) CRT Terminal type selected $'
+ENDIF;crt
+
+;
+
+IF vt52 ; DEC VT52
+ttytyp: db 'VT52$'
+ENDIF;vt52
+
+IF vt52
+vtval EQU 0 ; we don't need VT52 emulation
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+outlin: db esc,'H',esc,'J',cr,lf,tab,tab,'$'
+erascr: db esc,'H',esc,'J$' ;Clear screen and go home.
+eralin: db cr,esc,'K$' ;Clear line.
+curldn: db esc,'Y$' ;cursor leadin
+ttab: ;Table start location.
+ta: db esc,'A$',0 ;Cursor up.
+tb: db esc,'B$',0 ;Cursor down.
+tc: db esc,'C$',0 ;Cursor right.
+td: db esc,'D$',0 ;Cursor left
+te: db esc,'E$',0 ;Clear display
+tf: db esc,'F$',0 ;Enter Graphics Mode
+tg: db esc,'G$',0 ;Exit Graphics mode
+th: db esc,'H$',0 ;Cursor home.
+ti: db esc,'I$',0 ;Reverse linefeed.
+tj: db esc,'J$',0 ;Clear to end of screen.
+tk: db esc,'K$',0 ;Clear to end of line.
+ENDIF;vt52
+;
+
+IF adm22
+vtval EQU 1 ; we can do VT52 emulation
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+ttytyp: db 'ADM22$'
+outlin: db 1ah,cr,lf,tab,tab,'$'
+erascr: db 1ah,'$' ;Clear screen and go home.
+eralin: db esc,'>$' ;Clear line.
+curldn: db esc,'=$' ;Cursor lead-in
+ttab: ;Table start location.
+ta: db 0BH,'$',0,0 ;Cursor up.
+tb: db lf,'$',0,0 ;Cursor down.
+tc: db 0CH,'$',0,0 ;Cursor right.
+td: db bs,'$',0,0 ;Cursor left
+te: db 1ah,':$',0 ;Clear display
+tf: db '$',0,0,0 ;(can't) Enter Graphics Mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home.
+ti: db 0BH,'$',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;adm22
+;
+
+IF am230
+; Select initial setting for VT-52 emulation flag.
+vtval EQU 1
+defesc EQU '\'-100O ;The default is Control-\ -- it's easier
+ttytyp: db 'Am230$'
+outlin: db 'Z'-64,0,0,cr,lf,'$'
+erascr: db 'Z'-64,0,0,'$' ;Clear screen and home
+eralin: db esc,'R$',0 ;Erase line
+curldn: db cr,esc,'=$' ;Cursor lead-in
+ttab: ;Table start location ;(MUST be 4 bytes each)
+ta: db 'K'-64,'$',0,0 ;Cursor up, stop at top
+tb: db 'V'-64,'$',0,0 ;Cursor down, stop at bottom
+tc: db 'L'-64,'$',0,0 ;Cursor right, stop at right
+td: db 'H'-64,'$',0,0 ;Cursor left, stop at left
+te: db 'Z'-64,0,0,'$' ;Clear display (2 pad nulls)
+tf: db '$',0,0,0 ;(can't) Enter Graphics mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home
+ti: db esc,'j$',0 ;Reverse linefeed, scroll
+tj: db esc,'Y$',0 ;Clear to end of sreen
+tk: db esc,'T$',0 ;Clear to end of line
+ENDIF
+;
+;
+
+
+IF vt100
+ttytyp: db 'VT100$'
+ENDIF;vt100
+
+
+IF vt100
+; Note that we cannot support Graphics Mode or the H19 erase-screen command
+; (<esc>E), because the sequences are more than three bytes.
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+vtval EQU 0 ; we probably don't want VT52 emulation
+outlin: db esc,3CH,esc,'[H',esc,'[J',cr,lf,tab,tab,'$'
+erascr: db esc,'[H',esc,'[J$' ;Clear screen and go home.
+eralin: db cr,esc,'[K$' ;Clear line.
+curldn: db esc,'[$' ; Cursor leadin
+ttab:
+ta: db esc,'[A$' ; Cursor up.
+tb: db esc,'[B$' ; Cursor down.
+tc: db esc,'[C$' ; Cursor right.
+td: db esc,'[D$' ; Cursor left
+te: db '$',0,0,0 ; (can't) Clear display
+tf: db '$',0,0,0 ; (don't) Enter Graphics Mode
+tg: db '$',0,0,0 ; (don't) Exit Graphics mode
+th: db esc,'[H$' ; Cursor home.
+ti: db esc,'M$',0 ; Reverse linefeed.
+tj: db esc,'[J$' ; Clear to end of screen.
+tk: db esc,'[K$' ; Clear to end of line.
+ENDIF;vt100
+;
+
+IF gener or cpm3
+sysver: db 'Generic CP/M-80$'
+ENDIF;gener or cpm3
+
+
+IF soroq ;[29] Should this not be with terminals.....
+ttytyp: db 'Soroc IQ-120$'
+outlin: db 1EH,esc,'Y',cr,lf,tab,tab,'$'
+erascr: db 1EH,esc,'Y$' ;clear screen and home cursor
+eralin: db cr,esc,'T$' ;clear line
+curldn: db esc,'=$' ;cursor lead-in string
+delstr: db bs,' ',bs,bs,'$' ;??adjust for echoing delete
+ttab: ;table start location
+ta: db 0BH,'$',0 ;cursor up
+tb: db 0AH,'$',0 ;cursor down
+tc: db 0CH,'$',0 ;cursor right
+td: db 08H,'$',0 ;cursor left
+te: db esc,'*$',0 ;clear display (homes cursor)
+tf: db esc,')$',0 ;enter inverse video mode
+tg: db esc,'($',0 ;exit inverse video mode
+th: db 01EH,'$',0 ;home cursor
+ti: db 0BH,'$',0 ;reverse linefeed (insert line)
+tj: db esc,'Y$',0 ;clear to end of screen
+tk: db esc,'T$',0 ;clear to end of line
+ENDIF;soroq
+
+IF crt
+outlin: db cr,lf,'Starting ...$'
+erascr equ crlf ;"Home & clear" (best we can do).
+eralin: db '^U',cr,lf,'$' ;Clear line.
+prpack: db cr,lf,'RPack: $'
+pspack: db cr,lf,'SPack: $'
+ttab equ 0 ; no VT52 table
+ENDIF;crt
+;
+
+IF tvi912
+vtval EQU 1 ; we do emulation
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+ttytyp: db 'TVI912/920$'
+outlin: db 'Z'-64,0,0,cr,lf,'$'
+erascr: db 'Z'-64,0,0,'$' ;Clear screen and home
+eralin: db esc,'Y$',0 ;Clear to end of sreen
+curldn: db cr,esc,'=$' ;Cursor lead-in
+ttab: ;Table start location ;(MUST be 4 bytes each)
+ta: db 'K'-64,'$',0,0 ;Cursor up, stop at top
+tb: db 'J'-64,'$',0,0 ;Cursor down, stop at bottom
+tc: db 'L'-64,'$',0,0 ;Cursor right, stop at right
+td: db 'H'-64,'$',0,0 ;Cursor left, stop at left
+te: db 'Z'-64,0,0,'$' ;Clear display (2 pad nulls)
+tf: db '$',0,0,0 ;(can't) Enter Graphics mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home
+ti: db esc,'j$',0 ;Reverse linefeed, scroll
+tj: db esc,'Y$',0 ;Clear to end of sreen
+tk: db esc,'T$',0 ;Clear to end of line
+ENDIF;tvi912
+;
+;
+
+IF tvi925
+;(incidentally, works fine for Freedom 100 also [Toad Hall])
+;adm3a entry and tvi925 entry separated to remove warning message.
+vtval EQU 1 ; we VT52 emulation
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+ttytyp: db 'TVI925$'
+outlin: db 'Z'-64,0,0,cr,lf,'$'
+erascr: db 'Z'-64,0,0,'$' ;Clear screen and home
+eralin: db esc,'Y$',0 ;Clear to end of sreen
+curldn: db cr,esc,'=$' ;Cursor lead-in
+ttab: ;Table start location ;(MUST be 4 bytes each)
+ta: db 'K'-64,'$',0,0 ;Cursor up, stop at top
+tb: db 'V'-64,'$',0,0 ;Cursor down, stop at bottom
+tc: db 'L'-64,'$',0,0 ;Cursor right, stop at right
+td: db 'H'-64,'$',0,0 ;Cursor left, stop at left
+te: db 'Z'-64,0,0,'$' ;Clear display (2 pad nulls)
+tf: db '$',0,0,0 ;(can't) Enter Graphics mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home
+ti: db esc,'j$',0 ;Reverse linefeed, scroll
+tj: db esc,'Y$',0 ;Clear to end of sreen
+tk: db esc,'T$',0 ;Clear to end of line
+ENDIF;tvi925
+;
+;
+
+IF adm3a
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+ttytyp: db 'ADM3A$'
+outlin: db 'Z'-64,0,0,cr,lf,'$'
+erascr: db 'Z'-64,0,0,'$' ;Clear screen and home
+eralin: db esc,'Y$',0 ;Clear to end of sreen
+curldn: db cr,esc,'=$' ;Cursor lead-in
+ttab: ;Table start location ;(MUST be 4 bytes each)
+ta: db 'K'-64,'$',0,0 ;Cursor up, stop at top
+tb: db 'J'-64,'$',0,0 ;Cursor down CTRL-J
+tc: db 'L'-64,'$',0,0 ;Cursor right, stop at right
+td: db 'H'-64,'$',0,0 ;Cursor left, stop at left
+te: db 'Z'-64,0,0,'$' ;Clear display (2 pad nulls)
+tf: db '$',0,0,0 ;(can't) Enter Graphics mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 1EH,'$',0,0 ;Cursor home
+ti: db 'K'-64,'$',0,0 ;Reverse linefeed
+tj: db '$',0,0,0 ;(can't) Clear to end of screen
+tk: db '$',0,0,0 ;(can't) Clear to end of line
+ENDIF;adm3a
+
+
+IF smrtvd ; [7] new terminal
+vtval EQU 1 ; we do VT52 emulation
+defesc EQU '\'-100O ; escpae character, ok?
+ttytyp: db 'Smartvid-80$'
+outlin: db esc,'+',cr,lf,tab,tab,'$'
+eralin: db cr,esc,'T$' ;Clear to end of line.
+erascr: db esc,'+$' ;Clear screen and go home.
+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 ('A'-100O),'$',0,0 ;Cursor right.
+td: db ('H'-100O),'$',0,0 ;Cursor left.
+te: db ('L'-100O),'$',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 ('Z'-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;smrtvd
+
+IF h1500
+vtval EQU 1 ; we can do VT52 emulation
+defesc EQU '\'-100O ;Still Control-\ (just ran out of room...)
+ttytyp: db 'Hazeltine$'
+outlin: db 7eh,1ch,7eh,12h,'$'
+erascr: db 7eh,1ch,7eh,12h,'$' ;Clear screen and home
+eralin: db 7eh,13h,'$',0 ;Clear to end of sreen
+curldn: db 7eh,11h,'$',0 ;Cursor lead-in
+ttab: ;Table start location ;(MUST be 4 bytes each)
+ta: db 7eh,0ch,'$',0 ;Cursor up, stop at top
+tb: db 7eh,0bh,'$',0 ;Cursor down CTRL-J
+tc: db 10h,'$',0,0 ;Cursor right, stop at right
+td: db 8h,'$',0,0 ;Cursor left, stop at left
+te: db 7eh,1ch,'$',0 ;Clear display (2 pad nulls)
+tf: db '$',0,0,0 ;(can't) Enter Graphics mode
+tg: db '$',0,0,0 ;(can't) Exit Graphics mode
+th: db 7eh,0ch,'$',0 ;Cursor home
+ti: db 7eh,0ch,'$',0 ;Reverse linefeed
+tj: db '$',0,0,0 ;(can't) Clear to end of screen
+tk: db 7eh,0fh,'$',0 ;Clear to end of line
+ENDIF;h1500
+
+IF wyse ;[gv]
+vtval equ 1 ; we can do VT52 emulation
+defesc EQU '\' ;Still Control-\ (just ran out of room...)
+ttytyp: db ' [Wyse 100]',cr,lf,'$'
+outlin: db esc,'+$',0 ;Clear screen and home
+erascr: db esc,'+$',0 ;Clear screen and home
+eralin: db esc,'Y$',0 ;Clear to end of sreen
+curldn: db cr,esc,'=$' ;Cursor lead-in
+ttab: ;Table start location ;(MUST be 4 bytes each)
+ta: db 03h,'$',0,0 ;Cursor up, stop at top
+tb: db lf,'$',0,0 ;Cursor down, stop at bottom
+tc: db ff,'$',0,0 ;Cursor right, stop at right
+td: db bs,'$',0,0 ;Cursor left, stop at left
+te: db sub,0,0,'$' ;Clear display (2 pad nulls)
+tf: db '$',0,0,0 ;Enter Graphics mode NONE
+tg: db '$',0,0,0 ;Exit Graphics mode NONE
+th: db 1eh,'$',0,0 ;Cursor home
+ti: db esc,'v$',0 ;Reverse linefeed, scroll ???
+tj: db esc,'Y$',0 ;Clear to end of sreen
+tk: db esc,'T$',0 ;Clear to end of line
+ENDIF;wyse
+
+
+
+ovlend equ $ ; End of overlay
+
+IF lasm ;Not really needed, as M80 ignores END in include files
+ END
+ENDIF ;lasm
diff --git a/src/cpxz80.asm b/src/cpxz80.asm
new file mode 100644
index 0000000..82a5692
--- /dev/null
+++ b/src/cpxz80.asm
@@ -0,0 +1,350 @@
+IF NOT LASM
+.printx * CPXZ80.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-80 emulated on an IBM PC or clone running Z80MU.
+;
+; revision history (last edit first)
+;
+; edit 1, 2 December, 1987. Built code for Z80MU emulation. Uses BIOS
+; calls to 0FF12-15 to read/write from/to the PC COM1 port.
+;
+
+.printx * Assembling for Z80MU system *
+
+;
+; 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 CP4SYS.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 'CPXZ80.ASM (1) 2-Dec-87$' ; Used for family versions....
+
+
+
+sysxin: ; continuation of system dependent initialisation code
+ 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
+
+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:
+ ret
+
+;
+; 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...
+ jmp rskp ; take skip return - command not recognized.
+
+
+;
+;
+; 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:
+ 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:
+ ret
+;
+;
+; 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]
+spdtbl EQU 0 ;[hh] SET BAUD not supported.
+sphtbl EQU 0 ;[hh] ran out of room above...
+;
+;
+; This is the system-dependent SET PORT command.
+; HL contains the argument from the command table.
+sysprt:
+ ret
+
+prttbl equ 0 ; SET PORT not supported
+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:
+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:
+ mov c,e ;Console output via BIOS
+ jmp bcnout
+;
+
+;
+; outmdm - output a char from E to the modem.
+; the parity bit has been set as necessary.
+; returns nonskip; bc, de, hl preserved.
+outmdm:
+ mov c,e ; get char to c
+ call 0ff12h ; send to com1 via PC BIOS
+ 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:
+;Note: modem port should already be selected for mdI. [Toad Hall]
+ call 0ff15h ;Get the port status into A.
+ ana a ;See if the is non-null.
+ ret ; return with character or NULL 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 ; 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
+ ret
+
+;
+; 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 ;get a backspace
+ jmp 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
+
+
+sysver: db 'Z80MU on IBM PC $'
+IF lasm
+LINK CPXVDU.ASM
+ENDIF ;lasm - m80 will INCLUDE CPXVDU.ASM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+