home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / cpm86 / c86ker.src < prev    next >
Text File  |  2020-01-01  |  279KB  |  10,129 lines

  1. <<< c86cmd.a86 >>>
  2. ; * * * * * * * * * * * * * * *  version 2.8  * * * * * * * * * * * * * * *
  3. ; [32c] remove check for 0-length filename
  4. ; [32b] fix minor bugs
  5. ; [32a]    fix prompt to show default drive and user
  6. ;    RonB, 09/13/84
  7. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  8. ; [fdc]    Fix small glitch w/CMLEVL that issued msg spuriously sometimes.
  9. ; []    Introduced CMLEVL flag to intercept "empty" command-options
  10. ;    Reset by PRSERR, SET in 86KERMIT KERMIT:
  11. ;        B.E.; EIBEN at DEC-MARLBORO 2-May-84
  12. ; [30c] Isolate ANSI escape sequences for machine independence.
  13. ; [30b] Make DEL work like BS and ^X like ^U in command input.
  14. ;    RonB, 04/18/84
  15. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  16. ; [28d] Improve filename special character processing
  17. ;    RonB, 03/27/84
  18. ; [25]    Move logic for "seteol" and "escape" (from KERSYS) into here so those 
  19. ;    routines need not use internal CMD routines and variables.  For this 
  20. ;    purpose add 2 parse routines and codes: "cmcha" and "cmnum".  The point
  21. ;    of this is to keep calls to CMD modular since I want to eventually
  22. ;    replace the whole thing.
  23. ;    R. Garland    9-Mar-1984
  24. ; * * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * * *
  25. ;  [9]    Fix filename parsing, and add wildcard ability.
  26. ;    RonB,12/26/83
  27. ;  [8]    Show choices for ambiguous keywords, finish keyword on '?'
  28. ;    RonB,12/26/83
  29. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  30. ; This module contains all the routines and storage necessary for the
  31. ; command parser.  The command parser approximates that of the Tops-20
  32. ; COMND% JSYS.  This code is adapted from the IBM PC Kermit code which
  33. ; was adapted from the CP/M-80 Kermit code.
  34. ; COMND definitions.
  35.  
  36. cmcfm    equ    01H
  37. cmkey    equ    02H
  38. cmifi    equ    03H
  39. cmofi    equ    04H
  40. cmtxt    equ    05H
  41. cmcha    equ    06H
  42. cmnum    equ    07H
  43.  
  44.     DSEG $            ; Resume the data segment.
  45.  
  46. ; COMND storage.
  47.  
  48. cmer00    db    bell,'?Program error -- Invalid COMND call$'
  49. cmer01    db    bell,'?Ambiguous command$'
  50. cmer02    db    bell,'?Illegal input file spec$'
  51. cmer03    db    bell,'?Unrecognized instruction$'
  52. cmer04    db    bell,'?Invalid command or operand$'
  53. cmer05    db    bell,'?Missing command-option$'
  54. cmin00    db    ' Confirm with carriage return$'
  55. cmin01  db      ' Input file spec (possibly wild) $'
  56. cmin02    db    ' One of the following:$'            ;[8]
  57.  
  58. cmlevl    db    0        ;0 at main-level, 1 otherwise
  59. cmstat    db    0        ;What is presently being parsed.
  60. cmaflg    db    0        ;Non-zero when an action char has been found.
  61. cmccnt    db    0        ;Non-zero if a significant char is found.
  62. cmsflg    db    0        ;Non-zero when the last char was a space.
  63. cmostp    dw    0        ;Old stack pointer for reparse.
  64. cmrprs    dw    0        ;Address to go to on reparse.
  65. cmprmp    dw    0        ;Address of prompt.
  66. cmptab    dw    0        ;Address of present keyword table.
  67. cmhlp    dw    0        ;Address of present help.
  68. cmdbuf    rb    80H        ;Buffer for command parsing.
  69. cmfcb    dw    0        ;Pointer to FCB.
  70. cmfcb2    dw    0        ;Pointer to position in FCB.
  71. cmcptr    dw    0        ;Pointer for next char input.
  72. cmdptr    dw    0        ;Pointer into the command buffer.
  73. cmsiz    dw    0        ;Size info of user input.
  74. cmkptr    dw    0        ;Pointer to keyword.
  75. cmsptr    dw    0        ;Place to save a pointer.
  76. cmchr    db    0        ;Save char when checking ambiguity.
  77. cmten    dw    10        ;the number "10"
  78.  
  79. spchar    db    '!#$%&()+-/@\^`|~0000' ;Valid special characters ;[8][28d]
  80.  
  81. ;    This set of routines provides a user oriented way of parsing
  82. ;    commands.  It is similar to that of the COMND JSYS in TOPS-20.
  83.  
  84.     CSEG $            ;Resume coding.
  85.  
  86. ;    This routine prints the prompt in DX and specifies the reparse
  87. ;    address.
  88.  
  89. prompt:    pop    bx        ;Get the return address.
  90.     push    bx        ;Put it on the stack again.
  91.     mov    cmrprs, bx    ;Save as addr to go to on reparse.
  92.     mov    bx, 0        ;Clear out register.
  93.     add    bx, sp        ;Get the present stack pointer.
  94.     mov    cmostp, bx    ;Save for later restoral.
  95.     mov    cmprmp, dx    ;Save pointer to the prompt.
  96.     mov    bx, offset cmdbuf
  97.     mov    cmcptr, bx    ;Initialize the command pointer.
  98.     mov    cmdptr, bx
  99.     mov    cmaflg, 0    ;Zero the flags.
  100.     mov    cmlevl, 0    ;[fdc]Including the level-flag
  101.     mov    cmccnt, 0
  102.     mov    cmsflg, 0FFH
  103. reprompt:                            ;[32a] begin
  104.     call    tcrlf
  105. repmt2:    mov    dx, cmprmp    ;Print the prompt.
  106.     call    tmsg
  107.     mov    dl,defdrv    ;Print the default drive and user
  108.     add    dl,'A'
  109.     call    bout
  110.     mov    al,defusr
  111.     cbw
  112.     or    ax,ax        ;Only print the user number if nonzero
  113.     jz    repmt3
  114.     call    nout
  115. repmt3:    mov    dl,'>'
  116.     call    bout                        ;[32a] end
  117.     ret
  118.  
  119.  
  120. ;    This address is jumped to on reparse.
  121.  
  122. repars:    mov    sp, cmostp    ;new sp <-- old sp
  123.     mov    bx, offset cmdbuf
  124.     mov    cmdptr, bx
  125.     mov    cmsflg, 0FFH
  126.     mov    bx, cmrprs    ;Get the reparse address.
  127.     jmp    bx        ;Go there.
  128.  
  129. ;    This address can be jumped to on a parsing error.
  130.  
  131. prserr:    mov    ah, cmlevl    ;What level are we in?
  132.     cmp    ah, 0        ;
  133.     jz    prser1        ;skip error-message
  134.     mov    dx, offset cmer05 ;we're out of main-commands
  135.     call    tcrmsg        ;and got an empty option
  136.     mov    cmlevl, 0    ;reset level-flag
  137. prser1:    mov    sp, cmostp    ;Set new sp to old one.
  138.     mov    bx, offset cmdbuf
  139.     mov    cmcptr, bx    ;Initialize the command pointer.
  140.     mov    cmdptr, bx
  141.     mov    cmaflg, 0    ;Zero the flags.
  142.     mov    cmccnt, 0
  143.     mov    cmsflg, 0FFH
  144.     call    reprompt                    ;[32a]
  145.     mov    bx, cmrprs
  146.     jmp    bx
  147.  
  148.  
  149. ;    This routine parses the specified function in AH. Any additional
  150. ;    information is in DX and BX.
  151. ;    Returns +1 on success
  152. ;        +4 on failure (assumes a JMP follows the call)
  153.  
  154. comnd:    mov    cmstat, ah    ;Save what we are presently parsing.
  155.     call    cminbf        ;Get chars until an action or a erase char.
  156.     mov    ah, cmstat    ;Restore 'ah' for upcoming checks.
  157.     cmp    ah, cmcfm    ;Parse a confirm?
  158.     jz    cmcfrm        ;Go get one.
  159.     cmp    ah, cmkey    ;Parse a keyword?
  160.     jnz    cm1
  161.     jmp    cmkeyw        ;Try and get one.
  162. cm1:    cmp    ah, cmifi    ;Parse an input file spec?
  163.     jnz    cm2
  164.     jmp    cmifil        ;Go get one.
  165. cm2:    cmp    ah, cmofi    ;Output file spec?
  166.     jnz    cm3
  167.     jmp    cmofil        ;Go get one.
  168. cm3:    cmp    ah, cmtxt    ;Parse arbitrary text.
  169.     jnz    cm4
  170.     jmp    cmtext
  171. cm4:    cmp    ah, cmcha    ;[25] parse a single character?
  172.     jnz    cm5        ;[25]
  173.     jmp    cmchar        ;[25] go do it.
  174. cm5:    cmp    ah, cmnum    ;[25] parse a (decimal) number?
  175.     jnz    cm99        ;[25]
  176.     jmp    cmnumr        ;[25] go do it.
  177. cm99:    mov    dx, offset cmer00 ;"?Unrecognized COMND call" [25]
  178.     call    tcrmsg
  179.     ret
  180.  
  181. ; This routine gets a confirm.
  182.  
  183. cmcfrm:    call    cmgtch        ;Get a char.
  184.     cmp    ah, 0        ;Is it negative (a terminator;a space or
  185.                 ;a tab will not be returned here as they
  186.                 ;will be seen as leading white space)?
  187.     js    cmcfr0
  188.     ret            ;If not, return failure.
  189. cmcfr0:    and    ah, 7FH        ;Turn off the minus bit.
  190.     cmp    ah, esc        ;Is it an escape?
  191.     jne    cmcfr2
  192.     mov    dl, bell    ;Get a bell.
  193.     call    bout        ;Output the char.
  194.     mov    cmaflg, 0    ;Turn off the action flag.
  195.     mov    bx, cmcptr    ;Move the pointer to before the escape.
  196.     dec    bx
  197.     mov    cmcptr, bx
  198.     mov    cmdptr, bx
  199.     dec    cmccnt        ;Decrement the char count.
  200.     jmp    cmcfrm        ;Try again.
  201. cmcfr2:    cmp    ah, '?'        ;Curious?
  202.     jne    cmcfr3
  203.     mov    dx, offset cmin00 ;Print something useful.
  204.     call    tmsg
  205.     call    reprompt    ;Reprint the prompt        ;[32a]
  206.     mov    bx, cmdptr    ;Get the pointer into the    buffer.
  207.     mov    ah, '$'        ;Put a $ there for printing.
  208.     mov    [bx], ah
  209.     mov    bx, cmcptr
  210.     dec    bx        ;Decrement & save the buffer pointer.
  211.     mov    cmcptr, bx
  212.     mov    dx, offset cmdbuf
  213.     call    tmsg
  214.     mov    cmaflg, 0    ;Turn off the action flag.
  215.     jmp    repars        ;Reparse everything.
  216.  
  217. cmcfr3:                                ;[8] begin
  218. cmcfr4:    jmp    rskp
  219.  
  220.  
  221. ;    This routine parses a keyword from the table pointed
  222. ;    to in DX.  The format of the table is as follows:
  223. ;
  224. ;    addr:    db    n    ;Where n is the # of entries in the table.
  225. ;        db    m    ;M is the size of the keyword.
  226. ;        db    'string$' ;Where string is the keyword.
  227. ;        dw    ab    ;Where ab is data to be returned.
  228. ;
  229. ;    The keywords must be in alphabetical order.
  230.  
  231. cmkeyw:    mov    cmhlp, bx    ;Save the help string.
  232.     mov    cmptab, dx    ;Save the beginning of keyword table.
  233.     mov    bx, dx
  234.     mov    ch, [bx]    ;Get number of entries in table.
  235.     inc    bx
  236.     mov    dx, cmdptr    ;Save command pointer.
  237.     mov    cmsptr, dx    ;Save pointer's here.
  238. cmky1:    cmp    ch, 0        ;Any commands left to check?
  239.     jne    cmky2
  240.     ret
  241. cmky2:    dec    ch
  242.     mov    cl, 0        ;Keep track of how many chars read in so far.
  243.     call    cmgtch        ;Get a char.
  244.     cmp    ah, 0        ;Do we have a terminator?
  245.     jns    cmky2x 
  246.     jmp    cmky4        ;Negative number means we do.
  247. cmky2x:    inc    bx        ;Point to first letter of keyword.
  248.     inc    cl        ;Read in another char.
  249.     mov    al, [bx]              
  250.     cmp    ah, 'a'        ;Less than a?
  251.     jl    cmky21        ;If so, don't capitalize.
  252.     cmp    ah, 'z'+1    ;More than z?
  253.     jns    cmky21
  254.     and    ah, 137O    ;Capitalize the letter.
  255. cmky21:    cmp    ah, al
  256.     je    cmky3
  257.     jg    cmky2y
  258.     jmp    cmky41        ;Fail if ah preceeds al alphabetically.
  259. cmky2y:    jmp    cmky6        ;Not this keyword - try the next.
  260. cmky3:    inc    bx        ;We match here, how 'bout next char?
  261.     mov    al, [bx]
  262.     cmp    al, '$'        ;End of keyword?
  263.     jne    cmky3x
  264.     jmp    cmky7        ;Succeed.
  265. cmky3x:    mov    dl, al        ;Save al's char here.
  266.     call    cmgtch
  267.     inc    cl        ;Read in another char.
  268.     mov    al, dl
  269.     cmp    ah, 'a'
  270.     jl    cmky31
  271.     cmp    ah, 'z'+1
  272.     jns    cmky31
  273.     and    ah, 137O
  274. cmky31:    cmp    ah, esc+80H    ;Escape Recognition (escape w/minus bit on)?
  275.     je    cmky3y
  276.     cmp    ah, '?'+80H    ;A question mark?
  277.     je    cmky3y
  278.     cmp    ah, ' '+80H    ;A space?
  279.     je    cmky3y
  280.     cmp    ah, cr+80H    ;Carriage return?
  281.     je    cmky3y
  282.     jmp    cmky38
  283. cmky3y:    mov    cmkptr, bx    ;Save bx here.
  284.     mov    cmsiz, cx    ;Save size info.
  285.     mov    cmchr, ah    ;Save char for latter.
  286.     call    cmambg        ;See if input is ambiguous or not.
  287.         jmp    cmky32    ;Succeeded (not ambiguous).
  288.     mov    ah, cmchr
  289.     cmp    ah, esc+80H    ;Escape?
  290.  
  291. ; Display keyword choices and reparse if ambiguous        ;[8] begin
  292.     je    cmky3a
  293.     cmp    ah, ' '+80H    ;Space?
  294.     jne    cmky3b
  295. cmky3a:    dec    cmdptr        ;If so, back up over it.
  296. cmky3b:    mov    dx, offset cmin02 ;'One of the following:'
  297.     call    tcmsgc
  298.     mov    bx, cmkptr    ;Find beginning of current keyword
  299.     mov    cx, cmsiz
  300. cmky3c:    dec    bx        ;We are 'cl' characters into it
  301.     dec    cl
  302.     jnz    cmky3c
  303.     inc    bx
  304.     mov    cmkptr, bx    ;Save beginning of keyword
  305. cmky3d:    mov    dl, tab        ;Precede each keyword with a tab
  306.     call    bout
  307.     mov    dx,cmkptr    ;and display the keyword
  308.     call    tmsg
  309.     mov    bx, cmkptr    ;Move to the next keyword
  310. cmky3e:    inc    bx
  311.     cmp    byte ptr [bx], '$'
  312.     jnz    cmky3e
  313.     add    bx,4        ;Bypass '$', 2-byte return value, next length
  314.     mov    di, cmkptr    ;Get previous keyword for comparison
  315.     mov    cmkptr, bx    ;and save beginning of this keyword
  316.     mov    cx, cmsiz    ;Get number of characters to match
  317.     dec    ch        ;Are we at end of table?
  318.     js    cmky3g        ;  Yes, quit displaying
  319.     mov    cmsiz, cx
  320. cmky3f:    dec    cl
  321.     jz    cmky3d        ;This keyword also matches to 'cl' places
  322.     mov    ah,[bx]        ;Compare this keyword to last
  323.     cmp    ah,[di]
  324.     jne    cmky3g
  325.     inc    di
  326.     inc    bx
  327.     jmps    cmky3f
  328. cmky3g:    jmp    cmky50        ;Not equal or end of table, redisplay prompt
  329.                                 ;[8] end
  330.  
  331. cmky32:    mov    cx, cmsiz    ;Restore info.
  332.     mov    bx, cmkptr    ;Our place in the keyword table.
  333. cmk32a:    cmp    cmchr, ' '+80H    ;Space?            ;[8]
  334.     je    cmky35
  335.     cmp    cmchr, cr+80H    ;Carriage return?
  336.     je    cmky35
  337.     dec    cmcptr        ;Pointer into buffer of input.
  338.     mov    dx, cmcptr
  339. cmky33:    mov    ah, [bx]    ;Get next char in keyword.
  340.     cmp    ah, '$'        ;Are we done yet?
  341.     jz    cmky34
  342.     mov    di,dx
  343.     mov    [di], ah
  344.     inc    bx
  345.     inc    dx
  346.     inc    cmccnt
  347.     jmp    cmky33
  348. cmky34:    push    bx        ;Save pointer to return value    ;[8]
  349.     mov    ah, ' '
  350.     mov    di, dx
  351.     mov    [di], ah    ;Put a blank in the buffer.
  352.     inc    dx
  353.     mov    cmdptr, dx                        ;[8] begin
  354.     cmp    cmchr, '?'+80H    ;Question mark?
  355.     jne    cmk34a
  356.     mov    ah, '?'
  357.     mov    di,dx
  358.     mov    [di], ah
  359.     inc    dx
  360.     inc    cmccnt
  361.     push    dx
  362.     mov    dl, 08H        ;Erase question mark from display
  363.     call    bout
  364.     pop    dx
  365. cmk34a:    mov    cx, cmcptr    ;Remember where we were (for printing below).
  366.     mov    cmcptr, dx    ;Update our pointers.        ;[8] end
  367.     mov    ah, '$'
  368.     mov    di, dx
  369.     mov    [di], ah    ;Add '$' for printing.
  370.     mov    dx, cx        ;Point to beginning of filled in data.
  371.     call    tmsg
  372.     pop    bx        ;Recover pointer to return value ;[8]
  373.     inc    bx        ;Point to address we'll need.
  374.     mov    bx, [bx]
  375.     cmp    cmchr, 0BFH    ;Question mark?        ;[8] begin
  376.     je    cmk34b
  377.     mov    cmaflg, 0     ;If esc, turn off action flag
  378.     mov    cmsflg, 0FFH    ;   and pretend they typed a space
  379. cmk34b:    jmp    rskp                        ;[8] end
  380.  
  381. cmky35:    mov    ah, [bx]    ;Find end of keyword.    
  382.     inc    bx
  383.     cmp    ah, '$'
  384.     jne    cmky35    
  385.     mov    bx, [bx]    ;Address of next routine to call.
  386.     jmp    rskp
  387.  
  388. cmky38:    cmp    ah, al
  389.     jne    cmky6        ;Go to end of keyword and try next.
  390.     jmp    cmky3
  391.        
  392. cmky4:    and    ah, 7FH        ;Turn off minus bit.
  393.     cmp    ah, '?'        ;Need help?
  394.     je    cmky5
  395.     cmp    ah, ' '        ;Just a space - no error.
  396.     je    cmky51
  397.     cmp    ah, cr
  398.     je    cmky51
  399.     cmp    ah, esc        ;Ignore escape?
  400.     je    cmky43
  401. cmky41:    mov    dx, offset cmer03
  402.     call    tcrmsg
  403.     jmp    prserr        ;Parse error - give up.
  404.  
  405. cmky43:    mov    dl, bell    ;Ring a bell.
  406.     call    bout
  407.     mov    bx, cmcptr
  408.     dec    bx
  409.     mov    cmcptr, bx
  410.     mov    cmdptr, bx
  411.     dec    cmccnt        ;Don't count the escape.
  412.     mov    cmaflg, 0    ;Reset action flag.
  413.     inc    ch        ;Account for a previous 'dec'.
  414.     jmp    cmky1        ;Start over.
  415.  
  416. cmky5:    mov    dx,cmhlp    ;Print the help text.
  417.     call    tcmsgc
  418. cmky50:    call    reprompt    ;Reprint the prompt        ;[32a]
  419.     mov    bx,cmdptr    ;Get pointer into buffer.
  420.     mov    al, '$'
  421.     mov    [bx], al    ;Add dollar sign for printing.
  422.     mov    dx, offset cmdbuf
  423.     call    tmsg
  424.     mov    bx, cmdptr    ;[8] begin
  425.     mov    cmcptr, bx
  426.     mov    dx, offset cmdbuf
  427.     sub    bx, dx
  428.     mov    cmccnt, bl
  429.     mov    cmaflg, 0    ;Turn off the action flag.
  430.     jmp    repars
  431.  
  432. cmky51:    jmp    prserr
  433.  
  434. cmky6:    inc    bx        ;Find end of keyword.
  435.     mov    al, [bx]
  436.     cmp    al, '$'
  437.     jne    cmky6          
  438.     add    bx, 3        ;Beginning of next command.
  439.     mov    dx, cmsptr    ;Get old cmdptr.
  440.     mov    cmdptr, dx    ;Restore.
  441.     mov    cmsflg, 0FFH
  442.     jmp    cmky1        ;Keep trying.
  443.  
  444. cmky7:    call    cmgtch        ;Get char.
  445.     cmp    ah, 0
  446.     js    cmky71        ;Ok if a terminator.
  447.     dec    bx
  448.     jmp    cmky6        ;No match - try next keyword.
  449. cmky71:    mov    cmchr, ah                        ;[8] begin
  450.     jmp    cmk32a
  451.  
  452.  
  453. ; See if keyword is ambiguous from what the user has typed in.
  454.  
  455. cmambg:    cmp    ch, 0        ;Any keywords left to check?
  456.     jne    cmamb0
  457.     ret            ;If not then not ambiguous.
  458. cmamb0:    inc    bx        ;Go to end of keyword ...
  459.     mov    al, [bx]    ;So we can check the next one.
  460.     cmp    al, '$'
  461.     jne    cmamb0
  462.     add    bx, 4        ;Point to start of next keyword.
  463.     dec    cl        ;Don't count escape.
  464.     mov    dx, cmsptr    ;Buffer with input typed by user.
  465. cmamb1:    mov    ah, [bx]    ;Keyword char.    
  466.     mov    di, dx
  467.     mov    al, [di]    ;Input char.
  468.     cmp    al, 'a'        ;Do capitalizing.
  469.     jl    cmam11
  470.     cmp    al, 'z'+1
  471.     jns    cmam11
  472.     and    al, 137O
  473. cmam11:    cmp    ah, al        ;Keyword bigger than input (alphabetically)?
  474.     jle    cmamb2        ;No - keep checking.
  475.     ret            ;Yes - not ambiguous.
  476. cmamb2:    inc    bx        ;Advance one char.
  477.     inc    dx
  478.     dec    cl
  479.     jnz    cmamb1
  480.     jmp    rskp        ;Fail - it's ambiguous.
  481.  
  482. ; Parse an input file spec.
  483.  
  484. cmifil:    mov    wldflg, 0    ;Set to no wildcards.        ;[9]
  485.     mov    bx, dx        ;Get the fcb address in bx.
  486.     mov    cmfcb, bx    ;Save it.
  487.     mov    ch, 0        ;Initialize char count.
  488.     mov    ah, 0
  489.     mov    [bx], ah    ;Set the drive to default to current.
  490.     inc    bx
  491.     mov    cmfcb2, bx
  492.     mov    cl, ' '
  493. cmifi0:    mov    [bx], cl    ;Blank the FCB.
  494.     inc    bx
  495.     inc    ah
  496.     cmp    ah, 0BH        ;Twelve?
  497.     jl    cmifi0
  498. cmifi1:    call    cmgtch        ;Get another char.
  499.     cmp    ah, 0        ;Is it an action character.
  500.     jns    cmifi2
  501.     and    ah, 7FH        ;Turn off the action bit.
  502.     cmp    ah, '?'        ;A question mark?
  503.     jne    cmif12
  504.     mov    cmaflg, 0    ;Blank the action flag.
  505. ; '?' is a legal character in wildcard filenames.        ;[9] begin
  506. ; Make ESC take its place by giving info instead of beeping.    ;[32b]
  507.     mov    wldflg, 0FFH    ;Say we have a wildcard.
  508.     inc    cmdptr
  509.     jmp    cmifi8        ;Accept a '?'
  510. cmif12:    cmp    ah, esc        ;An escape?
  511.     jne    cmif13
  512.     dec    cmdptr
  513. cmf12a:    mov    cmaflg, 0    ;Turn off the action flag    ;[9] end
  514.     dec    cmcptr        ;Decrement the buffer pointer.
  515.     dec    cmccnt        ;Decrement count.
  516.     mov    dx, offset cmin01 ;Help message.
  517.     call    tmsg
  518.     call    reprompt    ;Reprint the prompt        ;[32a]
  519.     mov    bx, cmdptr
  520.     mov    al, '$'
  521.     mov    [bx], al    ;Put in dollar sign for printing.
  522.     mov    dx, offset cmdbuf
  523.     call    tmsg
  524.     jmp    repars
  525.  
  526. cmif13:    mov    ah, ch        ;It must be a terminator.
  527. ; The check for 0-length filenames will be performed by the    ;[32c]
  528. ; caller so as to allow the file specification to be optional.
  529.     cmp    ah, 0DH
  530.     js    cmf3y
  531.     jmp    cmifi9        ;If too long complain.
  532. cmf3y:    jmp    rskp        ;Otherwise we have succeeded.
  533. cmifi2:    cmp    ah, '.'
  534.     jne    cmifi3
  535.     inc    ch
  536.     mov    ah, ch
  537.     cmp    ah, 1H        ;Any chars yet?
  538.              jnz cmf2x
  539.     jmp    cmifi9        ;No, give error.
  540. cmf2x:    cmp    ah, 0AH        ;Tenth char?
  541.           js    cmf2y
  542.     jmp    cmifi9        ;Past it, give an error.
  543. cmf2y:    mov    dl, 9H
  544.     mov    dh, 0
  545.     mov    bx, cmfcb
  546.     add    bx, dx        ;Point to file type field.
  547.     mov    cmfcb2, bx
  548.     mov    ch, 9H        ;Say we've gotten nine.
  549.     jmp    cmifi1        ;Get the next char.
  550. cmifi3:    cmp    ah, ':'
  551.     jne    cmifi4
  552.     inc    ch
  553.     cmp    ch, 2H        ;Is it in right place for a drive?
  554.     je    cmif3x
  555.     jmp    cmifi9        ;If not, complain.
  556. cmif3x:    mov    ch, 0        ;Reset char count.
  557.     mov    bx, cmfcb2
  558.     dec    bx
  559.     mov    ah, [bx]    ;Get the drive name.
  560.     cmp    ah,'A'        ;Make sure it's in range A-P    ;[9] begin
  561.     jb    cmif3y
  562.     cmp    ah,'P'
  563.     jbe    cmif3z
  564. cmif3y:    jmp    cmifi9
  565. cmif3z:    sub    ah,'@'        ;Get the drive number.        ;[9] end
  566.     mov    cmfcb2, bx
  567.      mov bx, cmfcb
  568.     mov    [bx], ah    ;Put it in the fcb.
  569.     jmp    cmifi1
  570. cmifi4:    cmp    ah, '*'
  571.     jne    cmifi7
  572.     mov    ah, ch
  573.     cmp    ah, 8H        ;Is this in the name or type field?
  574.     jz    cmifi9        ;If its where the dot should be give up.
  575.     jns    cmifi5        ;Type.
  576.     mov    cl, 8H        ;Eight chars.
  577.     jmp    cmifi6
  578. cmifi5:    mov    cl, 0CH        ;Three chars.
  579. cmifi6:    mov    wldflg, 0FFH    ;Remember we had a wildcard.
  580.     mov    bx, cmfcb2    ;Get a pointer into the FCB.
  581.     mov    ah, '?'
  582.     mov    [bx], ah    ;Put a question mark in.
  583.     inc    bx
  584.     mov    cmfcb2, bx
  585.     inc    ch
  586.     mov    ah, ch
  587.     cmp    ah, cl
  588.     jl    cmifi6        ;Go fill in another.
  589.     jmp    cmifi1        ;Get the next char.
  590. cmifi7:
  591.  
  592. cmif7x:    cmp    ah,'0'
  593.     jb    cmif8x
  594.     cmp    ah,'9'
  595.     jbe    cmifi8
  596.     cmp    ah,'A'
  597.     jb    cmif8x
  598.     cmp    ah,'Z'
  599.     jbe    cmifi8
  600.     cmp    ah,'a'
  601.     jb    cmif8x
  602.     cmp    ah,'z'
  603.     ja    cmif8x                        ;[9] end
  604.     and    ah, 137O    ;Capitalize.
  605. cmifi8:    mov    bx, cmfcb2    ;Get the pointer into the FCB.
  606.     mov    [bx], ah    ;Put the char there.
  607.     inc    bx
  608.     mov    cmfcb2, bx
  609.     inc    ch
  610.     jmp    cmifi1
  611.  
  612. cmif8x:    push    es        ;Check list of special characters
  613.     mov    cx, ds        ;   which are legal in filenames
  614.     mov    es, cx        ;Scan uses ES register.
  615.     mov    di, offset spchar ;Special chars.
  616.     mov    cx, 20        ;Twenty of them.
  617.     mov    al, ah        ;Char is in al.
  618.     repnz    scasb        ;Search string for input char.
  619.     cmp    cx, 0        ;Was it there?
  620.     pop    es
  621.     jnz    cmifi8
  622.  
  623. cmifi9:    mov    dx, offset cmer02
  624.     call    tcrmsg
  625.     ret
  626.  
  627. cmofil:    jmp    cmifil        ;For now, the same as CMIFI.
  628.  
  629. ; Parse arbitrary text up to a CR.  Put chars into data buffer sent to
  630. ; the host (pointed to by BX).     Return updated pointer in BX and 
  631. ; input size in AH.
  632.  
  633. cmtext:    mov    cmptab, bx    ;Save pointer to data buffer.
  634.     mov    cl, 0        ;Init the char count.
  635. cmtxt1:    call    cmgtch        ;Get a char.
  636.     cmp    ah, 0        ;Terminator?
  637.     jns    cmtxt5        ;Nope, put into the buffer.
  638.     and    ah, 07FH
  639.     cmp    ah, esc        ;An escape?
  640.     jne    cmtxt2
  641.     mov    dl, bell    ;Ring a bell.
  642.     call    bout
  643.     mov    cmaflg, 0    ;Reset action flag.
  644.     dec    cmcptr        ;Move pointer to before the escape.
  645.     dec    cmdptr
  646.     dec    cmccnt        ;Decrement count.
  647.     jmp    cmtxt1        ;Try again.
  648. cmtxt2:    cmp    ah, '?'        ;Asking a question?
  649.     jz    cmtx2y                        ;[32b]
  650.     cmp    ah, ' '        ;Space?                ;[32b]
  651.     jz    cmtxt3
  652.     cmp    ah, ff        ;Formfeed?
  653.     jne    cmtx2x
  654.     call    clrscr
  655. cmtx2x:    mov    ah, cl        ;Return count in AH.
  656.     mov    bx, cmptab    ;Return updated pointer.
  657.     jmp    rskp
  658. cmtx2y:    inc    cmdptr                        ;[32b]
  659. cmtxt3:    mov    cmaflg, 0    ;Reset action flag to zero.
  660. cmtxt5:    inc    cl        ;Increment the count.
  661.     mov    bx, cmptab    ;Pointer into destination array.
  662.     mov    [bx], ah    ;Put char into the buffer.
  663.     inc    bx
  664.     mov    cmptab, bx
  665.     jmp    cmtxt1
  666.  
  667.  
  668. cminbf:    push    dx
  669.     push    bx
  670.     mov    cx, dx        ;Save value here too.
  671.     mov    ah, cmaflg    ;Is the action char flag set?
  672.     cmp    ah, 0
  673.     je    cminb1
  674.     jmp    cminb9        ;If so get no more chars.
  675. cminb1:    inc    cmccnt        ;Increment the char count.
  676.     call    bin
  677.     mov    ah, al        ;Keep char in 'ah'.
  678.     mov    bx, cmcptr    ;Get the pointer into the buffer.
  679.     mov    [bx], ah    ;Put it in the buffer.
  680.     inc    bx
  681.     mov    cmcptr, bx
  682.     cmp    ah, 15h        ;Is it a ^U?
  683.     je    cmnb12                        ;[30b]
  684.     cmp    ah, 18h        ;     or ^X?            ;[30b]
  685.     jne    cminb2
  686. cmnb12:    call    clrlin                        ;[30c]
  687.     call    repmt2        ;Reprint the prompt (no crlf)    ;[32a]
  688.     mov    bx, offset cmdbuf
  689.     mov    cmcptr, bx    ;Reset the point to the start.
  690.     mov    cmccnt, 0    ;Zero the count.
  691.     mov    dx, cx        ;Preserve original value of    dx.
  692.     jmp    repars        ;Go start over.
  693. cminb2:    cmp    ah, 08h        ;Is it a backspace?        ;[30b]
  694.     jz    cminb3
  695.     cmp    ah, 7fh        ;     or delete?        ;[30b]
  696.     jne    cminb4
  697.     mov    dx, offset delstr
  698.     call    tmsg
  699. cminb3:    mov    ah, cmccnt    ;Decrement the char count by two.
  700.     dec    ah
  701.     dec    ah
  702.     cmp    ah, 0        ;Have we gone too far?
  703.     jns    cmnb32        ;If not proceed.
  704.     mov    dl, bell    ;Ring the bell.
  705.     call    bout
  706.     jmp    cmnb12        ;Go reprint prompt and reparse.
  707. cmnb32:    mov    cmccnt, ah    ;Save the new char count.
  708.     mov    dx, offset clrspc ;Erase the character.
  709.     call    tmsg
  710.     mov    bx, cmcptr    ;Get the pointer into the buffer.
  711.     dec    bx        ;Back up in the buffer.
  712.     dec    bx
  713.     mov    cmcptr, bx
  714.     jmp    repars        ;Go reparse everything.
  715. cminb4:    cmp    ah, '?'        ;Is it a question mark.
  716.     jz    cminb6
  717.     cmp    ah, esc        ;Is it an escape?
  718.     jz    cminb6
  719.     cmp    ah, cr        ;Is it a carriage return?
  720.     jz    cminb5
  721.     cmp    ah, lf        ;Is it a line feed?
  722.     jz    cminb5
  723.     cmp    ah, ff        ;Is it a formfeed?
  724.     jne    cminb7
  725.     call    clrscr
  726. cminb5:    mov    ah, cmccnt    ;Have we parsed any chars yet?
  727.     cmp    ah, 1
  728.     jnz    cminb6
  729.     jmp    prserr        ;If not, just start over.
  730. cminb6:    mov    cmaflg, 0FFH    ;Set the action flag.
  731.     jmp    cminb9
  732. cminb7:    jmp    cminb1        ;Get another char.
  733.  
  734. cminb9:    pop    bx
  735.     pop    dx
  736.     ret
  737.  
  738. cmgtch:    push    cx
  739.     push    bx
  740.     push    dx
  741. cmgtc1:    mov    ah, cmaflg
  742.     cmp    ah, 0        ;Is it set.
  743.     jne    cmgt10
  744.     call    cminbf        ;If the action char flag is not set get more.
  745. cmgt10:    mov    bx, cmdptr    ;Get a pointer into the buffer.
  746.     mov    ah, [bx]    ;Get the next char.
  747.     inc    bx
  748.     mov    cmdptr, bx
  749.     cmp    ah, ' '        ;Is it a space?
  750.     jz    cmgtc2
  751.     cmp    ah, tab        ;Or a tab?
  752.     jne    cmgtc3
  753. cmgtc2:    mov    ah, cmsflg    ;Get the space flag.
  754.     cmp    ah, 0        ;Was the last char a    space?
  755.     jne cmgtc1        ;Yes, get another char.
  756.     mov    cmsflg, 0FFH    ;Set the space flag.
  757.     mov    ah, ' '
  758.     pop    dx
  759.     pop    bx
  760.     jmp    cmgtc5
  761. cmgtc3:    mov    cmsflg, 0    ;Zero the space flag.
  762.     pop    dx
  763.     pop    bx
  764.     cmp    ah, esc
  765.     jz    cmgtc5
  766.     cmp    ah, '?'        ;Is the user curious?
  767.     jz    cmgtc4
  768.     cmp    ah, cr
  769.     jz    cmgtc4
  770.     cmp    ah, lf
  771.     jz    cmgtc6                        ;[8]
  772.     cmp    ah, ff
  773.     je    cmgtc6                        ;[8]
  774.     pop    cx
  775.     ret            ;Not an action char, just return.
  776. cmgtc6:    mov    ah, cr        ;Convert lf & ff to cr        ;[8]
  777. cmgtc4:    dec    cmdptr
  778. cmgtc5:    or    ah, 80H        ;Make the char negative to indicate
  779.     pop    cx        ;it is a terminator.
  780.     ret
  781.  
  782. ; Parse a single character    ;[25] start
  783. ;    this is for setting the escape character
  784.  
  785. cmchar:
  786.     call    cmgtch        ;get a char
  787.     cmp    ah, 0
  788.     jns    cmchr1        ;go if not negative
  789.     and    ah, 7FH        ;turn off sign bit
  790.     cmp    ah, '?'        ;user curious?
  791.     jne    cmchr0        ;no - an error
  792.     mov    dx, bx        ;help string pointer was in bx
  793.     call    tmsg        ;print help stuff        ;[32a]
  794.     call    reprompt    ;Reprint the prompt        ;[32a]
  795.     mov    bx, cmdptr
  796.     mov    al, '$'
  797.     mov    [bx], al    ;add a "$" to what was typed
  798.     mov    dx, offset cmdbuf
  799.     call    tmsg        ;type it again
  800.     dec    cmcptr        ;but don't leave "$" ..
  801.     dec    cmccnt        ;in buffer
  802.     mov    cmaflg, 0    ;turn off action flag
  803.     jmp    repars        ;try again
  804. cmchr0:    mov    dx, offset erms20
  805.     call    tcrmsg        ;"illegal value" error
  806.     ret
  807. cmchr1:    mov    temp, ax    
  808.     call    cmcfrm        ;get a confirm
  809.      jmp    cmchr0        ;or else complain
  810.     mov    ax, temp
  811.     mov    bl, ah        ;return the character
  812.     jmp    rskp
  813.  
  814. ;    parse a (decimal) number.  Maximum allowed value in dx
  815. cmnumr:    
  816.     mov    temp1, 001H    ;initial multiplier of 1
  817.     mov    temp2, dx    ;storage for maximum
  818.     mov    temp, 0        ;zero running sum
  819.     call    cmgtch        ;get a char
  820.     cmp    ah, 0
  821.     jns    cmnum1        ;go if not negative
  822.     and    ah, 7FH        ;turn off sign bit
  823.     cmp    ah, '?'        ;user curious?
  824.     jne    cmnum0        ;no - an error
  825.     mov    dx, bx        ;help string pointer was in bx
  826.     call    tmsg        ;print help stuff        ;[32a]
  827.     call    reprompt    ;Reprint the prompt        ;[32a]
  828.     mov    bx, cmdptr
  829.     mov    al, '$'
  830.     mov    [bx], al    ;add a "$" to what was typed
  831.     mov    dx, offset cmdbuf
  832.     call    tmsg        ;type it again
  833.     dec    cmcptr        ;but don't leave "$" ..
  834.     dec    cmccnt        ;in buffer
  835.     mov    cmaflg, 0    ;turn off action flag
  836.     jmp    repars        ;try again
  837.     call    cmcfrm        ;get character (or confirm)
  838.      jmp    cmnum1        ;got a character
  839.                 ;fall through - too early for confirm
  840. cmnum0:    mov    dx, offset erms20
  841.     call    tcrmsg        ;"illegal value" message
  842.     ret
  843. cmnum1:    sub    ah, 030H    ;ASCII -> binary
  844.     jl    cmnum0        ;too small
  845.     cmp    ah, 09H
  846.     jg    cmnum0        ;too big
  847.     mov    bl, ah
  848.     mov    bh, 0        ;get number in low part of bx
  849.     mov    ax, temp    ;get running sum
  850.     mul    temp1        ;multiply by decimal place value
  851.     add    ax, bx        ;add in this digit
  852.     cmp    ax, temp2    ;over the maximum
  853.     jg    cmnum0        ;yes - error
  854.     mov    temp, ax    ;save running sum
  855.     mov    ax, temp1    ;get multiplier
  856.     mul    cmten        ;multiply multiplier by 10
  857.     mov    temp1, ax    ;save it
  858.     call    cmcfrm        ;get another character
  859.      jmp    cmnum1        ;not terminator - process it
  860.     mov    bx, temp    ;get value of number
  861.     jmp    rskp        ;return success
  862.                         ;[25] end
  863. <<< c86fil.a86 >>>
  864. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  865. ; [34c]    Add sorted wildcard SENDs with starting filename
  866. ; * * * * * * * * * * * * * * *  version 2.8  * * * * * * * * * * * * * * *
  867. ; [32c]    Allow replacement of output filename with trailer from RECEIVE.
  868. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  869. ; [31]    Fix display of file renaming.
  870. ;    RonB, 05/05/84
  871. ; [30c] Isolate ANSI escape sequences for machine independence.
  872. ; [29g]  Add 8th bit quoting
  873. ;    RonB, 04/15/84
  874. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  875. ; [28d]  Improve input filename processing, allow valid special chars
  876. ;    RonB, 03/27/84
  877. ; [23]    Modification to GTCEOF to fix ASCII mode transfer
  878. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  879. ; [Rg]    ^X/^Z file interruption.  Slight mod to GTNFIL.    Rg, 2/84
  880. ; * * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * * *
  881. ;  [par] Added calls to set parity, strip parity on input if
  882. ;    other than none parity is called for.
  883. ;     JD, 2/84
  884. ;  [16]    Add file-mode ASCII or BINARY processing.
  885. ;    RonB,01/02/84
  886. ;  [11]    Capitalize and parse filename being received.
  887. ;    RonB,12/27/83
  888. ;  [9]    Fix filename parsing, and add wildcard ability.
  889. ;    RonB,12/26/83
  890. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  891.     CSEG $
  892.  
  893. ;    Get the file name (including host to micro translation)
  894.  
  895. gofil:    cld
  896.     push    ds
  897.     pop    es
  898.     mov    si, offset data
  899.     mov    di, offset fcb
  900.     mov    al,0
  901.     stosb
  902.     mov    cx,11
  903.     mov    al,' '
  904.     rep stosb
  905.     mov    cx,24
  906.     mov    al,0
  907.     rep stosb
  908.     mov    di, offset fcb+1
  909.     mov    ah,0
  910. gofil1:    lodsb            ;Get a filename character
  911.     cmp    al,'.'
  912.     je    gofil2
  913.     cmp    al,0
  914.     je    gofil4
  915.     cmp    ah,8
  916.     jae    gofil1
  917.     call    gofl20        ;Capitalize, and replace strange chars ;[11]
  918.     stosb
  919.     inc    ah
  920.     jmps    gofil1
  921. gofil2:    mov    di, offset fcb+9
  922.     mov    ah,0
  923. gofil3:    lodsb            ;Get a file type character
  924.     cmp    al,'.'
  925.     je    gofil4
  926.     cmp    al,0
  927.     je    gofil4
  928.     cmp    ah,3
  929.     jae    gofil4
  930.     call    gofl20        ;Capitalize, and replace strange chars ;[11]
  931.     stosb
  932.     inc    ah
  933.     jmps    gofil3
  934. gofil4:    cmp    byte ptr fcb+1,' ' ;Any chars in first field?    ;[32c] begin
  935.     jne    gofil5        ; if not, set filename to '&'
  936.     mov    byte ptr fcb+1,'&'
  937. gofil5:    mov    si, offset fcb2+11 ;Replace with RECEIVE trailer
  938.     mov    di, offset fcb+11
  939.     mov    temp2, di
  940.     mov    ah,' '
  941. gofl5b:    mov    al,[si]        ;Get character from replacement filename
  942.     cmp    al,'?'
  943.     je    gofl5c
  944.     mov    [di],al        ;If not wild, simply replace existing letter
  945.     cmp    al,' '
  946.     je    gofl5c
  947.     mov    ah,'-'        ; and replace subsequent spaces with '-'
  948. gofl5c:    cmp    byte ptr [di],' '
  949.     jne    gofl5d        ;Replace spaces in filename with filler char
  950.     mov    [di],ah        ; either a space or a '-'.
  951.     cmp    ah,' '
  952.     jne    gofl5d
  953.     mov    temp2,di    ;Mark location where last space occurred
  954. gofl5d:    dec    di
  955.     dec    si
  956.     cmp    si,offset fcb2+8
  957.     jne    gofl5e
  958.     mov    ah,' '
  959. gofl5e:    cmp    si,offset fcb2
  960.     jae    gofl5b
  961.     sub    temp2,di
  962.     dec    temp2
  963.     cmp    temp2,8
  964.     jbe    gofl5f
  965.     mov    temp2,8
  966. gofl5f:    call    clrfln
  967.     mov    dx, offset fcb    ;Print the file name.
  968.     call    tfile                        ;[32c] end
  969.     cmp    flwflg, 0    ;Is file warning on?
  970.     jnz    gofl5x
  971.     jmp    gofil9        ;If not, just proceed.
  972. gofl5x:    mov    dx, offset fcb
  973.     call    openf        ;See if the file exists.
  974.     cmp    al, 0FFH    ;Does it exist?
  975.     jnz    gofil7
  976.     jmp    gofil9        ;If not create it.
  977.  
  978. gofil7:    mov    dx, offset scrfr ;Move cursor.
  979.     call    poscur                        ;[30c]
  980.     mov    dx, offset infms5 ;Inform the user we are renaming the file.
  981.     call    tmsg
  982.     mov    cx, temp2    ;Get the length of the file name. ;[32c] begin
  983.     mov    al, 0        ;Says if first field is full.
  984. gofil8:    cmp    cl, 8        ;Is the first field full?
  985.     jne    gofl81
  986.     mov    al, 0FFH    ;Set a flag saying so.
  987. gofl81:    mov    bx, offset fcb    ;Get the FCB.
  988.     add    bx, cx        ;Add in the character number.
  989.     mov    ah, '&'
  990.     mov    [bx], ah    ;Replace the char with an ampersand.
  991.     push    ax
  992.     push    bx
  993.     push    cx
  994.     mov    dx, offset fcb    ;See if the file exists.
  995.     call    openf
  996.     pop    cx
  997.     pop    bx
  998.     cmp    al, 0FFH    ;Does it exist?
  999.     pop    ax
  1000.     jz    gofl89        ;If not create it.
  1001.     cmp    al, 0        ;Get the flag.
  1002.     jz    gofl83
  1003.     dec    cl        ;Decrement the number of chars.
  1004.     cmp    cl, 0
  1005.     jz    gofl88        ;If no more, die.
  1006.     jmp    gofl81
  1007. gofl83:    inc    cl        ;Increment the number of chars.
  1008.     jmp    gofil8                        ;[32c] end
  1009.  
  1010. gofl88:    mov    dx, offset screrr
  1011.     call    poscur                        ;[30c]
  1012.     mov    dx, offset ermes4 ;Tell the user that we can't rename it.
  1013.     call    tmsg
  1014.     ret
  1015.  
  1016. gofl89:    push    dx
  1017.     mov    dx, offset fcb    ;Print the file name.        ;[31]
  1018.     call    tfile                        ;[31]
  1019.     pop    dx
  1020. gofil9:    mov    dx, offset fcb    ;Delete the file if it exists.
  1021.     call    delete
  1022.     mov    dx, offset fcb    ;Now create it.
  1023.     call    create
  1024.     cmp    al, 0FFH    ;Is the disk full?
  1025.     je    gofl9x
  1026.     jmp    rskp
  1027. gofl9x:    mov    dx, offset screrr ;Position cursor.
  1028.     call    poscur                        ;[30c]
  1029.     mov    dx, offset erms11
  1030.     call    tmsg
  1031.     ret
  1032.  
  1033. ; Make sure character in al is a legal filename character:    ;[11] begin
  1034. ; Mask 8th bit, capitalize, and replace all illegal
  1035. ; special characters with '#'
  1036.  
  1037. gofl20:    and    al, 7Fh        ;mask eighth bit        ;[28d]
  1038.     cmp    al, '0'        ;Check for digit
  1039.     jb    gofl21
  1040.     cmp    al, '9'
  1041.     jbe    gofl23
  1042.     cmp    al, 'A'        ;Check for uppercase letter
  1043.     jb    gofl21
  1044.     cmp    al, 'Z'
  1045.     jbe    gofl23
  1046.     cmp    al, 'a'        ;Check for lowercase letter
  1047.     jb    gofl21
  1048.     cmp    al, 'z'
  1049.     ja    gofl21
  1050.     and    al, 5Fh        ;Capitalize lowercase
  1051.     jmps    gofl23
  1052. gofl21:    push    di
  1053.     mov    di, offset spchar ;Special chars.
  1054.     mov    cx, 20        ;Twenty of them.
  1055.     repne    scasb        ;Search string for input char.
  1056.     je    gofl22
  1057.     mov    al, '#'        ;Replace illegal characters with '#'
  1058. gofl22:    pop    di                        ;[28d] end 
  1059. gofl23:    ret                            ;[11] end
  1060.  
  1061.  
  1062. ; Get next filename from sorted directory list.  Return skip on success,
  1063. ; plain return at end.
  1064.  
  1065. getfil:    cmp    cxzflg, 'Z'    ;[Rg] file interrupt flag set to 'Z'? ;[34c]
  1066.     je    gtfl9
  1067.     mov    si,dindex    ;Any more entries in list?
  1068.     cmp    si,dircnt
  1069.     jae    gtfl9
  1070.     cld
  1071. gtfl4:    push    ds
  1072.     pop    es
  1073.     mov    ds,word ptr membuf
  1074.     mov    cl,4
  1075.     shl    si,cl
  1076.     inc    si
  1077.     push    si
  1078.     mov    di,offset fcb2+1
  1079.     mov    cl,11
  1080.     repe    cmpsb
  1081.     pop    si
  1082.     jae    gtfl6        ;If above starting filename, use it
  1083.     push    es
  1084.     pop    ds
  1085.     inc    dindex
  1086.     mov    si,dindex
  1087.     cmp    si,dircnt
  1088.     jb    gtfl4
  1089.     mov    dx,offset erms28 ;No filenames below starting filename
  1090.     call    tcrmsg
  1091.     jmps    gtfl9
  1092. gtfl6:    mov    di,offset fcb+1
  1093.     mov    cx,11
  1094.     rep    movsb        ;Move the name to the FCB
  1095.     push    es
  1096.     pop    ds
  1097.     inc    dindex        ;Point to next entry
  1098.     call    getopn
  1099.     jmp    rskp
  1100. gtfl9:    mov    wldflg, 0    ;Reset wild card flag.
  1101.     ret                            ;[34c] end
  1102.  
  1103. ; open the file for sending
  1104.  
  1105. getopn:    mov    filflg, 0FFH    ;Nothing in the DMA.
  1106.     mov    eoflag, 0    ;Not the end of file.
  1107.     mov    dx, offset fcb
  1108.     call    openf        ;Open the file.
  1109.     ret
  1110.  
  1111. ;    Output the chars in a packet.
  1112.  
  1113. ptchr:    mov    temp1, ax    ;Save the    size.
  1114.     mov    bx, offset data    ;Beginning of received packet data.
  1115.     mov    outpnt, bx    ;Remember where we are.
  1116.     mov    ch, rquote    ;Quote char.
  1117. ptchr1:    dec    temp1        ;Decrement # of chars in packet.
  1118.     jnl    pt1
  1119.     jmp    rskp        ;Return successfully if done.
  1120. pt1:    dec    chrcnt        ;Decrement number of chars in dta.
  1121.     jns    ptchr2        ;Continue if space left.
  1122.     call    outbuf        ;Output it if full.
  1123.      jmp    r        ; Error return if disk is full.
  1124. ptchr2:    mov    bx, outpnt    ;Get position in packet data buffer.
  1125.     mov    ah, [bx]    ;Grab a char
  1126.     inc    bx
  1127.     mov    outpnt, bx    ;and bump pointer.
  1128.     mov    al, 00h        ;First assume no 8th bit    ;[29g] begin
  1129.     cmp    ebquot, 'N'    ;No 8th bit if we can't quote
  1130.     je    ptch21
  1131.     cmp    ebquot, 'Y'    ;  or if we can but aren't.
  1132.     je    ptch21
  1133.     cmp    ah, ebquot    ;Is this the 8th bit quote character?
  1134.     jne    ptch21
  1135.     mov    ah, [bx]    ;Get the quoted character
  1136.     inc    bx
  1137.     mov    outpnt, bx
  1138.     dec    temp1        ;Decrement # of chars in packet.
  1139.     mov    al, 80h        ;Set the 8th bit.        ;[29g] end
  1140. ptch21:    cmp    ah, ch        ;Is it the quote char?
  1141.     jne    ptchr4        ;If not proceed.
  1142.     mov    ah, [bx]    ;Get the quoted character
  1143.     inc    bx
  1144.     mov    outpnt, bx    ;and bump pointer.
  1145.     dec    temp1        ;Decrement # of chars in packet.
  1146.     mov    dl, ah        ;Save the parity bit in dl.    ;[29g] begin
  1147.     and    dl, 80H
  1148.     and    ah, 7FH        ;Turn off the parity bit.
  1149.     cmp    ah, ch        ;Is it the quote char?
  1150.     je    ptchr3        ;If so just go write it out.
  1151.     cmp    ebquot, 'N'    ;No 8th bit if we can't quote
  1152.     je    ptch22
  1153.     cmp    ebquot, 'Y'    ;  or if we can but aren't.
  1154.     je    ptch22
  1155.     cmp    ah, ebquot    ;Is this the 8th bit quote character?
  1156.     je    ptchr3        ;If so, just go write it out.
  1157. ptch22:    add    ah, 40H        ;Make it a control char again.    ;[29g] end
  1158.     and    ah, 7FH        ;Modulo 128.
  1159. ptchr3:    or    ah, dl        ;Or in the parity bit.
  1160. ptchr4:    or    ah, al        ;Or in the quoted 8th bit.    ;[29g]
  1161.     mov    bx, bufpnt    ;Destination buffer.
  1162.     mov    [bx], ah    ;Store it.
  1163.     inc    bx
  1164.     mov    bufpnt, bx    ;Update the pointer
  1165.     jmp    ptchr1        ;and loop to next char.
  1166.  
  1167.  
  1168.     ; output the buffer, reset bufpnt and chrcnt
  1169.  
  1170. outbuf:    push    bx
  1171.     push    cx
  1172.     mov    dx, offset fcb
  1173.     call    soutr        ;Write the record.
  1174.     pop    cx
  1175.     pop    bx
  1176.     cmp    al, 0        ;Successful.
  1177.     jz    outbf1
  1178.     cmp    al, 1
  1179.     jz    outbf0
  1180.     mov    dx, offset screrr
  1181.     call    poscur                        ;[30c]
  1182.     mov    dx, offset erms17 ;Record length exceeds DTA.
  1183.     call    tmsg
  1184.     ret
  1185. outbf0:    mov    dx, offset screrr
  1186.     call    poscur                        ;[30c]
  1187.     mov    dx, offset erms11 ;Disk full error.
  1188.     call    tmsg
  1189.     ret
  1190. outbf1:    mov    bx, offset dma    ;Addr for beginning.
  1191.     mov    bufpnt, bx    ;Store addr for beginning.
  1192.     mov    ax, bufsiz-1    ;Buffer size.
  1193.     mov    chrcnt, ax    ;Number of chars left.
  1194.     jmp    rskp
  1195.  
  1196.  
  1197. ;    Get the chars from the file.
  1198.  
  1199. gtchr:    mov    ch, squote    ;Keep quote char in c.
  1200.     cmp    filflg, 0    ;Is there anything in the DMA?
  1201.     jz    gtchr0        ;Yup, proceed.
  1202.     mov    cl, 0        ;No chars yet.
  1203.     call    inbuf
  1204.      jmp    gtceof        ;No more chars, go return EOF.
  1205. gtchr0:    mov    al, spsiz    ;Get the maximum packet size.
  1206.     sub    al, 5        ;Subtract the overhead.
  1207.     mov    ah, 0
  1208.     mov    temp1, ax    ;Number of chars we're to get.
  1209.     mov    bx, offset filbuf ;Where to put the data.
  1210.     mov    cbfptr, bx    ;Remember where we are.
  1211.     mov    cl, 0        ;No chars.
  1212. gtchr1:    dec    temp1        ;Decrement the number of chars left.
  1213.     jns    gtchr2        ;Go on if there is more than one left.
  1214.     mov    al, cl        ;Return the count in A.
  1215.     mov    ah, 0
  1216.     jmp    rskp
  1217. gtchr2:    mov    ax, chrcnt
  1218.     dec    ax
  1219.     jl    gtchr3
  1220.     mov    chrcnt, ax
  1221.     jmp    gtchr4
  1222. gtchr3:    call    inbuf        ;Get another buffer full.
  1223.     jmp    gtceof
  1224.     cmp    chrcnt, 0
  1225.     jne    gtchr4
  1226.     sub    cl, 2        ;Don't count controllified Z.
  1227.     mov    al, cl
  1228.     mov    ah, 0
  1229.     jmp    rskp
  1230. gtchr4:    mov    bx, bufpnt    ;Position in DMA.
  1231.     mov    ah, [bx]    ;Get a char from the file.
  1232.     inc    bx
  1233.     mov    bufpnt, bx
  1234.     cmp    ebquot, 'N'    ;Can we not do 8th bit quoting? ;[29g] begin
  1235.     je    gtch41
  1236.     cmp    ebquot, 'Y'    ;Or are we not?
  1237.     je    gtch41
  1238.     mov    dh, ah
  1239.     and    ah, 7Fh
  1240.     and    dh, 80h        ;Is the 8th bit set?
  1241.     je    gtch41        ;If not, no need for quoting
  1242.     dec    temp1        ;Decrement the number of characters left
  1243.     mov    dh, ebquot    ;Insert 8th bit quote char. in packet buffer
  1244.     mov    bx, cbfptr
  1245.     mov    [bx], dh
  1246.     inc    cbfptr
  1247.     inc    cl        ;Count the character
  1248. gtch41:    mov    dl, ah        ;Save the char.        ;[29g] end
  1249.     and    dl, 80H        ;Turn off all but parity.
  1250.     and    ah, 7FH        ;Turn off the parity.
  1251.     cmp    ah, ' '        ;Compare to a space.
  1252.     jl    gtchr5        ;If less then its a control char, handle it.
  1253.     cmp    ah, del        ;Is the char a delete?
  1254.     jz    gtchr5        ;Go quote it.
  1255.     cmp    ah, ch        ;Is it the quote char?
  1256.     je    gtch42        ;If so, insert it in the buffer ;[29g] begin
  1257.     cmp    ebquot, 'N'    ;Can we not do 8th bit quoting?
  1258.     je    gtchr8
  1259.     cmp    ebquot, 'Y'    ;Or are we not?
  1260.     je    gtchr8
  1261.     cmp    ah, ebquot    ;Is this the 8th bit quote character?
  1262.     jne    gtchr8        ;If not, proceed
  1263. gtch42:    dec    temp1        ;Decrement the chars remaining. ;[29g] end
  1264.     mov    bx, cbfptr    ;Position in character buffer.
  1265.     mov    [bx], ch    ;Precede char with send quote.
  1266.     inc    cbfptr
  1267.     inc    cl        ;Increment the char count.
  1268.     jmp    gtchr8
  1269. gtchr5:    or    ah, dl        ;Turn on the parity bit.
  1270.     cmp    ah, ('Z'-100O)    ;Is it a ^Z?
  1271.     jne    gtchr7        ;If not just proceed.
  1272.     cmp    binflg, 0    ;ASCII file?            ;[16] begin
  1273.     je    gtceof        ;If so, terminate
  1274.     cmp    eoflag, 0    ;EOF flag set?            ;[16] end
  1275.     jz    gtchr6        ;If not just go on.
  1276.     mov    bx, bufpnt
  1277.     mov    ax, chrcnt
  1278.     mov    dh, al        ;Get number of chars left in DMA.
  1279. gtch51:    dec    dh
  1280.     jns    gtch52        ;Any chars left?
  1281.     mov    chrcnt, 0    ;If not, say so.
  1282.     mov    al, cl        ;Return the count in A.
  1283.     mov    ah, 0
  1284.     jmp    rskp
  1285. gtch52:    mov    ah, [bx]    ;Get the next char.
  1286.     inc    bx        ;Move the pointer.
  1287.     cmp    ah, ('Z'-100O)    ;Is it a ^Z?
  1288.     jz    gtch51        ;If so see if they rest are.
  1289.  
  1290. gtchr6:    mov    ah, ('Z'-100O)    ;Restore the ^Z.
  1291. gtchr7:    xchg    ah, al
  1292.     mov    ah, 0
  1293.     mov    temp2, ax    ;Save the char.
  1294.     dec    temp1        ;Decrement char counter.
  1295.     mov    bx, cbfptr    ;Position in character buffer.
  1296.     mov    [bx], ch    ;Put the quote in the buffer.
  1297.     inc    cbfptr
  1298.     inc    cl        ;Increment the char count.
  1299.     mov    ax, temp2    ;Get the control char back.
  1300.     xchg    al, ah
  1301.     add    ah, 40H        ;Make the non-control.
  1302.     and    ah, 7FH        ;Modulo 200 octal.
  1303. gtchr8:    or    dl, dl        ;Do we have parity?        ;[29g]
  1304.     jz    gtch81        ;If not, just send it.        ;[29g]
  1305.     or    ah, dl        ;Or in the parity bit.
  1306.     cmp    parflg,parnon    ;[par] no parity?
  1307.     je    gtch81        ;[par] yes, keep going
  1308.     and    ah,7fh        ;[par] else turn off parity from file
  1309. ;[par]*** should probably mention that we're losing eighth bit here
  1310.     push    ax                        ;[29g] begin
  1311.     push    cx
  1312.     mov    dx, offset scrhi ;mention that high bit is being lost
  1313.     call    poscur                        ;[30c]
  1314.     mov    dx, offset hibit
  1315.     call    tmsg
  1316.     pop    cx
  1317.     pop    ax                        ;[29g] end
  1318. gtch81:    mov    bx, cbfptr    ;Position in character buffer.
  1319.     mov    [bx], ah    ;Put the char in the buffer.
  1320.     inc    cbfptr
  1321.     inc    cl        ;Increment the char count.
  1322.     jmp    gtchr1        ;Go around again.
  1323.  
  1324. gtceof:    cmp    cl, 0        ;Had we gotten any data?
  1325.     je    gteof0        ;Nope.
  1326.     mov    filflg,0FFh    ;[23] fix ASCII extra buffers at eof
  1327.     mov    eoflag,0FFh    ;[23]
  1328.     mov    al, cl
  1329.     mov    ah, 0
  1330.     jmp    rskp
  1331. gteof0:    mov    ah, 0FFH    ;Get a minus one.
  1332.     ret
  1333.  
  1334. ;Input the next DMA buffer.
  1335.  
  1336. inbuf:    mov    ah, eoflag    ;Have we reached the end?
  1337.     cmp    ah, 0
  1338.     jz    inbuf0
  1339.     ret            ;Return if set.
  1340. inbuf0:    push    bx
  1341.     push    cx
  1342.     mov    bx, offset dma    ;Set the r/w buffer pointer.
  1343.     mov    bufpnt, bx
  1344.     mov    dx, offset fcb
  1345.     call    sinr
  1346.     cmp    al, 0        ;End of file?
  1347.     je    inbuf1        ;Still have data left.
  1348.     mov    eoflag, 0FFH    ;Set End-of-file.
  1349.     mov    filflg, 0    ;Buffer not empty.
  1350.     mov    chrcnt, 0    ;Say no characters.
  1351.     pop    cx
  1352.     pop    bx
  1353.     ret
  1354.  
  1355. inbuf1:    mov    al, 80H        ;Use as counter for number of chars read.
  1356.     pop    cx
  1357.     pop    bx
  1358.     cmp    filflg, 0    ;Ever used DMS?
  1359.     jnz    inbf21        ;Nope, then don't change count.
  1360.     dec    al        ;Fix boundary error.
  1361. inbf21:    mov    ah, 0        ;Zero the flag (buffer not empty).
  1362.     mov    chrcnt, ax    ;Number of chars read from file.
  1363.     mov    filflg, 0    ;Buffer not empty.
  1364.     jmp    rskp
  1365.  
  1366.  
  1367.     DSEG $
  1368.  
  1369. temp1    dw    0
  1370. temp2    dw    0
  1371. dma    rb    80H
  1372. filbuf    rb    60H        ;Character buffer.
  1373. cpfcb    rb    25H        ;Save FCB in case of "*".
  1374. rdbuf    rb    80H
  1375. cnt    dw    0
  1376. fcb    rb    36
  1377. fcb2    rb    12        ;replacement receive filename    ;[32c]
  1378. chrcnt    dw    0        ;Number of chars in the file buffer.
  1379. filcnt    dw    0        ;Number of chars left to fill.
  1380. outpnt    dw    0        ;Position in packet.
  1381. bufpnt    dw    0        ;Position in file buffer.
  1382. fcbptr    dw    0        ;Position in FCB.
  1383. datptr    dw    0        ;Position in packet data buffer.
  1384. cbfptr    dw    0        ;Position in character buffer.
  1385. siz    dw    0        ;Size of data from gtchr.
  1386. filflg    db    0        ;Non-zero when nothing in DMA buffer.
  1387. filsiz    rw    02H        ;Double word for filesize (in bytes.)
  1388. eoflag    db    0        ;EOF flag;non-zero on EOF.
  1389. binflg    db    0        ;ASCII/Binary flag - 0 if ASCII file    ;[16]
  1390. wldflg    db    0        ;Assume no "*" in fn.
  1391. <<< c86ker.a86 >>>
  1392. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  1393. ;
  1394. ; [35]  Change file names in INCLUDE statements, fdc, 5 Jun 85
  1395. ;
  1396. ; [34]
  1397. ; (c)    Make memory allocation global, add sorted SEND capability.
  1398. ; (b)    Add LOCAL TYPE command to display files on screen
  1399. ; (a)    Fix directory file size calculation errors
  1400. ;    RonB, 11/13/84
  1401. ; * * * * * * * * * * * * * * *  version 2.8  * * * * * * * * * * * * * * *
  1402. ; [33] Fix printer on hanging system problem by letting CP/M handle the
  1403. ;    interrupts from the 7201 that we don't care about.  Thanks to
  1404. ;    Paul Ford, U. of Chicago Graduate School of Business
  1405. ;    WBC3, 10/1/84
  1406. ; [32]
  1407. ; (e)    Change all LEA xx,yy instructions to MOV xx,OFFSET yy
  1408. ; (d)    Add LOCAL and REMOTE command table entries, implementing LOCAL
  1409. ;    DELETE, DIRECTORY and SPACE commands (KERMIT,KERUTL)
  1410. ; (c)    Fix RECEIVE FILENAME to be different from GET (KERMIT,KERCMD,KERFIL)
  1411. ; (b)    Fix minor bugs (KERMIT,KERCMD)
  1412. ; (a)    Add SET option for default drive and user (KERMIT,KERCMD,KERUTL)
  1413. ;    RonB, 09/20/84
  1414. ;* * * * * * * * * * * * * * * version 2.7 * * * * * * * * * * * * * * *
  1415. ; [31]    Fix display of file rename
  1416. ;    RonB, 05/05/84
  1417. ;[fdc]    Add help message about "?" when starting up.
  1418. ;    Add help message about "<esc-char>?" when connecting.
  1419. ;    Fix glitch in Bernie's command level flagging (KERCMD).
  1420. ;    F. da Cruz, Columbia
  1421. ;
  1422. ;[]    Prefixed all ermes'sages with bell and changed ermes3 (secondary
  1423. ;    command didn't parse) from "?Not confirmed" to "?Unrecognized
  1424. ;    command-option".
  1425. ;    Prettied up (TABs between INSTR and AC's) and fixed SET command
  1426. ;    using RSKP convention - B.Eiben, EIBEN at DEC-Marlboro, 2-May-84
  1427. ; [30]
  1428. ; (e)    Recombine KERSYS and KERMIT.
  1429. ; (d)    Add SET PORT command, currently unimplemented (KERMIT,KERIO)
  1430. ; (c)    Isolate all machine dependencies in KERIO.
  1431. ; (b)    Make DEL work like BS and ^X like ^U in command input (KERCMD).
  1432. ; (a)    Add keyboard DEL key alteration for APC (KERIO).
  1433. ;    RonB, 04/18/84
  1434. ; [29]
  1435. ; (g)    Add 8th bit quoting (KERPRO,KERFIL,KERSYS).
  1436. ; (f)    Add QUIT command, synonymous to EXIT (KERSYS).
  1437. ; (e)    Move logging code to terminal module, make it a SET command,
  1438. ;    add quit/resume (^Q/^R) to make it more standard (KERTRM,KERSYS)
  1439. ; (d)    Expand receive buffer and check for packet overruns (KERPRO)
  1440. ; (c)    Clear FCB prior to opening or creating a file (KERUTL)
  1441. ; (b)    Add TAKE file processing, initially from KERMIT.INI
  1442. ;    (KERMIT,KERSYS,KERUTL)
  1443. ; (a)    Send error packet whenever a fatal error occurs (KERPRO)
  1444. ;    RonB, 04/08/84
  1445. ;* * * * * * * * * * * * * * * version 2.6 * * * * * * * * * * * * * * *
  1446. ; [28]
  1447. ; (e)    Add local stack for use in interrupt handling (KERIO)
  1448. ; (d)    Improve input filename processing, allow valid special chars
  1449. ;    (KERFIL,KERCMD)
  1450. ; (c)    Make disk full error messages more accurate (KERSYS)
  1451. ; (b)    Include filename in file-not-found error message (KERPRO,KERSYS)
  1452. ; (a)    Clear attribute bits from filename before sending (KERPRO)
  1453. ;    RonB, 03/27/84
  1454. ; [27]    add "Kermit-86" to interrupt messages.    Rg 20-Mar-1984
  1455. ; [26]    Move terminal emulation (TELNET) to a separate module: KERTRM.
  1456. ;    This is to "modularize" terminal emulation. Rg
  1457. ;
  1458. ; [25]    Move logic for "seteol" and "escape" from KERSYS into KERCMD so those 
  1459. ;    routines need not use internal CMD routines and variables.  For this 
  1460. ;    purpose add 2 parse routines and codes: "cmcha" and "cmnum".  Also
  1461. ;    eliminate the use of some KERCMD text strings in KERPRO.  The point
  1462. ;    of this is to keep calls to CMD modular since I want to eventually
  1463. ;    replace the whole thing.
  1464. ;    R. Garland    9-Mar-1984
  1465. ; [24]
  1466. ; (a)    Add terminal session logging (KERMIT,KERSYS,KERUTL)
  1467. ; (b)    Allow escape character to local-echo (KERMIT)
  1468. ;    RonB, 03/15/84
  1469. ;
  1470. ; [23]    Fix ASCII-mode-junk-at-end-of-file bug.  (KERFIL)    Rg
  1471. ;* * * * * * * * * * * * * * * version 2.5 * * * * * * * * * * * * * * *
  1472. ; [22]
  1473. ; (a) - Cosmetics - changed FILE-Warning to Warning, parallel to CP/M
  1474. ;    Version and makes SET FI Binary painless
  1475. ; (b) - made this version 2.5 to stop confusion -B.Eiben DEC Marlboro
  1476. ;    7-March-84
  1477. ; [21]
  1478. ; (a) - Add SET TIMER ON/OFF option, default is OFF (KERSYS,KERPRO)
  1479. ; (b) - Change SET FILE-MODE to SET FILE-TYPE to match VAX/VMS (KERSYS)
  1480. ; (c) - Move all Set/Show processing to KERSYS (KERMIT,KERSYS)
  1481. ;    RonB, 03/05/84
  1482. ; [20]
  1483. ; (a) -    Fix version & send/receive header for APC (KERSYS,KERPRO)
  1484. ; (b) - Add Break processing & set clock rate for NEC (KERIO)
  1485. ; (c) - Add escape character help in telnet mode (KERMIT,KERSYS)
  1486. ; (d) - Add a pseudo time-out to PRTOUT so it doesn't loop forever (KERIO)
  1487. ; (e) - Clean up environment better on KABORT (KERPRO,KERUTL)
  1488. ;    RonB, 03/02/84
  1489. ;* * * * * * * * * * * * * * * version 2.4 * * * * * * * * * * * * * * *
  1490. ; [19]    (let Bill's and Jeff's changes be 17 and 18)
  1491. ; (a) - Add flow control for input comm port buffer.  This is primarily to
  1492. ;  allow smooth scrolling and "Hold Screen" to work on the Rainbow.  Add
  1493. ;  associated Set, Show, and Help for same.  (KERSYS and KERIO)
  1494. ; (b) - Clear screen at beginning and end of program. (KERSYS and KERIO)
  1495. ; (c) - Give "bdos" mnemonic to interrupt 224. (KERUTL)
  1496. ; (d) - Change telnet to check keyboard between comm port reads. (KERMIT)
  1497. ;  Woops - can't get this dumb simple thing to work.  Save for later.
  1498. ; (e) - Put in Break transmission in connect mode. (KERMIT,KERIO)
  1499. ; (f) - Put in ^X/^Z file interruption. (KERSYS, KERPRO, KERFIL)
  1500. ; (g) - Put in timeouts for packet receive routines. (KERPRO)
  1501. ; [Rg] R. Garland, 2/84,    OC.GARLAND%CU20B@COLUMBIA-20.ARPA
  1502. ;    Columbia Univ.        OC.GARLAND@CU20B.BITNET  
  1503. ;* * * * * * * * * * * * * * * version 2.3 * * * * * * * * * * * * * * *
  1504. ; Fill in the missing parity routines to allow this program to work with
  1505. ; IBM mainframes and other systems that require parity (edit marked "[par]").
  1506. ; Include RonB's fixes for places where previous edit broke the NEC APC.
  1507. ; Jeff Damens, Columbia, 6 Feb 84
  1508. ;* * * * * * * * * * * * * * * version 2.2 * * * * * * * * * * * * * * *
  1509. ; Added CFIBFs (buffer clearing) where necessary, put conditional assembly
  1510. ; code all in two modules (86KERIO and 86KERSYS), created new module
  1511. ; (86KERSYS), added CTLPRT routine to print out control chars for the SHOW
  1512. ; command, made SERINI called once at the beginning of the program and nowhere
  1513. ; else and added user protocol timeouts (hitting a <CR>).
  1514. ; Bill Catchings:  12:36pm  Thursday, 19 January 1984
  1515. ;* * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * *
  1516. ;  [B.E. 3-Jan-83] added DTR-code (in 86kermit and 86kerio) for RAINBO
  1517. ;
  1518. ;  [16]    Add file-mode ASCII or BINARY processing.
  1519. ;  [15]    Clear screen lines before displaying packet debug.
  1520. ;  [14]    Fix nout to print decimal. (KERPRO)
  1521. ;  [13]    Use control-Z's for filler in partial sectors instead of nulls. (KERPRO)
  1522. ;  [12]    Allow user abort from the keyboard in the send and receive routines.
  1523. ;  [11]    Capitalize and parse filename being received. (KERFIL)
  1524. ;  [10]    Correct missing elements in the Show display.
  1525. ;  [9]    Fix filename parsing, and add wildcard ability. (KERCMD,KERPRO,KERFIL)
  1526. ;  [8]    Show choices for ambiguous keywords, finish keyword on '?' (KERCMD)
  1527. ;  [7]    Do tab expansion and suppress nulls while in telnet mode. (KERUTL)
  1528. ;  [6]    Add support for changing baud rate.
  1529. ;  [5]    Put OFF/ON command table in alphabetical order.
  1530. ;  [4]    Change default escape character to '^' because NEC keyboard doesn't
  1531. ;    generate a control-\.
  1532. ;  [3]    Change "esc,'[H'" to "esc,'[1;1H'" to get around bug in NEC BIOS.
  1533. ;    This should not affect operation on the Rainbow.
  1534. ;  [2]    Add a de-initialization routine for the serial port, to restore
  1535. ;    changed interrupt vectors, etc. (KERIO)
  1536. ;  [1]    Add I/O support for the NEC Advanced Personal Computer (KERIO)
  1537. ;    RonB,12/23/83
  1538. ;
  1539. ;
  1540. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  1541. ; KERMIT - KL10 Error-free Reciprocal Micro Interconnect over TTY-lines
  1542. ;
  1543. ;    Kermit Protocol Version 2
  1544. ;
  1545. ;    Based on the KERMIT Protocol.
  1546. ;
  1547. ;    Copyright (C) 1983 William B. Catchings III
  1548.  
  1549. ; This program implements the Kermit Protocol developed at Columbia
  1550. ; University.  This version is being written specifically for the
  1551. ; DEC Rainbow 100.  It will hopefully take advantage of much of what
  1552. ; was learned in implementing the CP/M-80, DEC-20 and other versions.
  1553.  
  1554. ; Things to do:
  1555. ;    Add new features from Kermit-80, like local CP/M functions
  1556. ;    Make all commands the same as those in Kermit-80
  1557.  
  1558. ; Now all system dependencies have been isolated in 86KERIO, which
  1559. ; will be implemented as a separate module for each system.  This
  1560. ; eliminates source code ballooning when other systems are added
  1561. ; which have (for example) non-ANSI screen controls and terminal
  1562. ; emulation capabilities, as well as specific port drivers.
  1563. ; Information about what routines are needed in the 86KERIO module
  1564. ; is given in the 86KERMIT.HLP and 86KERIO.HLP files.
  1565. ;
  1566. ; So far the systems supported are:
  1567. ;    NEC APC        in 86KERIO.APC
  1568. ;    DEC Rainbow    in 86KERIO.RB
  1569. ;
  1570. ; PIP 86KERIO.A86=86KERIO.???    - will make system-dependent routines available
  1571. ; ASM86 86KERMIT $PZ        - will assemble without listing
  1572. ; GENCMD 86KERMIT        - will LOAD
  1573. ; REN KERMIT.CMD=86KERMIT.CMD    - will make it "real" after testing
  1574.  
  1575.     TITLE    'Kermit'
  1576.  
  1577. TRUE    EQU    1
  1578. FALSE    EQU    0
  1579.  
  1580. ; Definitions:
  1581.  
  1582. soh    EQU    01O
  1583. bell    EQU    07O
  1584. tab    EQU    11O
  1585. lf    EQU    12O
  1586. ff    EQU    14O
  1587. cr    EQU    15O
  1588. xon    EQU    21O
  1589. xoff    EQU    23O
  1590. esc    EQU    33O
  1591. del    EQU    177O
  1592.  
  1593. parevn    EQU    00H        ;Even parity.            ;[21c] begin
  1594. parmrk    EQU    01H        ;Mark parity.
  1595. parnon    EQU    02H        ;No parity.
  1596. parodd    EQU    03H        ;Odd parity.
  1597. parspc    EQU    04H        ;Space parity.
  1598. ibmpar    EQU    parmrk        ;IBM's parity (mark).
  1599. defpar    EQU    parnon        ;Default parity (none).
  1600. defeco    EQU    00H        ;Default is echo off        ;[21a]
  1601. defesc    EQU    '\'-100O    ;Escape char is Control backslash by default.
  1602.                 ;note: generated by INS key on the APC.
  1603. deftmr    EQU    00H        ;Default is timer off        ;[21a]
  1604. deflog    EQU    00H        ;Default is logging off        ;[24a]
  1605. floxon    EQU    1        ;[19a]
  1606. flonon    EQU    0        ;[19a]
  1607. diasw    EQU    00H        ;Default is diagnostics off.    ;[21c] end
  1608.  
  1609.  
  1610. ; The actual program:
  1611.  
  1612.     CSEG            ;Start coding!
  1613.  
  1614.     call    getdrv        ;Save initial disk and user    ;[32a] begin
  1615.     mov    cpmdrv,al
  1616.     mov    defdrv,al
  1617.     call    getusr
  1618.     mov    cpmusr,al
  1619.     mov    defusr,al                    ;[32a] end
  1620.  
  1621. ;    The allocation amount of 245 pages was arrived at by trial and
  1622. ;    error.  This figure causes Concurrent CP/M on the NEC APC to only
  1623. ;    allocate one additional memory block.  (Since the blocks are 4K
  1624. ;    each, one would expect 256...)
  1625.  
  1626.     mov    cx,245
  1627. start1:    push    cx
  1628.     mov    word ptr membuf+2, cx    ;Allocate 4K (or less) bytes of memory
  1629.     mov    dx, offset membuf    ;   for sorting filenames
  1630.     call    allmem
  1631.     pop    cx
  1632.     cmp    al,0
  1633.     loopne    start1
  1634.     cmp    cx,0
  1635.     jne    reboot
  1636.     mov    dx, offset erms25    ;Not enough memory available:
  1637.     call    tcrmsg            ;   local dir, del, and type will
  1638.     mov    word ptr membuf+2, 0    ;   not be enabled, nor will wildcard
  1639.                     ;   sends.        ;[34c] end
  1640.  
  1641. reboot:    pushf            ;Push flags on CCP's stack.    ;[12]
  1642.     pop    ax        ;flags in AX.
  1643.     cli                            ;[32b]
  1644.     mov    bx, ds        ;Set SS to DS.
  1645.     mov    ss, bx
  1646.     mov    sp, offset stack ;Set up the stack pointer.
  1647.     push    ax        ;Restore the flags.
  1648.     popf
  1649.  
  1650.     call    inidma        ;Set DMA base and offset    ;[34c] begin
  1651.     call    serini        ;Do any necessary serial port initialization.
  1652.  
  1653.     call    dspver        ;Clear screen and print version header
  1654.     mov    dx, offset hlpmsg ;[fdc] Give help message about "?"
  1655.     call    tmsgcr        ;[fdc]
  1656.  
  1657. ; This is the main KERMIT loop.  It prompts for and gets the user's commands.
  1658.  
  1659. kermit:    mov    dx, offset kerm
  1660.     call    prompt        ;Prompt the user.
  1661.     mov    dx, offset comtab
  1662.     mov    bx, offset tophlp
  1663.     mov    ah, cmkey
  1664.     call    comnd
  1665.      jmp    kermt2        ;Tell them about the error.
  1666.     mov    cmlevl, 1    ;we're going into options
  1667.     call    bx        ;Call the routine returned.
  1668.      jmp    kermt3        ;Tell them about the error.
  1669.     cmp    extflg, 0    ;Check if the exit flag is set.
  1670.     je    kermit        ;If not, do it again.
  1671.     call    serfin        ;clean up serial port environment ;[2]
  1672.     mov    dl,cpmdrv    ;reset disk and user        ;[32a] begin
  1673.     call    setdrv        ; to initial defaults
  1674.     mov    dl,cpmusr
  1675.     call    setusr                        ;[32a] end
  1676.     call    haltf
  1677.     retf            ;Just in case!            ;[32b]
  1678.  
  1679. kermt2:    mov    dx, offset ermes1 ;Give an error.
  1680.     call    tcrmsg
  1681.     jmp    kermit
  1682.  
  1683. kermt3:    mov    dx, offset ermes3 ;Give an error.
  1684.     call    tcrmsg
  1685.     jmp    kermit
  1686.  
  1687.  
  1688. ; This is the EXIT command.  It leaves KERMIT and returns to CP/M.
  1689.  
  1690. exit:    mov     ah, cmcfm
  1691.     call    comnd        ;Get a confirm.
  1692.      jmp    r
  1693.     mov    extflg, 1    ;Set the exit flag.
  1694.     jmp    rskp
  1695.  
  1696. ; This is the HELP command.
  1697.  
  1698. help:    mov    ah, cmcfm
  1699.     call    comnd        ;Get a confirm.
  1700.      jmp    r
  1701.     mov    dx, offset tophlp ;Print some help.
  1702.     call    tmsg
  1703.     jmp    rskp
  1704.  
  1705.  
  1706. ; LOCAL - parse and perform local command            ;[32d] begin
  1707.  
  1708. loccmd:    mov    dx, offset loctab ;Parse a keyword from the local table.
  1709.     mov    bx, offset lochlp
  1710.     mov    ah,cmkey
  1711.     call    comnd
  1712.      jmp    r
  1713.     call    bx        ;Call the specific local routine
  1714.      jmp    r        ;We got an error
  1715.     jmp    rskp
  1716.  
  1717.  
  1718. ; DIRECTORY of local files
  1719.  
  1720. locdir:    mov    ah, cmifi    ;Parse an input filename
  1721.     mov    dx, offset fcb
  1722.     call    comnd
  1723.      jmp    r
  1724.     push    ax        ;Save length of filename
  1725.     mov    ah, cmcfm    ;Confirm it
  1726.     call    comnd
  1727.      jmp    r
  1728.     pop    ax
  1729.     cmp    ah, 0        ;Read in any chars?
  1730.     jne    locd1
  1731.     mov    di, offset fcb+1
  1732.     call    wldfcb        ;If not, set filename to all wild
  1733. locd1:    cmp    byte ptr fcb,0    ;Replace unspecified drive with default
  1734.     jne    locd2
  1735.     mov    al,defdrv
  1736.     inc    al
  1737.     mov    byte ptr fcb,al
  1738. locd2:    call    dirutl        ;perform directory action (in KERUTL)
  1739.      jmp    rskp        ;On error a message has already been issued
  1740.     jmp    locs2        ;jump to display space remaining
  1741.  
  1742.  
  1743. ; ERASE local files
  1744.  
  1745. locera:    mov    ah, cmifi    ;Parse an input filename
  1746.     mov    dx, offset fcb
  1747.     call    comnd
  1748.      jmp    r
  1749.     push    ax        ;Save length of filename
  1750.     mov    ah, cmcfm    ;Confirm it
  1751.     call    comnd
  1752.      jmp    r
  1753.     pop    ax
  1754.     cmp    ah, 0        ;Read in any chars?
  1755.     jne    loce1
  1756.     mov    dx, offset erms26 ;Illegal (blank) filename
  1757.     call    tcrmsg
  1758.      jmp    rskp
  1759. loce1:    call    erautl        ;Erase utility (in KERUTL)
  1760.      jmp    rskp        ;On error a message has already been issued
  1761.     jmp    rskp
  1762.  
  1763.  
  1764. ; TYPE local files
  1765.  
  1766. loctyp:    mov    ah, cmifi    ;Parse an input filename
  1767.     mov    dx, offset fcb
  1768.     call    comnd
  1769.      jmp    r
  1770.     push    ax        ;Save length of filename
  1771.     mov    ah, cmcfm    ;Confirm it
  1772.     call    comnd
  1773.      jmp    r
  1774.     pop    ax
  1775.     cmp    ah, 0        ;Read in any chars?
  1776.     jne    loct1
  1777.     mov    dx, offset erms26 ;Illegal (blank) filename
  1778.     call    tcrmsg
  1779.      jmp    rskp
  1780. loct1:    call    typutl        ;Type utility (in KERUTL)
  1781.      jmp    rskp        ;On error a message has already been issued
  1782.     jmp    rskp
  1783.  
  1784.  
  1785. ; SPACE remaining on disk
  1786.  
  1787. locsiz:    mov    ah, cmifi    ;Parse an input filename
  1788.     mov    dx, offset fcb
  1789.     call    comnd
  1790.      jmp    r
  1791.     push    ax        ;Save length of filename
  1792.     mov    ah, cmcfm    ;Confirm it
  1793.     call    comnd
  1794.      jmp    r
  1795.     pop    ax
  1796.     cmp    ah, 0        ;Read in any chars?
  1797.     je    locs1
  1798.     mov    dx, offset erms24 ;At most only a drive code should be entered
  1799.     call    tcrmsg
  1800.      jmp    rskp
  1801. locs1:    cmp    fcb,0
  1802.     jne    locs2
  1803.     mov    al,defdrv
  1804.     inc    al
  1805.     mov    fcb,al
  1806. locs2:    call    spcutl        ;Space utility (in KERUTL)
  1807.      jmp    rskp        ;On error a message has already been issued
  1808.     jmp    rskp
  1809.  
  1810.  
  1811. ; Fill a file control block filename with ?'s
  1812.  
  1813. wldfcb:    mov    ax,ds        ;Fill filename with ?'s.
  1814.     mov    es,ax
  1815.     mov    cx,11
  1816.     mov    al,'?'
  1817.     rep stosb
  1818.     mov    wldflg,0FFh    ;Set wildcard flag
  1819.     ret
  1820.  
  1821.  
  1822. ; REMOTE - parse and perform remote command
  1823. ;    (not yet implemented)
  1824.  
  1825. remcmd:    mov    ah,cmtxt    ;Parse arbitrary text up to a CR
  1826.     mov    bx, offset data
  1827.     call    comnd
  1828.      jmp    r
  1829.     mov    dx, offset infms6 ;Tell the user that it's not yet implemented.
  1830.     call    tcrmsg
  1831.     jmp    rskp
  1832.  
  1833. ;    mov    dx, offset remtab ;Parse a keyword from the remote table.
  1834. ;    mov    bx, offset remhlp
  1835. ;    mov    ah,cmkey
  1836. ;    call    comnd
  1837. ;     jmp    r
  1838. ;    call    bx        ;Call the specific remote routine
  1839. ;     jmp    r        ;We got an error
  1840. ;    jmp    rskp                        ;[31b] end
  1841.  
  1842.  
  1843. ; FINISH - tell remote KERSRV to exit.
  1844.  
  1845. finish:    mov    ah,cmcfm    ;Parse a confirm.
  1846.     call    comnd
  1847.      jmp    r
  1848.     mov    ah, 'F'
  1849.     call    gensen        ;Send the finish command.
  1850.     jmp    rskp
  1851.  
  1852. ; BYE - tell remote KERSRV to logout and then exit to CP/M.
  1853.  
  1854. bye:    mov    ah,cmcfm    ;Parse a confirm.
  1855.     call    comnd
  1856.      jmp    r
  1857.     mov    ah, 'L'
  1858.     call    gensen        ;Send the logout command.
  1859.     mov    extflg,1    ;Set exit flag.
  1860.     jmp    rskp
  1861.  
  1862. ; LOGOUT- tell remote KERSRV to logout.
  1863.  
  1864. logout:    mov    ah,cmcfm    ;Parse a confirm.
  1865.     call    comnd
  1866.      jmp    r
  1867.     mov    ah, 'L'
  1868.     call    gensen        ;Send the logout command.
  1869.     jmp    rskp
  1870.  
  1871. ; RECEIVE - Receive a file or files from the remote Kermit.    ;[32c] begin
  1872. ; A filespec can optionally be specified to rename the received file.
  1873.  
  1874. rec:    mov    ah, cmofi    ;Parse an output filename
  1875.     mov    dx, offset fcb2
  1876.     call    comnd
  1877.      jmp    r
  1878.     push    ax        ;Save length of filename
  1879.     mov    ah, cmcfm    ;Confirm it
  1880.     call    comnd
  1881.      jmp    r
  1882.     pop    ax
  1883.     cmp    ah, 0        ;Read in any chars?
  1884.     jne    rec1
  1885.     mov    di, offset fcb2+1
  1886.     call    wldfcb        ;If not, set filename to all wild
  1887. rec1:    cmp    byte ptr fcb2,0    ;Also make default drive a ?.
  1888.     jne    rec2
  1889.     mov    byte ptr fcb2,'?'
  1890. rec2:    call    read        ;Do the actual protocol work.
  1891.     jmp    rskp                        ;[32c] end
  1892.  
  1893. ; GET - Get a file or files from the remote server Kermit.
  1894.  
  1895. get:    mov    di, offset fcb2
  1896.     mov    byte ptr [di],'?'
  1897.     inc    di
  1898.     call    wldfcb        ;Receive any filename as is    ;[32c]
  1899.     mov    ah, cmtxt    ;Parse an arbitrary text string.
  1900.     mov    bx, offset data    ;Where to put the parsed text.
  1901.     call    comnd
  1902.      jmp    r
  1903.     cmp    ah, 0        ;Read in any chars?
  1904.     jne    get1        ;If not give an error.
  1905.     mov    dx, offset ermes5
  1906.     call    tcrmsg
  1907.     jmp    rskp
  1908. get1:    mov    al, ah
  1909.     mov    ah, 0
  1910.     mov    argbk1, ax    ;Remember number of chars we read.
  1911.     mov    ah, '$'        ;Used for printing.
  1912.     mov    [bx], ah
  1913.     call    init        ;Paint screen and initialize file buffers.
  1914.     call    cfibf        ;Clear any stacked NAKs.
  1915.     call    clrfln        ;Prepare to print filename.
  1916.     mov    dx, offset data    ;Print file name.
  1917.     call    tmsg
  1918.     mov    argblk, 0    ;Start at packet zero.
  1919.     mov    ah, 'R'        ;Receive init packet.
  1920.     call    spack        ;Send the packet.
  1921.      jmp    r
  1922.     call    read1        ;Join the read code.
  1923.     jmp    rskp
  1924.  
  1925. ; SEND - Send a file or files to the remote Kermit.
  1926.  
  1927. sencom:    mov    ah, cmifi    ;Parse an input file spec.
  1928.     mov    dx, offset fcb    ;Give the address for the FCB.
  1929.     call    comnd
  1930.      jmp    r        ;Give up on bad parse.
  1931.     cmp    ah,0        ;Check for null filename    ;[32c] begin
  1932.     jne    $+5
  1933.      jmp    r                        ;[32c] end
  1934.     cmp    wldflg,0FFh
  1935.     jne    sen7
  1936.     mov    ah, cmifi    ;Parse first file to send    ;[34c] begin
  1937.     mov    dx, offset fcb2
  1938.     call    comnd
  1939.      nop
  1940.      nop
  1941.      nop
  1942.     mov    bx,offset fcb2+1
  1943.     mov    cx,11
  1944. sen4:    cmp    byte ptr [bx],'?' ;Replace wildcards with spaces 
  1945.     jne    sen5          ;   in starting filename
  1946.     mov    byte ptr [bx],' '
  1947. sen5:    inc    bx
  1948.     loop    sen4
  1949.     mov    wldflg,0FFh    ;Show original filename as wild
  1950. sen7:    mov    ah, cmcfm
  1951.     call    comnd        ;Get a confirm.
  1952.      jmp    r        ;Didn't get a confirm.
  1953.     call    send
  1954.     jmp    rskp
  1955.  
  1956. ; SET - Set some Kermit parameter.
  1957.  
  1958. setcom:    mov    dx, offset settab ;Parse a keyword from the set table.
  1959.     mov    bx, offset sethlp
  1960.     mov    ah,cmkey
  1961.     call    comnd
  1962.      jmp    r
  1963.     call    bx        ;Call the specific set routine in KERSYS.
  1964.      jmp    r        ;We got an error
  1965.     jmp    rskp
  1966.  
  1967.  
  1968. ; STATUS - Give some statistics on the connection.
  1969.  
  1970. status:    jmp    show        ;Make STATUS and SHOW synonymous for now ;[32b]
  1971.  
  1972. ; TAKE - Specify file which will supply command input.        ;[29b] begin
  1973.  
  1974. take:    mov    ah, cmifi    ;Parse an input file spec.
  1975.     mov    dx, offset tkfcb ;Give the address for the FCB.
  1976.     call    comnd
  1977.      jmp    r        ;Give up on bad parse.
  1978.     cmp    ah,0        ;Check for null filename    ;[32c] begin
  1979.     jne    $+5
  1980.      jmp    r                        ;[32c] end
  1981.     mov    ah, cmcfm
  1982.     call    comnd        ;Get a confirm.
  1983.      jmp    r        ;Didn't get a confirm.
  1984.     mov    tkflg, 1    ;Turn on command file input
  1985.     mov    tkptr, 0    ;Indicate file not yet open
  1986.     jmp    rskp                        ;[29b] end
  1987.  
  1988. ; TRANSMIT file(s) with no protocol                ;[32e] begin
  1989.  
  1990. txmit:    mov    ah,cmtxt    ;Parse arbitrary text up to a CR
  1991.     mov    bx, offset data
  1992.     call    comnd
  1993.      jmp    r
  1994.     mov    dx, offset infms6 ;Tell the user that it's not yet implemented.
  1995.     call    tcrmsg
  1996.     jmp    rskp                        ;[32e] end
  1997.  
  1998. ; Set parity for character in Register AL.
  1999.  
  2000. dopar:    cmp    parflg, parnon    ;No parity?
  2001.     je    parret        ;Just return
  2002.     cmp    parflg, parevn    ;Even parity?
  2003.     jne    dopar0
  2004.     and    al, 7FH        ;Strip parity.
  2005.     jpe    parret        ;Already even, leave it.
  2006.     or    al, 80H        ;Make it even parity.
  2007.     jmp    parret
  2008. dopar0:    cmp    parflg, parmrk    ;Mark parity?
  2009.     jne    dopar1
  2010.     or    al, 80H        ;Turn on the parity bit.
  2011.     jmp    parret
  2012. dopar1:    cmp    parflg, parodd    ;Odd parity?
  2013.     jne    dopar2
  2014.     and    al, 7FH        ;Strip parity.
  2015.     jpo    parret        ;Already odd, leave it.
  2016.     or    al, 80H        ;Make it odd parity.
  2017.     jmp    parret
  2018. dopar2:    and    al, 7FH        ;Space parity - turn off parity bit.
  2019. parret:    ret
  2020.  
  2021.  
  2022.  
  2023. ; The following are the SET command subroutines        ;[21c] begin
  2024. ;    except for Baud rate and Port selection, which are
  2025. ;    isolated in the system dependent modules.
  2026.  
  2027. ; Sets debugging mode on and off.
  2028.  
  2029. debset:    mov    dx, offset ontab
  2030.     mov    bx, offset onhlp
  2031.     mov    ah, cmkey
  2032.     call    comnd
  2033.      jmp    r
  2034.     mov    temp1, bx
  2035.     mov    ah, cmcfm
  2036.     call    comnd        ;Get a confirm.
  2037.      jmp    r        ;Didn't get a confirm.
  2038.     mov    bx, temp1
  2039.     mov    debug, bl    ;Set the debug flag.
  2040.     jmp    rskp
  2041.  
  2042. ; Sets the default disk and user number for file operations    ;[32a] begin
  2043. ; Entry must be in one of the following forms:
  2044. ;    d:    = go to drive d (A through P)
  2045. ;    u:    = go to user u (0 through 15)
  2046. ;    du:    = go to drive d and user u
  2047. ;    :    = go to the defaults when Kermit was loaded
  2048. ; Whenever a drive is specified, even if it is the same as the current
  2049. ; default drive, the drive is logged in so that disks can be swapped
  2050. ; without exiting Kermit to type control-C.
  2051.  
  2052. defset:    mov    ah,cmtxt    ;Get the du: specification
  2053.     mov    bx, offset data
  2054.     call    comnd
  2055.      jmp    r
  2056.     mov    byte ptr [bx],0    ;Mark the end of input
  2057.     mov    ah,cmcfm    ;Confirm the input
  2058.     call    comnd
  2059.      jmp    r
  2060.     mov    newdrv,0FFh    ;set inputs to show no entry
  2061.     mov    newusr,0FFh
  2062.     mov    bx, offset data    ;analyze the input
  2063.     mov    al,[bx]
  2064.     cmp    al,'a'        ;check for lower case drive specification
  2065.     jb    defs10
  2066.     cmp    al,'p'
  2067.     jbe    defs05
  2068.     jmp    deferr
  2069. defs05:    sub    al,'a'
  2070.     jmps    defs15
  2071. defs10:    cmp    al,'A'        ;check for upper case drive specification
  2072.     jb    defs25
  2073.     cmp    al,'P'
  2074.     ja    deferr
  2075.     sub    al,'A'
  2076. defs15:    mov    newdrv,al    ;save the new drive specification
  2077. defs20:    inc    bx
  2078.     mov    al,[bx]
  2079. defs25:    cmp    al,':'        ;input must terminate with required colon
  2080.     je    defs50
  2081.     cmp    al,'0'        ;check for user number digit
  2082.     jb    deferr
  2083.     cmp    al,'9'
  2084.     ja    deferr
  2085.     sub    al,'0'
  2086.     mov    dl,al
  2087.     cmp    newusr,0FFh    ;is this the first digit?
  2088.     jne    defs30
  2089.     mov    newusr,dl    ; yes, just store the digit
  2090.     jmps    defs20
  2091. defs30:    mov    al,newusr    ; otherwise append digit to current value
  2092.     mov    dh,10
  2093.     mul    dh
  2094.     add    al,dl
  2095.     mov    newusr,al
  2096.     jmps    defs20
  2097. defs50:    inc    bx        ;we've seen a colon, it must be followed
  2098.     cmp    byte ptr [bx],0    ; by the null we stored earlier
  2099.     jne    deferr
  2100.     mov    al,newusr    ;are we setting a new user number?
  2101.     cmp    al,0FFh
  2102.     jne    defs60        ; yes, check its value
  2103.     cmp    al,newdrv    ; otherwise if neither drive nor user
  2104.     jne    defs70        ;  was specified and yet we saw the colon,
  2105.     mov    al,cpmdrv    ;  then return to the initial CP/M defaults.
  2106.     mov    newdrv,al
  2107.     mov    al,cpmusr
  2108. defs60:    cmp    al,15        ;make sure user is in range
  2109.     ja    deferr
  2110.     mov    defusr,al    ;save new user value
  2111.     mov    dl,al
  2112.     call    setusr
  2113. defs70:    mov    al,newdrv    ;are we setting a new drive?
  2114.     cmp    al,0FFh
  2115.     je    defs90
  2116.     mov    defdrv,al    ;save new drive value
  2117.     call    rstdsk        ;reset disk system to log in drive
  2118.     mov    dl,defdrv    ; then select new default
  2119.     call    setdrv
  2120. defs90:    jmp    rskp
  2121. deferr:    mov    dx, offset erms23
  2122.     call    tcrmsg
  2123.     jmp    rskp                        ;[32a] end
  2124.  
  2125. ; Set end-of-line character
  2126.  
  2127. eolset:                            ;[25] begin
  2128.     mov    dx, 01FH    ;maximum value of number allowed. (31)
  2129.     mov    bx, offset eolhlp ;help string for parser
  2130.     mov    ah, cmnum    ;look for a decimal number
  2131.     call    comnd        ;call the parser
  2132.      jmp    r
  2133.     mov    seol, bl    ;set the eol character
  2134.     jmp    rskp
  2135.  
  2136. escape:
  2137.     mov    bx, offset eschlp ;help string for parser
  2138.     mov    ah, cmcha    ;parser code for single character
  2139.     call    comnd        ;call parser
  2140.      jmp    r
  2141.     mov    escchr, bl    ;set the character
  2142.     jmp    rskp
  2143.                                 ;[25] end
  2144.  
  2145. ;    This is the SET file-type (ASCII or BINARY) command    ;[16] begin
  2146.  
  2147. fmset:    mov    dx, offset fmtab
  2148.     mov    bx, offset fmhlp
  2149.     mov    ah, cmkey
  2150.     call    comnd
  2151.      jmp    r
  2152.     mov    temp1, bx
  2153.     mov    ah, cmcfm
  2154.     call     comnd        ;Get a confirm.
  2155.      jmp    r        ;Didn't get a confirm.
  2156.     mov    bx, temp1
  2157.     mov    binflg, bl    ;Set the file-type flag.
  2158.     jmp    rskp                        ;[16] end
  2159.  
  2160. ;    This is the SET Warning command.
  2161.  
  2162. filwar:    mov    dx, offset ontab
  2163.     mov    bx, offset onhlp
  2164.     mov    ah, cmkey
  2165.     call    comnd
  2166.      jmp    r
  2167.     mov    temp1, bx
  2168.     mov    ah, cmcfm
  2169.     call    comnd        ;Get a confirm.
  2170.      jmp    r        ;Didn't get a confirm.
  2171.     mov    bx, temp1
  2172.     mov    flwflg, bl    ;Set the file warning flag.
  2173.     jmp    rskp
  2174.  
  2175. ;        Set flow-control flag            [19a] Begin
  2176.  
  2177. setflo:    mov    dx, offset flotab ;set up ON/OFF response
  2178.     mov    bx, offset flohlp
  2179.     mov    ah, cmkey
  2180.     call    comnd        ;get response
  2181.     jmp    r
  2182.     mov    temp1, bx    ;save response
  2183.     mov    ah, cmcfm
  2184.     call    comnd        ;get confirm
  2185.     jmp    r
  2186.     mov    bx, temp1
  2187.     mov    floctl, bl    ;set flag
  2188.     jmp    rskp                        ;[19a] end
  2189.  
  2190. ;    This is the SET IBM command.
  2191.  
  2192. ibmset:    mov    dx, offset ontab
  2193.     mov    bx, offset onhlp
  2194.     mov    ah, cmkey
  2195.     call    comnd
  2196.      jmp    r
  2197.     mov    temp1, bx
  2198.     mov    ah, cmcfm
  2199.     call    comnd        ;Get a confirm.
  2200.      jmp    r        ;Didn't get a confirm.
  2201.     mov    bx, temp1
  2202.     mov    ibmflg, bl    ;Set the IBM flag.
  2203.     cmp    bl, 0        ;Turning on or off?
  2204.     je    ibmst1        ;If off, set parity & local echo to defaults.
  2205.     mov    parflg, ibmpar    ;Set IBM parity.        ;[21a] begin
  2206.     mov    ecoflg, 1    ;Set local echo on.
  2207.     mov    tmrflg, 1    ;Set timer on.
  2208.     jmps    ibmst2
  2209. ibmst1:    mov    parflg, defpar    ;Set default parity.
  2210.     mov    ecoflg, defeco    ;Set local echo to default.
  2211.     mov    tmrflg, deftmr    ;Set timer to default.
  2212. ibmst2:    jmp    rskp                            ;[21a] end
  2213.  
  2214.  
  2215. ;    This is the LOCAL echo SET subcommand.
  2216.  
  2217. local:    mov    dx, offset ontab
  2218.     mov    bx, offset onhlp
  2219.     mov    ah, cmkey
  2220.     call    comnd
  2221.      jmp    r
  2222.     mov    temp1, bx    ;Save the parsed value.
  2223.     mov    ah, cmcfm
  2224.     call    comnd        ;Get a confirm.
  2225.      jmp    r        ;Didn't get a confirm.
  2226.     mov    bx, temp1
  2227.     mov    ecoflg, bl    ;Set the local echo flag.
  2228.     jmp    rskp
  2229.  
  2230.  
  2231. ;    This is the LOG filename SET command
  2232.  
  2233. log:    mov    ah, cmofi    ;Get an output filename
  2234.     mov    dx, offset lfcb    ;For a log file
  2235.     call    comnd
  2236.      jmp    r
  2237.     cmp    ah,0        ;Check for null filename    ;[32c] begin
  2238.     jne    $+5
  2239.      jmp    r                        ;[32c] end
  2240.     mov    ah, cmcfm    ;Confirm it
  2241.     call    comnd
  2242.      jmp    r
  2243.     mov    logflg, 0FFh    ;Turn logging on
  2244.     jmp    rskp
  2245.  
  2246.  
  2247. ;    This is the SET Parity command.
  2248.  
  2249. setpar:    mov    dx, offset partab
  2250.     mov    bx, offset parhlp
  2251.     mov    ah, cmkey
  2252.     call    comnd
  2253.      jmp    r
  2254.     mov    temp1, bx
  2255.     mov    ah, cmcfm
  2256.     call    comnd        ;Get a confirm.
  2257.      jmp    r        ;Didn't get a confirm.
  2258.     mov    bx, temp1
  2259.     mov    parflg, bl    ;Set the parity flag.
  2260.     jmp    rskp
  2261.  
  2262. ;    This is the SET Timer command.            ;[21a] begin
  2263.  
  2264. tmrset:    mov    dx, offset ontab
  2265.     mov    bx, offset onhlp
  2266.     mov    ah, cmkey
  2267.     call    comnd
  2268.      jmp    r
  2269.     mov    temp1, bx
  2270.     mov    ah, cmcfm
  2271.     call    comnd        ;Get a confirm.
  2272.      jmp    r        ;Didn't get a confirm.
  2273.     mov    bx, temp1
  2274.     mov    tmrflg, bl    ;Set the timer flag.
  2275.     jmp    rskp                    ;[21a] end
  2276.                             ;[21c] end
  2277.  
  2278. ;    The following are display subroutines used primarily    ;[21c] begin
  2279. ;    in the SHOW command.
  2280.  
  2281.                                 ;[10] begin
  2282. ;    This routine matches a table value and prints the corresponding
  2283. ;    keyword.  On entry:
  2284. ;            al = value to match
  2285. ;            bx = beginning address of table
  2286.  
  2287. tabprt:    mov    ah, 0        ;make it a word comparison
  2288.     mov    ch, [bx]    ;get the table size
  2289.     inc    bx
  2290. tabp1:    mov    dl, [bx]    ;get the offset to the value
  2291.     inc    bx        ;point to beginning of the keyword
  2292.     mov    dh, 0
  2293.     mov    si, dx
  2294.     cmp    ax, 1[bx+si]    ;does the value match?
  2295.     je    tabp2        ;yes, go print the keyword at [bx].
  2296.     add    bx, dx        ;otherwise go to next entry
  2297.     add    bx, 3
  2298.     dec    ch        ;any more entries
  2299.     jnz    tabp1        ;if so, go check the next
  2300.     mov    bx, offset erms20 ;else say value was not found
  2301. tabp2:    mov    dx, bx
  2302.     call    tmsg        ;display the keyword
  2303.     ret
  2304.                                 ;[10] end
  2305.  
  2306. ; This routine prints out the escape character in readable format.
  2307. ;    Call CTLPRT with any char in DL for similar output.
  2308.  
  2309. escprt:    mov    dl, escchr
  2310. ctlprt:    cmp    dl, ' '
  2311.     jge    escpr2
  2312.     push    dx
  2313.     mov    dx, offset esctl ;Print "Control-"
  2314.     call    tmsg
  2315.     pop    dx
  2316.     add    dl, 040H    ;Make it printable.
  2317. escpr2:    call    bout
  2318.     ret
  2319.  
  2320. ;    This routine prints "is on" if prior comparison was nonzero
  2321. ;    and otherwise prints "is off"
  2322.  
  2323. ponoff:    jz    ponof2        ;If not say so.
  2324.     mov    dx, offset onstr ;Say on.
  2325.     jmp    ponof3
  2326. ponof2:    mov    dx, offset offstr ;Say off.
  2327. ponof3:    call    tmsg
  2328.     ret
  2329.  
  2330. ; SHOW - Show the state of the parameters available from the SET command.
  2331.  
  2332. show:    mov    ah,cmcfm    ;Parse a confirm.
  2333.     call    comnd
  2334.      jmp    r
  2335.     call    tcrlf
  2336.  
  2337.     call    shobd        ;Display baud rate (system dependent)
  2338.  
  2339.     mov    dx, offset debst ;Debugging string.
  2340.     call    tcrmsg
  2341.     cmp    debug, 0    ;Is the debugging flag on?
  2342.     call    ponoff
  2343.  
  2344.     mov    dx, offset eolst ;End of line string.        ;[10] begin
  2345.     call    tcrmsg
  2346.     mov    dl, seol
  2347.     call    ctlprt                        ;[10] end
  2348.  
  2349.     mov    dx, offset escst ;Escape string.
  2350.     call    tcrmsg
  2351.     call    escprt        ;Print the escape char.
  2352.  
  2353.     mov    dx, offset fmst    ;File type string. [22d]    ;[16] begin
  2354.     call    tcrmsg
  2355.     mov    al, binflg    ;Print the keyword corresponding to the
  2356.     mov    bx, offset fmtab ;current value of binflg
  2357.     call    tabprt                        ;[16] end
  2358.  
  2359.     mov    dx, offset flostr                ;[19a] start
  2360.     call    tcrmsg        ;
  2361.     mov    al, floctl    ;show the current
  2362.     mov    bx, offset flotab ;setting for flow-control
  2363.     call    tabprt                        ;[19a] end
  2364.  
  2365.     mov    dx, offset ibmst ;IBM string.
  2366.     call    tcrmsg
  2367.     cmp    ibmflg, 0    ;Is the IBM flag on?
  2368.     call    ponoff
  2369.  
  2370.     mov    dx, offset locst ;Get the address of the local echo string.
  2371.     call    tcrmsg
  2372.     cmp    ecoflg, 0    ;Is the local echo flag on?
  2373.     call    ponoff        ;Print on or off.
  2374.  
  2375.     mov    dx, offset logst ;Logging string.
  2376.     call    tcrmsg
  2377.     mov    dx, offset lfcb    ;Print the log filename.
  2378.     call    tfile
  2379.     cmp    logflg, 0    ;Is the logging flag on?
  2380.     call    ponoff
  2381.  
  2382.     mov    dx, offset parst ;Parity string.
  2383.     call    tcrmsg
  2384.     mov    al, parflg    ;Print the keyword corresponding ;[10] begin
  2385.     mov    bx, offset partab ;to the current value of parflg
  2386.     call    tabprt
  2387.  
  2388.     call    shoprt        ;Port selection (system dependent) ;[30d]
  2389.  
  2390.     mov    dx, offset tmrst ;Timer on/off string        ;[21a] begin
  2391.     call    tcrmsg
  2392.     cmp    tmrflg, 0    ;Is the timer on?
  2393.     call    ponoff        ;Print on or off.        ;[21a] end
  2394.  
  2395.     mov    dx, offset filst ;File warning string.
  2396.     call    tcrmsg
  2397.     cmp    flwflg, 0    ;Is the file warning flag on?
  2398.     call    ponoff
  2399.  
  2400.     call    tcrlf        ;Print a crlf
  2401.     jmp    rskp                        ;[21c] end
  2402.  
  2403.  
  2404. dspver:    call    clrscr        ;Home cursor and clear the screen ;[30c] begin
  2405.     mov    dx, offset scrhdr ;Position to the version line.
  2406.     call    poscur
  2407.     call    bldon        ;Turn on bold (highlighted) display
  2408.     mov    dx, offset system ;Print the system identification
  2409.     call    tmsg
  2410.     mov    dx, offset versio ;Print the Kermit version header.
  2411.     call    tmsg
  2412.     call    bldoff        ;Turn off the highlight    ;[30c] end
  2413.     ret
  2414.  
  2415.  
  2416.     DSEG            ;Data segment.
  2417.  
  2418.     ORG    100H        ;Leave room for system page.
  2419.  
  2420.     RW    100        ;hundred word or so stack.
  2421. stack    RW    2
  2422.  
  2423.     ; COMND tables
  2424.  
  2425. comtab    db    22
  2426.     db    3,'BYE$'
  2427.     dw    bye
  2428.     db    7,'CONNECT$'
  2429.     dw    telnet
  2430.     db    6,'DELETE$'                    ;[32d] begin
  2431.     dw    locera
  2432.     db    9,'DIRECTORY$'
  2433.     dw    locdir
  2434.     db    5,'ERASE$'
  2435.     dw    locera                        ;[32d] end
  2436.     db    4,'EXIT$'
  2437.     dw    exit
  2438.     db    6,'FINISH$'
  2439.     dw    finish
  2440.     db    3,'GET$'
  2441.     dw    get
  2442.     db    4,'HELP$'
  2443.     dw    help
  2444.     db    5,'LOCAL$'                    ;[32d]
  2445.     dw    loccmd                        ;[32d]
  2446.     db    6,'LOGOUT$'
  2447.     dw    logout
  2448.     db    4,'QUIT$'                    ;[29f]
  2449.     dw    exit                        ;[29f]
  2450.     db    7,'RECEIVE$'
  2451.     dw    rec
  2452.     db    6,'REMOTE$'                    ;[32d]
  2453.     dw    remcmd                        ;[32d]
  2454.     db    4,'SEND$'
  2455.     dw    sencom
  2456.     db    3,'SET$'
  2457.     dw    setcom
  2458.     db    4,'SHOW$'
  2459.     dw    show
  2460.     db    5,'SPACE$'                    ;[32d]
  2461.     dw    locsiz                        ;[32d]
  2462.     db    6,'STATUS$'
  2463.     dw    status
  2464.     db    4,'TAKE$'                    ;[29b]
  2465.     dw    take                        ;[29b]
  2466.     db    8,'TRANSMIT$'                    ;[32e]
  2467.     dw    txmit                        ;[32e]
  2468.     db    4,'TYPE$'                    ;[34b]
  2469.     dw    loctyp                        ;[34b]
  2470.  
  2471. settab    db    14
  2472.     db    4,'BAUD$'
  2473.     dw    bdset                        ;[6] end
  2474.     db    9,'DEBUGGING$'
  2475.     dw    debset
  2476.     db    12,'DEFAULT-DISK$'                ;[32a] begin
  2477.     dw    defset                        ;[32a] end
  2478.     db    11,'END-OF-LINE$'
  2479.     dw    eolset
  2480.     db    6,'ESCAPE$'
  2481.     dw    escape
  2482.     db    9,'FILE-TYPE$'            ;[16] begin [21b]
  2483.     dw    fmset                    ;[16] end
  2484.     db    13,'FLOW-CONTROL$'                ;[19a]
  2485.     dw    setflo                        ;[19a]
  2486.     db    3,'IBM$'
  2487.     dw    ibmset
  2488.     db    10,'LOCAL-ECHO$'
  2489.     dw    local
  2490.     db    3,'LOG$'                    ;[24a]
  2491.     dw    log                        ;[24a]
  2492.     db    6,'PARITY$'
  2493.     dw    setpar
  2494.     db    4,'PORT$'                    ;[30d]
  2495.     dw    prtset
  2496.     db    5,'TIMER$'                    ;[21a]
  2497.     dw    tmrset                        ;[21a]
  2498.     db    7,'WARNING$'
  2499.     dw    filwar
  2500.  
  2501. loctab    db    5                        ;[32d] begin
  2502.     db    6,'DELETE$'
  2503.     dw    locera
  2504.     db    9,'DIRECTORY$'
  2505.     dw    locdir
  2506.     db    5,'ERASE$'
  2507.     dw    locera
  2508.     db    5,'SPACE$'
  2509.     dw    locsiz                        ;[32d] end
  2510.     db    4,'TYPE$'                    ;[34b]
  2511.     dw    loctyp                        ;[34b]
  2512.  
  2513. ontab    db    2        ;Two entries.
  2514.     db    3,'OFF$'                    ;[5] begin
  2515.     dw    0000H
  2516.     db    2,'ON$'
  2517.     dw    0001H                        ;[5] end
  2518.  
  2519. yestab    db    2        ;Two entries.
  2520.     db    2,'NO$'
  2521.     dw    0000H
  2522.     db    3,'YES$'
  2523.     dw    0001H
  2524.  
  2525. flotab    db    2        ;[19a] start
  2526.     db    4,'NONE$'
  2527.     dw    flonon
  2528.     db    8,'XON/XOFF$'
  2529.     dw    floxon        ;[19a] end
  2530.  
  2531. partab    db    5        ;Five entries.
  2532.     db    4,'EVEN$'
  2533.     dw    parevn
  2534.     db    4,'MARK$'
  2535.     dw    parmrk
  2536.     db    4,'NONE$'
  2537.     dw    parnon
  2538.     db    3,'ODD$'
  2539.     dw    parodd
  2540.     db    5,'SPACE$'
  2541.     dw    parspc
  2542.  
  2543. fmtab    db    2        ;Two entries.            ;[16] begin
  2544.     db    5,'ASCII$'
  2545.     dw    00H
  2546.     db    6,'BINARY$'
  2547.     dw    01H                        ;[16] end
  2548.  
  2549. hlpmsg    db    cr,lf,'Type ? at any point for help$'
  2550. cfrmes    db    ' Confirm with carriage return $'
  2551. filhlp    db    ' Input file spec (possibly wild) $'
  2552.  
  2553. tophlp    db    cr,lf,'      Basic Commands                            Other Commands'
  2554.     db    cr,lf,'CONNECT to host as a terminal             DELETE local files'
  2555.     db    cr,lf,'RECEIVE file(s) from host                 DIRECTORY of local files'
  2556.     db    cr,lf,'SEND file(s) to host                      HELP by giving this message'
  2557.     db    cr,lf,'SET a Kermit parameter                    LOCAL generic command'
  2558.     db    cr,lf,'SHOW the parameter values                 QUIT (same as EXIT)'
  2559.     db    cr,lf,'EXIT to CP/M                              SPACE remaining on disk'
  2560.     db    cr,lf,'                                          STATUS of Kermit'
  2561.     db    cr,lf,'      Server Commands                     TAKE command input from file'
  2562.     db    cr,lf,'GET file(s) from host                     TYPE local file on screen'
  2563.     db    cr,lf,'SEND file(s) to host'
  2564.     db    cr,lf,'REMOTE generic command'
  2565.     db    cr,lf,'FINISH running Kermit on the host'
  2566.     db    cr,lf,'LOGOUT the host'
  2567.     db    cr,lf,'BYE to host (LOGOUT, then EXIT)'
  2568.     db    '$'
  2569.  
  2570. sethlp    db    cr,lf,'BAUD rate'                ;[6]
  2571.     db    cr,lf,'DEBUGGING displays of transferred packets'
  2572.     db    cr,lf,'DEFAULT-DISK for file operations'    ;[32a]
  2573.     db    cr,lf,'END-OF-LINE character in packets'
  2574.     db    cr,lf,'ESCAPE character from terminal mode'
  2575.     db    cr,lf,'FILE-TYPE (ASCII or BINARY)'        ;[16][21b]
  2576.     db    cr,lf,'FLOW-CONTROL (NONE or XON/XOFF)'        ;[19a]
  2577.     db    cr,lf,'IBM mainframe communications mode'
  2578.     db    cr,lf,'LOCAL-ECHO echoing (half-duplex)'
  2579.     db    cr,lf,'LOG filename for terminal session logging' ;[24a]
  2580.     db    cr,lf,'PARITY type'
  2581.     db    cr,lf,'PORT to communicate on'            ;[30d]
  2582.     db    cr,lf,'TIMER for packet retransmission'        ;[21a]
  2583.     db    cr,lf,'WARNING for received filename conflicts'
  2584.     db    '$'
  2585.  
  2586. lochlp    db    cr,lf,'DELETE local files'            ;[32d] begin
  2587.     db    cr,lf,'DIRECTORY of local files'
  2588.     db    cr,lf,'SPACE remaining on disk'
  2589.     db    cr,lf,'TYPE local files on screen'        ;[34b]
  2590.     db    '$'                        ;[32d] end
  2591.  
  2592. flohlp    db    cr,lf,'NONE    XON/XOFF$'
  2593. onhlp    db    cr,lf,'OFF    ON$'
  2594. yeshlp    db    cr,lf,'NO    YES$'
  2595. parhlp    db    cr,lf,'NONE   MARK   ODD   EVEN   SPACE$'
  2596. fmhlp    db    cr,lf,'ASCII    BINARY$'            ;[16]
  2597. eolhlp    db    cr,lf,'Decimal digit between 0 and 31$'
  2598. eolerr    db    cr,lf,'Illegal end-of-line character$'
  2599. timhlp    db    cr,lf,'Decimal digit between 1 and 94$'
  2600. timerr    db    cr,lf,'Illegal timeout value$'
  2601. esctl    db    'Control-$'
  2602. eschlp    db    cr,lf,'Enter literal value (ex: Ctrl ])  $'
  2603. inthlp    db    'Kermit-86: Interrupt - type'        ;[27]
  2604.     db    cr,lf,'    ?   to display this message'    ;[20c] begin
  2605.     db    cr,lf,'    B   to send a Break signal to the port'
  2606.     db    cr,lf,'    C   to return to the Kermit-86> prompt'
  2607.     db    cr,lf,'    L   to toggle terminal session logging'    ;[24a]
  2608.     db    cr,lf,'    Q   to quit terminal session logging'    ;[29e]
  2609.     db    cr,lf,'    R   to resume terminal session logging'    ;[29e]
  2610.     db    cr,lf,'    $'
  2611. inthl2    db    '   to send a $'
  2612. inthl3    db    ' character to the port$'            ;[20c] end
  2613. onstr    db    ' is on$'
  2614. offstr    db    ' is off$'
  2615. flostr    db    'Flow control: $'                ;[19a]
  2616. bdst    db    'Baud rate: $'
  2617. debst    db    'Debug mode$'
  2618. eolst    db    'End-of-line character: $'
  2619. escst    db    'Escape char: $'
  2620. fmst    db    'File type is $'                ;[16][21b]
  2621. ibmst    db    'IBM flag$'
  2622. locst    db    'Local echo$'
  2623. logst    db    'Logging to $'                    ;[24a]
  2624. parst    db    'Parity: $'
  2625. tmrst    db    'Timer$'                    ;[21a]
  2626. timmes    db    'Timeout is $'
  2627. filst    db    'Warning$'
  2628.  
  2629. clrspc    db    ' ',10O,'$'        ;Clear space.
  2630.  
  2631. versio    db    ' CP/M-86 Kermit-86 - V2.9'
  2632.     db    cr,lf,lf,'$'
  2633. kerm    db    'Kermit-86 $'                    ;[32a]
  2634. pktlin    db    cr,'Number of packets:   '
  2635.     db    cr,lf,'Number of retries:   '
  2636.     db    cr,lf,'File name:  $'
  2637. spmes    db    'Spack:  $'
  2638. rpmes     db    'Rpack:  $'
  2639. hibit    db    'Warning - Non-ASCII char$'
  2640. ender    db    bell,bell,'$'
  2641. inms01    db    cr,lf,'[Kermit-86: Connecting to host...' ;[27][fdc]
  2642.     db    cr,lf,'  Type $'            ;[fdc]
  2643. inms02    db    ' C to return to PC, $'            ;[fdc]
  2644. inms25    db    ' ? for help]$'                ;[fdc]
  2645. inms03    db    '[Kermit-86: Back at PC]$'            ;[27]
  2646. infms3    db    'Completed    $'
  2647. infms4    db    'Failed       $'
  2648. infms5    db    'Renaming file to $'
  2649. infms6    db    '%Function not implemented$'
  2650. infms7    db    'Interrupted  $'                ;[19f]
  2651. infms8    db    'File interrupt (^X)  $'            ;[19f]
  2652. infms9    db    'File group interrupt (^Z)  $'            ;[19f]
  2653. infm10    db    ' Type: ^X to interrupt file,  ^Z to '        ;[19f][30c]
  2654.     db    'interrupt group,  ^C to "abort".$'        ;[19g][30c]
  2655. infm11    db    '[Kermit-86: Logging to $'            ;[24a][27]
  2656. infm12    db    ']$'                        ;[24a]
  2657. infm13    db    '[Kermit-86: Logging terminated]$'        ;[24a][27]
  2658. timoms    db    bell,'Timeout$'
  2659. ermes1    db    bell,'?Unrecognized command$'
  2660. ermes2    db    bell,'?Illegal character$'
  2661. ermes3    db    bell,'?Unrecognized command option$'
  2662. ermes4    db    bell,'?Unable to rename file$'
  2663. ermes5    db    bell,'?No receive file specification given$'
  2664. ermes7    db    bell,'?Unable to receive initiate$'
  2665. ermes8    db    bell,'?Unable to receive file name$'
  2666. ermes9    db    bell,'?Unable to receive end of file$'
  2667. erms10    db    bell,'?Unable to receive data$'
  2668. erms11    db    bell,'?Disk directory area full$'            ;[28c]
  2669. erms14    db    bell,'?Unable to receive an acknowledgement from the host$'
  2670. erms15    db    bell,'?Unable to find file $'            ;[28b]
  2671. erms17    db    bell,'?Disk data area full$'                ;[28c]
  2672. erms18    db    bell,'?Unable to tell host that session is finished$'
  2673. erms19    db    bell,'?Unable to tell host to logout$'
  2674. erms20    db    bell,'?Illegal value$'                ;[10]
  2675. erms21    db    '* Aborted *$'                    ;[12]
  2676. erms22    db    bell,'?Cannot open log file $'            ;[24a]
  2677. erms23    db    bell,'?Specify new default drive and (optional) user number as DU:$' ;[32a]
  2678. erms24    db    bell,'?Specify drive as D:$'            ;[32d]
  2679. erms25    db    bell,'?Not enough memory for sort buffer:'    ;[34c]
  2680.     db    cr,lf,'   Local DIRECTORY, DELETE, and TYPE operations'
  2681.     db    cr,lf,'   and wildcard SENDs will not be supported.$'
  2682. erms26    db    bell,'?Illegal filename$'
  2683. erms27    db    bell,'?Memory buffer overflow$'
  2684. erms28    db    bell,'?No filenames above specified starting name$'    ;[34c]
  2685.  
  2686. ; Cursor addressing items (row,col)            ;[19b],[30c] begin
  2687.  
  2688. scrhdr    db    3,1        ;Place for version header
  2689. scrnp    db    5,22        ;Place for number of packets.
  2690. scrnrt    db    6,22        ;Place for number of retries.
  2691. scrfln    db    7,12        ;Place for file name.
  2692. screrr    db    13,1        ;Place for error messages.
  2693. scrst    db    5,53        ;Place for "Complete".
  2694. scrrpr    db    14,1        ;Place for prompt.
  2695. scrhi    db    7,53        ;8th bit on in character.
  2696. scrfr    db    8,1        ;Rename file.            ;[31]
  2697. scrsp    db    9,1        ;Send packet
  2698. scrrp    db    11,1        ;Receive
  2699. scrint    db    6,53        ;[19f] interrupt acknowledge
  2700. scrhlp    db    24,1        ;[19f] help line
  2701.  
  2702.     ; Impure storage
  2703.  
  2704. extflg    db    0        ;Exit flag;non zero to exit.
  2705. ecoflg    db    defeco        ;Echo flag; non zero for local echoing.
  2706. escchr    db    defesc        ;Escape character for the connect command.
  2707. debug    db    diasw        ;Are we in debug mode?
  2708. tmrflg    db    deftmr        ;Is the timer enabled?
  2709. cpmdrv    db    0        ;Initial drive and user        ;[32a] begin
  2710. cpmusr    db    0
  2711. defdrv    db    0        ;Current default drive and user
  2712. defusr    db    0
  2713. newdrv    db    0        ;Storage for resetting drive and user
  2714. newusr    db    0                        ;[32a] end
  2715.  
  2716.  
  2717.     ESEG            ;Extra segment.
  2718.  
  2719.     INCLUDE C86CMD.A86    ;Get the COMND routines.
  2720.     INCLUDE C86FIL.A86    ;Get the file routines.
  2721.  
  2722. ;Note, the following file does not exist.  You have to copy one of the system
  2723. ;dependent files like C86XRB.A86 to a file of this name.
  2724.     INCLUDE C86XXX.A86    ;Get the I/O routines
  2725.  
  2726.     INCLUDE C86PRO.A86    ;Get the protocol routines.
  2727.     INCLUDE C86TRM.A86    ;Get terminal emulation [26]
  2728.     INCLUDE C86UTL.A86    ;Get the utility routines.
  2729.  
  2730.     DSEG $            ;Resume data segment.
  2731.  
  2732.     DB    0        ;Is this really necessary?
  2733.                 ;No, but without it you need to specify
  2734.                 ;link options to GENCMD so as to make the
  2735.                 ;load address allow for uninitialized storage.
  2736.                 ;This bypasses that necessity by including
  2737.                 ;all uninitialized storage in the load
  2738.                 ;module. - RonB
  2739.  
  2740.     END
  2741. <<< c86pro.a86 >>>
  2742. ; C86PRO.A86
  2743. ; * * * * * * * * * * * * * * * * version 3.0 * * ** * * * * * * * * * * * *
  2744. ; Allows packet echo - CGL
  2745. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  2746. ; [34c] Add sorted wildcard SENDs with initial filename
  2747. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  2748. ; [31] Fix display on file renaming.
  2749. ; RonB, 05/05/84
  2750. ; [30c] Isolate ANSI escape sequences for machine independence.
  2751. ; [29g]  Add 8th bit quoting.
  2752. ; [29d]  Enlarge receive buffer and check for packet overruns.
  2753. ; [29b]  Add TAKE processing (close command file when aborting).
  2754. ; [29a]  Send error packet when aborting.
  2755. ; RonB, 04/08/84
  2756. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  2757. ; [28b]  Make file-not-found error more informative (include filename).
  2758. ; [28a]  Clear attribute bits from filename before sending
  2759. ; RonB, 03/27/84
  2760. ; [25] - make KERCMD more modular by eliminating some use of text
  2761. ; strings by other modules (KERPRO, KERSYS), and moving some
  2762. ; parsing into KERCMD (ESCAPE and EOLSET logic in KERSYS)
  2763. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  2764. ;  [21a] Add timeout enable/disable
  2765. ; RonB,03/05/84
  2766. ;  [20a] Fix version & send/receive header
  2767. ;  [20e] Clean up environment better before rebooting in KABORT
  2768. ; RonB,03/02/84
  2769. ;  [19f] Add ^X/^Z file interruption - adapted from PC Kermit V1.20
  2770. ;  Put in Help line for above.
  2771. ;  [19g] Put in timeouts.
  2772. ; R. Garland 2/84
  2773. ; * * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * * *
  2774. ;  [14] Fix nout to print decimal.
  2775. ; RonB,12/28/83
  2776. ;  [13] Use control-Z's for filler in partial sectors instead of nulls.
  2777. ; RonB,12/27/83
  2778. ;  [12] Allow user abort from the keyboard in the send and receive routines.
  2779. ; RonB,12/27/83
  2780. ;  [9] Fix filename parsing, and add wildcard ability.
  2781. ; RonB,12/26/83
  2782. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  2783. ; This module contains the routines that actually implement the Kermit
  2784. ; protocol.
  2785.  
  2786. ; Packet definitions.
  2787.  
  2788. maxpkt equ '~'-' '+2O ;Maximum size of a packet.
  2789. maxtry equ 05O  ;Default number of retries on a packet.
  2790. imxtry equ 20O  ;Default number of retries send initiate.
  2791. drpsiz equ 5EH  ;Default receive packet size.
  2792. dspsiz equ 20H  ;Default send packet size.
  2793. dstime equ 0AH  ;Default send time out interval.
  2794. drtime equ 05H  ;Default receive time out interval.
  2795. dspad equ 00H  ;Default send padding.
  2796. drpad equ 00H  ;Default receive padding.
  2797. dspadc equ 00H  ;Default send padding char.
  2798. drpadc equ 00H  ;Default receive padding char.
  2799. dseol equ cr  ;Default send EOL char.
  2800. dreol equ cr  ;Default receive EOL char.
  2801. dsquot equ '#'  ;Default send quote char.
  2802. drquot equ '#'  ;Default receive quote char.
  2803. dqbin equ '&'  ;Default 8th-bit quote char. ;[29g]
  2804.  
  2805. bufsiz equ 80H  ;Size of DMA.
  2806.  
  2807. ; A few control characters
  2808.  
  2809. ctlc equ 03H  ;[19f]
  2810. ctlx equ 18H  ;[19f]
  2811. ctlz equ 1AH  ;[19f]
  2812.  
  2813.  DSEG $
  2814.  
  2815. ; Program storage.
  2816.  
  2817. belflg db 1  ;Use bell.
  2818. incmod db 0  ;Insert Character mode.
  2819. hierr db 0  ;Non-ascii char (non-zero if yes).
  2820. parflg db defpar  ;Parity flag (default none.)
  2821. flwflg db 0  ;File warning flag (default off).
  2822. ibmflg db 0  ;IBM flag (default off).
  2823. vmeflg db 0  ;VME flag (default off);
  2824. incnt dw 0  ;Number of chars read in from port.
  2825. pktptr dw 0  ;Position in receive packet.
  2826. spsiz db dspsiz  ;Send packet size.
  2827. rpsiz db drpsiz  ;Receive packet size.
  2828. stime db dstime  ;Send time out.
  2829. rtime db drtime  ;Receive time out.
  2830. spad db dspad  ;Send padding.
  2831. rpad db drpad  ;Receive padding.
  2832. spadch db dspadc  ;Send padding char.
  2833. rpadch db drpadc  ;Receive padding char.
  2834. seol db dseol  ;Send EOL char.
  2835. reol db dreol  ;Receive EOL char.
  2836. squote db dsquot  ;Send quote char.
  2837. rquote db drquot  ;Receive quote char.
  2838. ebquot db 'Y'  ;Send 8th-bit quote char.  ;[29g]
  2839. pktnum dw 0  ;Packet number.
  2840. numpkt dw 0  ;Total number of packets sent.
  2841. numrtr dw 0  ;Total number of retries.
  2842. numtry db 0  ;Number of tries on this packet.
  2843. oldtry db 0  ;Number of tries on previous packet.
  2844. cxzflg db 0  ;[19f] flag for ^X/^Z file interruption
  2845. state db 0  ;Present state of the automaton.
  2846. packet rb 4  ;Packet (data is part of it).
  2847. data rb 60H  ;Data and checksum field of packet. ;[29d]
  2848. recpkt rb 100H  ;Receive packet storage.  ;[29d]
  2849. temp dw 0
  2850. argblk dw 0  ;For subroutine arguments.
  2851. argbk1 dw 0
  2852. argbk2 dw 0
  2853. argbk3 dw 0
  2854. tickst dw 10*(7470/clckrt);[19g] "magic" formula for loops/tick
  2855.     ;[19g] CLCKRT is the system clock rate ...
  2856.     ;[19g] ... defined in KERIO
  2857. ticklp dw 0  ;[19g] Dynamic loop count for tick
  2858. tickct db dstime  ;[19g] # ticks for timeout to occur
  2859. tmodon db 0  ;[19g] flag for time-out message
  2860.  
  2861.  CSEG $
  2862.  
  2863. ; Check for a user abort or interrupt during the send or receive ;[12] begin
  2864. ;   modified by Rg.
  2865. kabort:
  2866.  call dbinst  ;Check if a char has been typed.
  2867.   jmp r  ;[19f]  Merrily return.
  2868.  call dbin  ;Get the character.
  2869.  cmp al, ctlc ;Abort if control-C [19f]
  2870.  je kabrt2
  2871.  cmp al, ctlx ;[19f] Is it control-x ?
  2872.  je kabrta  ;[19f] yes
  2873.  cmp al, ctlz ;[19f] control-z ?
  2874.  jne kabrtb  ;[19f] no
  2875. kabrta: add al, 100O ;[19f] make into 'X' or 'Z'
  2876.  mov cxzflg, al ;[19f] set the flag
  2877.  call intmsg  ;[19f] reassure the user
  2878.  ret   ;[19f] return
  2879. kabrtb: cmp al, cr  ;if <cr> do a timeout  ;[29a] begin
  2880.  jne kabrtc
  2881.  pop bx  ;return of kabort
  2882.  pop bx  ;receive packet pointer
  2883.     ;... next is return of inpkt
  2884.  ret   ;return to timeout routine ;[29a] end
  2885. kabrtc: cmp al, escchr ;or the escape character followed by 'C'.
  2886.  jne kabrt9
  2887.  mov cx, 1000 ;Only wait just so long for the next char.
  2888. kabrt1: push cx
  2889.  call dbin
  2890.  pop cx
  2891.  cmp al, 0
  2892.  loope kabrt1
  2893.  cmp al, ctlc ;Control-C also works here. [19f]
  2894.  je kabrt2
  2895.  and al, 137O ;Capitalize it.
  2896.  cmp al, 'C'  ;If not a 'C' then continue.
  2897.  jne kabrt9
  2898. kabrt2: cmp tkflg, 0 ;Close any command file in use ;[29b] begin
  2899.  je kabrt3
  2900.  call tkcls      ;[29b] end
  2901. kabrt3: call binst  ;Clear out extraneous input ;[29a] begin
  2902.   jmp kabrt4 ;If none, go abort this transmission.
  2903.  call bin
  2904.  jmps kabrt2
  2905. kabrt4: pop bx  ;return from kabort
  2906.  pop bx  ;receive packet pointer
  2907.  pop bx  ;return from inpkt
  2908.  pop bx  ;return from rpack
  2909.     ;... next is return from r??? to read
  2910.  mov dx, offset erms21 ;Print '* aborted *' message.
  2911.  jmp fatal      ;[29a] end
  2912. kabrt9: mov dl, bell ;beep    [19f]
  2913.  call dbout  ;    [19f]
  2914.  ret   ;return no error  [19f]
  2915.  
  2916.  
  2917. ; Send the generic finish command to the remote Kermit.
  2918.  
  2919. finsen: mov ah, 'F'  ;Ask for the finish command.
  2920.  call gensen
  2921.  ret
  2922.  
  2923.  
  2924. ; Send the generic logout command to the remote Kermit.
  2925.  
  2926. byesen: mov ah, 'L'  ;Ask for the logout command.
  2927.  call gensen
  2928.  ret
  2929.  
  2930.  
  2931. ; This procedure processes all the generic single packet sends.
  2932.  
  2933. gensen: mov temp, ax ;Save the specific generic command.
  2934.  mov numtry, 0 ;Initialize count.
  2935.  call cfibf  ;Clear out input buffer of extra NAKs.
  2936. fins1: mov ah, numtry
  2937.  cmp ah, maxtry ;Too many times?
  2938.  js fins3  ;Nope, try it.
  2939. fins2: mov dx, offset erms18
  2940.  call tcrmsg
  2941.  ret
  2942.  
  2943. fins3: inc numtry  ;Increment number of tries.
  2944.  mov argblk, 0 ;Packet number zero.
  2945.  mov argbk1, 1 ;One piece of data.
  2946.  mov bx, offset data
  2947.  mov ax, temp ;Get the generic command.
  2948.  mov [bx], ah ;Finish running Kermit.
  2949.  mov ah, 'G'  ;Generic command packet.
  2950.  call spack
  2951.   jmp fins2 ;Tell user and die.
  2952.  call rpack  ;Get ACK.
  2953.   jmp fins1  ;Go try again.
  2954.  cmp ah, 'Y'  ;Got an ACK?
  2955.  jnz fins4
  2956.  ret   ;Yes, then we're done.
  2957. fins4: cmp ah, 'E'  ;Error packet?
  2958.  jnz fins1  ;Try sending it again.
  2959.  call error1
  2960.  ret
  2961.  
  2962. ; Packet routines
  2963.  
  2964. ; Send_Packet
  2965. ; This routine assembles a packet from the arguments given and sends it
  2966. ; to the host.
  2967. ;
  2968. ; Expects the following:
  2969. ; AH     - Type of packet (D,Y,N,S,R,E,F,Z,T)
  2970. ; ARGBLK - Packet sequence number
  2971. ; ARGBK1 - Number of data characters
  2972. ;
  2973. ; Returns: +1 always
  2974.  
  2975. spack: push ax  ;Save the packet type.
  2976.  mov bx, offset packet ;Get address of the send packet.
  2977.  mov ah, soh  ;Get the start of header char.
  2978.  mov [bx], ah ;Put in the packet.
  2979.  inc bx  ;Point to next char.
  2980.  mov ax, argbk1 ;Get the number of data chars.
  2981.  xchg ah, al
  2982.  add ah, ' '+3 ;Real packet character count made printable.
  2983.  mov [bx], ah ;Put in the packet.
  2984.  inc bx  ;Point to next char.
  2985.  mov cl, ah  ;Start the checksum.
  2986.  mov ax, argblk ;Get the packet number.
  2987.  xchg ah, al
  2988.  add ah, ' '  ;Add a space so the number is printable.
  2989.  mov [bx], ah ;Put in the packet.
  2990.  inc bx  ;Point to next char.
  2991.  add cl, ah  ;Add the packet number to the checksum.
  2992.  pop ax  ;Get the packet type.
  2993.  mov [bx], ah ;Put in the packet.
  2994.  inc bx  ;Point to next char.
  2995.  add cl, ah  ;Add the type to the checksum.
  2996.  mov dx, argbk1 ;Get the packet size.
  2997. spack2: cmp dx, 0  ;Are there any chars of data?
  2998.   jz spack3  ; No, finish up.
  2999.  dec dx  ;Decrement the char count.
  3000.  mov ah, [bx] ;Get the next char.
  3001.  inc bx  ;Point to next char.
  3002.  add cl, ah  ;Add the char to the checksum.
  3003.  jmp spack2  ;Go try again.
  3004. spack3:
  3005. sp3x: mov ah, cl  ;Get the character total.
  3006.  mov ch, cl  ;Save here too (need 'cl' for shift).
  3007.  and ah, 0C0H ;Turn off all but the two high order bits.
  3008.  mov cl, 6
  3009.  shr ah, cl  ;Shift them into the low order position.
  3010.  mov cl, ch
  3011.  add ah, cl  ;Add it to the old bits.
  3012.  and ah, 3FH  ;Turn off the two high order bits.  (MOD 64)
  3013.  add ah, ' '  ;Add a space so the number is printable.
  3014.  mov [bx], ah ;Put in the packet.
  3015.  inc bx  ;Point to next char.
  3016.  mov ah, seol ;Get the EOL the other host wants.
  3017.  mov [bx], ah ;Put in the packet.
  3018.  inc bx  ;Point to next char.
  3019.  mov ah, 0  ;Get a null.
  3020.  mov [bx], ah ;Put in the packet.
  3021.  cmp debug, 0 ;debug mode.
  3022.  je spack4
  3023.  inc bx
  3024.  mov ah, '$'
  3025.  mov [bx], ah
  3026.  mov dx, offset scrsp ;Print string to move cursor.
  3027.  call poscur      ;[30c] begin
  3028.  call clreol  ;Clear current line
  3029.  mov dl, lf  ;  and next one
  3030.  call bout
  3031.  call clreol
  3032.  mov dx, offset scrsp ;Print string to move cursor.
  3033.  call poscur      ;[30c] end
  3034.  mov dx, offset spmes
  3035.  call tmsg
  3036.  mov dx, offset packet
  3037.  call tmsg  ;Debug end.
  3038. spack4: call outpkt  ;Call the system dependent routine.
  3039.  jmp rskp
  3040.  
  3041.  
  3042. ; Write out a packet.
  3043.  
  3044. outpkt: mov dh, spad ;Get the number of padding chars.
  3045. outpk2: dec dh
  3046.  cmp dh, 0
  3047.  jl outpk3  ;If none left proceed.
  3048.  mov al, spadch ;Get the padding char.
  3049.  call prtout  ;Output it.
  3050.  jmp outpk2
  3051. outpk3: mov bx, offset packet ;Point to the packet.
  3052. outlup: mov al, [bx] ;Get the next character.
  3053.  cmp al, 0  ;Is it a null?
  3054.  jnz outlp2
  3055.  ret
  3056. outlp2: call prtout  ;Output the character.
  3057.  inc bx  ;Increment the char pointer.
  3058.  jmp outlup
  3059.  
  3060.  
  3061. ; Receive_Packet
  3062. ; This routine waits for a packet arrive from the host.
  3063.  
  3064. rpack: call inpkt  ;Read up to a carriage return.
  3065.   jmp rptimo  ; User timed us out.
  3066. rpack0: call getchr  ;Get a character.
  3067.   jmp rpack  ; Hit the carriage return, go try again.
  3068.  cmp ah, soh  ;Is the char the start of header char?
  3069.   jne rpack0  ; No, go until it is.
  3070. rpack1: call getchr  ;Get a character.
  3071.   jmp r  ; Hit the carriage return, return bad.
  3072.  cmp ah, soh  ;Is the char the start of header char?
  3073.   jz rpack1  ; Yes, then go start over.
  3074.  mov cl, ah  ;Start the checksum.
  3075.  sub ah, ' '+3 ;Get the real data count.
  3076.  mov dh, ah  ;Save it for later.
  3077.  mov al, ah  ;Swap halves.
  3078.  mov ah, 0
  3079.  mov argbk1, ax ;Save the data count.
  3080.  call getchr  ;Get a character.
  3081.   jmp r  ; Hit the carriage return, return bad.
  3082.  cmp ah, soh  ;Is the char the start of header char?
  3083.   jz rpack1  ; Yes, then go start over.
  3084.  add cl, ah  ;Add it to the checksum.
  3085.  sub ah, ' '  ;Get the real packet number.
  3086.  mov al, ah  ;Swap halves.
  3087.  mov ah, 0
  3088.  mov argblk, ax ;Save the packet number.
  3089.  call getchr  ;Get a character.
  3090.   jmp r  ; Hit the carriage return, return bad.
  3091.  cmp ah, soh  ;Is the char the start of header char?
  3092.   jz rpack1  ; Yes, then go start over.
  3093.  mov temp, ax ;Save the message type.
  3094.  ; CGL mod for VME packet echo
  3095.  cmp ah, packet + 3       ; compare with the type of this received one
  3096.  je rpack           ; if the same go back and get next
  3097.  ; end of CGL mod
  3098.  add cl, ah  ;Add it to the checksum.
  3099.  mov bx, offset data ;Point to the data buffer.
  3100. rpack2: dec dh  ;Any data characters?
  3101.   js rpack3  ; If not go get the checksum.
  3102.  call getchr  ;Get a character.
  3103.   jmp r  ; Hit the carriage return, return bad.
  3104.  cmp ah, soh  ;Is the char the start of header char?
  3105.   jz rpack1  ; Yes, then go start over.
  3106.  mov [bx], ah ;Put the char into the packet.
  3107.  inc bx  ;Point to the next character.
  3108.  add cl, ah  ;Add it to the checksum.
  3109.  jmp rpack2  ;Go get another.
  3110. rpack3: call getchr  ;Get a character.
  3111.   jmp r  ; Hit the carriage return, return bad.
  3112.  cmp ah, soh  ;Is the char the start of header char?
  3113.   jz rpack1  ; Yes, then go start over.
  3114.  sub ah, ' '  ;Turn the char back into a number.
  3115.  mov dh, cl  ;Get the character total.
  3116.  and dh, 0C0H ;Turn off all but the two high order bits.
  3117.  mov ch, cl
  3118.  mov cl, 6
  3119.  shr dh, cl  ;Shift them into the low order position.
  3120.  mov cl, ch
  3121.  add dh, cl  ;Add it to the old bits.
  3122.  and dh, 3FH  ;Turn off the two high order bits.  (MOD 64)
  3123.  cmp dh, ah  ;Are they equal?
  3124.   jz rpack4  ; If so finish up.
  3125.  call cfibf  ;Clear out any other characters on the line.
  3126.  ret   ;And return failure.
  3127.  
  3128. rpack4: mov ah, 0
  3129.  mov [bx], ah ;Put a null at the end of the data.
  3130.  mov ax, temp ;Get the type.
  3131.  call cfibf  ;Clear out any other characters on the line.
  3132.  jmp rskp
  3133.  
  3134. rptimo: call cfibf  ;On a time out clear out any remaining chars.
  3135.  ret
  3136.  
  3137. inpkt: mov bx, offset recpkt ;Point to the beginning of the packet.
  3138.  mov incnt, 0
  3139. inpkt2: mov al, stime ;[19g] set up timeout loop.
  3140.  mov tickct, al ;[19g]
  3141.  mov ax, tickst ;[19g] "magic" number loops/tick
  3142.  mov ticklp, ax ;[19g]
  3143. inpkta: cmp tmrflg, 0 ;Is timeout disabled?   ;[21a]
  3144.  je inpktb  ;  If so, skip tick routine  ;[21a]
  3145.  dec ticklp  ;[19g]
  3146.  cmp ticklp, 0 ;[19g] done this tick?
  3147.  jne inpktb  ;[19g] not yet
  3148.  mov ax, tickst ;[19g] reload loop count
  3149.  mov ticklp, ax ;[19g]
  3150.  call ticmsg  ;[19g] beep for debugging
  3151.  dec tickct  ;[19g]
  3152.  cmp tickct, 0 ;[19g] timed-out?
  3153.  jne inpktb  ;[19g] not yet
  3154.  call tmomsg  ;[19g] alert user
  3155.  jmp inpkt9  ;[19g] go time-out
  3156. inpktb: push bx  ;[19g][12] bx gets trashed by kb status check.
  3157.  call kabort  ;[19g] Doesn't return if user aborted.
  3158.  pop bx  ;[19g]
  3159.  call instat  ;Any char there?
  3160.   jmp inpkta  ; Go until there is one.
  3161.  call inchr  ;Get the character.
  3162.  mov [bx], al ;Put the char in the packet.
  3163.  inc bx
  3164.  inc incnt
  3165.  cmp incnt, length recpkt ;Have we overrun the input buffer? ;[29d]
  3166.  jb inpktc
  3167.  jmp inpkt  ;If so, just clear and restart
  3168. inpktc: cmp al, reol ;Is it the EOL char?  ;[29d] end
  3169.  jne inpkt2  ;If not loop for another.
  3170.  cmp incnt, 1 ;Ignore bare CR.
  3171.  jne inpkt6
  3172.  jmp  inpkt
  3173. inpkt6: cmp ibmflg, 0 ;Is this the (dumb) IBM mainframe?
  3174.  jz inpkt4  ;If not then proceed.
  3175. inpkt5: cmp state, 'S' ;Check if this is the Send-Init packet.
  3176.  jz inpkt4  ;If so don't wait for the XON.
  3177. inpkt3: call instat  ;Wait for the turn around char.
  3178.   jmp inpkt3
  3179.  call inchr
  3180.  cmp al, xon  ;Is it the IBM turn around character?
  3181.  jne inpkt3  ;If not, go until it is.
  3182. inpkt4: cmp debug, 0
  3183.  jz inpkt7  ;If not debugging don't print the packet.
  3184.  mov al, '$'  ;Get a dollar sign.
  3185.  mov [bx], al ;Put in the packet.
  3186.  inc bx  ;Point to next char.
  3187.  mov dx, offset scrrp ;Print the packet.
  3188.  call poscur      ;[30c] begin
  3189.  call clreol  ;Clear current line
  3190.  mov dl, lf  ;  and next one
  3191.  call bout
  3192.  call clreol
  3193.  mov dx, offset scrrp ;Print string to move cursor.
  3194.  call poscur      ;[30c] end
  3195.  mov dx, offset rpmes
  3196.  call tmsg
  3197.  mov dx, offset recpkt
  3198.  call tmsg
  3199.  
  3200. inpkt7: mov bx, offset recpkt
  3201.  mov pktptr, bx ;Save the packet pointer.
  3202.  call tmoclr  ;[19g] Clear timeout message
  3203.  jmp rskp  ;If so we are done.
  3204.  
  3205. inpkt9: ret   ;return failure on time out.
  3206.  
  3207.  
  3208. getchr: push bx
  3209.  mov bx, pktptr ;Get the packet pointer.
  3210.  mov ah, [bx] ;Get the char.
  3211.  inc bx
  3212.  mov pktptr, bx
  3213.  pop bx  ;Restore BX.
  3214.  cmp ah, reol ;Is it the EOL char?
  3215.  jne getcr2  ;If not return retskp.
  3216.  ret   ;If so return failure.
  3217. getcr2: jmp rskp
  3218.  
  3219.  
  3220. ;This is where we go if we get an error packet.  A call to ERROR
  3221. ; positions the cursor and prints the message.  A call to ERROR1
  3222. ; just prints a CRLF and then the message.
  3223.  
  3224. error: mov state, 'A' ;Set the state to abort.
  3225.  mov dx, offset screrr
  3226.  call poscur      ;[30c]
  3227.  jmp error2
  3228. error1: call tcrlf
  3229. error2: mov bx, offset data ;Get to the string.
  3230.  add bx, argbk1 ;Add the length of the data.
  3231.  mov ah, '$'  ;Put a dollar sign at the end.
  3232.  mov [bx], ah
  3233.  mov dx, offset data ;Print the error message.
  3234.  call tmsg
  3235.  ret
  3236.  
  3237. ; Jump here if we die during a transfer.  Print the error message in
  3238. ; DX and abort.
  3239.  
  3240. fatal: push dx  ;Save the error message.
  3241.  mov dx, offset screrr
  3242.  call poscur      ;[30c]
  3243.  pop dx
  3244.  call tmsg
  3245.  jmp abort  ;Change the state to abort.
  3246.  
  3247. ; Print the status message in DX, ring the bell and position of the prompt.
  3248.  
  3249. fnstat: push dx
  3250.  mov dx, offset scrst ;Print string to move cursor.
  3251.  call poscur      ;[30c]
  3252.  pop dx
  3253.  call tmsg
  3254.  mov dx, offset ender ;Ring them bells.
  3255.  call tmsg
  3256.  mov dx, offset scrhlp ;[19f] Cursor position
  3257.  call poscur      ;[30c]
  3258.  call clreol  ;[19f] Clear help line  ;[30c]
  3259.  mov dx, offset scrrpr ;Put cursor back
  3260.  call poscur      ;[30c]
  3261.  ret
  3262.  
  3263.  
  3264. ; This routine sets up the data for init packet (either the
  3265. ; Send_init or ACK packet).
  3266.  
  3267. rpar: mov ah, rpsiz ;Get the receive packet size.
  3268.  add ah, ' '  ;Add a space to make it printable.
  3269.  mov [bx], ah ;Put it in the packet.
  3270.  mov ah, rtime ;Get the receive packet time out.
  3271.  add ah, ' '  ;Add a space.
  3272.  mov 1[bx], ah ;Put it in the packet.
  3273.  mov ah, rpad ;Get the number of padding chars.
  3274.  add ah, ' '
  3275.  mov 2[bx], ah ;Put it in the packet.
  3276.  mov ah, rpadch ;Get the padding char.
  3277.  add ah, 100O ;Uncontrol it.
  3278.  and ah, 7FH
  3279.  mov 3[bx], ah ;Put it in the packet.
  3280.  mov ah, reol ;Get the EOL char.
  3281.  add ah, ' '
  3282.  mov 4[bx], ah ;Put it in the packet.
  3283.  mov ah, rquote ;Get the quote char.
  3284.  mov 5[bx], ah ;Put it in the packet.
  3285.  mov ah, ebquot ;Get 8th-bit quote char ;[29g] begin
  3286.  mov 6[bx], ah ;Put it in the packet.
  3287.  mov ah, '1'  ;Set single character check type
  3288.  mov 7[bx], ah ;Put it in the packet.
  3289.  mov ah, ' '  ;Set no repeat prefix
  3290.  mov 8[bx], ah ;Put it in the packet.
  3291.  mov ah, 0  ;Initialize capability byte
  3292.  cmp tmrflg, 0 ;Are we able to time out?
  3293.  je rpar1  ;  No, leave bit set to zero
  3294.  or ah, 20h  ;  Otherwise set timeout capability flag
  3295. rpar1: add ah, ' '  ;Add space to make it printable
  3296.  mov 9[bx], ah ;Put it in the packet.
  3297.  mov ah, 10  ;Ten pieces of data.  ;[29g] end
  3298.  ret
  3299.  
  3300. ; This routine reads in all the send_init packet information.
  3301.  
  3302. spar: push cx  ;Save CX.
  3303.  mov cx, ax  ;Save the number of arguments.
  3304.  mov ah, [bx] ;Get the max packet size.
  3305.  sub ah, ' '  ;Subtract a space.
  3306.  mov spsiz, ah ;Save it.
  3307.  mov ax, cx  ;[19g]
  3308.  cmp al, 2  ;[19g] Fewer than two pieces?
  3309.  jge spar1  ;[19g]    ;[29g]
  3310.  jmp sparx1      ;[29g]
  3311. spar1: mov ah, 1[bx] ;[19g] Get the timeout value
  3312.  sub ah, ' '  ;[19g]
  3313.  mov stime, ah ;[19g] save it.
  3314.  mov ax, cx
  3315.  cmp al, 3  ;Fewer than three pieces?
  3316.  jge spar2      ;[29g]
  3317.  jmp sparx2      ;[29g]
  3318. spar2: mov ah, 2[bx] ;Get the number of padding chars.
  3319.  sub ah, ' '
  3320.  mov spad, ah
  3321.  mov ax, cx
  3322.  cmp al, 4  ;Fewer than four pieces?
  3323.  jge spar3      ;[29g]
  3324.  jmp sparx3      ;[29g]
  3325. spar3: mov ah, 3[bx] ;Get the padding char.
  3326.  add ah, 100O ;Re-controlify it.
  3327.  and ah, 7FH
  3328.  mov spadch, ah
  3329.  mov ax, cx
  3330.  cmp al, 5  ;Fewer than five pieces?
  3331.  jge spar4      ;[29g]
  3332.  jmp sparx4      ;[29g]
  3333. spar4: mov ah, 4[bx] ;Get the EOL char.
  3334.  sub ah, ' '
  3335.  mov seol, ah
  3336.  mov ax, cx
  3337.  cmp al, 6  ;Fewer than six pieces?
  3338.  jge spar5      ;[29g]
  3339.  jmp sparx5      ;[29g]
  3340. spar5: mov ah, 5[bx] ;Get the quote char.
  3341.  mov squote, ah
  3342.  mov ax, cx      ;[29g] begin
  3343.  cmp al, 7  ;Fewer than seven pieces?
  3344.  jge spar6
  3345.  jmp sparx6
  3346. spar6: mov ah, 6[bx] ;Get the 8th-bit quote char.
  3347.  call doquo  ;Set the quote character.
  3348.  jmp sparxx
  3349. sparx1: mov stime, dstime ;Default timeout interval
  3350. sparx2: mov spad, dspad ;Default number of padding chars
  3351. sparx3: mov spadch, dspadc ;Default pad character
  3352. sparx4: mov seol, dseol ;Default eol character
  3353. sparx5: mov squote, dsquot ;Default send quote character.
  3354. sparx6: mov ebquot, 'N' ;No 8th bit quoting.
  3355. sparxx: pop cx      ;[29g] end
  3356.  ret   ;If so we are done.
  3357.  
  3358. ; Set 8-bit quote character based on my capabilities  ;[29g] begin
  3359. ; and the other Kermit's request.
  3360.  
  3361. doquo: cmp ebquot,'N' ;Can I do 8-bit quoting at all?
  3362.  je dq2  ;No - so forget it.
  3363.  cmp ebquot,'Y' ;Can I do it if requested?
  3364.  jne dq0  ;No - it's a must that I do it.
  3365.  mov ebquot,ah ;Do whatever he wants.
  3366.  jmp dq2
  3367. dq0: cmp ah,'Y'  ;I need quoting - can he do it?
  3368.  je dq2  ;Yes - then all is settled.
  3369.  cmp ah,'N'  ;No - then don't quote.
  3370.  je dq1
  3371.  cmp ah,ebquot ;Both need quoting - chars must match.
  3372.  je dq2
  3373.  mov ah,'N'
  3374. dq1: mov ebquot,ah
  3375. dq2: mov ah,ebquot
  3376.  cmp ah,rquote ;Same prefix?
  3377.  je dq3  ;Not allowed, so don't do quoting.
  3378.  cmp ah,squote ;Same prefix here?
  3379.  je dq3  ;This is illegal too.
  3380.  ret
  3381. dq3: mov ebquot,'N' ;Quoting will not be done.
  3382.  ret       ;[29g] end
  3383.  
  3384. ; These are some utility routines.
  3385.  
  3386. ; Increment the packet number.
  3387.  
  3388. incpkt: inc ax  ;Increment it.
  3389.  and ax, 3FH  ;Turn off the two high order bits.
  3390.  mov pktnum, ax ;Save modulo 64 of the number.
  3391.  inc numpkt  ;Increment the number of packets.
  3392.  ret
  3393.  
  3394. ; Check if the packet number is the present packet.
  3395.  
  3396. chkpeq: mov ax, argblk ;Get the packet number.
  3397.  cmp ax, pktnum ;Is it the right packet number?
  3398.  je chkpe2
  3399.  ret   ;No.
  3400. chkpe2: jmp rskp  ;Yes.
  3401.  
  3402. ; Is the packet number one more than present.
  3403.  
  3404. chkpom: mov ax, pktnum ;Get the present packet number.
  3405.  inc ax  ;Increment.
  3406.  and ax, 03FH ;Account for wraparound.
  3407.  cmp ax, argblk ;Is the packet's number one more than now?
  3408.  jz chkpm2  ;Yes, success.
  3409.  ret
  3410. chkpm2: jmp rskp
  3411.  
  3412. ; Check if the packet number is the previous packet.
  3413.  
  3414. chkpol: inc oldtry  ;Save the updated number of tries.
  3415.  mov ax, pktnum ;Get the present packet number.
  3416.  cmp ax, 0  ;Had we wrapped around?
  3417.  jne chkpl2
  3418.  mov ax, 64
  3419. chkpl2: dec ax  ;Decrement.
  3420.  cmp ax, argblk ;Is the packet's number one less than now?
  3421.  je chkpl3
  3422.  jmp rskp
  3423. chkpl3: ret
  3424.  
  3425. ; Abort
  3426.  
  3427. abort: mov argblk, 0 ;packet number 0  ;[29a] begin
  3428.  mov argbk1, 0 ;no data
  3429.  mov ah, 'E'  ;error type
  3430.  call spack
  3431.   jmp $       ;[29a] end
  3432.  mov state, 'A' ;Otherwise abort.
  3433.  ret
  3434.  
  3435. ; ACK the packet.
  3436.  
  3437. uupack: call updat  ;[19f] entry which doesn't zero argbk1
  3438.  jmp ack1  ;[19f]
  3439. upack: call updat  ;Update the number of tries.
  3440. ack: mov argbk1, 0 ;No data.  (Packet number already in argblk).
  3441. ack1: mov ah, 'Y'  ;Acknowledge packet.
  3442.  call spack  ;Send the packet.
  3443.   jmp r
  3444.  jmp rskp
  3445.  
  3446. updat: mov ah, numtry ;Get the number of tries.
  3447.  mov oldtry, ah ;Save it.
  3448.  mov numtry, 0 ;Reset the number of tries.
  3449.  ret
  3450.  
  3451. ; Re-ACK the previous packet.
  3452.  
  3453. reack: call nretry  ;Increment and print the number of retries.
  3454.  mov numtry, 0 ;Reset the number of tries.
  3455.  mov ah, 'Y'  ;Acknowledge packet.
  3456.  call spack  ;Send the packet.
  3457.   jmp r
  3458.  jmp rskp
  3459.  
  3460. ; NAK that packet.
  3461.  
  3462. nak: mov ax, pktnum ;Get the packet number we're waiting for.
  3463.  mov argblk, ax
  3464.  mov argbk1, 0
  3465.  mov ah, 'N'  ;NAK that packet.
  3466.  call spack
  3467.   jmp abort
  3468.  call nretry  ;Increment and print the number of retries.
  3469.  ret   ;Go around again.
  3470.  
  3471. ; Print the number of retries.
  3472.  
  3473. nretry: inc numrtr  ;Increment the number of retries.
  3474. pretry: mov dx, offset scrnrt
  3475.  call poscur      ;[30c]
  3476.  mov ax, numrtr
  3477.  call nout  ;Write the number of retries.
  3478.  ret
  3479.  
  3480. ; Print the number of packets.
  3481.  
  3482. pnmpkt: mov dx, offset scrnp ;Print string to move cursor.
  3483.  call poscur      ;[30c]
  3484.  mov ax, numpkt
  3485.  call nout  ;Write the number of packets.
  3486.  ret
  3487.  
  3488. ; This routine prints the number in AX on the screen.
  3489.  
  3490. nout: push ax  ;save all registers  ;[14] begin
  3491.  push bx
  3492.  push cx
  3493.  push dx
  3494.  mov cx, 0  ;number of digits to print
  3495.  mov bx, 10  ;radix to use for dividing
  3496. nout1: mov dx, 0  ;clear high word of dividend
  3497.  div bx  ;divide dx:ax by 10
  3498.  push dx  ;push this remainder
  3499.  inc cx  ;count it
  3500.  cmp ax, 0  ;anything left in the quotient?
  3501.  jne nout1  ;   if so, keep dividing
  3502. nout2: pop dx  ;get a digit
  3503.  add dl, '0'  ;make it ascii
  3504.  push cx  ;save our count
  3505.  call bout  ;print the digit
  3506.  pop cx  ;repeat until all digits printed
  3507.  loop nout2
  3508.  pop dx  ;restore all registers
  3509.  pop cx
  3510.  pop bx
  3511.  pop ax
  3512.  ret
  3513.  
  3514. ; Initialize file buffers and paint screen.
  3515.  
  3516. init:
  3517.  call dspver  ;Clear screen and display version header
  3518.  mov dx, offset scrnp ;Position to packet location
  3519.  call poscur
  3520.  mov dx, offset pktlin      ;[20a]
  3521.  call tmsg
  3522.  mov dx, offset scrhlp ;[19f] Cursor position
  3523.  call poscur  ;[19f] for help line   ;[30c]
  3524.  call revon  ;Bottom line reverse   ;[30c]
  3525.  mov dx, offset infm10 ;[19f] Help for file transfer
  3526.  call tmsg  ;[19f]
  3527.  call revoff       ;[30c]
  3528.  
  3529. init1: mov chrcnt, bufsiz ;Number of chars left.
  3530.  mov bufpnt, offset dma ;Addr for beginning.
  3531.  ret
  3532.  
  3533.  
  3534. ;  Clear out the old filename on the screen.
  3535.  
  3536. clrfln: mov dx, offset scrfr ;Move cursor to file rename. ;[31] begin
  3537.  call poscur
  3538.  call clreol  ;Clear to EOL.   ;[31] end
  3539.  mov dx, offset scrfln ;Move cursor to file name position.
  3540.  call poscur      ;[30c]
  3541.  call clreol  ;Clear to EOL.   ;[30c]
  3542.  ret
  3543.  
  3544. ; acknowledge ^X/^Z with a message  [19f] start
  3545. intmsg: mov dx, offset scrint ;position info
  3546.  call poscur  ;output it   ;[30c]
  3547.  mov dx, offset infms8 ;File message
  3548.  cmp cxzflg, 'X' ;but first check
  3549.  je intm01  ;yes it was X
  3550.  mov dx, offset infms9 ;no it was 'Z' - file group.
  3551.  cmp cxzflg, 'Z' ;or was it?
  3552.  je intm01  ;yes - go output
  3553.  call clreol  ;anything else - clear line ;[30c]
  3554.  jmps intm02      ;[30c]
  3555. intm01: call tmsg  ;output it
  3556. intm02: ret   ;goodbye [19f] end
  3557.  
  3558. ; let the time-out clock "tick" ;[19g] start
  3559. ticmsg: mov dl, bell ;output a ...
  3560.  call dbout  ;... beep!
  3561.  ret
  3562.  
  3563. ; notify of time-out
  3564. tmomsg: mov dx, offset scrst ;cursor position
  3565.  call poscur      ;[30c]
  3566.  mov dx, offset timoms ;timeout message
  3567.  call tmsg
  3568.  mov tmodon, 1 ;flag for message
  3569.  ret
  3570.  
  3571. ; clear time-out message
  3572. tmoclr: cmp tmodon, 0 ;message on screen?
  3573.  jne tmocl1  ;yes - go get it
  3574.  ret   ;nothing to clear - return
  3575. tmocl1: mov dx, offset scrst ;cursor position
  3576.  call poscur      ;[30c]
  3577.  call clreol  ;clear line   ;[30c]
  3578.  mov tmodon, 0 ;indicate line is clear
  3579.  ret   ;[19g] end
  3580.  
  3581. ; RECEIVE command
  3582.  
  3583. read: call init  ;Paint the screen and initialize file buffers.
  3584.  call cfibf  ;Clear out any stacked NAKs.
  3585. read1: mov numpkt, 0 ;Set the number of packets to zero.
  3586.  mov numrtr, 0 ;Set the number of retries to zero.
  3587.  mov pktnum, 0 ;Set the packet number to zero.
  3588.  mov numtry, 0 ;Set the number of tries to zero.
  3589.  mov cxzflg, 0 ;[19f] reset ^X/^Z flag
  3590.  call pretry
  3591.  mov state, 'R' ;Set the state to receive initiate.
  3592. read2: call pnmpkt
  3593.  mov ah, state ;Get the state.
  3594.  cmp ah, 'D'  ;Are we in the data send state?
  3595.  jne read3
  3596.  call rdata
  3597.  jmp read2
  3598. read3: cmp ah, 'F'  ;Are we in the file receive state?
  3599.  jne read4
  3600.  call rfile  ;Call receive file.
  3601.  jmp read2
  3602. read4: cmp ah, 'R'  ;Are we in the receive initiate state?
  3603.  jne read5
  3604.  call rinit
  3605.  jmp read2
  3606. read5: cmp ah, 'C'  ;Are we in the receive complete state?
  3607.  jne read6
  3608.  mov dx, offset infms3 ;Plus a little cuteness.
  3609.  cmp cxzflg,0 ;[19f] an interruption?
  3610.  je read59  ;[19f] no - do normal thing
  3611.  mov dx, offset infms7 ;[19f] substitute 'interrupted' message.
  3612. read59: call fnstat
  3613.  ret
  3614. read6: mov dx, offset infms4 ;Plus a little cuteness.
  3615.  call fnstat
  3616.  ret
  3617.  
  3618.  
  3619. ; Receive routines
  3620.  
  3621. ; Receive init
  3622.  
  3623. rinit: mov ah, numtry ;Get the number of tries.
  3624.  cmp ah, imxtry ;Have we reached the maximum number of tries?
  3625.  jl rinit2
  3626.  mov dx, offset ermes7 ;Print this error and die.
  3627.  jmp fatal
  3628.  
  3629. rinit2: inc ah  ;Increment it.
  3630.  mov numtry, ah ;Save the updated number of tries.
  3631.  call rpack  ;Get a packet.
  3632.   jmp nak  ; Trashed packet: nak, retry.
  3633.  cmp ah, 'S'  ;Is it a send initiate packet?
  3634.  jne rinit3  ;If not see if its an error.
  3635.  mov ebquot, 'Y' ;Initialize my 8th-bit quote flag ;[29g]
  3636.  mov ah, numtry ;Get the number of tries.
  3637.  mov oldtry, ah ;Save it.
  3638.  mov numtry, 0 ;Reset the number of tries.
  3639.  mov ax, argblk ;Returned packet number.  (Synchronize them.)
  3640.  call incpkt  ;Increment the packet number.
  3641.  mov ax, argbk1 ;Get the number of arguments received.
  3642.  mov bx, offset data ;Get a pointer to the data.
  3643.  call spar  ;Get the data into the proper variables.
  3644.  mov bx, offset data ;Get a pointer to our data block.
  3645.  call rpar  ;Set up the receive parameters.
  3646.  xchg ah, al
  3647.  mov ah, 0
  3648.  mov argbk1, ax ;Store the returned number of arguments.
  3649.  call ack1  ;ACK the packet.
  3650.   jmp abort
  3651.  mov ah, 'F'  ;Set the state to file send.
  3652.  mov state, ah
  3653.  ret
  3654. rinit3: cmp ah, 'E'  ;Is it an error packet?
  3655.  jne rinit4
  3656.  call error
  3657. rinit4: jmp abort
  3658.  
  3659.  
  3660. ; Receive file
  3661.  
  3662. rfile: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  3663.  jl rfile1
  3664.  mov dx, offset ermes8 ;Print this error and die.
  3665.  jmp fatal
  3666.  
  3667. rfile1: inc numtry  ;Save the updated number of tries.
  3668.  call rpack  ;Get a packet.
  3669.   jmp nak  ; Trashed packet: nak, retry.
  3670.  
  3671.  cmp ah, 'S'  ;Is it a send initiate packet?
  3672.  jne rfile2  ; No, try next type.
  3673.  cmp oldtry, imxtry ;Have we reached the maximum number of tries?
  3674.  jl rfil12  ;If not proceed.
  3675.  mov dx, offset ermes7 ;Print this error and die.
  3676.  jmp fatal
  3677. rfil12: call chkpol  ;Check the packet number, is it right?
  3678.   jmp nak  ;No, NAK and try again.
  3679.  mov bx, offset data ;Get a pointer to our data block.
  3680.  call rpar  ;Set up the parameter information.
  3681.  xchg ah, al
  3682.  mov ah, 0
  3683.  mov argbk1, ax ;Save the number of arguments.
  3684.  call reack  ;Re-ACK the old packet.
  3685.   jmp abort
  3686.  ret
  3687.  
  3688. rfile2: cmp ah, 'Z'  ;Is it an EOF packet?
  3689.  jne rfile3  ; No, try next type.
  3690.  cmp oldtry, maxtry ;Have we reached the maximum number of tries?
  3691.  jl rfil21  ;If not proceed.
  3692.  mov dx, offset ermes9 ;Print this error and die.
  3693.  jmp fatal
  3694. rfil21: call chkpol  ;Check the packet number, is it right?
  3695.   jmp nak  ;No, NAK and try again.
  3696.  mov argbk1, 0 ;No data.
  3697.  call reack  ;Re-ACK the previous packet
  3698.   jmp abort
  3699.  ret
  3700.  
  3701. rfile3: cmp ah, 'F'  ;Start of file?
  3702.  jne rfile4
  3703.  call chkpeq  ;Packet numbers equal?
  3704.   jmp nak  ; No, NAK it and try again.
  3705.  call incpkt  ;Increment the number of packets.
  3706.  call gofil  ;Get a file to write to.
  3707.   jmp abort
  3708.  call init1  ;Initialize all the file buffers.
  3709.  call upack  ;Update counters and ACK the packet.
  3710.   jmp abort
  3711.  mov state, 'D' ;Set the state to data receive.
  3712.  ret
  3713.  
  3714. rfile4: cmp ah, 'B'  ;End of transmission?
  3715.  jne rfile5
  3716.  call chkpeq  ;Packet numbers equal?
  3717.   jmp nak  ; No, NAK it and try again.
  3718.  call ack  ;ACK the packet.
  3719.   jmp abort
  3720.  mov state, 'C' ;Set the state to complete.
  3721.  ret
  3722.  
  3723. rfile5: cmp ah, 'E'  ;Is it an error packet?
  3724.  jne rfile6
  3725.  call error
  3726. rfile6: jmp abort
  3727.  
  3728.  
  3729. ; Receive data
  3730.  
  3731. rdata: cmp numtry, maxtry ;Get the number of tries.
  3732.  jl rdata1
  3733.  mov dx, offset erms10 ;Print this error and die.
  3734.  jmp fatal
  3735.  
  3736. rdata1: inc numtry  ;Save the updated number of tries.
  3737.  call rpack  ;Get a packet.
  3738.   jmp nak  ; Trashed packet: nak, retry.
  3739.  
  3740.  cmp ah, 'D'  ;Is it a data packet?
  3741.  je rdat11
  3742.  jmp rdata2  ; No, try next type.
  3743. rdat11: call chkpeq  ;Packet numbers equal?
  3744.   jmp rdat12  ; No, check if previous packet.
  3745.  call incpkt  ;Increment the number of packets.
  3746.  mov ax, argbk1 ;Get the length of the data.
  3747.  cmp cxzflg, 0 ;[19f] interrupt requested?
  3748.  jne rdat1a  ;[19f] yes - skip put to file.
  3749.  call ptchr
  3750.   jmp abort  ; Unable to write out chars;abort.
  3751.  call upack  ;ACK the packet.
  3752.   jmp abort
  3753.  ret
  3754. rdat1a: mov bx, offset data ;[19f] data location
  3755.  mov ah, cxzflg ;[19f] get the ^X/^Z flag
  3756.  mov [bx], ah ;[19f] stick it in the packet
  3757.  mov argbk1, 1 ;[19f] data length is 1
  3758.  call uupack  ;[19f] ACK the packet (without zeroing argbk1)
  3759.   jmp abort  ;[19f]
  3760.  ret   ;[19f]
  3761.  
  3762. rdat12: cmp oldtry, maxtry ;Have we reached the maximum number of tries?
  3763.  jl rdat13  ;If not proceed.
  3764.  mov dx, offset erms10 ;Print this error and die.
  3765.  jmp fatal
  3766. rdat13: call chkpol  ;Check the packet number, is it right?
  3767.   jmp nak  ;No, NAK it and try again.
  3768.  mov argbk1, 0 ;No data.
  3769.  call reack  ;Re-ACK the previous packet.
  3770.   jmp abort
  3771.  ret
  3772.  
  3773. rdata2: cmp ah, 'F'  ;Start of file?
  3774.  jne rdata3  ; No, try next type.
  3775.  cmp oldtry, maxtry ;Have we reached the maximum number of tries?
  3776.  jl rdat21  ;If not proceed.
  3777.  mov dx, offset ermes8 ;Print this error and die.
  3778.  jmp fatal
  3779. rdat21: call chkpol  ;Check the packet number, is it right?
  3780.   jmp nak  ; No, NAK it and try again.
  3781.  mov argbk1, 0 ;No data.
  3782.  call reack  ;Re-ACK the previous packet
  3783.   jmp abort
  3784.  ret
  3785.  
  3786. rdata3: cmp ah, 'Z'  ;Is it a EOF packet?
  3787.  je rdat32
  3788.  jmp rdata4  ;Try and see if its an error.
  3789. rdat32: call chkpeq  ;Packet numbers equal?
  3790.   jmp nak  ; No, NAK it and try again.
  3791.  call incpkt  ;Increment the packet number.
  3792.  cmp cxzflg, 0 ;This file interrupted? [19f] start
  3793.  jne rdat3a  ;yes jump
  3794.  cmp argbk1, 1 ;1 byte of data in EOF packet?
  3795.  jmp rdat3b  ;no - finish up file
  3796.  mov bx, offset data ;pointer to data
  3797.  mov ah, [bx] ;get the data
  3798.  cmp ah, 'D'  ;is it D as in Discard?
  3799.  jne rdat3b  ;no - finish writing file
  3800. rdat3a: mov dx, offset fcb ;get file's fcb
  3801.  call delete  ;delete the file.
  3802.  cmp cxzflg, 'X' ;Kill one file or batch?
  3803.  jne rdat37  ;whole batch - leave flag
  3804.  mov cxzflg, 0 ;clear flag
  3805.  call intmsg  ;clear message
  3806.  jmp rdat37  ;go to clean up.  [19f] end
  3807. rdat3b: mov bx, bufpnt ;Get the dma pointer.
  3808.  mov ax, 80H
  3809.  sub ax, chrcnt ;Get the number of chars left in the DMA.
  3810.  cmp ax, 80H
  3811.  jne rdat34
  3812.  call outbuf  ;Write out buffer if no room for ^Z.
  3813.   jmp abort
  3814.  jmp rdat36  ;Go close the file.
  3815. rdat34: mov cl, 'Z'-100O ;Put in a ^Z for EOF.
  3816.  mov [bx], cl
  3817.  inc ax
  3818.  dec chrcnt
  3819.  mov cx, chrcnt
  3820.  mov temp, cx
  3821.  inc bx
  3822. rdt3: inc ax
  3823.  cmp ax, 80H
  3824.  jg rdat35  ;Pad till full.
  3825.  mov cl, 1AH  ;Use control-Z's  ;[13]
  3826.  mov [bx], cl
  3827.  inc bx
  3828.  jmp rdt3
  3829. rdat35: call outbuf  ;Output the last buffer.
  3830.   jmp abort  ; Give up if the disk is full.
  3831. rdat36: mov dx, offset fcb
  3832.  call closf  ;Close up the file.
  3833. rdat37: call upack  ;ACK the packet.
  3834.   jmp abort
  3835.  mov state, 'F'
  3836.  ret
  3837.  
  3838. rdata4: cmp ah, 'E'  ;Is it an error packet.
  3839.  jne rdata5
  3840.  call error
  3841. rdata5: jmp abort
  3842.  
  3843.  
  3844. ; Send a file.
  3845.  
  3846. send: cmp wldflg,0FFh
  3847.  je send12
  3848.  mov dircnt,0 ;If not wild, just use the name in the FCB
  3849.  mov dindex,0
  3850.  call getopn  ;Open the file
  3851.  jmps send19
  3852. send12: call getwld  ;If wild, get sorted list of matching names
  3853.   jmp r  ;  on error, message already printed
  3854.  mov dindex,0 ;Start at first one
  3855.  call getfil  ;Get and open first file
  3856.   jmp r
  3857. send19: call init  ;Paint the screen and initialize file buffers.
  3858.  call cfibf  ;Clear out any stacked NAKs.
  3859.  mov pktnum, 0 ;Set the packet number to zero.
  3860.  mov numtry, 0 ;Set the number of tries to zero.
  3861.  mov numpkt, 0 ;Set the number of packets to zero.
  3862.  mov numrtr, 0 ;Set the number of retries to zero.
  3863.  call pretry  ;Print the number of retries.
  3864.  mov state,'S' ;Set the state to receive initiate.
  3865. send2: call pnmpkt  ;Print the number of packets.
  3866.  cmp state, 'S' ;Are we in the send initiate state?
  3867.  jne send3
  3868.  call sinit
  3869.  jmp send2
  3870. send3: cmp state, 'F' ;Are we in the file send state?
  3871.  jne send4
  3872.  call sfile  ;Call send file.
  3873.  jmp send2
  3874. send4: cmp state, 'D' ;Are we in the data send state?
  3875.  jne send5
  3876.  call sdata
  3877.  jmp send2
  3878. send5: cmp state, 'Z' ;Are we in the EOF state?
  3879.  jne send6
  3880.  call seof
  3881.  jmp send2
  3882. send6: cmp state, 'B' ;Are we in the eot state?
  3883.  jne send7
  3884.  call seot
  3885.  jmp send2
  3886. send7: cmp state, 'C' ;Are we in the send complete state?
  3887.  jne send8
  3888.  mov dx, offset infms3 ;Plus a little cuteness.
  3889.  cmp cxzflg, 0 ;[19f] Interrupted?
  3890.  je send7a  ;[19f] no
  3891.  mov dx, offset infms7 ;[19f] substitute "interrupted" message
  3892. send7a: call fnstat
  3893.  ret
  3894. send8: mov dx, offset infms4 ;Plus a little cuteness.
  3895.  call fnstat
  3896.  ret
  3897.  
  3898.  
  3899. ; Send routines
  3900.  
  3901. ; Send initiate
  3902.  
  3903.  
  3904. sinit: cmp numtry, imxtry ;Have we reached the maximum number of tries?
  3905.  jl sinit2
  3906.  mov dx, offset erms14
  3907.  jmp fatal
  3908. sinit2: mov ah, 'Y'  ;Reset our quote capability ;[29g] begin
  3909.  cmp parflg, parnon ;If we have parity,
  3910.  je sini21  ;  send our quote preference
  3911.  mov ah, dqbin
  3912. sini21: mov ebquot, ah ;Set our quote capability ;[29g] end
  3913.  inc numtry  ;Save the updated number of tries.
  3914.  mov bx, offset data ;Get a pointer to our data block.
  3915.  call rpar  ;Set up the parameter information.
  3916.  xchg ah, al
  3917.  mov ah, 0
  3918.  mov argbk1, ax ;Save the number of arguments.
  3919.  mov ax, numpkt ;Get the packet number.
  3920.  mov argblk, ax
  3921.  mov ah, 'S'  ;Send initiate packet.
  3922.  call spack  ;Send the packet.
  3923.   jmp abort
  3924.  call rpack  ;Get a packet.
  3925.   jmp r  ; Trashed packet don't change state, retry.
  3926.  cmp ah, 'Y'  ;ACK?
  3927.  jne sinit3  ;If not try next.
  3928.  call chkpeq  ;Is it the right packet number?
  3929.   jmp nretry  ;Increment the retries and go try again.
  3930.  call incpkt  ;Increment the packet number.
  3931.  mov ax, argbk1 ;Get the number of pieces of data.
  3932.  mov bx, offset data ;Pointer to the data.
  3933.  call spar  ;Read in the data.
  3934.  mov ah, numtry ;Get the number of tries.
  3935.  mov oldtry, ah ;Save it.
  3936.  mov numtry, 0 ;Reset the number of tries.
  3937.  mov state, 'F' ;Set the state to file send.
  3938.  ret
  3939.  
  3940. sinit3: cmp ah, 'N'  ;NAK?
  3941.  jne sinit4  ;If not see if its an error.
  3942.  call nretry
  3943.  ret
  3944.  
  3945. sinit4: cmp ah, 'E'  ;Is it an error packet?
  3946.  jne sinit5
  3947.  call error
  3948. sinit5: jmp abort
  3949.  
  3950.  
  3951. ; Send file header
  3952.  
  3953. sfile: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  3954.  jl sfile1
  3955.  mov dx, offset erms14
  3956.  jmp fatal
  3957. sfile1: inc numtry  ;Increment it.
  3958.  mov cxzflg, 0 ;[19f] clear ^X/^Z flag
  3959.  push ds
  3960.  pop es
  3961.  mov di, offset data ;Get a pointer to our data block.
  3962.  mov si, offset fcb+1 ;Pointer to file name in FCB.
  3963.  mov cx,11
  3964. sfil11: cmp cx,3  ;Separate file type with period
  3965.  jne sfil12
  3966.  mov al,'.'
  3967.  stosb
  3968. sfil12: lodsb
  3969.  and al,7Fh  ;Strip off attribute bits
  3970.  cmp al,' '  ;Printable, nonspace characters only
  3971.  jbe sfil13
  3972.  cmp al,7Fh
  3973.  jae sfil13
  3974.  stosb
  3975. sfil13: loop sfil11
  3976.  mov byte ptr [di],'$' ;Terminate filename for printing
  3977.  sub di, offset data
  3978.  mov argbk1, di ;Save number of characters in name
  3979.  call clrfln
  3980.  mov dx, offset data ;Print file name.
  3981.  call tmsg
  3982.  
  3983.  mov ax, pktnum ;Get the packet number.
  3984.  mov argblk, ax
  3985.  mov ah, 'F'  ;File header packet.
  3986.  call spack  ;Send the packet.
  3987.   jmp abort
  3988.  call rpack  ;Get a packet.
  3989.   jmp r  ; Trashed packet don't change state, retry.
  3990.  cmp ah, 'Y'  ;ACK?
  3991.  jne sfile2  ;If not try next.
  3992.  call chkpeq  ;Packet number right.
  3993.   jmp nretry  ;Increment the retries and go try again.
  3994. sfil14: call incpkt  ;Increment the packet number.
  3995.  call updat  ;Update the number of tries.
  3996.  
  3997. sfil15: mov byte ptr fcb+20h,0 ;Set the record number to zero.
  3998.  mov eoflag, 0 ;Indicate not EOF.
  3999.  mov filflg, 0FFh ;Indicate file buffer empty.
  4000.  call gtchr
  4001.   jmp sfil16  ;Error go see if its EOF.
  4002.  jmp sfil18  ;Got the chars, proceed.
  4003. sfil16: cmp ah, 0FFH ;Is it EOF?
  4004.  je sfil17
  4005.  jmp abort  ;If not give up.
  4006. sfil17: mov state, 'Z' ;Set the state to EOF.
  4007.  ret
  4008. sfil18: mov siz, ax
  4009.  mov state, 'D' ;Set the state to data send.
  4010.  ret
  4011.  
  4012. sfile2: cmp ah, 'N'  ;NAK?
  4013.  jne sfile3  ;Try if error packet.
  4014.  call chkpom  ;Is the packet's number one more than now?
  4015.   jmp nretry  ;Increment the retries and go try again.
  4016.  jmp sfil14  ;If so, join the ACK.
  4017.  
  4018. sfile3: cmp ah, 'E'  ;Is it an error packet.
  4019.  jne sfile4
  4020.  call error
  4021. sfile4: jmp abort
  4022.  
  4023.  
  4024. ; Send data
  4025.  
  4026. sdata: cmp cxzflg, 0 ;[19f] Interrupt flag on?
  4027.  je sdata0  ;[19f] no
  4028.  mov state, 'Z' ;[19f] yes - abort sending file
  4029.  ret
  4030. sdata0: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  4031.  jl sdata1
  4032.  mov dx, offset erms14
  4033.  jmp fatal
  4034. sdata1: inc numtry  ;Increment it.
  4035.  mov dx, offset data ;Get a pointer to our data block.
  4036.  mov datptr, dx
  4037.  mov dx, offset filbuf ;Pointer to chars to be sent.
  4038.  mov cbfptr, dx
  4039.  mov cx, 1  ;First char.
  4040. sdat11: mov bx, cbfptr
  4041.  mov ah, [bx]
  4042.  inc cbfptr
  4043.  mov bx, datptr
  4044.  mov [bx], ah ;Put the char in the data packet.
  4045.  inc datptr  ;Save position in data packet.
  4046.  inc cx  ;Increment the count.
  4047.  cmp cx, siz  ;Have we transfered that many?
  4048.  jle sdat11  ;If not get another.
  4049.  mov ax, siz  ;Number of char in char buffer.
  4050.  mov argbk1, ax
  4051.  mov ax, pktnum ;Get the packet number.
  4052.  mov argblk, ax
  4053.  mov ah, 'D'  ;Data packet.
  4054.  call spack  ;Send the packet.
  4055.   jmp abort
  4056.  call rpack  ;Get a packet.
  4057.   jmp r  ; Trashed packet don't change state, retry.
  4058.  cmp ah, 'Y'  ;ACK?
  4059.  jne sdata2  ;If not try next.
  4060.  call chkpeq  ;Right packet number?
  4061.   jmp nretry  ;Increment the retries and go try again.
  4062. sdat12: call incpkt  ;Increment the packet number.
  4063.  call updat  ;Update the number of tries.
  4064.  cmp argbk1,1 ;1 byte of data there?  [19f] start
  4065.  jne sdt12b  ;no - go on
  4066.  mov bx, offset data ;pointer to data
  4067.  mov ah, [bx] ;get the data
  4068.  cmp ah, 'X'  ;an 'X'?
  4069.  je sdt12a  ;yes - go
  4070.  cmp ah, 'Z'  ;or a 'Z'
  4071.  je sdt12a  ;also go
  4072.  jmp sdt12b  ;neither one - go on
  4073. sdt12a: mov cxzflg, ah ;'X' or 'Z' - set the interrupt flag [19f] end
  4074.  ret
  4075. sdt12b: call gtchr
  4076.   jmp sdat13  ;Error go see if its EOF.
  4077.  mov siz, ax  ;Save the size of the data gotten.
  4078.  ret
  4079.  
  4080. sdat13: cmp ah, 0FFH ;Is it EOF?
  4081.  je sdat14
  4082.  jmp abort  ;If not give up.
  4083.  
  4084. sdat14: mov state, 'Z' ;Set the state to EOF.
  4085.  ret
  4086. sdata2: cmp ah, 'N'  ;NAK?
  4087.  jne sdata3  ;See if is an error packet.
  4088.  call chkpom  ;Is the packet's number one more than now?
  4089.   jmp nretry  ;Increment the retries and go try again.
  4090.  jmp sdat12
  4091.  
  4092. sdata3: cmp ah, 'E'  ;Is it an error packet.
  4093.  jne sdata4
  4094.  call error
  4095. sdata4: jmp abort
  4096.  
  4097.  
  4098. ; Send EOF
  4099.  
  4100. seof: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  4101.  jl seof1
  4102.  mov dx, offset erms14
  4103.  jmp fatal
  4104. seof1: inc numtry  ;Increment it.
  4105.  mov ax, pktnum ;Get the packet number.
  4106.  mov argblk, ax
  4107.  mov argbk1, 0 ;No data.
  4108.  cmp cxzflg, 0 ;[19f] interrupt flag set?
  4109.  je seof1a  ;[19f] no - go on
  4110.  mov bx, offset data ;[19f] point to data
  4111.  mov ah, 'D'  ;[19f] get 'D' as in Discard
  4112.  mov [bx], ah ;[19f] stuff it into packet
  4113.  mov argbk1, 1 ;[19f] set data length of 1
  4114. seof1a: mov ah, 'Z'  ;EOF packet.
  4115.  call spack  ;Send the packet.
  4116.  jmp abort
  4117.  call rpack  ;Get a packet.
  4118.   jmp r  ; Trashed packet don't change state, retry.
  4119.  cmp ah, 'Y'  ;ACK?
  4120.  jne seof2  ;If not try next.
  4121.  call chkpeq  ;Is it the right packet number?
  4122.   jmp nretry  ;Increment the retries and go try again.
  4123. seof12: call incpkt  ;Increment the packet number.
  4124.  call updat  ;Update the number of tries.
  4125.  mov dx, offset fcb ;Close the file.
  4126.  call closf
  4127.  call getfil  ;Get and open the next file.
  4128.   jmp seof13  ; No more.
  4129.  mov state, 'F' ;Set the state to file send.
  4130.  cmp cxzflg, 'X' ;[19f] 'X' in interrupt flag?
  4131.  mov cxzflg, 0 ;[19f] meantime reset it
  4132.  jne sef13a  ;[19f] no - go on
  4133.  call intmsg  ;[19f] clear interrupt message
  4134. sef13a: ret   ;[19f] goodbye
  4135. seof13: mov state, 'B' ;Set the state to EOT.
  4136.  ret
  4137.  
  4138. seof2: cmp ah, 'N'  ;NAK?
  4139.  jne seof3  ;Try and see if its an error packet.
  4140.  call chkpom  ;Is the packet's number one more than now?
  4141.   jmp nretry  ;Increment the retries and go try again.
  4142.  jmp seof12
  4143.  
  4144. seof3: cmp ah, 'E'  ;Is it an error packet?
  4145.  jne seof4
  4146.  call error
  4147. seof4: jmp abort
  4148.  
  4149.  
  4150. ; Send EOT
  4151.  
  4152. seot: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  4153.  jl seot1
  4154.  mov dx, offset erms14
  4155.  jmp fatal
  4156. seot1: inc numtry  ;Increment it.
  4157.  mov ax, pktnum ;Get the packet number.
  4158.  mov argblk, ax
  4159.  mov argbk1, 0 ;No data.
  4160.  mov ah, 'B'  ;EOF packet.
  4161.  call spack  ;Send the packet.
  4162.   jmp abort
  4163.  call rpack  ;Get a packet.
  4164.   jmp r  ;Trashed packet don't change state, retry.
  4165.  cmp ah, 'Y'  ;ACK?
  4166.  jne seot2  ;If not try next.
  4167.  call chkpeq  ;Is it the right packet number.
  4168.   jmp nretry  ;Increment the retries and go try again.
  4169. seot12: call incpkt  ;Increment the packet number.
  4170.  call updat  ;Update the number of tries.
  4171.  mov state, 'C' ;Set the state to file send.
  4172.  ret
  4173.  
  4174. seot2: cmp ah, 'N'  ;NAK?
  4175.  jne seot3  ;Is it error.
  4176.  call chkpom  ;Is the packet's number one more than now?
  4177.   jmp nretry  ;Increment the retries and go try again.
  4178.  jmp seot12
  4179.  
  4180. seot3: cmp ah, 'E'  ;Is it an error packet.
  4181.  jne seot4
  4182.  call error
  4183. seot4: jmp abort
  4184. <<< c86trm.a86 >>>
  4185. ; * * * * * * * * * * * * * * * version 2.7 * * * * * * * * * * * * * * * *
  4186. ; [fdc]    Print message about how to get help during connect.
  4187. ; [29e]    Move terminal session logging to terminal module.
  4188. ; * * * * * * * * * * * * * * * version 2.6 * * * * * * * * * * * * * * * *
  4189. ; [24b revisited]    Fix handling of double-escape character
  4190. ;    RonB, 03/22/84
  4191. ; [26]
  4192. ;      Move TELNET stuff from KERMIT to a this module: KERTRM.
  4193. ;    This is to modularize terminal emulation.
  4194. ;
  4195. ;      integrate keyboard check in-line.  This allows keyboard check
  4196. ;    between port checks to work without blowing the stack.
  4197. ;
  4198. ;    to improve speed, let the port-to-screen routine loop for a certain
  4199. ;    number of characters before checking the keyboard.  If we
  4200. ;    check every time,  we lose a few characters at 9600 baud 
  4201. ;    without flow control.
  4202. ;
  4203. ;    Mar-1984.    R. Garland - Columbia University.
  4204. ;
  4205. ; [24]
  4206. ; (a)   Add terminal session logging (KERMIT,KERSYS,KERUTL)
  4207. ; (b)   Allow escape character to local-echo (KERMIT)
  4208. ;    RonB, 03/15/84
  4209. ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  4210.  
  4211.     cseg    $        ;resume code segment
  4212.  
  4213. ; This is the CONNECT command.  It makes the local Kermit act as a terminal.
  4214.  
  4215. telnet:    mov    ah,cmcfm
  4216.     call    comnd        ;Get a confirm.
  4217.      jmp    r        ; Didn't get a confirm.
  4218.     mov    dx, offset inms01 ;Confirmed, print informatory message.
  4219.     call    tcrmsg
  4220.     call    escprt
  4221.     mov    dx, offset inms02
  4222.     call    tmsg        ;[fdc] Say how to get help during connect.
  4223.     call    escprt        ;[fdc]
  4224.     mov    dx, offset inms25    ;[fdc]
  4225.     call    tmsgcr        ;[fdc]
  4226.     cmp    logflg, 0    ;Is logging specified?        ;[24a] begin
  4227.     je    telnt1
  4228.     call    logopn        ;If so, open the log file
  4229.      jmp    logerr                        ;[24a] end
  4230.  
  4231. telnt1:            ;Check keyboard.
  4232.     mov    teloop, cx    ;initialize loop counter
  4233.     call    dbinst        ;Any chars out there?
  4234.      jmp    telntx        ; If not, check serial port
  4235.     call    dbin        ;Yes, then get the char.
  4236.     cmp    al, escchr    ;Is it an escape char?
  4237.     jz    intchr        ;If so go process it.
  4238. telnty:    call    dopar        ;Set parity (if any).        ;[24b]
  4239.     mov    dx, ax
  4240.     call    prtout        ;Output the char to the port.
  4241.     cmp    ecoflg, 0    ;Is the echo flag turned on?
  4242.     jz    telnt2        ;no - go on
  4243.     and     dl, 7FH        ;Turn off the parity bit.
  4244.     call     dbout        ;Echo the character.
  4245. telntx:    mov    cx, telnct    ;load count for telnt2 loop
  4246. telnt2:            ;Check serial port.
  4247.     mov    teloop, cx    ;save loop count
  4248.     call    instat        ;Any characters available?
  4249.      jmp    telnt1        ; No, check keyboard
  4250.     call    inchr        ;Get the character.
  4251.     and    al, 7FH        ;Strip off parity bit.
  4252.     mov    dl, al        ;Get the character.
  4253.     call    dbout        ;output to screen.
  4254.     mov    cx, teloop    ;get loop counter
  4255.     loop    telnt2        ;loop a bunch of characters before
  4256.                 ;checking keyboard - for speed.
  4257.     jmp    telnt1        ;go back and check keyboard.
  4258.  
  4259. intchr:    call    dbin        ;Get a char.
  4260.     cmp    al, 0        ;Is the char a null?
  4261.     jz    intchr        ;If so, go until we get a char.
  4262.     mov    bl, al        ;Save the actual char.
  4263.     and    al, 137O    ;Convert to upper case.
  4264.             ;C = close
  4265.     cmp    al, 'C'        ;Is it close?
  4266.     jne    intch0
  4267.     call    logcls        ;Close the log file        ;[24a]
  4268.     mov    dx, offset inms03
  4269.     call    tcmsgc        ;return to micro message
  4270.     jmp    rskp        ;return from telnet
  4271.             ;B = break
  4272. intch0:    cmp    al,'B'        ;[19e] Is it "send break"?
  4273.     jne    intch1        ;[19e] no.
  4274.     call    prtbrk        ;[19e] send a break.
  4275.     jmp    telnt2        ;[19e]
  4276.             ;escape character
  4277. intch1:    cmp    bl, escchr    ;Is it the escape char?
  4278.     jne    intch2        ;If not, go send a beep to the user.
  4279.     mov    al, bl        ;If so, uncapitalize it        ;[24b]
  4280.     jmp    telnty        ;go on, we are done here.        ;[24b]
  4281.             ;? = help
  4282. intch2:    cmp    bl, '?'        ;Is it a cry for help?            ;[20c]
  4283.     jne    intch3
  4284.     mov    dx, offset inthlp    ;If so, display help message on screen
  4285.     call    tcrmsg
  4286.     call    escprt
  4287.     mov    dx, offset inthl2
  4288.     call    tmsg
  4289.     call    escprt
  4290.     mov    dx, offset inthl3
  4291.     call    tmsgcr
  4292.     jmp    intchr        ;Keep looking for escape character.    ;[20c]
  4293.             ;L = toggle logging
  4294. intch3:    cmp    al, 'L'        ;Is it the logging toggle?    ;[24a] begin
  4295.     jne    intch4
  4296.     cmp    logflg, 0    ;Is logging now off?
  4297.     jne    intc32
  4298. intc31:    mov    logflg, 0FFh    ;If so, set to 'on' value.
  4299.     call    logopn        ;Open log file.
  4300.         jmp    logerr
  4301.     jmp    telnt2
  4302. intc32:    mov    logflg, 0
  4303.     call    logcls        ;Close the log file.
  4304.     jmp    telnt2                        ;[24a] end
  4305.             ;Q = quit logging            ;[29e] begin
  4306. intch4:    cmp    al, 'Q'
  4307.     jne    intch5
  4308.     cmp    logflg, 0    ;If logging currently enabled,
  4309.     jne    intc32        ;  go set flag to 'off'
  4310.     jmp    telnt2
  4311.             ;R = resume logging
  4312. intch5:    cmp    al, 'R'
  4313.     jne    intch6
  4314.     cmp    logflg, 0    ;If logging currently disabled,
  4315.     je    intc31        ;  go set flag to 'on'
  4316.     jmp    telnt2                        ;[29e] end
  4317.             ;error = beep!
  4318. intch6:    mov    dl, bell    ;Otherwise send a beep.
  4319.     call    dbout
  4320.     jmp    telnt2
  4321.  
  4322. logerr:    mov    logflg, 0    ;Reset logging on file error    ;[24a] begin
  4323.     call    logcls        ;Make sure log file is closed
  4324.     mov    dx, offset erms22 ;Print an error message.
  4325.     call    tcrmsg
  4326.     mov    dx, offset lfcb
  4327.     call    tfile
  4328.     call    tcrlf
  4329.     jmp    rskp        ;And keep doing whatever we were ;[24a] end
  4330.  
  4331. ; These are the file handling routines for terminal session logging.
  4332. ; LOGOPN opens the logfile in lfcb.
  4333.  
  4334. logopn:    mov    byte ptr lfcb+12,0
  4335.     mov    byte ptr lfcb+13,0
  4336.     mov    byte ptr lfcb+14,0
  4337.     mov    dx, offset lfcb
  4338.     call    gtjfn        ;Is file already present?
  4339.     cmp    al, 0FFh
  4340.     jne    logo4        ;If so, go seek to its end & open it.
  4341.     mov    bx, offset lfcb+1 ;Don't allow wild or blank name
  4342.     cmp    byte ptr [bx], ' '
  4343.     je    logo2
  4344.     cmp    wldflg, 0
  4345.     je    logo3
  4346. logo2:    cld
  4347.     push    ds
  4348.     pop    es
  4349.     mov    di, offset lfcb    ;Make it "KERMIT.LOG" instead
  4350.     mov    si, offset lognam
  4351.     mov    cx, 12
  4352.     rep movsb
  4353. logo3:    mov    dx, offset lfcb
  4354.     call    create        ;Otherwise create the file.
  4355.     mov    bx, offset lfcb
  4356.     mov    byte ptr 32[bx], 0    ;Zero "CR" field
  4357.     mov    bx, offset dma
  4358.     cmp    al, 0FFh    ;If no more directory space
  4359.     jne    logo9
  4360.     ret            ;  then return an error
  4361.  
  4362. logo4:    cld
  4363.     push    ds
  4364.     pop    es
  4365.     mov    di, offset lfcb+1 ;Get the unambiguous filename
  4366.     mov    si, offset dma+1
  4367.     mov    cl, 5
  4368.     shl    al, cl
  4369.     mov    ah, 0
  4370.     add    si, ax
  4371.     mov    cx, 11
  4372.     rep movsb
  4373.     mov    dx, offset lfcb
  4374.     call    openf
  4375.     mov    dx, offset lfcb    ;Get existing file size
  4376.     call    sizef
  4377.     mov    bx, offset lfcb
  4378.     cmp    byte ptr 35[bx], 0
  4379.     je    logo5        ;If file is too full
  4380.     ret            ;  then return an error
  4381. logo5:    cmp    word ptr 33[bx], 0    ;Is the file totally empty?
  4382.     je    logo8        ;  if so, don't look for control-Z.
  4383.     dec    word ptr 33[bx]    ;Point to last record in file
  4384.     mov    dx, offset lfcb
  4385.     call    rinr        ;Read random
  4386.     mov    bx, offset dma-1 ;Look for the terminating control-Z.
  4387.     mov    cx, 80h
  4388. logo6:    inc    bx
  4389.     cmp    byte ptr [bx], 'Z'-100O
  4390.     je    logo9
  4391.     loop    logo6
  4392.     mov    dx, offset lfcb
  4393.     call    soutr        ;If no control-Z, then start a new buffer
  4394. logo8:    mov    bx, offset dma
  4395. logo9:    mov    bufpnt, bx    ;Save current buffer location.
  4396.     mov    logfil, 0FFh    ;Flag that file is open
  4397.     mov    dx, offset infm11 ;And display status on the terminal
  4398.     call    tmsg
  4399.     mov    dx, offset lfcb    ;Including the file name
  4400.     call    tfile
  4401.     mov    dx, offset infm12
  4402.     call    tmsgcr
  4403.     jmp    rskp        ;Return success.
  4404.  
  4405. ; LOGCLS - closes the log file, but only if it was open
  4406.  
  4407. logcls:    cmp    logfil, 0    ;Is file open?
  4408.     je    logc3        ;No, just return.
  4409.     cmp    bufpnt, offset dma ;Do we have an empty buffer?
  4410.     je    logc2
  4411.     mov    bx, bufpnt    ;If not, fill remainder with control-Z's
  4412.     mov    cx, offset DMA+80h
  4413.     sub    cx, bx
  4414.     mov    al, 'Z'-100O
  4415. logc1:    mov    [bx], al
  4416.     inc    bx
  4417.     loop    logc1
  4418.     mov    dx, offset lfcb    ;Write out last buffer
  4419.     call    soutr
  4420. logc2:    mov    dx, offset lfcb    ;Close the log file
  4421.     call    closf
  4422.     mov    dx, offset infm13 ;Tell user so.
  4423.     call    tcmsgc
  4424.     mov    logfil, 0    ;Show file closed.
  4425. logc3:    ret                            ;[24a] end
  4426.  
  4427.  
  4428.  
  4429. ;    data specific to terminal emulation
  4430.  
  4431.     dseg    $
  4432.  
  4433. telnct    dw    10        ;count of characters to take from port
  4434.                 ;for the screen before checking keyboard.
  4435. teloop    dw    0        ;active loop counter
  4436. logflg    db    deflog        ;Is logging enabled?        ;[24a] begin
  4437. logfil    db    0        ;Is the log file open?
  4438. lognam    db    0,'KERMIT  LOG'    ;Default log filename
  4439. lfcb    db    0,'KERMIT  LOG'    ;Logging file control block
  4440.     rb    24                        ;[24a] end
  4441. <<< c86utl.a86 >>>
  4442. ;* * * * * * * * * * * * * * * version 2.9 * * * * * * * * * * * * * * *
  4443. ; [34c]    Make DMA initialization and buffer allocation global
  4444. ; [34b]    Add LOCAL TYPE command
  4445. ; [34a]    Fix bugs in directory listing file sizes
  4446. ;* * * * * * * * * * * * * * * version 2.8 * * * * * * * * * * * * * * *
  4447. ; [32d]    Add routines to get disk parameters for space calculation
  4448. ; [32a]    Add routines to get and set default disk and user numbers
  4449. ;* * * * * * * * * * * * * * * version 2.7 * * * * * * * * * * * * * * *
  4450. ; [29c]  Clear FCB prior to opening or creating a file.
  4451. ; [29b]  Add TAKE command file processing.
  4452. ;    RonB, 04/08/84
  4453. ;* * * * * * * * * * * * * * * version 2.6 * * * * * * * * * * * * * * *
  4454. ;  [24a] Add terminal session logging
  4455. ;    RonB, 03/15/84
  4456. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  4457. ;  [20e] Add regular console status check, in addition to direct I/O check.
  4458. ;    RonB,03/02/84
  4459. ;  [19c] Give "bdos" mnemonic for vector 224.
  4460. ; * * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * * *
  4461. ;  [7]    Do tab expansion and suppress nulls while in telnet mode.
  4462. ;    RonB,12/24/83
  4463. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  4464.  
  4465. ; BDOS command codes
  4466.  
  4467. bdos    equ    224
  4468. reset    EQU    00H
  4469. conin    EQU    01H
  4470. conout    EQU    02H
  4471. rdrin    EQU    03H
  4472. punout    EQU    04H
  4473. lstout    EQU    05H
  4474. dconio    EQU    06H
  4475. gtiob    EQU    07H
  4476. prstr    EQU    09H
  4477. consta    EQU    0BH
  4478. resetd    EQU    0DH                        ;[32a]
  4479. stdrv    EQU    0EH                        ;[32a]
  4480. opnfil    EQU    0FH
  4481. clsfil    EQU    10H
  4482. sfirst    EQU    11H
  4483. snext    EQU    12H
  4484. delf    EQU    13H
  4485. readf    EQU    14H
  4486. writef    EQU    15H
  4487. makef    EQU    16H
  4488. gtdrv    EQU    19H                        ;[32a]
  4489. gtalv    EQU    1BH                        ;[32d]
  4490. gtrov    EQU    1DH                        ;[32d]
  4491. statr    EQU    1EH
  4492. gtdpb    EQU    1FH                        ;[32d]
  4493. stusr    EQU    20H                        ;[32a]
  4494. readr    EQU    21H
  4495. writer    EQU    22H
  4496. cflsz    EQU    23H
  4497. dmaset    EQU    1AH
  4498. dmabas    EQU    33H
  4499. allocm    EQU    37H                        ;[32d]
  4500. freem    EQU    39H                        ;[32d]
  4501.  
  4502.     DSEG $                        ;[29b] begin
  4503.  
  4504. ; TAKE command file processing data area.
  4505.  
  4506. tkfcb    db    0,'KERMIT  INI',0,0,0,0        ;FCB with default name
  4507.     rb    19
  4508. tkbuf    rb    80h                ;Input buffer
  4509. tkptr    dw    0                ;Buffer pointer
  4510. tkflg    db    1                ;Initially enable file input
  4511.  
  4512. ; Messages and storage for directory operations
  4513.  
  4514. dirm01    db    'Drive $'                    ;[32d] begin
  4515. dirm02    db    ', User $'
  4516. dirm03    db    '    K$'
  4517. dirm04    db    ' : $'        ;directory column separator
  4518. dirm05    db    ' files, $'
  4519. dirm06    db    'K listed$'
  4520. dirm07    db    '  $'        ;displayed at start of each row
  4521. eram01    db    tab,'Delete? $'
  4522. eram02    db    tab,'...not deleted$'
  4523. eram03    db    tab,'...deleted$'
  4524. eram04    db    ' $'        ;displayed at start of each row
  4525. erahlp    db    cr,lf,'Respond with ''Y'' to delete this file,'
  4526.     db    cr,lf,'             ''N'' to bypass this file,'
  4527.     db    cr,lf,'         or ''ESC'' to return to the Kermit-86> prompt.$'
  4528. spcm01    db    'K (out of $'
  4529. spcm02    db    'K) remaining on drive $'
  4530. morm01    db    '--more--$'
  4531. morm02    db    'Return: next line, Space: next page, ^X: next file, ^Z: quit$'
  4532. membuf    rb    5        ;memory control block
  4533. dirbuf    rb    16
  4534. dindex    dw    0        ;index to first entry in row
  4535. dlngth    dw    0        ;length of directory list
  4536. dircnt    dw    0        ;files in directory list
  4537. dirsiz    dw    0        ;kbytes in directory list
  4538. remK    dw    0        ;Kbytes remaining on disk
  4539. maxK    dw    0        ;Kbytes available if disk was empty
  4540. DSM    dw    0        ;drive maximum allocation blocks
  4541. KPB    dw    0        ;drive Kbytes Per Block        ;[32d] end
  4542.  
  4543.     CSEG $            ;Resume coding segment.
  4544.  
  4545. tkst:    cmp    tkptr, 0    ;Is file open yet?
  4546.     jne    tkst1
  4547.     call    tkopn
  4548.      jmp    r        ;If open failure
  4549. tkst1:    mov    bx, tkptr    ;Do we need a new record?
  4550.     cmp    bx, offset tkbuf+80h
  4551.     jb    tkst2
  4552.     call    tkread
  4553.     mov    bx, tkptr
  4554. tkst2:    cmp    byte ptr [bx], 1Ah    ;Are we at end of file?
  4555.     je    tkst3
  4556.     jmp    rskp        ;If not, say we have a character.
  4557. tkst3:    call    tkcls        ;  otherwise end the file
  4558.     jmp    r
  4559.  
  4560. tkin:    call    tkst        ;If no file input,
  4561.      jmp    bin        ;  get it from the console.
  4562.     mov    bx, tkptr
  4563.     mov    al, [bx]    ;Get character from command file record.
  4564.     inc    tkptr
  4565.     cmp    al, lf        ;Ignore <lf> in file
  4566.     je    tkin
  4567.     push    ax
  4568.     mov    dl, al        ;Echo it to the display.
  4569.     call    bout
  4570.     pop    ax
  4571.     ret
  4572.  
  4573. tkopn:    mov    dx, offset tkfcb ;Open the command file
  4574.     call    fcbzer        ;zero fcb trailer
  4575.     mov    cl, opnfil
  4576.     int    bdos
  4577.     inc    al
  4578.     jz    tkopn1
  4579.     mov    tkptr, offset tkbuf+80h ;If success, show we need a read
  4580.     jmp    rskp
  4581. tkopn1:    mov    tkflg, 0    ;On failure, turn off file input flag.
  4582.     ret
  4583.  
  4584. tkread:    mov    dx, offset tkbuf ;Set dma to our location.
  4585.     call    setdma
  4586.     mov    dx, offset tkfcb
  4587.     call    sinr        ;Read a record.
  4588.     cmp    al, 0
  4589.     je    tkrd1
  4590.     mov    tkbuf, 1Ah    ;If failure, load buffer with EOF.
  4591. tkrd1:    mov    tkptr, offset tkbuf    ;Reinitialize buffer pointer.
  4592.     call    inidma        ;Reset dma to normal.
  4593.     ret
  4594.  
  4595. tkcls:    mov    dx, offset tkfcb ;Close command file.
  4596.     call    closf
  4597.     mov    tkflg, 0    ;Turn off file input flag.
  4598.     ret                            ;[29b] end
  4599.  
  4600.  
  4601. ; Local directory operation
  4602.  
  4603. dirutl:    call    getwld        ;fill buffer with matching names
  4604.      jmp    r        ;on failure a message has already been printed
  4605.     cmp    dircnt,0
  4606.     jne    locd3
  4607.      ret
  4608. locd3:    mov    dirsiz,0
  4609.     mov    ax,dircnt
  4610.     dec    ax        ;calculate number of entries in each column
  4611.     shr    ax,1        ; = ((count-1)/4)+1
  4612.     shr    ax,1
  4613.     inc    ax
  4614.     mov    dlngth,ax
  4615.     call    tcrlf
  4616.     mov    dx, offset dirm01 ;print header: Drive X, User nn:
  4617.     call    tcrmsg
  4618.     mov    dl,fcb        ;display the drive letter
  4619.     add    dl,'A'-1
  4620.     call    bout
  4621.     mov    dx, offset dirm02
  4622.     call    tmsg
  4623.     mov    al,defusr    ;display the user number
  4624.     cbw
  4625.     call    nout
  4626.     mov    dl,':'
  4627.     call    bout
  4628.     mov    dindex,0    ;table entry in first column
  4629.     mov    cx,dlngth
  4630. locd4a:    push    cx
  4631.     mov    dx, offset dirm07 ;Start new row
  4632.     call    tcrmsg
  4633.     mov    si,dindex
  4634.     mov    cx,4
  4635. locd4b:    push    si
  4636.     push    cx
  4637.     push    ds
  4638.     mov    ds,word ptr membuf
  4639.     mov    cl,4        ;change entry number to table offset
  4640.     shl    si,cl
  4641.     inc    si        ;skip user number
  4642.     mov    cx,8        ;Eight characters in filename
  4643. locd5b:    lodsb            ;get a filename character
  4644.     mov    dl,al
  4645.     push    cx
  4646.     call    bout        ;print it
  4647.     pop    cx
  4648.     loop    locd5b
  4649.     mov    dl,'.'        ;separate filename and type with a period
  4650.     call    bout
  4651.     mov    cx,3        ;Three characters in file type
  4652. locd5c:    lodsb            ;get a file type character
  4653.     mov    dl,al
  4654.     push    cx
  4655.     call    bout        ;print it
  4656.     pop    cx
  4657.     loop    locd5c
  4658.     lodsw            ;get file size
  4659.     pop    ds
  4660.     add    dirsiz,ax    ;add filesize to listing size
  4661.     mov    di, offset dirm03 ;message for file size (____K)
  4662.     mov    cx,3
  4663. locd5d:    mov    byte ptr [di],' ' ;first blank out the last size
  4664.     inc    di
  4665.     loop    locd5d
  4666.     mov    bx,10
  4667. locd5e:    mov    dx,0        ;fill in current size
  4668.     div    bx
  4669.     add    dl,'0'
  4670.     mov    [di],dl
  4671.     dec    di
  4672.     cmp    ax,0
  4673.     jne    locd5e
  4674.     mov    dx, offset dirm03 ;print size message
  4675.     call    tmsg
  4676.     pop    cx
  4677.     cmp    cx,1        ;follow all but last column with separator
  4678.     je    locd5f
  4679.     mov    dx, offset dirm04 ;print column separator
  4680.     push    cx
  4681.     call    tmsg
  4682.     pop    cx
  4683. locd5f:    pop    si
  4684.     add    si,dlngth
  4685.     cmp    si,dircnt
  4686.     jae    locd6
  4687.     loop    locd4b
  4688. locd6:    inc    dindex
  4689.     pop    cx
  4690.     dec    cx
  4691.     jz    locd8
  4692.     jmp    locd4a
  4693. locd8:    call    tcrlf        ;end the last row
  4694.     call    tcrlf        ;add a blank row
  4695.     mov    ax,dircnt    ;display file count
  4696.     call    nout
  4697.     mov    dx, offset dirm05
  4698.     call    tmsg
  4699.     mov    ax,dirsiz    ;display total file size
  4700.     call    nout
  4701.     mov    dx, offset dirm06
  4702.     call    tmsg
  4703.     jmp    rskp
  4704.  
  4705.  
  4706. ; Erase utility function
  4707.  
  4708. erautl:    call    getwld
  4709.      jmp    r        ;On error a message has already been printed
  4710.     mov    dindex,0
  4711. loce3:    mov    si,dindex
  4712.     cmp    si,dircnt
  4713.     jb    loce4
  4714.     jmp    loce9
  4715. loce4:    mov    cl,4
  4716.     shl    si,cl
  4717.     inc    si
  4718.     mov    di, offset fcb+1    ;FCB already has drive code
  4719.     push    ds
  4720.     pop    es
  4721.     mov    ds, word ptr membuf
  4722.     mov    cx,15
  4723.     rep    movsb
  4724.     push    es
  4725.     pop    ds
  4726.     mov    dx, offset eram04    ;Start new row
  4727.     call    tcrmsg
  4728.     mov    dx, offset fcb
  4729.     call    tfile
  4730.     mov    dx, offset eram01    ;'<tab>Delete? '
  4731.     call    tmsg
  4732. loce5a:    call    dbinst            ;clear out all typeahead
  4733.      jmp    loce5b
  4734.     call    dbin
  4735.     jmps    loce5a
  4736. loce5b:    call    dbin            ;get response
  4737.     cmp    al,0            ;NUL is ignored
  4738.     je    loce5b
  4739.     cmp    al,cr            ;CR bypasses file
  4740.     je    loce5d
  4741.     cmp    al,' '            ;any nonprintable char aborts
  4742.     jb    loce8
  4743.     cmp    al,7Fh
  4744.     jae    loce8
  4745.     push    ax
  4746.     mov    dl,al            ;echo the printable response
  4747.     call    bout
  4748.     pop    ax
  4749.     cmp    al,'?'            ;request for help?
  4750.     jne    loce5c
  4751.     mov    dx, offset erahlp    ;help message
  4752.     call    tcmsgc
  4753.     jmp    loce3
  4754. loce5c:    or    al,'a'-'A'        ;convert to lower case
  4755.     cmp    al,'y'
  4756.     je    loce6
  4757. loce5d:    mov    dx, offset eram02    ;'    ...not deleted'
  4758.     call    tmsg
  4759.     jmp    loce7
  4760. loce6:    cmp    byte ptr fcb+14,0    ;make file read-write if necessary
  4761.     je    loce6a
  4762.     mov    dx, offset fcb
  4763.     call    setatr
  4764. loce6a:    mov    dx, offset fcb        ;delete file
  4765.     call    delete
  4766.     mov    dx, offset eram03     ;'    ...deleted'
  4767.     call    tmsg
  4768. loce7:    inc    dindex
  4769.     jmp    loce3
  4770. loce8:    mov    dx, offset eram02    ;'    ...not deleted' when aborting
  4771.     call    tmsg
  4772. loce9:    call    tcrlf
  4773.     jmp    rskp
  4774.  
  4775.  
  4776. ; Type utility function
  4777.  
  4778. typutl:    call    getwld
  4779.      jmp    r        ;On error a message has already been printed
  4780.     mov    dindex,0
  4781. loct3:    mov    si,dindex        ;Get next filename in table
  4782.     cmp    si,dircnt
  4783.     jb    loct4
  4784.     jmp    loct9
  4785. loct4:    mov    dlngth,1
  4786.     mov    cl,4
  4787.     shl    si,cl
  4788.     inc    si
  4789.     mov    di, offset fcb+1
  4790.     push    ds
  4791.     pop    es
  4792.     mov    ds, word ptr membuf
  4793.     mov    cx,15
  4794.     rep    movsb
  4795.     push    es
  4796.     pop    ds
  4797.     call    tcrlf            ;Display the filename
  4798.     mov    dx, offset fcb
  4799.     call    tfile
  4800.     call    tcrlf
  4801.     mov    dx, offset fcb
  4802.     call    openf            ;Open the file
  4803.     inc    al
  4804.     jnz    loct5
  4805.     jmp    loct6b
  4806. loct5:    mov    dx, offset fcb        ;Read a record
  4807.     call    sinr
  4808.     cmp    al,0
  4809.     jne    loct6
  4810.     mov    bx,offset dma
  4811. loct5a:    mov    dl,[bx]            ;Get a character
  4812.     cmp    dl,1Ah
  4813.     je    loct6
  4814.     and    dl,7Fh
  4815.     push    bx
  4816.     push    dx
  4817.     call    bout            ;Print the character
  4818.     pop    dx
  4819.     cmp    dl,lf
  4820.     jne    loct5b
  4821.     inc    dlngth            ;Count lf characters
  4822.     cmp    dlngth,22        ;If more than 22, then pause for input
  4823.     jb    loct5b
  4824.     call    more
  4825.      jmp    loct5c
  4826. loct5b:    pop    bx
  4827.     inc    bx
  4828.     cmp    bx,offset dma+128
  4829.     jb    loct5a
  4830.     jmps    loct5
  4831. loct5c:    pop    bx
  4832.     jmps    loct6a
  4833. loct6:    mov    ax,dindex        ;EOF in file
  4834.     inc    ax
  4835.     cmp    ax,dircnt
  4836.     jae    loct6a
  4837.     call    tcrlf
  4838.     call    more
  4839.      jmp    loct6a
  4840. loct6a:    mov    dx, offset fcb        ;Close file
  4841.     call    closf
  4842.     call    tcrlf
  4843. loct6b:    inc    dindex            ;Move on to next file
  4844.     jmp    loct3
  4845. loct9:    jmp    rskp
  4846.  
  4847.  
  4848. more:    call    revon
  4849.     mov    dx,offset morm01    ;Show --more-- message
  4850.     call    tmsg
  4851.     call    revoff
  4852. more1:    call    dbin            ;Get response
  4853.     cmp    al,0            ; ignore nulls
  4854.     je    more1
  4855.     push    ax
  4856.     call    clrlin
  4857.     mov    dl,tab            ;This is to fool CP/M so it
  4858.     call    bout            ;  gets tab stops right
  4859.     mov    dl,cr
  4860.     call    bout
  4861.     pop    ax
  4862.     and    al,7Fh
  4863.     cmp    al,'?'            ;? gives help
  4864.     jne    more2
  4865.     call    revon
  4866.     mov    dx,offset morm02    ;Show help message
  4867.     call    tmsg
  4868.     call    revoff
  4869.     jmps    more1
  4870. more2:    cmp    al,cr            ;cr, lf go to next line
  4871.     je    more4
  4872.     cmp    al,lf
  4873.     je    more4
  4874.     mov    dlngth,0        ;Everything else resets line count
  4875.     cmp    al,0Fh            ;^O, ^X go to next file
  4876.     je    more6
  4877.     cmp    al,18h
  4878.     je    more6
  4879.     cmp    al,03h            ;^C, ^Z, q quit
  4880.     je    more5
  4881.     cmp    al,1Ah
  4882.     je    more5
  4883.     or    al,'a'-'A'
  4884.     cmp    al,'q'
  4885.     je    more5
  4886. more4:    jmp    rskp            ;Next line, page
  4887. more5:    mov    ax,dircnt        ;Quit
  4888.     mov    dindex,ax
  4889. more6:    ret                ;Next file
  4890.  
  4891.  
  4892. ; Space remaining utility
  4893.  
  4894. spcutl:    call    getprm        ;Get the disk parameters for calculation
  4895.     call    tcrlf
  4896.     mov    ax,remK        ;Display the number of Kbytes remaining
  4897.     call    nout
  4898.     mov    dx, offset spcm01
  4899.     call    tmsg
  4900.     mov    ax,maxK        ;And the total number on the drive.
  4901.     call    nout
  4902.     mov    dx, offset spcm02
  4903.     call    tmsg
  4904.     mov    dl,fcb        ;Finally say which drive it is.
  4905.     add    dl,'A'-1
  4906.     call    bout
  4907.     mov    dl,':'
  4908.     call    bout
  4909.     call    tcrlf
  4910.     jmp    rskp
  4911.  
  4912.  
  4913. ; get and save disk parameters which relate to block allocation and size
  4914.  
  4915. getprm:    mov    newdrv,0    ;initialize flag
  4916.     mov    dl,fcb        ;specified drive must be the default
  4917.     dec    dl        ; which is true if drive was not specified
  4918.     jl    gprm2
  4919.     cmp    dl,defdrv    ; or if specified drive matches the default
  4920.     je    gprm2
  4921.     mov    newdrv,0FFh    ;otherwise show that we changed default
  4922.     push    dx
  4923.     call    getrov        ;make sure the desired drive is write enabled
  4924.     pop    dx        ; or else the data may be inaccurate
  4925.     mov    cl,dl
  4926.     mov    ax,1
  4927.     shl    ax,cl
  4928.     and    ax,bx
  4929.     jz    gprm1
  4930.     push    dx
  4931.     call    rstdsk        ;if read-only, reset all drives
  4932.     pop    dx
  4933. gprm1:    call    setdrv        ;select the new drive as default
  4934. gprm2:    push    es
  4935.     call    getdpb        ;get address of DPB in ES:BX
  4936.     mov    cl,es:2[bx]    ;get Block Shift Factor
  4937.     sub    cl,3
  4938.     mov    ax,1
  4939.     shl    ax,cl
  4940.     mov    KPB,ax        ;save Kbytes Per Block
  4941.     mov    cx,es:5[bx]    ;get DSM maximum block number
  4942.     mov    DSM,cx        ;save for file size and allocation calculation
  4943.     inc    cx        ;number of blocks includes block 0
  4944.     mul    cx
  4945.     mov    maxK,ax        ;Maximum number of Kbytes
  4946.     mov    remK,ax        ;Kbytes remaining
  4947.     mov    ax,es:7[bx]    ;subtract directory allocation from maxK
  4948.     mov    cl,5
  4949.     shr    ax,cl
  4950.     inc    ax
  4951.     sub    maxK,ax
  4952.     call    getalv        ;get address of allocation vector in ES:BX
  4953.     mov    ax,DSM        ;compute length of vector = (DSM/8)+1
  4954.     mov    cl,3
  4955.     shr    ax,cl
  4956.     inc    ax
  4957.     mov    cx,ax
  4958.     mov    ax,0        ;Count allocated blocks:
  4959. gprm3:    mov    dl,es:[bx]    ;for each byte in vector,
  4960.     inc    bx
  4961.     push    cx
  4962.     mov    cx,8        ;  for each bit in byte,
  4963. gprm4:    test    dl,1
  4964.     jz    gprm5
  4965.     inc    ax        ;    if bit is set, then block is allocated
  4966. gprm5:    shr    dl,1
  4967.     loop    gprm4
  4968.     pop    cx
  4969.     loop    gprm3
  4970.     mul    KPB        ;convert allocated blocks to Kbytes
  4971.     sub    remK,ax        ;subtract allocated Kbytes from remK
  4972.     pop    es
  4973.     cmp    newdrv,0    ;reset default drive if we changed it
  4974.     je    gprm6
  4975.     mov    dl,defdrv
  4976.     call    setdrv
  4977. gprm6:    ret
  4978.  
  4979.  
  4980. ; This subroutine fills the previously allocated memory buffer with a sorted
  4981. ; list of filenames matching the wild name in fcb.  On failure, if there were
  4982. ; no files, it prints an appropriate error message and simply returns.  On
  4983. ; success, it returns to the skip location with the number of entries
  4984. ; in the list in dircnt.  Each buffer entry is 16 bytes long and contains
  4985. ; the user number at offset 0, the filename (with all attribute bits stripped)
  4986. ; at offset 1-11, the allocated size in Kbytes at offset 12-13, and the
  4987. ; read-only and system flags at offsets 14 and 15.
  4988.  
  4989. getwld:    mov    byte ptr fcb+12,'?' ;Match any extent
  4990.     mov    byte ptr fcb+13,'?'
  4991.     mov    byte ptr fcb+14,'?'
  4992.     call    getprm        ;get disk parameters for size calculation
  4993.     mov    dircnt,0    ;zero file count and total space occupied
  4994.     mov    dx, offset fcb
  4995.     call    gtjfn        ;get first filename
  4996.     cmp    al,0FFh
  4997.     jne    gwld2
  4998.     mov    dx, offset erms15 ;unable to find file
  4999.     call    tcrmsg
  5000.     mov    dx, offset fcb
  5001.     call    tfile
  5002.      ret
  5003. gwld2:    mov    cl,5        ;find file directory entry
  5004.     shl    al,cl
  5005.     mov    ah,0
  5006.     mov    si, offset dma
  5007.     add    si,ax        ;pointer to filename (incl. user number)
  5008.     mov    di, offset dirbuf
  5009.     push    ds
  5010.     pop    es
  5011.     mov    ax,9[si]    ;get read-only and system flags
  5012.     and    ax,8080h    ;keep only attribute bits
  5013.     mov    14[di],ax    ;save flags at end of buffer
  5014.     mov    cx,12
  5015. gwld2a:    lodsb
  5016.     and    al,7Fh        ;get rid of all attribute bits
  5017.     stosb
  5018.     loop    gwld2a
  5019.     add    si,4        ;look at allocation area
  5020.     mov    ax,0        ;initialize block count
  5021.     cmp    DSM,256        ;if <256 blocks, then each takes a byte
  5022.     jb    gwld2c
  5023.     mov    cx,8        ;8 blocks, one word each
  5024. gwld2b:    cmp    word ptr [si],0
  5025.     je    gwld2e
  5026.     inc    si
  5027.     inc    si
  5028.     inc    ax
  5029.     loop    gwld2b
  5030.     jmps    gwld2e
  5031. gwld2c:    mov    cx,16        ;16 blocks, one byte each
  5032. gwld2d:    cmp    byte ptr [si],0
  5033.     je    gwld2e
  5034.     inc    si
  5035.     inc    ax
  5036.     loop    gwld2d
  5037. gwld2e:    mul    KPB        ;convert blocks to kbytes
  5038.     stosw            ;save this FCB's allocation
  5039.     mov    ax,dircnt
  5040.     cmp    ax,word ptr membuf+2 ;don't exceed buffer length
  5041.     jb    gwld2f
  5042.     mov    dx,offset erms27 ; if memory exceeded, print warning
  5043.     call    tcmsgc        ;     and use what info we have
  5044.     jmp    gwld4
  5045. gwld2f:    mov    si, offset dirbuf ;go back to start of filename
  5046.     mov    es,word ptr membuf ;find correct location in sorted file list
  5047.     mov    di,0
  5048.     mov    cx,dircnt    ;number of entries already in list
  5049.     jcxz    gwld3e
  5050. gwld3a:    push    cx
  5051.     push    si
  5052.     push    di
  5053.     mov    cx,12
  5054.     repe    cmpsb
  5055.     jb    gwld3d        ;table entry greater than this file, insert
  5056.     ja    gwld3c        ;table entry less than this file, keep looking
  5057.     lodsw            ;else table entry same as file
  5058.     add    es:[di],ax    ; ...add this FCB's allocation to size
  5059. gwld3b:    pop    di
  5060.     pop    si
  5061.     pop    cx
  5062.     jmp    gwld3f        ;go get next filename
  5063. gwld3c:    pop    di        ;haven't found insert location yet
  5064.     pop    si
  5065.     pop    cx
  5066.     add    di,16
  5067.     loop    gwld3a
  5068.     jmp    gwld3e        ;if greater than all entries, insert at end
  5069. gwld3d:    pop    di        ;insertion point
  5070.     pop    si        ;filename pointer
  5071.     pop    ax        ;number of entries following insertion point
  5072.     push    si
  5073.     push    di
  5074.     mov    cl,4        ;each entry occupies 16 bytes
  5075.     shl    ax,cl
  5076.     add    di,ax
  5077.     dec    di
  5078.     mov    si,di        ;point to last byte of table
  5079.     add    di,16        ;move last part down 16 bytes
  5080.     mov    cx,ax
  5081.     push    ds        ;save filename segment
  5082.     push    es        ;make all action in table segment
  5083.     pop    ds
  5084.     std            ;decrement pointers after each move
  5085.     rep    movsb
  5086.     cld
  5087.     pop    ds        ;restore filename segment
  5088.     pop    di        ;insertion point
  5089.     pop    si        ;filename pointer
  5090. gwld3e:    mov    cx,16        ;insert filename in table
  5091.     rep    movsb
  5092.     inc    dircnt        ;count new entry
  5093. gwld3f:    mov    dx, offset fcb    ;look for another matching filename
  5094.     call    gnjfn
  5095.     cmp    al,0FFh
  5096.     je    gwld4
  5097.     jmp    gwld2        ;go process next filename
  5098. gwld4:    push    ds
  5099.     pop    es
  5100.     jmp    rskp
  5101.  
  5102. ; General output utility routines
  5103.  
  5104. tmsgcr:    call    tmsg        ;Print the string
  5105.     call    tcrlf        ;Print a CRLF.
  5106.     ret
  5107.  
  5108. tcrmsg:    push    dx        ;Don't trash our string.
  5109.     call    tcrlf        ;Print a CRLF.
  5110.     pop    dx        ;Restore our string.
  5111.     call    tmsg        ;Print the string
  5112.     ret
  5113.  
  5114. tcmsgc:    push    dx        ;Don't trash our string.
  5115.     call    tcrlf        ;Print a CRLF.
  5116.     pop    dx        ;Restore our string.
  5117.     call    tmsg        ;Print the string
  5118.     call    tcrlf        ;Print a CRLF.
  5119.     ret
  5120.  
  5121. tcrlf:    mov    dl,cr        ;print a crlf
  5122.     call    bout
  5123.     mov    dl,lf
  5124.     call    bout
  5125.     ret
  5126.  
  5127. tmsg:    push    bx        ;Don't clobber my ACs.
  5128.     mov    cl, prstr    ;Ask BDOS for string printing.
  5129.     int    bdos        ;What a way to call the BDOS.
  5130.     pop    bx
  5131.     ret
  5132.  
  5133. tfile:    mov    bx, dx        ;Print filename in [dx]'s FCB    ;[24a] begin
  5134.     mov    dl, [bx]    ;If explicit drive number, display it.
  5135.     cmp    dl, 0
  5136.     je    tfil1
  5137.     add    dl, 'A'-1
  5138.     push    bx
  5139.     call    bout
  5140.     mov    dl, ':'
  5141.     call    bout
  5142.     pop    bx
  5143. tfil1:    mov    cx, 11        ;Now display 11 chars of filename
  5144. tfil2:    push    cx
  5145.     cmp    cx, 3        ;With period before file type
  5146.     jne    tfil3
  5147.     push    bx
  5148.     mov    dl, '.'
  5149.     call    bout
  5150.     pop    bx
  5151. tfil3:    inc    bx
  5152.     mov    dl, [bx]
  5153.     cmp    dl, ' '        ;Don't include spaces
  5154.     je    tfil4
  5155.     push    bx
  5156.     call    bout
  5157.     pop    bx
  5158. tfil4:    pop    cx
  5159.     loop    tfil2
  5160.     ret                            ;[24a] end
  5161.  
  5162.  
  5163. bout:    mov    cl, conout    ;Ask BDOS for character printing.
  5164.     int    bdos
  5165.     ret
  5166.  
  5167. bin:    cmp    tkflg, 0    ;Check for command file input.    ;[29b] begin
  5168.     je    bin1
  5169.     jmp    tkin                        ;[29b] end
  5170. bin1:    mov    cl, conin    ;Get a char from the console.
  5171.     int    bdos
  5172.     ret
  5173.  
  5174. binst:    cmp    tkflg, 0    ;Check for command file input.    ;[29b] begin
  5175.     je    binst1
  5176.     jmp    tkst                        ;[29b] end
  5177. binst1:    mov    cl, consta    ;Console input status check    ;[20e] begin
  5178.     int    bdos
  5179.     or    al, al        ;Result 0 if no character ready
  5180.     jz    bins2
  5181.     jmp    rskp        ;Return SKIP if character ready
  5182. bins2:    ret                            ;[20e] end
  5183.  
  5184. dbout:    cmp    dl, 0        ;Skip null fillers. 
  5185.     je    dbout3
  5186.     call    logchr        ;Log the character if necessary ;[24a]
  5187.     call    dotab        ;Do any necessary tab expansion.
  5188.     jmp    r        ; No more chars to output.
  5189. dbout2:    mov    cl, dconio    ;Put a char to the console.
  5190.     int    bdos
  5191. dbout3:    ret
  5192.  
  5193. dbin:    push    dx
  5194.     mov    cl, dconio    ;Get a char from the console without
  5195.     mov    dl, 0FFH    ; interference.
  5196.     int    bdos
  5197.     pop    dx
  5198.     ret
  5199.  
  5200. dbinst:    push    dx
  5201.     mov    cl, dconio    ;Check the console's input status.
  5202.     mov    dl, 0FEH
  5203.     int    bdos
  5204.     pop    dx
  5205.     or    al, al        ;Result 0 if no character ready ;[20e] begin
  5206.     jz    dbins2
  5207.     jmp    rskp        ;Return SKIP if character ready
  5208. dbins2:    ret                            ;[20e] end
  5209.  
  5210. ;Log the terminal output character
  5211.  
  5212. logchr:    cmp    logfil, 0    ;Only log if file is open    ;[24a] begin
  5213.     je    logch9
  5214.     mov    bx, bufpnt    ;Store the character in the buffer.
  5215.     mov    [bx], dl
  5216.     inc    bx
  5217.     cmp    bx, offset dma+80h    ;Have we filled a buffer?
  5218.     jb    logch1
  5219.     push    dx        ;If so, write it to file.
  5220.     mov    dx, offset lfcb
  5221.     call    soutr
  5222.     pop    dx
  5223.     mov    bx, offset dma
  5224. logch1:    mov    bufpnt, bx
  5225. logch9:    ret            ;Return to output routine    ;[24a] end
  5226.  
  5227. ;Halt this program.
  5228.  
  5229. haltf:    mov    cl, reset    ;End this program.
  5230.     int    bdos
  5231.     ret            ;One never knows!
  5232.  
  5233. ;Reset the disk system to log in drives                ;[32a] begin
  5234.  
  5235. rstdsk:    mov    cl,resetd
  5236.     int    bdos
  5237.     call    inidma        ;Concurrent CP/M also resets DMA address
  5238.     ret
  5239.  
  5240. ;Get and set the default disk drive
  5241.  
  5242. getdrv:    mov    cl,gtdrv
  5243.     int    bdos
  5244.     ret            ;returns drive in al (A=0 through P=15)
  5245.  
  5246. setdrv:    mov    cl,stdrv    ;new drive number (A=0 through P=15) in dl
  5247.     int    bdos
  5248.     ret
  5249.  
  5250. ;Get and set the default user number
  5251.  
  5252. getusr:    mov    cl,stusr
  5253.     mov    dl,0FFh
  5254.     int    bdos
  5255.     ret            ;returns user in al (0-15)
  5256.  
  5257. setusr:    mov    cl,stusr    ;new user number (0-15) in dl
  5258.     int    bdos
  5259.     ret                            ;[32a] end
  5260.  
  5261.  
  5262. ; Get the address of the disk allocation vector            ;[32d] begin
  5263.  
  5264. getalv:    mov    cl,gtalv
  5265.     int    bdos
  5266.     ret
  5267.  
  5268. ; Get the disk read-only vector
  5269.  
  5270. getrov:    mov    cl,gtrov
  5271.     int    bdos
  5272.     ret
  5273.  
  5274. ; Set file attributes according to FCB in dx
  5275.  
  5276. setatr:    mov    cl,statr
  5277.     int    bdos
  5278.     ret
  5279.  
  5280. ; Get the address of the DPB
  5281.  
  5282. getdpb:    mov    cl,gtdpb
  5283.     int    bdos
  5284.     ret
  5285.  
  5286. ; Allocate a block of memory.  MCB address is in dx.
  5287.  
  5288. allmem:    mov    cl,allocm
  5289.     int    bdos
  5290.     ret
  5291.  
  5292. ; Free a previously allocated block of memory.  MCB address is in dx.
  5293.  
  5294. fremem:    mov    cl,freem
  5295.     int    bdos
  5296.     ret                            ;[32d] end
  5297.  
  5298.  
  5299. ; Get the first file in a wild card search.
  5300.  
  5301. gtjfn:    mov    cl, sfirst
  5302.     int    bdos
  5303.     ret
  5304.  
  5305. ; Get the next file in a wild card search.
  5306.  
  5307. gnjfn:    mov    cl, snext
  5308.     int    bdos
  5309.     ret
  5310.  
  5311. ; Close the file pointed to by the FCB in DX.
  5312.  
  5313. closf:    mov    cl, clsfil
  5314.     int    bdos
  5315.     ret
  5316.  
  5317. ; Open the file pointed to by the FCB in DX.
  5318.  
  5319. openf:    call    fcbzer        ;clear the fcb trailer        ;[29c]
  5320.     mov    cl, opnfil
  5321.     int    bdos
  5322.     ret
  5323.  
  5324. ; Create the file pointed to by the FCB in DX.
  5325.  
  5326. create:    call    fcbzer        ;clear the fcb trailer        ;[29c]
  5327.     mov    cl, makef
  5328.     int    bdos
  5329.     ret
  5330.  
  5331. fcbzer:    push    bx        ;Clear the end of the FCB    ;[29c] begin
  5332.     push    cx        ;  prior to opening or creating a file.
  5333.     mov    bx, dx
  5334.     add    bx, 12
  5335.     mov    ch, 0
  5336.     mov    cl, 23
  5337. fcbz1:    mov    [bx], ch
  5338.     inc    bx
  5339.     loop    fcbz1
  5340.     pop    cx
  5341.     pop    bx
  5342.     ret                            ;[29c] end
  5343.  
  5344. ; Write a record to the file pointed to by the FCB in DX.
  5345.  
  5346. soutr:    mov    cl, writef
  5347.     int    bdos
  5348.     ret
  5349.  
  5350. ; Read a record from the file pointed to by the FCB in DX.
  5351.  
  5352. sinr:    mov    cl, readf
  5353.     int    bdos
  5354.     ret
  5355.  
  5356. ; Delete the file pointed to by the FCB in DX.
  5357.  
  5358. delete:    mov    cl, delf
  5359.     int    bdos
  5360.     ret
  5361.  
  5362. ; Sets dma to the default buffer.  Functions that change this must call this
  5363. ; function to reset it before continuing
  5364.  
  5365. inidma:    push    dx
  5366.     mov    dx, offset dma
  5367.     call    setdma
  5368.     pop    dx
  5369.     ret
  5370.  
  5371. ; Sets the DMA to the offset pointed to in DX and the base in DS.
  5372.  
  5373. setdma:    mov    cl, dmaset
  5374.     int    bdos
  5375.     mov    dx, ds
  5376.     mov    cl, dmabas
  5377.     int    bdos
  5378.     ret
  5379.  
  5380. ; Do random access read, write, or file size checks, FCB is in dx
  5381.  
  5382. rinr:    mov    cl, readr
  5383.     int    bdos
  5384.     ret
  5385.  
  5386. routr:    mov    cl, writer
  5387.     int    bdos
  5388.     ret
  5389.  
  5390. sizef:    mov    cl, cflsz
  5391.     int    bdos
  5392.     ret
  5393.  
  5394. ; Jumping to this location is like retskp.  It assumes the instruction
  5395. ;   after the call is a jmp addr.
  5396.  
  5397. rskp:    pop    bp
  5398.     add    bp, 3
  5399.     push    bp
  5400.     ret
  5401.  
  5402.  
  5403. ; Jumping here is the same as a ret.
  5404.  
  5405. r:    ret
  5406. <<< c86xap.a86 >>>
  5407. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  5408. ; [36]    Add calls to support Concurrent CP/M.
  5409. ; [34]    Make BREAK be correct length (250 ms).
  5410. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  5411. ; [30d] Add SET PORT command, currently unimplemented.
  5412. ; [30c] Isolate all machine dependencies in KERIO.
  5413. ; [30a] Add keyboard DEL key alteration for APC
  5414. ;    RonB, 04/18/84
  5415. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  5416. ; [28e] Switch to local stack on interrupts.
  5417. ;    RonB, 03/28/84
  5418. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  5419. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  5420. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  5421. ;    RonB,03/02/84
  5422. ; [19a] Add XON/XOFF type flow control
  5423. ; [19b]    Clear screen and beginning and end of program.
  5424. ; [19e]    Add PRTBRK to send break to port (Rainbow only)
  5425. ; [19g]    Put in EQU for clock rate for timing loops.
  5426. ;    Rg, 2/84     <Oc.Garland%CU20B@Columbia-20>
  5427. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  5428. ;  [par] Added calls to set parity, strip parity on input if
  5429. ;        other than none parity is called for.
  5430. ;     JD, 2/84
  5431. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  5432. ;  [2]    Add a de-initialization routine for the serial port, to restore
  5433. ;    changed interrupt vectors, etc.
  5434. ;    RonB,12/23/83
  5435. ;  [1]    Add I/O support for the NEC Advanced Personal Computer
  5436. ;    RonB,12/23/83
  5437. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  5438.  
  5439. ; This module contains all the low level communications port I/O
  5440. ; routines.
  5441.  
  5442. ; Here are the I/O routines for the NEC APC.
  5443.  
  5444.     CSEG $
  5445.  
  5446. ; Clock rate *10 for timing loops    ;[19g]
  5447. clckrt    equ    49        ;[19g]  4.9 Mhz            ;[20b]
  5448.  
  5449. ; Interrupt vector locations, in data segment 0
  5450.  
  5451. mnioff    equ    84h        ;sio interrupt offset
  5452. mniseg    equ    86h        ;sio interrupt segment
  5453.  
  5454. ; 8259 Interrupt controller (master)
  5455.  
  5456. iccmd    equ    20h        ;interrupt command register
  5457. icmask    equ    22h        ;interrupt mask register
  5458.  
  5459. ; 8259 commands and masks
  5460.  
  5461. icEOI    equ    20h        ;end of interrupt (command)
  5462. ictmof    equ    08h        ;disable timer (mask)
  5463. icmnof    equ    02h        ;disable RS232 (mask)
  5464.  
  5465. ; 8253-5 Interval Timer
  5466.  
  5467. tmdata    equ    2bh        ;baud set (chan 1)
  5468. tmcmd    equ    2fh        ;baud timer command port
  5469.  
  5470. ; 8253 Timer commands
  5471.  
  5472. tmch1    equ    76h        ;select & init timer channel 1
  5473.  
  5474. ; 8251A USART controller
  5475.  
  5476. mndata    equ    30h        ;    data port
  5477. mnsts1    equ    32h        ;in  status port
  5478. mnsts2    equ    34h        ;in  nec special status port
  5479. mncmd    equ    32h        ;out command port
  5480. mnmsk    equ    34h        ;out interrupt mask port
  5481. mntdc    equ    36h        ;out transmit disable port
  5482.  
  5483. ; 8251 status port 1 bits
  5484.  
  5485. mninp    equ    02h        ;receive ready value
  5486. mnout    equ    01h        ;send ready value
  5487. mndsr    equ    80h        ;data set ready
  5488.  
  5489. ; 8251 status port 2 bits
  5490.  
  5491. mncts    equ    04h        ;clear to send
  5492.  
  5493. ; 8251 initialization instructions
  5494.  
  5495. ;    command instructions
  5496.  
  5497. ctxe    equ    01h        ;transmit enable
  5498. cdtr    equ    02h        ;dtr signal high
  5499. crxe    equ    04h        ;receive enable
  5500. cbrk    equ    08h        ;send break
  5501. cerr    equ    10h        ;error reset
  5502. crts    equ    20h        ;rts signal high
  5503. cmode    equ    40h        ;reset - go to mode instruction format
  5504. chunt    equ    80h        ;hunt for sync characters
  5505.  
  5506. ;    mode instructions
  5507.  
  5508. m1x    equ    01h        ;baud rate factor: 1x
  5509. m16x    equ    02h        ;                  16x
  5510. m64x    equ    03h        ;                  64x
  5511. m5d    equ    00h        ;data bits: 5
  5512. m6d    equ    04h        ;           6
  5513. m7d    equ    08h        ;           7
  5514. m8d    equ    0Ch        ;           8
  5515. mpn    equ    00h        ;parity: none
  5516. mpo    equ    10h        ;        odd
  5517. mpe    equ    30h        ;        even
  5518. m1s    equ    40h        ;stop bits: 1
  5519. m15s    equ    80h        ;           1.5
  5520. m2s    equ    0C0h        ;           2
  5521.  
  5522. ; 8251 interrupt mask port bits
  5523.  
  5524. txmsk    equ    01h        ;disable transmit complete interrupt
  5525. rxmsk    equ    02h        ;disable receive complete interrupt
  5526. tbemsk    equ    04h        ;disable transmit buffer empty interrupt
  5527.  
  5528. outlmt    EQU    1000H        ;Number of times to check output status
  5529.                 ; before giving up on send.        ;[20d]
  5530.  
  5531. ; dispatch:    Under Concurrent CP/M, releases the processor for other
  5532. ;        use when waiting for either the receive or the send status
  5533. ;        routines to indicate success.
  5534.  
  5535. dispatch:
  5536.     push    ax
  5537.     push    bx
  5538.     push    cx
  5539.     mov    cl,8Eh            ; P-Dispatch
  5540.     int    224
  5541.     pop    cx
  5542.     pop    bx
  5543.     pop    ax
  5544.     ret
  5545.  
  5546.  
  5547. ; Test if port is ready to send next char.  Returns RSKP if ready.
  5548. ; Trashes dx.
  5549.  
  5550. outwt:    cmp    floctl, floxon    ;are we doing flow-control?    [19a] start
  5551.     jne    outwt1        ;no - go on
  5552.     cmp    xofrcv, true    ;are we being held?
  5553.     je    outwt3        ;yes - return status not ready
  5554. outwt1:    push    ax
  5555.     mov    dx,mnsts1
  5556.     in    al,dx
  5557.     and    al,mndsr+mnout
  5558.     sub    al,mndsr+mnout
  5559.     jnz    outwt2
  5560.     mov    dx,mnsts2
  5561.     in    al,dx
  5562.     and    al,mncts
  5563.     jnz    outwt4
  5564. outwt2:    pop    ax
  5565. outwt3:    call    dispatch    ;let other CCPM processes have a chance    ;[36]
  5566.      ret
  5567. outwt4:    pop    ax
  5568.     jmp    rskp
  5569.  
  5570.  
  5571. ; Output data to port. Trashes DX and prints char in AL.
  5572.  
  5573. outchr:    mov    dx,mndata
  5574.     out    dx,al
  5575.     ret
  5576.  
  5577.  
  5578. ; Output the character in AL, checking first to make sure the port is clear.
  5579.  
  5580. prtout:    call    dopar        ;[par] set parity
  5581.     push    dx
  5582.     push    cx                        ;[20d] begin
  5583.     mov    cx,outlmt
  5584. prtou2:    call    outwt        ;Wait until the port is ready
  5585.      loop    prtou2        ; or too much time has passed.
  5586.      nop
  5587.     call    outchr        ;Output it.
  5588.     pop    cx                        ;[20d] end
  5589.     pop    dx
  5590.     ret
  5591.  
  5592.  
  5593. ; Test if data is available from port.
  5594.  
  5595. instat:    cmp    mnchrn,0    ;Any chars in the buffer?
  5596.     jne    inst2
  5597.     call    dispatch    ;let other CCPM processes have a chance    ;[36]
  5598.      ret
  5599. inst2:    jmp    rskp
  5600.  
  5601.  
  5602. ; Input data from port.  Preserves all registers and returns char in
  5603. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  5604. ; already there.
  5605.  
  5606. inchr:    push    bx
  5607.     cli            ;Disable interrupts while were are playing.
  5608.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  5609.     mov    bx,mnchop    ;Get the pointer into the buffer.
  5610.     inc    bx        ;Increment to the next char.
  5611.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  5612.     jb    inchr2
  5613.     mov    bx, offset mnchrs ;If so wrap around to the start.
  5614. inchr2:    mov    mnchop,bx    ;Save the updated pointer.
  5615.     mov    al,[bx]        ;Get the character.
  5616.     sti            ;All done, we can restore interrupts.
  5617.     pop    bx
  5618.     cmp    parflg,parnon    ;[par] no parity?
  5619.     je    inchr3        ;[par] yup, don't bother stripping
  5620.     and    al,7fh        ;[par] checking parity, strip off
  5621. inchr3:    cmp    floctl, floxon    ;do flow-control?        [19a] start
  5622.     je    inchr4        ;If yes jump
  5623.     ret
  5624. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  5625.     je    inchr5        ;Jump if yes
  5626.     ret
  5627. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  5628.     jb    inchr6        ;yes - jump
  5629.     ret
  5630. inchr6:    push    ax        ;save current character
  5631.     mov    al, xon
  5632.     call    prtout        ;send an XON
  5633.     mov    xofsnt, false    ;turn off the flag
  5634.     pop    ax        ;get back character
  5635.     ret            ;                [19a] end
  5636.  
  5637.  
  5638.  
  5639. mnax    dw    0        ;Storage in CSEG        ;[28e] begin
  5640. mnsp    dw    0        ;  for use by interrupt handler
  5641. mnsseg    dw    0
  5642. mndseg    dw    0
  5643.  
  5644. ; This routine handles the interrupts on input.
  5645.  
  5646. mnint:    cli
  5647.     mov    cs:mnax, ax    ;Save interrupt stack location.
  5648.     mov    ax, sp
  5649.     mov    cs:mnsp, ax
  5650.     mov    ax, ss
  5651.     mov    cs:mnsseg, ax
  5652.     mov    ax, cs:mndseg    ;Switch to our internal stack.
  5653.     mov    ss, ax
  5654.     mov    sp, offset mnstk
  5655.     push    ds        ;Save all registers.
  5656.     push    es
  5657.     push    bp
  5658.     push    di
  5659.     push    si
  5660.     push    dx
  5661.     push    cx
  5662.     push    bx
  5663.     mov    ds, ax        ;Get our data segment address.
  5664.     call    mnproc        ;Process the character.
  5665.     mov    dx, iccmd
  5666.     mov    al, icEOI    ;signal end of interrupt to controller
  5667.     out    dx, al
  5668.     pop    bx        ;Restore all registers.
  5669.     pop    cx
  5670.     pop    dx
  5671.     pop    si
  5672.     pop    di
  5673.     pop    bp
  5674.     pop    es
  5675.     pop    ds
  5676.     mov    ax, cs:mnsp    ;Restore the original stack.
  5677.     mov    sp, ax
  5678.     mov    ax, cs:mnsseg
  5679.     mov    ss, ax
  5680.     mov    ax, cs:mnax
  5681.     iret            ;Return from the interrupt.    ;[28e] end
  5682.  
  5683.  
  5684. ; This routine (called by MNINT) gets a char from the serial port
  5685. ; and puts it in the ring buffer.
  5686.  
  5687. mnproc:    mov    dx,mnsts1
  5688.     in    al,dx        ;Get the port status.
  5689.     and    al,mninp    ;Is a character waiting?
  5690.     jnz    mnpro2        ;   Yes, go take care of it.
  5691.      ret            ;   No, just a false alarm.
  5692.  
  5693. mnpro2:    mov    dx,mndata
  5694.     in    al,dx        ;Read the char.
  5695.     cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  5696.     jne    mnpr2b        ;no - go on
  5697.     cmp    al, xoff    ;is it an XOFF?
  5698.     jne    mnpr2a        ;no - go on
  5699.     mov    xofrcv, true    ;set the flag
  5700.     ret
  5701. mnpr2a:    cmp    al, xon        ;an XON?
  5702.     jne    mnpr2b        ;no
  5703.     mov    xofrcv, false    ;clear the flag
  5704.     ret            ;                [19a] end
  5705. mnpr2b:    cmp    mnchrn,mnchnd    ;Is the buffer full?
  5706.     je    mnperr        ;If so, take care of the error.
  5707.     inc    mnchrn        ;Increment the character count.
  5708.     mov    bx,mnchip    ;Get the buffer input pointer.
  5709.     inc    bx        ;Increment it.
  5710.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  5711.     jb    mnpro3
  5712.     mov    bx, offset mnchrs ;Yes, point to the start again.
  5713. mnpro3:    mov    mnchip,bx    ;Save the pointer.
  5714.     mov    [bx],al        ;Put the character in the buffer.
  5715.     cmp    floctl, floxon    ;do flow-control?        [19a] start
  5716.     je    mnpro4        ;If yes jump
  5717.     ret
  5718. mnpro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  5719.     jnz    mnpro5
  5720.     ret            ;return if we have
  5721. mnpro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  5722.     ja    mnpro6        ;yes - jump
  5723.     ret
  5724. mnpro6:    mov    al, xoff
  5725.     call    prtout        ;send an XOFF
  5726.     mov    xofsnt, true    ;set the flag
  5727.     ret            ;                [19a] End
  5728.  
  5729. mnperr:    ret            ;Just return on an error for now.
  5730.  
  5731.  
  5732. ; prtbrk - send a break        ;                [20b] start
  5733.  
  5734. prtbrk:                ;
  5735.     mov    dx,mncmd    ;break goes to command port
  5736.     mov    al,cbrk+crts+cerr+crxe+cdtr+ctxe ;add break to normal command
  5737.     out    dx,al
  5738.     mov    ax, 275        ;.. for 275 millisec's        [34]
  5739.     call    mswait        ;                [34]
  5740.     mov    al,crts+cerr+crxe+cdtr+ctxe ;RTS & DTR high, Rx & Tx enabled
  5741.     out    dx,al        ;return to normal setting
  5742.     ret            ;                 [19e] end
  5743.  
  5744. mswait:                ;                [34] start
  5745.     mov    cx,5*clckrt    ; inner loop count for 1 millisec.
  5746. mswai1:
  5747.     sub    cx,1        ;** inner loop takes 20 clock cycles
  5748.     jnz    mswai1        ;**
  5749.     dec    ax        ; outer loop counter
  5750.     jnz    mswait        ; wait another millisecond
  5751.     ret            ;                [34] end
  5752.  
  5753.  
  5754. ; serini - This routine initializes all devices that need it.
  5755. ;       Called at the start of the program.
  5756.  
  5757. serini:    cmp    mninit,0FFh    ; must only do this initialization once
  5758.     je    serin2
  5759.     mov    mninit,0FFh
  5760.  
  5761.     push    es
  5762.  
  5763. ; Make DEL key return a 7F code rather than the 18 (control-X)    ;[30a] begin
  5764. ; that it ordinarily does.  This involves modifying a key
  5765. ; conversion table in the BIOS.  Version 1.107 and later
  5766. ; contain a pointer to this table at 40:256C, but earlier
  5767. ; versions which do not are still in common use, so I will
  5768. ; try to find it with a direct search.
  5769.  
  5770.     cld
  5771.     mov    ax, 40h        ;BIOS segment
  5772.     mov    es, ax
  5773.     mov    di, 2500h    ;Start of BIOS
  5774.     mov    al, 0FCh    ;Key gives this value
  5775.     mov    ah, 18h        ;Translated to this value
  5776.     mov    cx, -1
  5777. serina:    repnz    scasb        ;Look for the key value
  5778.     or    cx, cx        ;Zero if search failed
  5779.     jz    serinb        ; If so, do nothing
  5780.     cmp    es:[di], ah    ;Translation value next?
  5781.     jne    serina        ; If not, keep looking
  5782.     mov    kbpat, di    ;Save the location we're patching.
  5783.     mov    al, 7Fh        ;Insert a DEL character
  5784.     mov    es:[di], al
  5785. serinb:                ;...and continue    ;[30a] end
  5786.  
  5787.  
  5788.     mov    dx,icmask
  5789.     in    al,dx        ;get current interrupt mask
  5790.     mov    mnxmsk,al    ;save it for restore
  5791.  
  5792. ;    NEC recommends that the timer be turned off during interrupt-driven
  5793. ;    serial I/O, but this disables the clock and keyboard repeat.  I have
  5794. ;    not had any bad results from leaving it enabled.  I will leave the
  5795. ;    disabling code here in case something develops. -- RonB
  5796.  
  5797. ;    or    al,ictmof+icmnof;mask off timer and sio interrupts
  5798.     or    al,icmnof    ;mask off sio interrupt
  5799.     out    dx,al
  5800.  
  5801.     mov    ax,ds        ;save data segment in cseg
  5802.     mov    cs:mndseg,ax    ;   for use by the interrupt handler
  5803.  
  5804.     mov    ax,0        ;point to zero page to replace
  5805.     mov    es,ax        ;the sio interrupt vector
  5806.     mov    ax,es:.mniseg    ;after first saving the current vector
  5807.     mov    mnxseg,ax
  5808.     mov    ax,es:.mnioff
  5809.     mov    mnxoff,ax
  5810.     cli
  5811.     mov    ax,cs
  5812.     mov    es:.mniseg,ax
  5813.     mov    ax,offset mnint
  5814.     mov    es:.mnioff,ax
  5815.     sti
  5816.  
  5817.     call    stmode        ;set mode & baud to defaults
  5818.     call    stbaud
  5819.  
  5820.     mov    dx,mntdc
  5821.     mov    al,00h        ;enable transmission of data
  5822.     out    dx,al
  5823.  
  5824.     mov    dx,mndata    ;dummy read to clear buffer
  5825.     in    al,dx
  5826.  
  5827.     mov    dx,mnmsk
  5828.     mov    al,txmsk+tbemsk    ;set interrupt mask (enable read int)
  5829.     out    dx,al
  5830.  
  5831.     mov    dx,icmask
  5832.     in    al,dx        ;enable sio interrupts
  5833.     and    al,not icmnof
  5834.     out    dx,al
  5835.  
  5836.     pop    es
  5837.  
  5838. serin2:    ret
  5839.  
  5840.  
  5841. ; serfin - this routine is used to "undo" what serini has done, called
  5842. ;       just before exiting back to cp/m.
  5843.  
  5844. serfin:
  5845.     cmp    mninit,0FFh    ;check if initialization has been done
  5846.     jne    serfn2        ;if not, don't de-initialize
  5847.     mov    mninit,0
  5848.  
  5849.     push    es
  5850.  
  5851. ; Unpatch the keyboard conversion table                ;[30a] begin
  5852. ; Restore control-X value for DEL key from our 7F value.
  5853.  
  5854.     les    di, dword ptr kbpat        ;Get the patch location
  5855.     or    di, di        ;Did we patch it at all?
  5856.     jz    serfia        ; If not, skip this
  5857.     mov    kbpat, 0    ;Show no longer patched
  5858.     mov    al, 18h        ;Restore control-X value
  5859.     mov    es:[di], al
  5860. serfia:                ;...and continue    ;[30a] end
  5861.  
  5862.     cli
  5863.     mov    dx,icmask
  5864.     mov    al,mnxmsk    ;restore the old interrupt mask
  5865.     out    dx,al
  5866.     mov    ax,0
  5867.     mov    es,ax
  5868.     mov    ax,mnxseg    ;restore sio interrupt vector
  5869.     mov    es:.mniseg,ax
  5870.     mov    ax,mnxoff
  5871.     mov    es:.mnioff,ax
  5872.     sti
  5873.  
  5874.     pop    es
  5875.  
  5876. serfn2:    ret
  5877.  
  5878.  
  5879. ; This routine clears the serial port input buffer.  It is called to
  5880. ; clear out excess NAKs that can result from server mode operation.
  5881.  
  5882. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  5883.     mov    mnchip, OFFSET mnchrs-1+mnchnd ;Reset input pointer.
  5884.     mov    mnchop, OFFSET mnchrs-1+mnchnd ;Reset output pointer.
  5885.     ret
  5886.  
  5887. ; set the parity, number of data bits, and number of stop bits
  5888.  
  5889. stmode:    mov    dx,mncmd
  5890.     mov    al,0        ;recommended reset procedure:
  5891.     out    dx,al        ;three 0's followed by a cmode
  5892.     mov    al,0
  5893.     out    dx,al
  5894.     mov    al,0
  5895.     out    dx,al
  5896.     mov    al,cmode    ;enable mode setting
  5897.     out    dx,al
  5898.     mov    al,m1s        ;1 stop, no parity, 8 data, 16x baud
  5899.     add    al,mpn        ;Note: these adds are distinct to
  5900.     add    al,m8d        ;      allow the 8251 time to reset
  5901.     add    al,m16x
  5902.     out    dx,al
  5903.     mov    al,crts+cerr+crxe+cdtr+ctxe ;RTS & DTR high, Rx & Tx enabled
  5904.     out    dx,al
  5905.     ret
  5906.  
  5907.  
  5908. ; set the baud rate
  5909.  
  5910. stbaud:    mov    al,mnbaud    ;get the baud rate information
  5911.     cmp    al,12        ;check for valid range (0-12)
  5912.     ja    stb02
  5913.     mov    bx,offset baudtb;get address of baud rate table
  5914.     add    al,al        ;compute word offset
  5915.     mov    ah,0
  5916.     add    bx,ax
  5917.     mov    dx,tmcmd
  5918.     mov    al,tmch1    ;select timer channel 1
  5919.     out    dx,al
  5920.     mov    dx,tmdata
  5921.     mov    ax,[bx]        ;get value
  5922.     out    dx,al        ;output low byte
  5923.     mov    al,ah
  5924.     out    dx,al        ;output high byte
  5925. stb02:    ret
  5926.  
  5927.     dseg $
  5928.  
  5929. ;    Serial port default parameters
  5930.  
  5931. mnbaud    db    6        ;300 baud
  5932.  
  5933. ;    Interval Timer values (assumes 16x baud rate mode)
  5934.  
  5935. baudtb    dw    0C00h        ;50 baud    0
  5936.     dw    0800h        ;75 baud    1
  5937.     dw    0600h        ;100 baud    2
  5938.     dw    0574h        ;110 baud    3
  5939.     dw    0400h        ;150 baud    4
  5940.     dw    0300h        ;200 baud    5
  5941.     dw    0200h        ;300 baud    6
  5942.     dw    0100h        ;600 baud    7
  5943.     dw    0080h        ;1200 baud    8
  5944.     dw    0040h        ;2400 baud    9
  5945.     dw    0020h        ;4800 baud    10
  5946.     dw    0010h        ;9600 baud    11
  5947.     dw    0008h        ;19200 baud    12
  5948.  
  5949. mninit    db    0        ;set to 0FFh if initialization has been done
  5950. mnxmsk     db    0        ;8259 interrupt mask storage
  5951. mnxseg    dw    0        ;system sio interrupt vector
  5952. mnxoff    dw    0
  5953.  
  5954. mnchnd    equ    512        ;Size of circular buffer.
  5955. mnchrs    rb    mnchnd        ;Circular character buffer for input.
  5956. mnchip    dw    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  5957. mnchop    dw    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  5958. mnchrn    dw    0        ;Number of chars in the buffer.
  5959.  
  5960. mntrg1    equ    128        ;[19a] Low trigger point for Auto XON/XOFF
  5961. mntrg2    equ    384        ;[19a] High trigger point for Auto XON/XOFF
  5962.  
  5963. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  5964. xofsnt    db    0        ;[19a] set if XOFF was sent
  5965. xofrcv    db    0        ;[19a] set if XOFF was recieved
  5966.  
  5967.     rw    32        ;Interrupt stack        ;[28e]
  5968. mnstk    dw    0        ;bottom of stack        ;[28e]
  5969.  
  5970. kbpat    dw    0000h,0040h    ;patch location for DEL key    ;[30a]
  5971.  
  5972.  
  5973.     CSEG $
  5974.  
  5975. ; The following routines do the SET and SHOW for the machine dependent
  5976. ; features of Kermit.  At present there are only two:  baud rate setting
  5977. ; and port selection.
  5978.  
  5979. ;    This is the SET BAUD rate subcommand
  5980.  
  5981. bdset:    mov    dx, offset bdtab
  5982.     mov    bx, offset bdhlp
  5983.     mov    ah, cmkey
  5984.     call    comnd
  5985.      jmp    r
  5986.     mov    temp1, bx
  5987.     mov    ah, cmcfm
  5988.     call    comnd        ;Get a confirm.
  5989.      jmp    r        ; Didn't get a confirm.
  5990.     mov    bx, temp1
  5991.     mov    mnbaud, bl    ;Set the baud rate table index.
  5992.     call    stbaud
  5993.     jmp    rskp
  5994.  
  5995. ;    This is the SET PORT subcommand (not implemented in APC)
  5996.  
  5997. prtset:    mov    ah, cmcfm
  5998.     call    comnd        ;Get a confirm.
  5999.      jmp    $+3        ; Didn't get a confirm.
  6000.     mov    dx, offset infms6 ;Tell user it's not implemented
  6001.     call    tcrmsg
  6002.     jmp    rskp
  6003.  
  6004.  
  6005. ; The following procedures implement the SHOW command for the system
  6006. ; dependent features of baud rate and port selection.
  6007.  
  6008. shobd:    mov    dx, offset bdst    ;Baud rate string.
  6009.     call    tcrmsg
  6010.     mov    al, mnbaud    ;Print the keyword corresponding to the
  6011.     mov    bx, offset bdtab ; current value of mnbaud.
  6012.     call    tabprt
  6013.     ret
  6014.  
  6015. shoprt:    ret            ;Port selection not implemented.
  6016.  
  6017.  
  6018.     DSEG $
  6019.  
  6020. bdtab    db    13        ;Thirteen entries        ;[6] begin
  6021.     db    3,'100$'
  6022.     dw    0002H
  6023.     db    3,'110$'
  6024.     dw    0003H
  6025.     db    4,'1200$'
  6026.     dw    0008H
  6027.     db    3,'150$'
  6028.     dw    0004H
  6029.     db    5,'19200$'
  6030.     dw    000CH
  6031.     db    3,'200$'
  6032.     dw    0005H
  6033.     db    4,'2400$'
  6034.     dw    0009H
  6035.     db    3,'300$'
  6036.     dw    0006H
  6037.     db    4,'4800$'
  6038.     dw    000AH
  6039.     db    2,'50$'
  6040.     dw    0000H
  6041.     db    3,'600$'
  6042.     dw    0007H
  6043.     db    2,'75$'
  6044.     dw    0001H
  6045.     db    4,'9600$'
  6046.     dw    000BH                        ;[6] end
  6047.  
  6048. bdhlp    db    cr,lf,'    50    100    150    300    1200    4800    19200'
  6049.     db    cr,lf,'    75    110    200    600    2400    9600$'
  6050.  
  6051.  
  6052.  
  6053. ; The following routines do screen control.  These are isolated here because
  6054. ; the screen control sequences are likely to vary from system to system, even
  6055. ; though the Rainbow and APC (the only systems implemented to date) both use
  6056. ; ANSI sequences for this purpose.
  6057.  
  6058.     CSEG $
  6059.  
  6060. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  6061.  
  6062. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  6063.     mov    cl, 10
  6064.     mov    al, [bx]    ;Get row value
  6065.     sub    ah, ah
  6066.     div    cl        ;units digit in ah, tens digit in al
  6067.     add    ax, '00'    ;Convert both to ASCII
  6068.     mov    word ptr anspos+2, ax    ;Save reversed (al,ah)
  6069.     mov    al, 1[bx]    ;Do same for column value
  6070.     sub    ah, ah
  6071.     div    cl
  6072.     add    ax, '00'
  6073.     mov    word ptr anspos+5, ax
  6074.     mov    dx, offset anspos    ;Print cursor positioning string.
  6075.     call    tmsg
  6076.     ret
  6077.  
  6078. ; CLRSCR - homes cursor and clears screen.
  6079.  
  6080. clrscr:    mov    dx, offset apccls
  6081.     call    tmsg
  6082.     ret
  6083.  
  6084. ; CLRLIN - clears from cursor to end of line.
  6085.  
  6086. clrlin:    mov    dl, cr        ;Go to beginning of line
  6087.     call    bout
  6088. clreol:    mov    dx, offset ansclr ;Clear from cursor to end of line
  6089.     call    tmsg
  6090.     ret
  6091.  
  6092. ; REVON - turns on reverse video display
  6093.  
  6094. revon:    mov    dx, offset ansron
  6095.     call    tmsg
  6096.     ret
  6097.  
  6098. ; REVOFF - turns off reverse video display
  6099.  
  6100. revoff:    mov    dx, offset ansrof
  6101.     call    tmsg
  6102.     ret
  6103.  
  6104. ; BLDON - turns on bold (highlighted) display
  6105.  
  6106. bldon:    ret
  6107.  
  6108. ; BLDOFF - turns off bold (highlighted) display
  6109.  
  6110. bldoff:    ret
  6111.  
  6112.  
  6113.     DSEG $
  6114.  
  6115. anspos    db    esc,'[00;00H$'    ;Position cursor to row and column
  6116. apccls    db    1Eh,1Ah,'$'    ;Home cursor and clear screen
  6117. ansclr    db    esc,'[K$'    ;Clear from cursor to end of line
  6118. ansron    db    esc,'[7m$'    ;Turn on reverse video
  6119. ansrof    db    esc,'[m$'    ;Turn off reverse video
  6120.  
  6121.  
  6122. ; Here tab expansion is done if necessary.  If not, just return retskp.
  6123.  
  6124.     cseg $
  6125.  
  6126. dotab:    cmp    dl, tab        ;A tab?
  6127.     je    dotab1
  6128.     jmp    rskp        ;No, just proceed.
  6129. dotab1:    mov    curbuf, 2    ;Report cursor position command.
  6130.     mov    dx, offset curbuf
  6131.     mov    cl, 7
  6132.     int    220        ;Special BIOS function.
  6133.     mov    al, curbuf+2    ;Column position in binary (0-79).
  6134.     and    al, 07h        ;Number of spaces needed
  6135.     mov    cx, 0008h    ;  = 8 - (col mod 8)
  6136.     sub    cl, al
  6137. dotab2:    push    cx
  6138.     mov    dl, ' '
  6139.     call    dbout2
  6140.     pop    cx
  6141.     loop    dotab2
  6142.     ret
  6143.  
  6144.     dseg $
  6145. curbuf    db    2,0,0        ;command, row, column of cursor position ;[7]
  6146.  
  6147. delstr  db    10O,10O,'$'    ;Delete string.
  6148.  
  6149. system    db    '        NEC Advanced Personal Computer$'    ;[1][20a]
  6150. <<< c86xfj.a86 >>>
  6151. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  6152. ; [30e] Add support for Fujitsu Micro 16s
  6153. ;    Chris Barker, 01/04/85
  6154. ; [30d] Add SET PORT command, currently unimplemented.
  6155. ; [30c] Isolate all machine dependencies in KERIO.
  6156. ; [30a] Add keyboard DEL key alteration for APC
  6157. ;    RonB, 04/18/84
  6158. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  6159. ; [28e] Switch to local stack on interrupts.
  6160. ;    RonB, 03/28/84
  6161. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  6162. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  6163. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  6164. ;    RonB,03/02/84
  6165. ; [19a] Add XON/XOFF type flow control
  6166. ; [19b]    Clear screen and beginning and end of program.
  6167. ; [19e]    Add PRTBRK to send break to port (Rainbow only)
  6168. ; [19g]    Put in EQU for clock rate for timing loops.
  6169. ;    Rg, 2/84     <Oc.Garland%CU20B@Columbia-20>
  6170. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  6171. ;  [par] Added calls to set parity, strip parity on input if
  6172. ;        other than none parity is called for.
  6173. ;     JD, 2/84
  6174. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  6175. ;  [2]    Add a de-initialization routine for the serial port, to restore
  6176. ;    changed interrupt vectors, etc.
  6177. ;    RonB,12/23/83
  6178. ;  [1]    Add I/O support for the NEC Advanced Personal Computer
  6179. ;    RonB,12/23/83
  6180. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  6181.  
  6182. ; This module contains all the low level communications port I/O
  6183. ; routines.
  6184.  
  6185. ; Here are the I/O routines for the Fujitsu Micro 16s
  6186.  
  6187.     CSEG $
  6188.  
  6189. ; Clock rate *10 for timing loops    ;[19g]
  6190. clckrt    equ    80        ;[19g]  8.0 Mhz            ;[30e]
  6191.  
  6192. ; Interrupt vector locations, in data segment 0
  6193.  
  6194. mnioff    equ    30h        ;sio interrupt offset
  6195. mniseg    equ    32h        ;sio interrupt segment
  6196.  
  6197. ; 8259 Interrupt controller (master)
  6198.  
  6199. iccmd    equ    00h        ;interrupt command register
  6200. icmask    equ    02h        ;interrupt mask register
  6201.  
  6202. ; 8259 commands and masks
  6203.  
  6204. icEOI    equ    20h        ;end of interrupt (command)
  6205. ;ictmof    equ    08h        ;disable timer (mask)
  6206. icmnof    equ    04h        ;disable RS232 (mask)
  6207.  
  6208. ; Baud Rate controller (MB 14417)
  6209.  
  6210. bdport    equ    0FD59h        ;baud rate select (read/write)
  6211.  
  6212. ; 8251A USART controller
  6213.  
  6214. mndata    equ    0FD06h        ;    data port
  6215. mnsts1    equ    0FD07h        ;in  status port
  6216. mncmd    equ    0FD07h        ;out command port
  6217.  
  6218. ; 8251 status port 1 bits
  6219.  
  6220. mninp    equ    02h        ;receive ready value
  6221. mnout    equ    01h        ;send ready value
  6222. mndsr    equ    80h        ;data set ready
  6223.  
  6224. ; 8251 initialization instructions
  6225.  
  6226. ;    command instructions
  6227.  
  6228. ctxe    equ    01h        ;transmit enable
  6229. cdtr    equ    02h        ;dtr signal high
  6230. crxe    equ    04h        ;receive enable
  6231. cbrk    equ    08h        ;send break
  6232. cerr    equ    10h        ;error reset
  6233. crts    equ    20h        ;rts signal high
  6234. cmode    equ    40h        ;reset - go to mode instruction format
  6235. chunt    equ    80h        ;hunt for sync characters
  6236.  
  6237. ;    mode instructions
  6238.  
  6239. m1x    equ    01h        ;baud rate factor: 1x
  6240. m16x    equ    02h        ;                  16x
  6241. m64x    equ    03h        ;                  64x
  6242. m5d    equ    00h        ;data bits: 5
  6243. m6d    equ    04h        ;           6
  6244. m7d    equ    08h        ;           7
  6245. m8d    equ    0Ch        ;           8
  6246. mpn    equ    00h        ;parity: none
  6247. mpo    equ    10h        ;        odd
  6248. mpe    equ    30h        ;        even
  6249. m1s    equ    40h        ;stop bits: 1
  6250. m15s    equ    80h        ;           1.5
  6251. m2s    equ    0C0h        ;           2
  6252.  
  6253. outlmt    equ    1000h        ;Number of times to check output status
  6254.                 ; before giving up on send.        ;[20d]
  6255.  
  6256.  
  6257. ; Test if port is ready to send next char.  Returns RSKP if ready.
  6258. ; Trashes dx.
  6259.  
  6260. outwt:    cmp    floctl, floxon    ;are we doing flow-control?    [19a] start
  6261.     jne    outwta        ;no - go on
  6262.     cmp    xofrcv, true    ;are we being held?
  6263.     jne    outwta        ;no - ok go on
  6264.     ret            ;held - say we're busy.    [19a] end
  6265. outwta:    push    ax
  6266.     mov    dx,mnsts1
  6267.     in    al,dx
  6268.     and    al,mndsr+mnout
  6269.     sub    al,mndsr+mnout
  6270.     jz    outwt2
  6271. outwt1:    pop    ax
  6272.      ret
  6273. outwt2:    pop    ax
  6274.     jmp    rskp
  6275.  
  6276.  
  6277. ; Output data to port. Trashes DX and prints char in AL.
  6278.  
  6279. outchr:    mov    dx,mndata
  6280.     out    dx,al
  6281.     ret
  6282.  
  6283.  
  6284. ; Output the character in AL, checking first to make sure the port is clear.
  6285.  
  6286. prtout:    call    dopar        ;[par] set parity
  6287.     push    dx
  6288.     push    cx                        ;[20d] begin
  6289.     mov    cx,outlmt
  6290. prtou2:    call    outwt        ;Wait until the port is ready
  6291.      loop    prtou2        ; or too much time has passed.
  6292.      nop
  6293.     call    outchr        ;Output it.
  6294.     pop    cx                        ;[20d] end
  6295.     pop    dx
  6296.     ret
  6297.  
  6298.  
  6299. ; Test if data is available from port.
  6300.  
  6301. instat:    cmp    mnchrn,0    ;Any chars in the buffer?
  6302.     jnz    inst2
  6303.      ret
  6304. inst2:    jmp    rskp
  6305.  
  6306.  
  6307. ; Input data from port.  Preserves all registers and returns char in
  6308. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  6309. ; already there.
  6310.  
  6311. inchr:    push    bx
  6312.     cli            ;Disable interrupts while were are playing.
  6313.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  6314.     mov    bx,mnchop    ;Get the pointer into the buffer.
  6315.     inc    bx        ;Increment to the next char.
  6316.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  6317.     jb    inchr2
  6318.     lea    bx,mnchrs    ;If so wrap around to the start.
  6319. inchr2:    mov    mnchop,bx    ;Save the updated pointer.
  6320.     mov    al,[bx]        ;Get the character.
  6321.     sti            ;All done, we can restore interrupts.
  6322.     pop    bx
  6323.     cmp    parflg,parnon    ;[par] no parity?
  6324.     je    inchr3        ;[par] yup, don't bother stripping
  6325.     and    al,7fh        ;[par] checking parity, strip off
  6326. inchr3:    cmp    floctl, floxon    ;do flow-control?        [19a] start
  6327.     je    inchr4        ;If yes jump
  6328.     ret
  6329. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  6330.     je    inchr5        ;Jump if yes
  6331.     ret
  6332. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  6333.     jb    inchr6        ;yes - jump
  6334.     ret
  6335. inchr6:    push    ax        ;save current character
  6336.     mov    al, xon
  6337.     call    prtout        ;send an XON
  6338.     mov    xofsnt, false    ;turn off the flag
  6339.     pop    ax        ;get back character
  6340.     ret            ;                [19a] end
  6341.  
  6342.  
  6343.  
  6344. mnax    dw    0        ;Storage in CSEG        ;[28e] begin
  6345. mnsp    dw    0        ;  for use by interrupt handler
  6346. mnsseg    dw    0
  6347. mndseg    dw    0
  6348.  
  6349. ; This routine handles the interrupts on input.
  6350.  
  6351. mnint:    cli
  6352.     mov    cs:mnax, ax    ;Save interrupt stack location.
  6353.     mov    ax, sp
  6354.     mov    cs:mnsp, ax
  6355.     mov    ax, ss
  6356.     mov    cs:mnsseg, ax
  6357.     mov    ax, cs:mndseg    ;Switch to our internal stack.
  6358.     mov    ss, ax
  6359.     lea    sp, mnstk
  6360.     push    ds        ;Save all registers.
  6361.     push    es
  6362.     push    bp
  6363.     push    di
  6364.     push    si
  6365.     push    dx
  6366.     push    cx
  6367.     push    bx
  6368.     mov    ds, ax        ;Get our data segment address.
  6369.     call    mnproc        ;Process the character.
  6370.     mov    dx, iccmd
  6371.     mov    al, icEOI    ;signal end of interrupt to 8259A
  6372.     out    dx, al
  6373.     pop    bx        ;Restore all registers.
  6374.     pop    cx
  6375.     pop    dx
  6376.     pop    si
  6377.     pop    di
  6378.     pop    bp
  6379.     pop    es
  6380.     pop    ds
  6381.     mov    ax, cs:mnsp    ;Restore the original stack.
  6382.     mov    sp, ax
  6383.     mov    ax, cs:mnsseg
  6384.     mov    ss, ax
  6385.     mov    ax, cs:mnax
  6386.     iret            ;Return from the interrupt.    ;[28e] end
  6387.  
  6388.  
  6389. ; This routine (called by MNINT) gets a char from the serial port
  6390. ; and puts it in the ring buffer.
  6391.  
  6392. mnproc:    mov    dx,mnsts1
  6393.     in    al,dx        ;Get the port status.
  6394.     and    al,mninp    ;Is a character waiting?
  6395.     jnz    mnpro2        ;   Yes, go take care of it.
  6396.      ret            ;   No, just a false alarm.
  6397.  
  6398. mnpro2:    mov    dx,mndata
  6399.     in    al,dx        ;Read the char.
  6400.     cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  6401.     jne    mnpr2b        ;no - go on
  6402.     cmp    al, xoff    ;is it an XOFF?
  6403.     jne    mnpr2a        ;no - go on
  6404.     mov    xofrcv, true    ;set the flag
  6405.     ret
  6406. mnpr2a:    cmp    al, xon        ;an XON?
  6407.     jne    mnpr2b        ;no
  6408.     mov    xofrcv, false    ;clear the flag
  6409.     ret            ;                [19a] end
  6410. mnpr2b:    cmp    mnchrn,mnchnd    ;Is the buffer full?
  6411.     je    mnperr        ;If so, take care of the error.
  6412.     inc    mnchrn        ;Increment the character count.
  6413.     mov    bx,mnchip    ;Get the buffer input pointer.
  6414.     inc    bx        ;Increment it.
  6415.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  6416.     jb    mnpro3
  6417.     lea    bx,mnchrs    ;Yes, point to the start again.
  6418. mnpro3:    mov    mnchip,bx    ;Save the pointer.
  6419.     mov    [bx],al        ;Put the character in the buffer.
  6420.     cmp    floctl, floxon    ;do flow-control?        [19a] start
  6421.     je    mnpro4        ;If yes jump
  6422.     ret
  6423. mnpro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  6424.     jnz    mnpro5
  6425.     ret            ;return if we have
  6426. mnpro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  6427.     ja    mnpro6        ;yes - jump
  6428.     ret
  6429. mnpro6:    mov    al, xoff
  6430.     call    prtout        ;send an XOFF
  6431.     mov    xofsnt, true    ;set the flag
  6432.     ret            ;                [19a] End
  6433.  
  6434. mnperr:    ret            ;Just return on an error for now.
  6435.  
  6436.  
  6437. ; prtbrk - send a break        ;                [20b] start
  6438.  
  6439. prtbrk:
  6440.     mov    dx,mncmd    ;break goes to command port
  6441.     mov    al,cbrk+crts+cerr+crxe+cdtr+ctxe ;add break to normal command
  6442.     out    dx,al
  6443.     mov    cx, 25000    ;sit for a while
  6444. prtbk1:    loop    prtbk1
  6445.     mov    al,crts+cerr+crxe+cdtr+ctxe ;RTS & DTR high, Rx & Tx enabled
  6446.     out    dx,al        ;return to normal setting
  6447.     ret            ;                 [20b] end
  6448.  
  6449.  
  6450. ; serini - This routine initializes all devices that need it.
  6451. ;       Called at the start of the program.
  6452.  
  6453. serini:    cmp    mninit,0FFh    ; must only do this initialization once
  6454.     je    serin2
  6455.     mov    mninit,0FFh
  6456.  
  6457.     push    es
  6458.  
  6459.     mov    dx,icmask
  6460.     in    al,dx        ;get current interrupt mask
  6461.     mov    mnxmsk,al    ;save it for restore
  6462.  
  6463. ;    or    al,ictmof+icmnof;mask off timer and sio interrupts
  6464.     or    al,icmnof    ;mask off sio interrupt
  6465.     out    dx,al
  6466.  
  6467.     mov    ax,ds        ;save data segment in cseg
  6468.     mov    cs:mndseg,ax    ;   for use by the interrupt handler
  6469.  
  6470.     mov    ax,0        ;point to zero page to replace
  6471.     mov    es,ax        ;the sio interrupt vector
  6472.     mov    ax,es:.mniseg    ;after first saving the current vector
  6473.     mov    mnxseg,ax
  6474.     mov    ax,es:.mnioff
  6475.     mov    mnxoff,ax
  6476.     cli
  6477.     mov    ax,cs
  6478.     mov    es:.mniseg,ax
  6479.     mov    ax,offset mnint
  6480.     mov    es:.mnioff,ax
  6481.     sti
  6482.  
  6483. ;    call    stmode        ;set mode & baud to defaults
  6484.     call    stbaud
  6485.  
  6486.     mov    dx,mndata    ;dummy read to clear buffer
  6487.     in    al,dx
  6488.  
  6489.     mov    dx,icmask
  6490.     in    al,dx        ;enable sio interrupts
  6491.     and    al,not icmnof
  6492.     out    dx,al
  6493.  
  6494.     pop    es
  6495.  
  6496. serin2:    ret
  6497.  
  6498.  
  6499. ; serfin - this routine is used to "undo" what serini has done, called
  6500. ;       just before exiting back to cp/m.
  6501.  
  6502. serfin:
  6503.     call    clrscr        ;[19b] clear screen    ;[30c]
  6504.  
  6505.     cmp    mninit,0FFh    ;check if initialization has been done
  6506.     jne    serfn2        ;if not, don't de-initialize
  6507.     mov    mninit,0
  6508.  
  6509.     push    es
  6510.  
  6511.     cli
  6512.     mov    dx,icmask
  6513.     mov    al,mnxmsk    ;restore the old interrupt mask
  6514.     out    dx,al
  6515.     mov    ax,0
  6516.     mov    es,ax
  6517.     mov    ax,mnxseg    ;restore sio interrupt vector
  6518.     mov    es:.mniseg,ax
  6519.     mov    ax,mnxoff
  6520.     mov    es:.mnioff,ax
  6521.     sti
  6522.  
  6523.     pop    es
  6524.  
  6525. serfn2:    ret
  6526.  
  6527.  
  6528. ; This routine clears the serial port input buffer.  It is called to
  6529. ; clear out excess NAKs that can result from server mode operation.
  6530.  
  6531. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  6532.     mov    mnchip, OFFSET mnchrs-1+mnchnd ;Reset input pointer.
  6533.     mov    mnchop, OFFSET mnchrs-1+mnchnd ;Reset output pointer.
  6534.     ret
  6535.  
  6536. ; set the parity, number of data bits, and number of stop bits
  6537.  
  6538. stmode:                ;do this all in stbaud for micro16s
  6539. ; set the baud rate
  6540. stbaud:    mov    al,mnbaud    ;get the baud rate information
  6541.     cmp    al,6        ;check for valid range (0-6)
  6542.     ja    stb03        ;j/ out of valid range
  6543.     mov    bx,offset baudtb;get address of baud rate table
  6544.     mov    ah,0
  6545.     add    bx,ax
  6546.     mov    dx,bdport
  6547.     mov    al,[bx]        ;get value
  6548.     out    dx,al        ;output byte
  6549.     mov    al,m64x
  6550.     jne    stb02        ;
  6551.     mov    al,m16x        ;for 19200 bd
  6552. stb02:    push    ax
  6553.     mov    dx,mncmd
  6554.     mov    al,0        ;recommended reset procedure:
  6555.     out    dx,al        ;three 0's followed by a cmode
  6556.     mov    al,0
  6557.     out    dx,al
  6558.     mov    al,0
  6559.     out    dx,al
  6560.     mov    al,cmode    ;enable mode setting
  6561.     out    dx,al
  6562.     pop    ax
  6563.     add    al,m1s        ;1 stop, no parity, 8 data, 16x baud
  6564.     add    al,mpn        ;Note: these adds are distinct to
  6565.     add    al,m8d        ;      allow the 8251 time to reset
  6566.     out    dx,al
  6567.     mov    al,crts+cerr+crxe+cdtr+ctxe ;RTS & DTR high, Rx & Tx enabled
  6568.     out    dx,al
  6569.  
  6570. stb03:    ret
  6571.  
  6572.     dseg $
  6573.  
  6574. ;    Serial port default parameters
  6575.  
  6576. mnbaud    db    5        ;9600 baud
  6577.  
  6578. ;    Interval Timer values (assumes 64x baud rate mode)
  6579.  
  6580. baudtb    db    00h        ;300 baud    0
  6581.     db    11h        ;600 baud    1
  6582.     db    22h        ;1200 baud    2
  6583.     db    33h        ;2400 baud    3
  6584.     db    44h        ;4800 baud    4
  6585.     db    55h        ;9600 baud    5
  6586.     db    44h        ;19200 baud    6 - requires 16x rate mode
  6587.  
  6588. mninit    db    0        ;set to 0FFh if initialization has been done
  6589. mnxmsk     db    0        ;8259 interrupt mask storage
  6590. mnxseg    dw    0        ;system sio interrupt vector
  6591. mnxoff    dw    0
  6592.  
  6593. mnchnd    equ    512        ;Size of circular buffer.
  6594. mnchrs    rb    mnchnd        ;Circular character buffer for input.
  6595. mnchip    dw    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  6596. mnchop    dw    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  6597. mnchrn    dw    0        ;Number of chars in the buffer.
  6598.  
  6599. mntrg1    equ    128        ;[19a] Low trigger point for Auto XON/XOFF
  6600. mntrg2    equ    384        ;[19a] High trigger point for Auto XON/XOFF
  6601.  
  6602. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  6603. xofsnt    db    0        ;[19a] set if XOFF was sent
  6604. xofrcv    db    0        ;[19a] set if XOFF was recieved
  6605.  
  6606.     rw    32        ;Interrupt stack        ;[28e]
  6607. mnstk    dw    0        ;bottom of stack        ;[28e]
  6608.  
  6609.  
  6610.     CSEG $
  6611.  
  6612. ; The following routines do the SET and SHOW for the machine dependent
  6613. ; features of Kermit.  At present there are only two:  baud rate setting
  6614. ; and port selection.
  6615.  
  6616. ;    This is the SET BAUD rate subcommand
  6617.  
  6618. bdset:    lea    dx, bdtab
  6619.     lea    bx, bdhlp
  6620.     mov    ah, cmkey
  6621.     call    comnd
  6622.     jmp    r
  6623.     mov    temp1, bx
  6624.     mov    ah, cmcfm
  6625.     call    comnd        ;Get a confirm.
  6626.     jmp    r        ; Didn't get a confirm.
  6627.     mov    bx, temp1
  6628.     mov    mnbaud, bl    ;Set the baud rate table index.
  6629.     call    stbaud
  6630.     jmp    rskp
  6631.  
  6632. ;    This is the SET PORT subcommand (not implemented in APC)
  6633.  
  6634. prtset:    mov    ah, cmcfm
  6635.     call    comnd        ;Get a confirm.
  6636.     jmp    $+3        ; Didn't get a confirm.
  6637.     lea    dx, infms6    ;Tell user it's not implemented
  6638.     call    tcrmsg
  6639.     jmp    rskp
  6640.  
  6641.  
  6642. ; The following procedures implement the SHOW command for the system
  6643. ; dependent features of baud rate and port selection.
  6644.  
  6645. shobd:    lea    dx, bdst    ;Baud rate string.
  6646.     call    tcrmsg
  6647.     mov    al, mnbaud    ;Print the keyword corresponding to the
  6648.     lea    bx, bdtab    ;   current value of mnbaud.
  6649.     call    tabprt
  6650.     ret
  6651.  
  6652. shoprt:    ret            ;Port selection not implemented.
  6653.  
  6654.  
  6655.     DSEG $
  6656.  
  6657. bdtab    db    7        ;Thirteen entries        ;[6] begin
  6658.     db    4,'1200$'
  6659.     dw    0002h
  6660.     db    5,'19200$'
  6661.     dw    0006h
  6662.     db    4,'2400$'
  6663.     dw    0003h
  6664.     db    3,'300$'
  6665.     dw    0000h
  6666.     db    4,'4800$'
  6667.     dw    0004h
  6668.     db    3,'600$'
  6669.     dw    0001h
  6670.     db    4,'9600$'
  6671.     dw    0006h                        ;[6] end
  6672.  
  6673. bdhlp    db    cr,lf,' 300    600    1200    2400'
  6674.     db    cr,lf,'    4800    9600    19200$'
  6675.  
  6676.  
  6677.  
  6678. ; The following routines do screen control.  These are isolated here because
  6679. ; the screen control sequences are likely to vary from system to system, even
  6680. ; though the Rainbow and APC (the only systems implemented to date) both use
  6681. ; ANSI sequences for this purpose.
  6682.  
  6683.     CSEG $
  6684.  
  6685. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  6686.  
  6687. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  6688.     mov    ax, [bx]    ;
  6689.     add    ax, '  '    ;Add 20h to both row and column
  6690.     mov    word ptr anspos+2, ax
  6691.     lea    dx, anspos    ;Print cursor positioning string.
  6692.     call    tmsg
  6693.     ret
  6694.  
  6695. ; CLRSCR - homes cursor and clears screen.
  6696.  
  6697. clrscr:    lea    dx, fujcls
  6698.     call    tmsg
  6699.     ret
  6700.  
  6701. ; CLRLIN - clears from cursor to end of line.
  6702.  
  6703. clrlin:    mov    dl, cr        ;Go to beginning of line
  6704.     call    bout
  6705. clreol:    lea    dx, ansclr    ;Clear from cursor to end of line
  6706.     call    tmsg
  6707.     ret
  6708.  
  6709. ; REVON - turns on reverse video display
  6710.  
  6711. revon:    lea    dx, ansron
  6712.     call    tmsg
  6713.     ret
  6714.  
  6715. ; REVOFF - turns off reverse video display
  6716.  
  6717. revoff:    lea    dx, ansrof
  6718.     call    tmsg
  6719.     ret
  6720.  
  6721. ; BLDON - turns on bold (highlighted) display
  6722.  
  6723. bldon:    lea    dx, ansbon    ;
  6724.     call    tmsg        ;
  6725.     ret
  6726.  
  6727. ; BLDOFF - turns off bold (highlighted) display
  6728.  
  6729. bldoff:    lea    dx, ansbof    ;
  6730.     call    tmsg        ;
  6731.     ret
  6732.  
  6733.  
  6734.     DSEG $
  6735.  
  6736. anspos    db    esc,'=00$'    ;Position cursor to row and column
  6737. fujcls    db    1Eh,1Ah,'$'    ;Home cursor and clear screen
  6738. ansclr    db    esc,'T$'    ;Clear from cursor to end of line
  6739. ansron    db    esc,'G',0Ch,'$'    ;Turn on reverse video (green)
  6740. ansrof    db    esc,'G',04h,'$'    ;Turn off reverse video (green)
  6741. ansbon    db    esc,'G',05h,'$'    ;Turn on bold (uses blue)
  6742. ansbof    db    esc,'G',04h,'$'    ;Turn off bold (back to green)
  6743.  
  6744.  
  6745. ; Here tab expansion is done if necessary.  If not, just return retskp.
  6746.  
  6747.     cseg $
  6748.  
  6749. dotab:    jmp    rskp        ;No, just proceed.
  6750.  
  6751.     dseg $
  6752. curbuf    db    2,0,0        ;command, row, column of cursor position
  6753.  
  6754. delstr    db    10O, 10O, '$'    ;Delete string.
  6755.  
  6756. system    db    '           FUJITSU Micro 16s     $'    ;[1][20a]
  6757. <<< c86xfu.a86 >>>
  6758. ; STARTSYSDEP    ; This is so:
  6759. ;               ;     PIP LISTING=86KERMIT.LST[WSSTARTSYSDEP^ZQENDxSYSDEP^Z]
  6760. ;               ; will work.
  6761. ;
  6762. ;
  6763. ; **************************************************************************
  6764. ;
  6765. ; This is the i/o support module for the Future Computers FX20/FX30
  6766. ; Running CP/M-86 or Concurrent CP/M. 
  6767. ;
  6768. ;  Tony Chabot, University of Birmingham, UK   October 1985
  6769. ;  (Based on the version for the Honeywell MSE by Mark Hewitt).
  6770. ;
  6771. ;  This module checks which type of CP/M system it is running under,
  6772. ;  and alters its performance accordingly. No separate assembly is
  6773. ;  required for CP/M-86 and Concurrent.
  6774. ;  It is preferable to use the KERUTL from Concurrent implementations
  6775. ;  as that will work with both types of CP/M, whereas the standard
  6776. ;  version of KERUTL (for CP/M-86) will not work fully with Concurrent.
  6777. ;
  6778. ;  This implementation allows only the modem port to be used. 
  6779. ;  This is because the printer port does not have its rx interrupt request
  6780. ;  line connected to the 8259 interrupt controller.
  6781. ;
  6782. ;  The modem port uses a 7201 Multi Protocol Serial Controller, situated
  6783. ;  at address C120-C123, with the relevant addresses for the modem part
  6784. ;  of it being C121 & C123.(Note - the FX20/FX30 manual incorrectly gives
  6785. ;  the addresses as C122 and C123).
  6786. ;  The baud rate generator is an 8253-5, timer 1.
  6787. ;  The range of addresses for this device is C060-C063. The generator
  6788. ;  has a 4MHz clock input (gleaned from a scope, so this is not too accurate,
  6789. ;  but a frequency meter seemed to think the frequency was 1MHz +- 10% !).
  6790. ;  The 7201 is programmed to divide by 16, so the baud rate divider is given
  6791. ;  by
  6792. ;  divider = 4000000/(16*baudrate)
  6793. ;
  6794. ;  The 8259 interrupt controller is programmed (by CP/M) to base its vectors
  6795. ;  at 100. The relationship between the 8259 IR lines and the requesting device
  6796. ;  is:
  6797. ;
  6798. ;    IR0    ?
  6799. ;    IR1    PIT (out0)
  6800. ;    IR2    7201
  6801. ;    IR3    ?
  6802. ;    IR4    ?
  6803. ;    IR5    Keyboard 8251 RxRdy
  6804. ;    IR6    Printer  8251 TxRdy
  6805. ;    IR7    Pulled up.
  6806. ;
  6807. ;  Only IR0, IR1 and IR5 have useful interrupt service routines, as well
  6808. ;  as the predefined vectors and CP/M system call vectors. All other
  6809. ;  vectors point, via some register saving code, to an illegal interrupt
  6810. ;  routine. It is thus simple to patch the vector for the 7201 (at 108-10B)
  6811. ;  to point to our ISR.
  6812. ;
  6813. ;  ** W A R N I N G **
  6814. ;
  6815. ;  The 7201 also handles the LAN, so if you have lan software running, it
  6816. ;  is likely that this code will cause problems.
  6817. ;
  6818. ;
  6819. ; **************************************************************************
  6820.     CSEG $
  6821.  
  6822. ; Port base definitions
  6823.  
  6824. bgen    equ    0C060h        ; Baud Rate Generator            (8253-5)
  6825. ictrl    equ    0C000h        ; Interrupt Controller           (8259A)
  6826.  
  6827. ; And the I/O ports themselves
  6828.  
  6829. bgcmd    equ    bgen+3        ; Baud rate generator command port
  6830.  
  6831. iccmd    equ    ictrl+0        ; Interrupt controller command port
  6832. icmask    equ    ictrl+1        ; Interrupt controller mask register port
  6833.  
  6834. mdmcmd    equ    0C123h        ; modem command port
  6835. mdmbg    equ    bgen+1        ; Baud rate countdown value for modem port
  6836. mdmio    equ    0C121h        ;modem data io port (Note-FX30 manual is wrong)
  6837. ptrcmd    equ    0C122h
  6838. ;
  6839. ;
  6840. ;    Port selection
  6841. ;
  6842. pmdm    equ    0
  6843. ;
  6844. ; Interrupt vectors in page 0
  6845. ;
  6846. mdmvec    equ    0108h        ; Interrupt vector for modem.
  6847. ;
  6848. ; Interrupt masks
  6849. ;
  6850. immdm    equ    04h        ; Mask for modem port.
  6851. ;
  6852. ;  Baud rate generator command words
  6853. ;
  6854. mdmbsel    equ    76h        ; Select modem baud rate register
  6855. ;
  6856. ;  Interrupt controller commands
  6857. ;
  6858. iceoi    equ    20h        ; end of interrupt
  6859. ;
  6860. ;  I/O register bits:
  6861. ;
  6862. ;  For 7201 'Multiprotocol Serial Communications Controller' ( a name
  6863. ;  worthy of IBM !).
  6864. ;
  6865. ccreg0    equ    00h        ; Control instruction - select register 0
  6866. ccreg1    equ    01h        ; Control instruction - select register 1
  6867. ccreg2    equ    02h        ; Control instruction - select register 2
  6868. ccreg3    equ    03h        ; Control instruction - select register 3
  6869. ccreg4    equ    04h        ; Control instruction - select register 4
  6870. ccreg5    equ    05h        ; Control instruction - select register 5
  6871. ccreg6    equ    06h        ; Control instruction - select register 6
  6872. ccreg7    equ    07h        ; Control instruction - select register 7
  6873.  
  6874. c0null    equ    00h        ; Register 0 - null command
  6875. c0abort    equ    08h        ; Register 0 - send abort
  6876. c0resi    equ    10h        ; Register 0 - reset ext. status ints.
  6877. c0chrst    equ    18h        ; Register 0 - channel reset
  6878. c0eninc    equ    20h        ; Register 0 - enable int. on next character
  6879. c0rpti    equ    28h        ; Register 0 - reset pending tx int./DMA req.
  6880. c0errst    equ    30h        ; Register 0 - error reset
  6881. c0eoi    equ    38h        ; Register 0 - end of interrupt
  6882. c0rxcrc    equ    40h        ; Register 0 - reset rx CRC checker
  6883. c0txcrc    equ    80h        ; Register 0 - reset tx CRC generator
  6884. c0ricrc    equ    0C0h        ; Register 0 - reset idle/CRC latch
  6885.  
  6886. c1stien    equ    01h        ; Register 1 - external/status int enable
  6887. c1txien    equ    02h        ; Register 1 - transmitter interrupt enable
  6888. c1cav    equ    03h        ; Register 1 - condition affects vector
  6889. c1noi    equ    00h        ; Register 1 - no rx or DMA interrupts
  6890. c1i1st    equ    08h        ; Register 1 - int. on 1st received character
  6891. c1iall    equ    10h        ; Register 1 - int. on all received characters
  6892. c1ialp    equ    18h        ; Register 1 - int on all rx'd chars, no parity
  6893. c1wrxtx    equ    20h        ; Register 1 - WAIT on rx/tx
  6894. c1txbcm    equ    40h        ; Register 1 - TX byte count mode enbable
  6895. c1wten    equ    80h        ; Register 1 - WAIT function enable
  6896. ;
  6897. ;  and some useful abbreviations
  6898. ;
  6899. c1norm    equ    c1ialp
  6900. ;
  6901. c2dma0    equ    00h        ; Register 2 - No DMA
  6902. c2dma1    equ    01h        ; Register 2 - DMA mode 1
  6903. c2dma2    equ    02h        ; Register 2 - DMA mode 2
  6904. c2dma3    equ    03h        ; Register 2 - DMA mode 3
  6905. c2pri    equ    04h        ; Register 2 - Set DMA priority
  6906. c2ack0    equ    00h        ; Register 2 - Int Ack mode 0 (NV,D432)
  6907. c2ack1    equ    08h        ; Register 2 - Int Ack mode 1 (NV, D432)
  6908. c2ack2    equ    10h        ; Register 2 - Int Ack mode 2 (NV, D210)
  6909. c2ack4    equ    20h        ; Register 2 - Int Ack mode 4 (8085 master)
  6910. c2ack5    equ    28h        ; Register 2 - Int Ack mode 5 (8085 slave)
  6911. c2ack6    equ    30h        ; Register 2 - Int Ack mode 6 (8086)
  6912. c2ack7    equ    38h        ; Register 2 - Int Ack mode 7(8085/8259A slave)
  6913. c2rxim    equ    40h        ; Register 2 - rx interrupt mask
  6914. c2syncb    equ    80h        ; Register 2 - pin 10 ~RTSB or ~SYNCB
  6915.  
  6916. c3rxen    equ    01h        ; Register 3 - receive enable
  6917. c3scli    equ    02h        ; Register 3 - sync character load inhibit
  6918. c3asm    equ    04h        ; Register 3 - address search mode
  6919. c3rxcrc    equ    08h        ; Register 3 - receiver CRC enable
  6920. c3hunt    equ    10h        ; Register 3 - enter hunt phase
  6921. c3aen    equ    20h        ; Register 3 - auto enables on DCD/CTS
  6922. c3r5bit equ    00h        ; Register 3 - 5 bit data
  6923. c3r6bit equ    40h        ; Register 3 - 6 bit data
  6924. c3r7bit equ    80h        ; Register 3 - 7 bit data
  6925. c3r8bit equ    0C0h        ; Register 3 - 8 bit data
  6926. ;
  6927. ;  and some useful abbreviations
  6928. ;
  6929. c3norm    equ    c3rxen+c3r8bit
  6930. ;
  6931. c4pen    equ    01h        ; Register 4 - parity enable
  6932. c4ep    equ    02h        ; Register 4 - even parity
  6933. c41stp    equ    04h        ; Register 4 - 1 stop bit
  6934. c415stp    equ    08h        ; Register 4 - 1.5 stop bits
  6935. c42stp    equ    0C0h        ; Register 4 - 2 stop bits
  6936. c48syn    equ    00h        ; Register 4 - 8 bit internal sync (monosync)
  6937. c416syn    equ    10h        ; Register 4 - 16 bit internal sync (bisync)
  6938. c4sdlc    equ    20h        ; Register 4 - SDLC
  6939. c4exts    equ    30h        ; Register 4 - External sync
  6940. c41clk    equ    00h        ; Register 4 - 1x clock rate
  6941. c416clk    equ    40h        ; Register 4 - 16x clock rate
  6942. c432clk    equ    80h        ; Register 4 - 32x clock rate
  6943. c464clk    equ    0C0h        ; Register 4 - 64x clock rate
  6944. ;
  6945. ;  and some useful abbreviations
  6946. ;
  6947. c4norm    equ    c41stp+c416clk
  6948. ;
  6949. c5txcrc    equ    01h        ; Register 5 - transmitter CRC enable
  6950. c5rts    equ    02h        ; Register 5 - request to send
  6951. c5poly    equ    04h        ; Register 5 - CRC polynomial select
  6952. c5txen    equ    08h        ; Register 5 - transmitter enable
  6953. c5sbrk    equ    10h        ; Register 5 - send break
  6954. c5t5bit    equ    00h        ; Register 5 - transmit 5 bit data
  6955. c5t6bit    equ    20h        ; Register 5 - transmit 6 bit data
  6956. c5t7bit    equ    40h        ; Register 5 - transmit 7 bit data
  6957. c5t8bit    equ    60h        ; Register 5 - transmit 8 bit data
  6958. c5dtr    equ    80h        ; Register 5 - data terminal ready
  6959. ;
  6960. ;  and some useful abbreviations
  6961. ;
  6962. c5norm    equ    c5rts+c5txen+c5t8bit+c5dtr
  6963. ;
  6964. cs0rxr    equ    01h        ; Status register 0 - received char ready
  6965. cs0ip    equ    02h        ; Status register 0 - interrupt pending
  6966. cs0tbe    equ    04h        ; Status register 0 - tx buffer empty
  6967. cs0dcd    equ    08h        ; Status register 0 - data carrier detect
  6968. cs0sync    equ    10h        ; Status register 0 - sync status
  6969. cs0cts    equ    20h        ; Status register 0 - clear to send
  6970. cs0idle    equ    40h        ; Status register 0 - idle CRC latch status
  6971. cs0brk    equ    80h        ; Status register 0 - break detect
  6972.  
  6973. cs1sent    equ    01h        ; Status register 1 - all sent
  6974. cs1sdlc    equ    0Eh        ; Status register 1 - SDLC residue code
  6975. cs1pe    equ    10h        ; Status register 1 - parity error
  6976. cs1oe    equ    20h        ; Status register 1 - overrun error
  6977. cs1fe    equ    40h        ; Status register 1 - framing error
  6978. cs1eosf    equ    80h        ; Status register 1 - end of SDLC frame
  6979.  
  6980.  
  6981. ;    System call defs for concurrent version.
  6982. p_dispatch    equ    8Eh    ; Reschedule.
  6983. f_errmode    equ    2Dh    ; Set BDOS error mode.
  6984.  
  6985. ;
  6986. ; Clock rate *10 for timing loops    ;[19g]
  6987. ;
  6988. clckrt    equ    80            ;[19g]  8.0 Mhz
  6989. ;
  6990. ;  Maximum number of examinations of output port to be ready before
  6991. ;  rescheduling.
  6992. ;
  6993. outlmt    equ    1000h
  6994.  
  6995. ;
  6996. ;  The executable code starts here
  6997. ;
  6998. ;
  6999. ; ===========================================================================
  7000. ;
  7001. ;                        INITIALISATION ROUTINES
  7002. ;
  7003. ; ===========================================================================
  7004. ;
  7005. ; INTERFACE ROUTINE SERINI - Initialisation code
  7006. ;
  7007. serini:    cmp    mninit, true    ; Ensure that we only initialise once
  7008.     je    serin2
  7009.     mov    mninit, true
  7010.  
  7011. ;    Get type of CP/M system.
  7012. ;
  7013.     mov    cl,0ch
  7014.     int    bdos
  7015.     mov    cpmtyp, bh
  7016.  
  7017. ;
  7018. ;  Initialise the screen
  7019. ;
  7020.     call    clrscr        ; Clear the screen.
  7021. ;
  7022. ;  Disable I/O interrupts, and save the old interrupt mask.
  7023. ;
  7024.     mov    dx, icmask    ; read the current interrupt mask
  7025.     in    al, dx
  7026.     mov    oldmsk, al    ; and save it
  7027.     or    al, immdm    ; mask off i/o interrupts
  7028.     out    dx, al        ; and reprogram interrupt controller
  7029. ;
  7030. ;  Save the system i/o interrupt vectors
  7031. ;
  7032.     mov    ax, ds        ; save the data segment in code segment
  7033.     mov    cs:mndseg, ax    ;   for use by interrupt handler
  7034.  
  7035.     mov    ax, 0        ; point to zero page and save both the
  7036.     mov    es, ax        ;   system's i/o interrupt vectors
  7037.     mov    ax,es:.mdmvec+0    ;     for the modem channel
  7038.     mov    vscoff, ax
  7039.     mov    ax, es:.mdmvec+2
  7040.     mov    vscseg, ax
  7041.  
  7042. ;  Configure the default port
  7043. ;
  7044.     mov    ax, 0        ; point to zero page and set the interrupt
  7045.     mov    es, ax        ;   vector for the modem/printer channel to my
  7046.                 ;     interrupt service routine
  7047.     mov    ax, offset isr    ; set offset address
  7048.     mov    es:.mdmvec+0, ax
  7049.     mov    ax, cs        ; set segment address
  7050.     mov    es:.mdmvec+2, ax
  7051.  
  7052.     call    setmode        ; set UART mode for current port
  7053.     call    setbaud        ; set the baud rate for the current port
  7054.     call    mnflush        ; flush and enable the current port
  7055.     call    inton        ; turn interrupts on for current port
  7056.  
  7057. ;    If concurrent, set BDOS error mode.
  7058. ;
  7059.     cmp    cpmtyp, 14h
  7060.     jne    serin2
  7061.     mov    cl, f_errmode
  7062.     mov    dl, 0FEh    ; Set err mode to display and return.
  7063.     int    bdos
  7064.  
  7065. serin2:    ret            ; initialisation over
  7066.  
  7067. ;
  7068. ; INTERFACE ROUTINE SERFIN - restore environment (as far as possible)
  7069. ;                            to that which existed before we played with it
  7070. ;
  7071. serfin:    cmp    mninit, true    ; only deinitialise if necessary
  7072.     jne    serfn2
  7073.     mov    mninit, false
  7074. ;
  7075. ;  Disable i/o interrupt while we reset the vectors
  7076. ;
  7077.     mov    dx, icmask    ; get present interrupt mask
  7078.     in    al, dx        ; and turn off all i/o interrupts
  7079.     or    al, immdm    ;   from the modem channel
  7080.     out    dx, al        ; reprogram the interrupt controller
  7081. ;
  7082. ;  Reset the i/o interrupt vectors
  7083. ;
  7084.     mov    ax, 0        ; point at page 0 and reset the int. vectors
  7085.     mov    es, ax
  7086.     mov    ax, vscoff    ;   for the modem/printer port
  7087.     mov    es:.mdmvec+0, ax
  7088.     mov    ax, vscseg
  7089.     mov    es:.mdmvec+2, ax
  7090. ;
  7091. ; turn interrupts back on (or off...)
  7092. ;
  7093.     mov    al, oldmsk    ; restore original interrupt mask
  7094.     out    dx, al
  7095. ;
  7096. ;  Reset screen modes
  7097. ;
  7098.     call    clrscr        ; Be tidy - clear the screen.
  7099.  
  7100. serfn2:    ret            ; deinitialisation over
  7101.  
  7102. ;
  7103. ;
  7104. ; INTERNAL ROUTINE SETMODE - set the operating mode for current port's UART.
  7105. ;
  7106. setmode:
  7107.     push    ax
  7108.     push    dx        ; we'll need this
  7109.  
  7110.     mov    dx, mdmcmd    ; Command port adrs.
  7111.  
  7112.     mov    al, c0chrst    ; reset the port
  7113.     out    dx, al
  7114.     mov    al, c0resi+ccreg4 ; select register 4
  7115.     out    dx, al
  7116.     mov    al, c4norm    ; 16x Clock, 1 stop bit, no parity
  7117.     out    dx, al
  7118.     mov    al, c0resi+ccreg3 ; Select register 3
  7119.     out    dx, al
  7120.     mov    al, c3norm    ; 8 bits/character, RX enable
  7121.     out    dx, al
  7122.     mov    al, c0resi+ccreg5 ; select register 5
  7123.     out    dx, al
  7124.     mov    al, c5norm    ; 8 bits/character, TX enable RTS and DTR
  7125.     out    dx, al
  7126.     mov    al, c0resi+ccreg1 ; select register 1
  7127.     out    dx, al
  7128.     mov    al, c1norm    ; Interrupt enable
  7129.     out    dx, al
  7130.     
  7131.     pop    dx        ; modes now set, restore regs. and return
  7132.     pop    ax
  7133.     ret
  7134.  
  7135. ;
  7136. ;  INTERNAL ROUTINE SETBAUD - set the baud rate of a current port.
  7137. ;                             port number in cport.
  7138. ;                             timer countdown table offset in cbaud.
  7139. ;
  7140. setbaud:
  7141.     push    bx        ; we'll be using this
  7142.     push    dx        ; and this
  7143.     push    ax        ; and this too
  7144.  
  7145.     mov    al, bdtab    ; check that rate is legal
  7146.     dec    al        ; pick up number of valid rates from BDTAB
  7147.     cmp    cbaud, al    ;  0 <= cbaud <= [bdtab]-1
  7148.     ja    setbd2        ; just return if not legal
  7149.  
  7150.     mov    bx, offset bdtct; get timer value
  7151.     mov    al, cbaud    ; from timer countdown table
  7152.     mov    ah, 0
  7153.     add    al, al        ; word offset
  7154.     add    bx, ax        ; bx now points to correct value
  7155.  
  7156.     mov    dx, bgcmd    ; dx is now baud rate generator command port
  7157.  
  7158.     cmp    cport, pmdm    ; is it the modem port?
  7159.     jne    setbd2        ; just return if not
  7160.  
  7161.     mov    al, mdmbsel    ; set baud rate for modem port
  7162.     out    dx, al
  7163.     mov    dx, mdmbg
  7164.     jmp    setbd3
  7165.  
  7166. setbd3:    mov    ax, [bx]    ; set the countdown value
  7167.     out    dx, al
  7168.     mov    al, ah
  7169.     out    dx, al
  7170.  
  7171. setbd2:    pop    ax        ; baud rate set, retore regs. and return
  7172.     pop    dx
  7173.     pop    bx
  7174.     ret
  7175.  
  7176. ;
  7177. ;  INTERNAL ROUTINE MNFLUSH - enable and flush current port.
  7178. ;                             Port in cport.
  7179. ;
  7180. mnflush:
  7181.     push    ax        ; preserve registers
  7182.     push    dx
  7183.  
  7184.     mov    dx, mdmio    ; Modem data port adrs.
  7185.     in    al, dx        ; flush the port
  7186.     in    al, dx
  7187.     in    al, dx
  7188.     mov    dx, mdmcmd    ; reset any pending interrupts
  7189.     mov    al, c0errst
  7190.     out    dx, al
  7191.     mov    al, c0resi
  7192.     out    dx, al
  7193.  
  7194.     pop    dx        ; port flushed, retore regs. and return
  7195.     pop    ax
  7196.     ret
  7197.  
  7198. ;
  7199. ; INTERNAL ROUTINE INTON - enable interrupts for the selected port
  7200. ;               (This version simply enables the modem port!)
  7201. ;                          Ensure that the port selected is enabled, and
  7202. ;                          that all other ports are as the system would
  7203. ;                          wish them!
  7204. inton:    
  7205.     push    ax
  7206.     push    dx
  7207.  
  7208.     mov    dx, icmask
  7209.     in    al,dx        ; Read current interrupt mask.
  7210.     and    al, not immdm    ; Enable modem interrupts.
  7211.     out    dx, al
  7212.  
  7213. inton2:    pop    dx
  7214.     pop    ax        ; interrupts now enabled - restore regs.
  7215.     ret            ;   and return
  7216.  
  7217.     DSEG $            ; Data used by initialisation/deinitialisation
  7218.  
  7219. mninit    db    false        ; flag set when initialised
  7220. oldmsk    rb    1        ; Old interrupt mask
  7221. cpmtyp    db    0        ; CP/M type (0 = CP/M-86, 14h = concurrent).
  7222. ;
  7223.  
  7224. ;  Current port status
  7225. ;
  7226. cport    db    pmdm        ; current port number - default to modem
  7227. cbaud    db    8        ; current baud rate - default to 4800
  7228. ciop    dw    mdmio        ; current i/o port - default to modem
  7229. ccmdp    dw    mdmcmd        ; current command/status port - default modem
  7230. ;
  7231. ;  Storage for system interrupt vectors
  7232. ;
  7233. vscoff    rw    1        ; offset for system v.24/printer int. vector
  7234. vscseg    rw    1        ; seg. address for system v.24/printer int. vec
  7235. ;
  7236. ;  Baud rate timer countdown table
  7237. ;  (The accuracy of these is uncertain as the baud rate generator clock
  7238. ;  frequency was measured with a scope).
  7239. ;
  7240. bdtct    dw    5000        ;    50 baud, code  0
  7241.     dw    3333        ;    75
  7242.     dw    2273        ;   110
  7243.     dw    1667        ;   150
  7244.     dw    833        ;   300
  7245.     dw    417        ;   600
  7246.     dw    208        ;  1200
  7247.     dw    104        ;  2400
  7248.     dw    52        ;  4800
  7249.     dw    26        ;  9600
  7250.     dw    13        ; 19200
  7251.  
  7252.     CSEG $
  7253.  
  7254. ; ===========================================================================
  7255. ;
  7256. ;                             SET COMMANDS
  7257. ;
  7258. ; ===========================================================================
  7259. ;
  7260. ;  INTERFACE ROUTINE BDSET - set baud rate for current port (cport).
  7261. ;                            save current baud rate in cbaud.
  7262. ;
  7263. bdset:    mov    dx, offset bdtab    ; table of valid baud rates
  7264.     mov    bx, offset bdhlp    ; help information for SET BAUD
  7265.     mov    ah, cmkey        ; Command parser - KEYWORD lookup
  7266.     call    comnd
  7267.       jmp    r            ; error return
  7268.     mov    settmp, bx        ; Normal return - save value
  7269.     mov    ah, cmcfm        ; Command parser - CONFIRM
  7270.     call comnd
  7271.       jmp    r
  7272.     mov    bx, settmp
  7273.     mov    cbaud, bl        ; save the baud rate
  7274.     call    setbaud            ; and set it for the current port
  7275.     jmp    rskp            ; end of parsing SET BAUD command
  7276.  
  7277.     DSEG $
  7278.  
  7279. settmp    rw    1            ; temporary storage for baud rate
  7280.  
  7281.     CSEG $
  7282. ;
  7283. ;  INTERFACE ROUTINE PRTSET - set the current port.
  7284. ;
  7285. prtset:    mov    dx, offset potab    ; table of valid port names
  7286.     mov    bx, offset pohlp    ; help information for SET PORT
  7287.     mov    ah, cmkey        ; Command parser - KEYWORD lookup
  7288.     call    comnd
  7289.       jmp    r            ; error return
  7290.  
  7291.     mov    settmp, bx        ; Normal return - save value
  7292.  
  7293.     mov    ah, cmcfm        ; Command parser - CONFIRM
  7294.     call comnd
  7295.       jmp    r
  7296.     jmp    rskp            ; end of parsing SET PORT command
  7297. ;
  7298. ;  Data required by the SET commands
  7299. ;
  7300.     DSEG $                ; SET command data
  7301. ;
  7302. ;  Baud rate table
  7303. ;
  7304. bdtab    db    11            ; number of entries
  7305.     db    3, '110$'        ; size of entry, and the keyword$
  7306.     dw    02            ; value returned
  7307.     db    3, '150$'
  7308.     dw    03
  7309.     db    4, '1200$'
  7310.     dw    06
  7311.     db    5, '19200$'
  7312.     dw    10
  7313.     db    4, '2400$'
  7314.     dw    07
  7315.     db    3, '300$'
  7316.     dw    04
  7317.     db    4, '4800$'
  7318.     dw    8
  7319.     db    2, '50$'
  7320.     dw    00
  7321.     db    3, '600$'
  7322.     dw    05
  7323.     db    2, '75$'
  7324.     dw    01
  7325.     db    4, '9600$'
  7326.     dw    09
  7327. ;
  7328. ;  Help table for baud rate setting
  7329. ;
  7330. bdhlp    db    cr, lf, '    50     75    110    150    300    600'
  7331.     db    cr, lf, '  1200   2400   4800   9600  19200'
  7332.     db    '$'
  7333. ;
  7334. ;  Port table
  7335. ;
  7336. potab    db    1
  7337.     db    5, 'MODEM$'
  7338.     dw    pmdm
  7339. ;
  7340. ;  Help table for port selection
  7341. ;
  7342. pohlp    db    cr, lf, 'MODEM$'
  7343.  
  7344.     CSEG $
  7345.  
  7346. ; ===========================================================================
  7347. ;
  7348. ;                              SHOW COMMANDS
  7349. ;
  7350. ; ===========================================================================
  7351.  
  7352. ;
  7353. ;  INTERFACE ROUTINE SHOBD - display the currently set baud rate within
  7354. ;                            the SHOW command.
  7355. ;
  7356. shobd:    mov    dx, offset bdst    ;Baud rate string.
  7357.     call    tcrmsg
  7358.     mov    al, cbaud    ;Print the keyword corresponding to the
  7359.     mov    bx, offset bdtab; current value of mnbaud.
  7360.     call    tabprt
  7361.     ret
  7362.  
  7363. ;
  7364. ;  INTERFACE ROUTINE SHOPRT - display the currently selected communication
  7365. ;                             port within the SHOW command.
  7366. ;
  7367. shoprt:    mov    dx, offset prtst    ; Port name string
  7368.     call    tcrmsg
  7369.     mov    al, cport        ; current port code
  7370.     mov    bx, offset potab    ; and print the corresponding
  7371.     call    tabprt            ;   textual description
  7372.     mov    dx, offset prtst2
  7373.     call    tmsg
  7374.     ret
  7375.  
  7376.     DSEG $
  7377.  
  7378. prtst    db    'Communicating via $'
  7379. prtst2    db    ' port$'
  7380.  
  7381.     CSEG $
  7382.  
  7383. ; ===========================================================================
  7384. ;
  7385. ;                                I/O ROUTINES
  7386. ;
  7387. ; ===========================================================================
  7388. ;
  7389. ;  INTERNAL ROUTINE ISR - Interrupt service routine for modem port.
  7390. ;
  7391.  
  7392. isr:    
  7393.     cli                ; disable intrerupts
  7394.     mov    cs:mnax, ax        ; save ax - we will need a register
  7395.     mov    ax, sp
  7396.     mov    cs:mnsp, ax        ; save current stack pointer
  7397.     mov    ax, ss
  7398.     mov    cs:mnsseg, ax        ; Save current stack segment
  7399.     mov    ax, cs:mndseg        ; Switch to my stack
  7400.     mov    ss, ax
  7401.     mov    sp, offset mnstk
  7402.     push    ds            ; Save registers
  7403.     push    es
  7404.     push    bp
  7405.     push    di
  7406.     push    si
  7407.     push    dx
  7408.     push    cx
  7409.     push    bx
  7410.     mov    ds, ax            ; set our data segment address
  7411. ;
  7412. ;  That's the housekeeping out of the way - now we can start
  7413. ;
  7414.  
  7415.     mov    dx, mdmcmd        ; see if char. ready at default port
  7416.     in    al, dx
  7417.     test    al, cs0rxr        ; is there a character for us?
  7418.     jz    iprt3            ; no - clear interrupt, and return
  7419.  
  7420. iprt2:    mov    dx, mdmio        ; Fetch the character
  7421.     in    al, dx
  7422.     call    iproc            ; Process the character in AL
  7423.  
  7424. iprt3:    mov    dx, iccmd        ; Signal end of interrupt to
  7425.     mov    al, iceoi        ;   interrupt controller
  7426.     out    dx, al
  7427.  
  7428.     mov    dx, ptrcmd        ; Clear interrupt status at 
  7429.     mov    al, c0eoi        ;   7201
  7430.     out    dx, al            ;    (note we use the A channel).
  7431.  
  7432.     pop    bx            ; Restore registers
  7433.     pop    cx
  7434.     pop    dx
  7435.     pop    si
  7436.     pop    di
  7437.     pop    bp
  7438.     pop    es
  7439.     pop    ds
  7440.     mov    ax, cs:mnsp        ; restore interrupt stack
  7441.     mov    sp, ax
  7442.     mov    ax, cs:mnsseg        ; restore original stack segment
  7443.     mov    ss, ax
  7444.     mov    ax, cs:mnax        ; restore original AX
  7445.     iret                ; all over - return
  7446.  
  7447. ;
  7448. ;  CSEG data required by interrupt service routine
  7449. ;
  7450. mnax    dw    0        ; temp. copy of AX
  7451. mnsp    dw    0        ; interrupt stack pointer
  7452. mnsseg    dw    0        ; interrupt stack segment
  7453. mndseg    dw    0        ; location of our data segment
  7454.  
  7455. ;
  7456. ; INTERNAL ROUTINE IPROC - process incoming character from Rx interrupt
  7457. ;                          Character in AL
  7458. ;
  7459.  
  7460. iproc:    cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  7461.     jne    ipr2b        ;no - go on
  7462.     cmp    al, xoff    ;is it an XOFF?
  7463.     jne    ipr2a        ;no - go on
  7464.     mov    xofrcv, true    ;set the flag
  7465.     ret
  7466.  
  7467. ipr2a:    cmp    al, xon        ;an XON?
  7468.     jne    ipr2b        ;no
  7469.     mov    xofrcv, false    ;clear the flag
  7470.     ret            ;                [19a] end
  7471.  
  7472. ipr2b:    cmp    mnchrn,mnchnd    ;Is the buffer full?
  7473.     je    iperr        ;If so, take care of the error.
  7474.     inc    mnchrn        ;Increment the character count.
  7475.     mov    bx,mnchip    ;Get the buffer input pointer.
  7476.     inc    bx        ;Increment it.
  7477.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  7478.     jb    ipro3
  7479.     mov    bx, offset mnchrs ;Yes, point to the start again.
  7480. ipro3:    mov    mnchip,bx    ;Save the pointer.
  7481.     mov    [bx],al        ;Put the character in the buffer.
  7482.     cmp    floctl, floxon    ;do flow-control?        [19a] start
  7483.     je    ipro4        ;If yes jump
  7484.     ret
  7485.  
  7486. ipro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  7487.     jnz    ipro5
  7488.     ret            ;return if we have
  7489.  
  7490. ipro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  7491.     ja    ipro6        ;yes - jump
  7492.     ret
  7493.  
  7494. ipro6:    mov    al, xoff
  7495.     call    prtout        ;send an XOFF
  7496.     mov    xofsnt, true    ;set the flag
  7497.     ret            ;                [19a] End
  7498.  
  7499. iperr:    ret            ; just return on error for now
  7500.  
  7501. ;
  7502. ;  INTERFACE ROUTINE CFIBF - Clear serial port input buffer
  7503. ;
  7504. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  7505.     mov    mnchip, OFFSET mnchrs-1+mnchnd ;Reset input pointer.
  7506.     mov    mnchop, OFFSET mnchrs-1+mnchnd ;Reset output pointer.
  7507.     ret
  7508.  
  7509. ;
  7510. ;  INTERFACE ROUTINE PRTOUT - send character in AL to current port.
  7511. ;
  7512. prtout:    call    dopar        ; set parity if necessary
  7513.     push    dx
  7514.     push    cx
  7515.  
  7516.     mov    cx, outlmt
  7517. prtou2:    call    outwait        ; wait for port to be free, or timeout
  7518.       loop    prtou2
  7519.       nop
  7520.     call    outchr        ; output the character
  7521.     pop    cx
  7522.     pop    dx
  7523.     ret
  7524.  
  7525. ;
  7526. ; INTERNAL ROUTINE OUTWAIT - test if port ready for next char to be sent.
  7527. ;                            returns RSKP if ready.
  7528. ;
  7529. outwait:
  7530.     cmp    floctl, floxon
  7531.     jne    outwt1
  7532.     cmp    xofrcv, true
  7533.     je    outwt3
  7534. outwt1:
  7535.     push    ax
  7536.     mov    dx, mdmcmd
  7537.     in    al, dx
  7538.     test    al, cs0tbe
  7539.     jnz    outwt4
  7540.     pop    ax
  7541. outwt3:    
  7542.     cmp    cpmtyp, 14h    ; Concurrent?
  7543.     jne    outwt35        ; No.
  7544.     call    dispatch    ; Yes - redispatch the processor.
  7545. outwt35:
  7546.     ret
  7547.  
  7548. outwt4:    pop    ax
  7549.     jmp    rskp
  7550. ;
  7551. ;  INTERNAL ROUTINE OUTCHR - send data to a port
  7552. ;
  7553. outchr:    mov    dx, mdmio
  7554.     out    dx, al
  7555.     ret
  7556.  
  7557. ;
  7558. ; INTERFACE ROUTINE INSTAT - determine if there is any data to receive.
  7559. ;
  7560. instat:    cmp    mnchrn, 0        ; any characters in buffer?
  7561.     jne    inst2
  7562.     ret
  7563. inst2:    jmp    rskp
  7564.  
  7565. ;
  7566. ;  INTERFACE ROUTINE INCHR - read a character from a port
  7567. ;
  7568. inchr:    push    bx
  7569.     cli            ;Disable interrupts while were are playing.
  7570.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  7571.     mov    bx,mnchop    ;Get the pointer into the buffer.
  7572.     inc    bx        ;Increment to the next char.
  7573.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  7574.     jb    inchr2
  7575.     mov    bx, offset mnchrs ;If so wrap around to the start.
  7576. inchr2:    mov    mnchop,bx    ;Save the updated pointer.
  7577.     mov    al,[bx]        ;Get the character.
  7578.     sti            ;All done, we can restore interrupts.
  7579.     pop    bx
  7580.     cmp    parflg,parnon    ;[par] no parity?
  7581.     je    inchr3        ;[par] yup, don't bother stripping
  7582.     and    al,7fh        ;[par] checking parity, strip off
  7583. inchr3:    cmp    floctl, floxon    ;do flow-control?        [19a] start
  7584.     je    inchr4        ;If yes jump
  7585.     ret
  7586. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  7587.     je    inchr5        ;Jump if yes
  7588.     ret
  7589. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  7590.     jb    inchr6        ;yes - jump
  7591.     ret
  7592. inchr6:    push    ax        ;save current character
  7593.     mov    al, xon
  7594.     call    prtout        ;send an XON
  7595.     mov    xofsnt, false    ;turn off the flag
  7596.     pop    ax        ;get back character
  7597.     ret            ;                [19a] end
  7598.  
  7599. ;
  7600. ;  INTERFACE ROUTINE PRTBRK - Send a BREAK sequence to the default port
  7601. ;
  7602. prtbrk:    mov    dx, mdmcmd        ; Modem port cmd byte.
  7603.     cmp    cport, pmdm        ; is it modem port?
  7604.     jne    brka            ; must be an error - just return
  7605.  
  7606. brkc:
  7607.     mov    al, c0resi+ccreg5    ; Break to modem port.
  7608.     out    dx, al            ; Select register 5
  7609.     mov    al, c5norm+c5sbrk    ; 8 bits, TX enable, Break, RTS & DTR
  7610.     out    dx, al
  7611.     mov    ax, 275            ; for 275 mS
  7612.     call    mswait
  7613.     mov    al, c0resi+ccreg5    ; select register 5
  7614.     out    dx, al
  7615.     mov    al, c5norm        ; 8 bits, TX enable, RTS & DTR
  7616.     out    dx, al
  7617.     ret
  7618.  
  7619. brka:    ret
  7620.  
  7621.     DSEG $
  7622. ;
  7623. ;  Input character queue
  7624. ;
  7625. mnchnd    equ    512        ;Size of circular buffer.
  7626. mnchrs    rb    mnchnd        ;Circular character buffer for input.
  7627. mnchip    dw    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  7628. mnchop    dw    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  7629. mnchrn    dw    0        ;Number of chars in the buffer.
  7630.  
  7631. mntrg1    equ    128        ;[19a] Low trigger point for Auto XON/XOFF
  7632. mntrg2    equ    384        ;[19a] High trigger point for Auto XON/XOFF
  7633.  
  7634. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  7635. xofsnt    db    0        ;[19a] set if XOFF was sent
  7636. xofrcv    db    0        ;[19a] set if XOFF was recieved
  7637. ;
  7638. ;  a small stack for interrupt handling
  7639. ;
  7640.     rw    64        ;Interrupt stack        ;[28e]
  7641. mnstk    dw    0        ;bottom of stack        ;[28e]
  7642.  
  7643.     CSEG $
  7644.  
  7645. ; ===========================================================================
  7646. ;
  7647. ;                             UTILITY ROUTINES
  7648. ;
  7649. ; ===========================================================================
  7650. ;
  7651. ; INTERNAL ROUTINE MSWAIT - Delay for AL milliseconds
  7652. ;
  7653. mswait:                ;                [34] start
  7654.     mov    cx,5*clckrt    ; inner loop count for 1 millisec.
  7655. mswai1:
  7656.     sub    cx,1        ;** inner loop takes 20 clock cycles
  7657.     jnz    mswai1        ;**
  7658.     dec    ax        ; outer loop counter
  7659.     jnz    mswait        ; wait another millisecond
  7660.     ret            ;                [34] end
  7661.  
  7662.  
  7663. ;
  7664. ; INTERNAL ROUTINE DISPATCH
  7665. ;
  7666. ;    Function    Redispatch processor.
  7667. ;
  7668. ;    Inputs        None.
  7669. ;
  7670. ;    Outputs        None.
  7671. ;
  7672. ;    Side effects    Processor is redispatched.
  7673. ;            All registers preserved.
  7674. ;
  7675. dispatch:
  7676.     push    ax
  7677.     push    bx
  7678.     push    cx
  7679.     mov    cl, p_dispatch
  7680.     int    bdos
  7681.     pop    cx
  7682.     pop    bx
  7683.     pop    ax
  7684.     ret
  7685.  
  7686.  
  7687. ; ===========================================================================
  7688. ;
  7689. ;                        SCREEN CONTROL ROUTINES
  7690. ;
  7691. ; ===========================================================================
  7692. ;
  7693. ; INTERFACE ROUTINE POSCUR - positions cursor to row and col (each 1 byte)
  7694. ;                            pointed to by dx.
  7695. ;
  7696.  
  7697. poscur:    
  7698.     mov    bx, dx        ;Do cursor positioning.
  7699.     mov    dx, offset scrpos    ;Print cursor positioning string.
  7700.     call    tmsg
  7701.     mov    al, [bx]    ;Get row value
  7702.     add    ax, 1Fh        ;Convert to ASCII
  7703.     mov    dl,al
  7704.     push    bx        ;(Gets clobbered by bout)
  7705.     call    bout
  7706.     pop    bx
  7707.     mov    al, 1[bx]    ;Do same for column value
  7708.     add    ax, 1Fh
  7709.     mov    dl,al
  7710.     call    bout
  7711.     ret
  7712.  
  7713. ;
  7714. ; INTERFACE ROUTINE CLRSCR - homes cursor and clears screen.
  7715. ;
  7716.  
  7717. clrscr:    mov    dx, offset scrcls
  7718.     call    tmsg
  7719.     ret
  7720. ;
  7721. ; INTERFACE ROUTINE CLRLIN - clears line.
  7722. ;
  7723.  
  7724. clrlin:    mov    dl, cr        ;Go to beginning of line
  7725.     call    bout
  7726. ;
  7727. ;    ...FALL THROUGH
  7728. ;
  7729. ;  INTERFACE ROUTINE CLREOL - clear to end of line
  7730. ;
  7731.  
  7732. clreol:    mov    dx, offset scrclr ;Clear from cursor to end of line
  7733.     call    tmsg
  7734.     ret
  7735.  
  7736. ;
  7737. ; INTERFACE ROUTINE REVON - turns on reverse video display
  7738. ;
  7739.  
  7740. revon:    mov    dx, offset scrron
  7741.     call    tmsg
  7742.     ret
  7743.  
  7744. ;
  7745. ; INTERFACE ROUTINE REVOFF - turns off reverse video display
  7746. ;
  7747.  
  7748. revoff:    mov    dx, offset scrrof
  7749.     call    tmsg
  7750.     ret
  7751. ;
  7752. ; INTERFACE ROUTINE BLDON - turns on bold (highlighted) display
  7753. ;
  7754.  
  7755. bldon:    mov    dx, offset scrbon
  7756.     call    tmsg
  7757.     ret
  7758. ;
  7759. ; INTERFACE ROUTINE BLDOFF - turns off bold (highlighted) display
  7760. ;
  7761.  
  7762. bldoff:    mov    dx, offset scrbof
  7763.     call    tmsg
  7764.     ret
  7765.  
  7766.  
  7767.     DSEG $
  7768.  
  7769. scrpos    db    esc, 'Y$'    ;Position cursor to row and column
  7770. scrcls    db    esc, 'E$'    ;Home cursor and clear screen
  7771. scrclr    db    esc, 'K$'    ;Clear from cursor to end of line
  7772. scrron    db    esc, 'p$'    ;Turn on reverse video
  7773. scrrof    db    esc, 'q$'    ;Turn off reverse video
  7774. scrbon    db    esc, 'm$'    ; Bold on (Actually underline).
  7775. scrbof    db    esc, 'n$'    ; Bold off
  7776.  
  7777.     CSEG $
  7778. ;
  7779. ; INTERFACE ROUTINE DOTAB - do tab expansion if necessary
  7780. ;
  7781. dotab:    jmp    rskp        ; assume h/w does it for now
  7782.  
  7783. ;
  7784. ;  Assorted textual constants required as part of the machine interface
  7785. ;
  7786.     DSEG $
  7787.  
  7788. delstr  db    esc,'D ',esc,'D$'    ;Delete string.
  7789. system    db    '  Future Computers FX20/FX30 (TC - Oct 85)$'
  7790.  
  7791.     CSEG $
  7792. ;
  7793. ; ENDSYSDEP
  7794. ;
  7795. <<< c86xr2.a86 >>>
  7796. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  7797. ; [35a] Kermit now sets a default baud rate.
  7798. ; [35b] Implemented the SET BAUD command.
  7799. ; [35c] Implemented the baud rate function to the SHOW command.
  7800. ;       The above was done to make operation compatable with CPM-80 version 
  7801. ;       and simplify use by non computer orientated users.
  7802. ;       Mark Woollard, 4/12/85, Animal and Grassland Research Institute
  7803. ; * * * * * * * * * * * * * * *  version 2.8  * * * * * * * * * * * * * * *
  7804. ; [34] Insert milli-second wait-loop for Break-timing - label MSWAIT:
  7805. ; [33] Fix printer on hanging system problem by letting CP/M handle the
  7806. ;    interrupts from the 7201 that we don't care about.  Thanks to
  7807. ;    Paul Ford, U. of Chicago Graduate School of Business
  7808. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  7809. ; [30d] Add SET PORT command, currently unimplemented.
  7810. ; [30c] Isolate all machine dependencies in KERIO.
  7811. ;    RonB, 04/18/84
  7812. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  7813. ; [28e] Switch to local stack on interrupts.
  7814. ;    RonB, 03/28/84
  7815. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  7816. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  7817. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  7818. ;    RonB,03/02/84
  7819. ; [19a] Add XON/XOFF type flow control
  7820. ; [19b]    Clear screen and beginning and end of program.
  7821. ; [19e]    Add PRTBRK to send break to port (Rainbow only)
  7822. ; [19g]    Put in EQU for clock rate for timing loops.
  7823. ;    Rg, 2/84     <Oc.Garland%CU20B@Columbia-20>
  7824. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  7825. ;  [par] Added calls to set parity, strip parity on input if
  7826. ;    other than none parity is called for.
  7827. ;     JD, 2/84
  7828. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  7829. ;  [2]    Add a de-initialization routine for the serial port, to restore
  7830. ;    changed interrupt vectors, etc.
  7831. ;    RonB,12/23/83
  7832. ;  [1]    Add I/O support for the NEC Advanced Personal Computer
  7833. ;    RonB,12/23/83
  7834. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  7835.  
  7836. ; This module contains all the low level communications port I/O
  7837. ; routines.
  7838.  
  7839. ; The following is the I/O code for the DEC Rainbow.
  7840.  
  7841.         CSEG $
  7842.  
  7843. ; Clock rate *10 for timing loops    ;[19g]
  7844. clckrt    equ    48        ;[19g]  4.8 Mhz 
  7845.  
  7846. ; Interrupt vector locations, in data segment 
  7847. mnstat    EQU    042H        ;Status port.
  7848. mndata    EQU    040H        ;Data port.
  7849. mnctrl    EQU    002H        ;Control port.
  7850.  
  7851. ; Interrupt vector locations.  These are all in data segment 0.
  7852.  
  7853. mnoff    EQU    90H        ;Main data port interrupt routine offset.
  7854. mnseg    EQU    92H        ;Main data port interrupt routine segment.
  7855.  
  7856. output    EQU    04H        ;Bit for output ready.
  7857. input    EQU    01H        ;Bit for input ready.
  7858.  
  7859. outlmt    EQU    1000H        ;Number of times to check output status
  7860.                 ; before giving up on send.        ;[20d]
  7861.  
  7862. defbd    EQU    0BH        ; [35a] Default baud rate, 0=50 baud, 1=75, 
  7863.                 ; 2=110, 3=134.5, 4=150, 5=200, 6=300, 7=600
  7864.                 ; 8=1200, 9=1800, 10=2000, 11=2400, 12=3600
  7865.                 ; 13=4800, 14=9600 and 15=19200
  7866.  
  7867. ; Input data from port.  Preserves all ACs and returns char in
  7868. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  7869. ; already there.
  7870.  
  7871. inchr:    push    bx
  7872.     cli            ;Disable interrupts while were are playing.
  7873.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  7874.     mov    bx, mnchop    ;Get the pointer into the buffer.
  7875.     inc    bx        ;Increment to the next char.
  7876.     cmp    bx, offset mnchrs+mnchnd ;Past the end?
  7877.     jb    inchr2
  7878.     mov    bx, offset mnchrs ;If so wrap around to the start.
  7879. inchr2:    mov    mnchop, bx    ;Save the updated pointer.
  7880.     mov    al, [bx]    ;Get the character.
  7881.     sti            ;All done, we can restore interrupts.
  7882.     pop    bx
  7883.     cmp    parflg,parnon    ;[par] no parity?
  7884.     je    inchr3        ;[par] yup, don't bother stripping
  7885.     and    al,7fh        ;[par] checking parity, strip off
  7886. inchr3:    cmp    floctl, floxon    ; do flow control?        [19a] start
  7887.     je    inchr4        ;If yes jump
  7888.     ret
  7889. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  7890.     je    inchr5        ;Jump if yes
  7891.     ret
  7892. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  7893.     jb    inchr6        ;yes - jump
  7894.     ret
  7895. inchr6:    push    ax        ;save current character
  7896.     mov    al, xon
  7897.     call    prtout        ;send an XON
  7898.     mov    xofsnt, false    ;turn off the flag
  7899.     pop    ax        ;get back character
  7900.     ret            ;                [19a] end
  7901.  
  7902.  
  7903. ; Output data to port. Trashes DX and prints char in AL.
  7904.  
  7905. outchr:    mov    dx, mndata
  7906.     out    dx, al
  7907.     ret
  7908.  
  7909.  
  7910. ; Test if data is available from port.
  7911.  
  7912. instat:    cmp    mnchrn, 0    ;Any chars in the buffer?
  7913.     jnz    inst2
  7914.      ret
  7915. inst2:    jmp    rskp
  7916.  
  7917.  
  7918. ; Test if port is ready to send next char.  Returns RETSKP if ready.
  7919. ; Trashes dx.
  7920.  
  7921. outwt:    cmp    floctl, floxon    ;are we doing flow-control?    [19a] start
  7922.     jne    outwta        ;no - go on
  7923.     cmp    xofrcv, true    ;are we being held?
  7924.     jne    outwta        ;no - ok go on
  7925.     ret            ;held - say we're busy.    [19a] end
  7926. outwta:    push    ax
  7927.     mov    dx, mnstat
  7928.     in    al, dx
  7929.     test    al, output
  7930.     pop    ax
  7931.     jnz    outwt2
  7932.      ret
  7933. outwt2:    jmp    rskp
  7934.  
  7935.  
  7936. ; Output the character, checking first to make sure the port is clear.
  7937.  
  7938. prtout:    call    dopar        ;[par]
  7939.     push    dx
  7940.     push    cx                        ;[20d] begin
  7941.     mov    cx,outlmt
  7942. prtou2:    call    outwt        ;Wait until the port is ready
  7943.      loop    prtou2        ; or too much time has passed.
  7944.      nop
  7945.     call    outchr        ;Output it.
  7946.     pop    cx                        ;[20d] end
  7947.     pop    dx
  7948.     ret
  7949.  
  7950.  
  7951. mnax    dw    0        ;Storage in CSEG        ;[28e] begin
  7952. mnsp    dw    0        ;  for use by interrupt handler
  7953. mnsseg    dw    0
  7954. mndseg    dw    0
  7955.  
  7956. ; This routine handles the interrupts on input.
  7957.  
  7958. mnint:    cli
  7959.     mov    cs:mnax, ax    ;Save interrupt stack location.
  7960.     mov    ax, sp
  7961.     mov    cs:mnsp, ax
  7962.     mov    ax, ss
  7963.     mov    cs:mnsseg, ax
  7964.     mov    ax, cs:mndseg    ;Switch to our internal stack.
  7965.     mov    ss, ax
  7966.     mov    sp, offset mnstk
  7967.     push    ds        ;Save all registers.
  7968.     push    es
  7969.     push    bp
  7970.     push    di
  7971.     push    si
  7972.     push    dx
  7973.     push    cx
  7974.     push    bx
  7975.     mov    ds, ax
  7976.     call    mnproc        ;Process the character.
  7977.     mov    dx, mnstat    ;Get the status port.
  7978.     mov    al, 38H
  7979.     out    dx, al        ;Tell the port we finished with the interrupt.
  7980.     pop    bx        ;Restore all registers.
  7981.     pop    cx
  7982.     pop    dx
  7983.     pop    si
  7984.     pop    di
  7985.     pop    bp
  7986.     pop    es
  7987.     pop    ds
  7988.     mov    ax, cs:mnsp    ;Restore the original stack.
  7989.     mov    sp, ax
  7990.     mov    ax, cs:mnsseg
  7991.     mov    ss, ax
  7992.     mov    ax, cs:mnax
  7993.     iret            ;Return from the interrupt.    ;[28e] end
  7994.  
  7995.  
  7996. ; This routine (called by MNINT) gets a char from the main port
  7997. ; and puts it in the infamous circular buffer.
  7998.  
  7999. mnproc:    mov    dx, mnstat
  8000.     in    al, dx        ;Get the port status.
  8001.     test    al, input    ;Any there?
  8002.     jnz    mnpro2        ;Yup, go take care of it.
  8003.  
  8004. ;[33] Begin addition
  8005. ; If not a received character, simulate an interrupt transferring
  8006. ; control to the CPM routine. Let it handle worrisome things like
  8007. ; someone turning on the printer.
  8008.  
  8009.      pushf            ; Save flags, like an int.
  8010.      callf dword ptr mnoldo    ; Call CPM's routine.
  8011.      ret            ; Now back to MNINT.
  8012.  
  8013. ;[33] End addition
  8014.  
  8015. mnpro2:    mov    al, 1        ;Point to RR1.
  8016.     out    dx, al
  8017.     in    al, dx        ;Read RR1.
  8018.     mov    ah, al        ;Save it.
  8019.     mov    al, 30H        ;Reset any errors.
  8020.     out    dx, al
  8021.     mov    dx, mndata
  8022.     in    al, dx        ;Read the char.
  8023.     cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  8024.     jne    mnpr2b        ;no - go on
  8025.     cmp    al, xoff    ;is it an XOFF?
  8026.     jne    mnpr2a        ;no - go on
  8027.     mov    xofrcv, true    ;set the flag
  8028.     ret
  8029. mnpr2a:    cmp    al, xon        ;an XON?
  8030.     jne    mnpr2b        ;no
  8031.     mov    xofrcv, false    ;clear the flag
  8032.     ret            ;                [19a] end
  8033. mnpr2b:    cmp    mnchrn, mnchnd    ;Is the buffer full?
  8034.     je    mnperr        ;If so, take care of the error.
  8035.     inc    mnchrn        ;Increment the character count.
  8036.     mov    bx, mnchip    ;Get the buffer input pointer.
  8037.     inc    bx        ;Increment it.
  8038.     cmp    bx, offset mnchrs+mnchnd ;Past the end?
  8039.     jb    mnpro3
  8040.     mov    bx, offset mnchrs ;Yes, point to the start again.
  8041. mnpro3:    mov    mnchip, bx    ;Save the pointer.
  8042.     mov    [bx], al    ;Put the character in the buffer.
  8043.     cmp    floctl, floxon    ;do flow control?        [19a] start
  8044.     je    mnpro4        ;If yes jump
  8045.     ret
  8046. mnpro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  8047.     jnz    mnpro5
  8048.     ret            ;return if we have
  8049. mnpro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  8050.     ja    mnpro6        ;yes - jump
  8051.     ret
  8052. mnpro6:    mov    al, xoff
  8053.     call    prtout        ;send an XOFF
  8054.     mov    xofsnt, true    ;set the flag
  8055.     ret            ;                [19a] End
  8056.  
  8057. mnperr:    ret            ;Just return on an error for now.
  8058.  
  8059.  
  8060. ; prtbrk - send a break        ;                [19e] start
  8061.  
  8062. prtbrk:                ;
  8063.     mov    dx, mnstat    ;status reg. address for port
  8064.     mov    al, 15H        ;select reg. 5
  8065.     out    dx, al        ;
  8066.     mov    al, 0FAH    ;8 bits, TX, Break, RTS, & DTR
  8067.     out    dx, al        ;Turn Break on
  8068.     mov    ax, 275        ;.. for 275 millisec's        [34]
  8069.     call    mswait        ;                [34]
  8070.     mov    al, 15H        ;select reg. 5
  8071.     out    dx, al        ;
  8072.     mov    al, 0EAH    ;same as above without Break
  8073.     out    dx, al        ;turn it off
  8074.     ret            ;                 [19e] end
  8075.  
  8076. mswait:                ;                [34] start
  8077.     mov    cx,5*clckrt    ; inner loop count for 1 millisec.
  8078. mswai1:
  8079.     sub    cx,1        ;** inner loop takes 20 clock cycles
  8080.     jnz    mswai1        ;**
  8081.     dec    ax        ; outer loop counter
  8082.     jnz    mswait        ; wait another millisecond
  8083.     ret            ;                [34] end
  8084. ;
  8085. ; Init the 7201 for 8 bits, no parity, and 1 stop bit.
  8086.  
  8087. serini:    call    ansmod        ;Switch from VT52 to ANSI mode    ;[30c]
  8088.  
  8089.     mov    ax, ds
  8090.     mov    cs:mndseg, ax    ;Save the data segment somewhere in CSEG.
  8091.     push    ds        ;Save the data segment.
  8092.     mov    ax, 0
  8093.     mov    ds, ax        ;We want DSEG = 0.
  8094.     cli            ;Turn off interrupts.
  8095.     mov    bx, .mnoff    ;[33] Get original interrupt offset.
  8096.     mov    es, .mnseg    ;[33] Get original interrupt segment.
  8097.     mov    ax, offset mnint;Point to the interrupt routine offset.
  8098.     mov    .mnoff, ax    ;Put in the main port interrupt offset addr.
  8099.     mov    ax, cs        ;Get our code segment.
  8100.     mov    .mnseg, ax    ;Put in the main port interrupt segment addr.
  8101.     sti            ;Restore interrupts.
  8102.     pop    ds        ;Restore data segment.
  8103.  
  8104.     mov    mnoldo, bx    ;[33] Stash original serial interrupt offset.
  8105.     mov    mnolds, es    ;[33] Stash original segment.
  8106.  
  8107.     mov    dx, mnstat    ;Point to status port.
  8108.     mov    al, 18H
  8109.     out    dx, al        ;Reset the port.
  8110.     mov    al, 14H
  8111.     out    dx, al        ;Select register 4.
  8112.     mov    al, 44H        ;16X clock, 1 stop bit, no parity.
  8113.     out    dx, al
  8114.     mov    al, 13H
  8115.     out    dx, al        ;Select register 3.
  8116.     mov    al, 0C1H    ;8 bits/char, RX enable.
  8117.     out    dx, al
  8118.     mov    al, 15H
  8119.     out    dx, al        ;Select register 5.
  8120.     mov    al, 0EAH    ;8 bits/char, TX enable, RTS and DTR.
  8121.     out    dx, al
  8122.     mov    al, 11H
  8123.     out    dx, al        ;Select register 1.
  8124.     mov    al, 18H
  8125.     out    dx, al        ;Enable interrupt processing on this port.
  8126.     mov    dx, mnctrl    ;point to comm control port
  8127.     mov    al, 0F0H    ;set RTS & DTR high
  8128.     out    dx, al
  8129.     mov    al,defbd    ; [35a] Get default baud
  8130.     mov    dl,al        ; Save it
  8131.     mov    cl,4        ; Move low nibble into high
  8132.     shl    al,cl        ;
  8133.     or    al,dl        ; Replace low nibble
  8134.     out    6,al        ; Write to baud control port
  8135.     mov    baudrt,al    ; Save it for show baud         ;[35a] end
  8136.     ret
  8137.  
  8138. serfin:    
  8139.     call    clrscr        ;[19b] clear screen        ;[30c]
  8140.  
  8141.     ret            ;Nothing to deinitialize on Rainbow.
  8142.  
  8143. ; This routine clears the serial port input buffer.  It is called to
  8144. ; clear out excess NAKs that can result from server mode operation.
  8145.  
  8146. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  8147.     mov    mnchip, offset mnchrs-1+mnchnd ;Reset input pointer.
  8148.     mov    mnchop, offset mnchrs-1+mnchnd ;Reset output pointer.
  8149.     ret
  8150.  
  8151.     DSEG $
  8152.  
  8153. mnchnd    equ    256        ;[19a] Size of circular buffer.
  8154. mntrg1    equ    64        ;[19a] Low trigger point for Auto XON/XOFF
  8155. mntrg2    equ    192        ;[19a] High trigger point for Auto XON/XOFF
  8156.  
  8157. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  8158. xofsnt    db    0        ;[19a] set if XOFF was sent
  8159. xofrcv    db    0        ;[19a] set if XOFF was recieved
  8160.  
  8161. mnchrn    DW    0        ;[19a] Number of chars in the buffer.
  8162. mnchrs    RB    mnchnd        ;Circular character buffer for input.
  8163. mnchip    DW    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  8164. mnchop    DW    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  8165.  
  8166. mnoldo    RW    1        ;[33] CPM's 7201 interrupt vector offset
  8167. mnolds    RW    1        ;[33] and segment.
  8168.  
  8169.     rw    32        ;Interrupt stack        ;[28e]
  8170. mnstk    dw    0        ;bottom of stack        ;[28e]
  8171.  
  8172. baudrt    rb    1        ;Current baud rate
  8173.  
  8174.     CSEG $
  8175.  
  8176. ; The following routines do the SET and SHOW for the machine dependent
  8177. ; features of Kermit.  At present there are only two:  baud rate setting
  8178. ; and port selection.
  8179.  
  8180. ;    This is the SET BAUD rate subcommand (not implemented in Rainbow)
  8181.  
  8182. bdset:    mov    ah, cmcfm
  8183.     call    comnd            ;Get a confirm.
  8184.     jmp    bdset1            ; Didn't get a confirm.
  8185.     jmp    bdset2            ; [35b] Go and ask for baud
  8186. bdset1:    mov    dx, offset ermes3    ; Tell user unknown command option
  8187.     call    tcrmsg
  8188.     jmp    rskp
  8189. bdset2:    mov    dx, offset bdlst    ; Print list of baud speeds
  8190.     call    tmsg
  8191. bdstrt:    mov    cl,1            ; Get a response from keyboard
  8192.     int    224
  8193.     and    al,5fH            ; Force upper case
  8194.     cmp    al,'A'
  8195.     jnb    bdset3            ; AL >= 'A'...
  8196.     jmp    bdset4            ; Response too low
  8197. bdset3:    cmp    al,'P'
  8198.     jle    bdset5            ; AL <= 'P'...
  8199. bdset4:    mov    dx,offset rtrmss    ; Incorrect response so delete char
  8200.     call    tmsg            ; typed and make keyboard beep
  8201.     jmp    bdstrt            ; Go and try again...
  8202. bdset5:    sub    al,'A'            ; Convert to internal baud rate code
  8203.     mov    dl,al            ; Save AL
  8204.     mov    cl,4            ; Move lower nibble into upper
  8205.     shl    al,cl
  8206.     or    al,dl            ; replace lower nibble
  8207.     out    6,al            ; Write to baud port
  8208.     mov    baudrt,al        ; Save for SHOW BAUD         ;[35b] end
  8209.     jmp    rskp
  8210.  
  8211. ;    This is the SET PORT subcommand (not implemented in Rainbow)
  8212.  
  8213. prtset:    mov    ah, cmcfm
  8214.     call    comnd        ;Get a confirm.
  8215.      jmp    $+3        ; Didn't get a confirm.
  8216.     mov    dx, offset infms6 ;Tell user it's not implemented
  8217.     call    tcrmsg
  8218.     jmp    rskp
  8219.  
  8220.  
  8221. ; The following procedures implement the SHOW command for the system
  8222. ; dependent features of baud rate and port selection.
  8223.  
  8224. ; SHOW BAUD command
  8225.  
  8226. shobd:    mov    dx, offset bdst        ;[35c] Print 'Baud rate:'
  8227.     call    tcrmsg
  8228.     mov    al,baudrt        ; Get current baud rate
  8229.     and    al,0FH            ; Mask off high nibble
  8230.     mov    cl,6            ; Multiply by 6
  8231.     mul    cl
  8232.     add    ax, offset bdmss2    ; Set up DX as an offset into
  8233.     mov    dx,ax            ; the list of baud strings
  8234.     call    tmsg            ; Print the string
  8235.     ret                ;             ;[35c] end
  8236.  
  8237. shoprt:    ret            ;Port selection not implemented.
  8238.  
  8239.  
  8240.  
  8241.  
  8242. ; The following routines do screen control.  These are isolated here because
  8243. ; the screen control sequences are likely to vary from system to system, even
  8244. ; though the Rainbow and APC (the only systems implemented to date) both use
  8245. ; ANSI sequences for this purpose.
  8246.  
  8247.     CSEG $
  8248.  
  8249. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  8250.  
  8251. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  8252.     mov    cl, 10
  8253.     mov    al, [bx]    ;Get row value
  8254.     sub    ah, ah
  8255.     div    cl        ;units digit in ah, tens digit in al
  8256.     add    ax, '00'    ;Convert both to ASCII
  8257.     mov    word ptr anspos+2, ax    ;Save reversed (al,ah)
  8258.     mov    al, 1[bx]    ;Do same for column value
  8259.     sub    ah, ah
  8260.     div    cl
  8261.     add    ax, '00'
  8262.     mov    word ptr anspos+5, ax
  8263.     mov    dx, offset anspos ;Print cursor positioning string.
  8264.     call    tmsg
  8265.     ret
  8266.  
  8267. ; CLRSCR - homes cursor and clears screen.
  8268.  
  8269. clrscr:    mov    dx, offset anscls
  8270.     call    tmsg
  8271.     ret
  8272.  
  8273. ; CLRLIN - clears from cursor to end of line.
  8274.  
  8275. clrlin:    mov    dl, cr        ;Go to beginning of line
  8276.     call    bout
  8277. clreol:    mov    dx, offset ansclr ;Clear from cursor to end of line
  8278.     call    tmsg
  8279.     ret
  8280.  
  8281. ; REVON - turns on reverse video display
  8282.  
  8283. revon:    mov    dx, offset ansron
  8284.     call    tmsg
  8285.     ret
  8286.  
  8287. ; REVOFF - turns off reverse video display
  8288.  
  8289. revoff:    mov    dx, offset ansrof
  8290.     call    tmsg
  8291.     ret
  8292.  
  8293. ; BLDON - turns on bold (highlighted) display
  8294.  
  8295. bldon:    mov    dx, offset ansbon
  8296.     call    tmsg
  8297.     ret
  8298.  
  8299. ; BLDOFF - turns off bold (highlighted) display
  8300.  
  8301. bldoff:    mov    dx, offset ansbof
  8302.     call    tmsg
  8303.     ret
  8304.  
  8305. ; ANSMOD - enters ANSI mode from VT52 mode
  8306.  
  8307. ansmod:    mov    dx, offset ansion
  8308.     call    tmsg
  8309.     ret
  8310.  
  8311.     DSEG $
  8312.  
  8313. anspos    db    esc,'[00;00H$'        ;Position cursor to row and column
  8314. anscls    db    esc,'[H',esc,'[J$'    ;Home cursor and clear screen
  8315. ansclr    db    esc,'[K$'        ;Clear from cursor to end of line
  8316. ansron    db    esc,'[7m$'        ;Turn on reverse video
  8317. ansrof    db    esc,'[m$'        ;Turn off reverse video
  8318. ansbon    db    esc,'[1m$'        ;Turn on bold (highlight) display
  8319. ansbof    db    esc,'[m$'        ;Turn off bold display
  8320. ansion    db    esc,'<$'        ;Enter ANSI mode
  8321.  
  8322. ; Here tab expansion is done if necessary.  If not, just return retskp.
  8323.  
  8324.     CSEG $
  8325. dotab:    jmp rskp
  8326.  
  8327.     DSEG $
  8328. delstr    db    ' ',10O,10O,'$'    ;Delete string.
  8329.  
  8330. system    db    '                DEC Rainbow-100$'
  8331.  
  8332. bdlst    db    esc,'[H',esc,'[J','Baud rates available :'    ;[35b] Baud rate list 
  8333.     db    cr,lf,cr,lf,'       A)    50'            ;for SET BAUD
  8334.     db    cr,lf,'       B)    75'
  8335.     db    cr,lf,'       C)   110'
  8336.     db    cr,lf,'       D)   134.5'
  8337.     db    cr,lf,'       E)   150'
  8338.     db    cr,lf,'       F)   200'
  8339.     db    cr,lf,'       G)   300'
  8340.     db    cr,lf,'       H)   600'
  8341.     db    cr,lf,'       I)  1200'
  8342.     db    cr,lf,'       J)  1800'
  8343.     db    cr,lf,'       K)  2000'
  8344.     db    cr,lf,'       L)  2400'
  8345.     db    cr,lf,'       M)  3600'
  8346.     db    cr,lf,'       N)  4800'
  8347.     db    cr,lf,'       O)  9600'
  8348.     db    cr,lf,'       P) 19200'
  8349.     db    cr,lf,cr,lf,'Enter choice > $'
  8350.  
  8351. rtrmss    db    8,' ',8,7,'$'        ;[35b] Delete char and beep string
  8352.  
  8353. bdmss2    db    '50   $'        ;[35c] Used by SHOW BAUD option
  8354.     db    '75   $'
  8355.     db    '110  $'
  8356.     db    '134.5$'
  8357.     db    '150  $'
  8358.     db    '200  $'
  8359.     db    '300  $'
  8360.     db    '600  $'
  8361.     db    '1200 $'
  8362.     db    '1800 $'
  8363.     db    '2000 $'
  8364.     db    '2400 $'
  8365.     db    '3600 $'
  8366.     db    '4800 $'
  8367.     db    '9600 $'
  8368.     db    '19200$'
  8369. <<< c86xrb.a86 >>>
  8370. ; * * * * * * * * * * * * * * *  version 2.8  * * * * * * * * * * * * * * *
  8371. ; [34] Insert milli-second wait-loop for Break-timing - label MSWAIT:
  8372. ; [33] Fix printer on hanging system problem by letting CP/M handle the
  8373. ;    interrupts from the 7201 that we don't care about.  Thanks to
  8374. ;    Paul Ford, U. of Chicago Graduate School of Business
  8375. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  8376. ; [30d] Add SET PORT command, currently unimplemented.
  8377. ; [30c] Isolate all machine dependencies in KERIO.
  8378. ;    RonB, 04/18/84
  8379. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  8380. ; [28e] Switch to local stack on interrupts.
  8381. ;    RonB, 03/28/84
  8382. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  8383. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  8384. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  8385. ;    RonB,03/02/84
  8386. ; [19a] Add XON/XOFF type flow control
  8387. ; [19b]    Clear screen and beginning and end of program.
  8388. ; [19e]    Add PRTBRK to send break to port (Rainbow only)
  8389. ; [19g]    Put in EQU for clock rate for timing loops.
  8390. ;    Rg, 2/84     <Oc.Garland%CU20B@Columbia-20>
  8391. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  8392. ;  [par] Added calls to set parity, strip parity on input if
  8393. ;    other than none parity is called for.
  8394. ;     JD, 2/84
  8395. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  8396. ;  [2]    Add a de-initialization routine for the serial port, to restore
  8397. ;    changed interrupt vectors, etc.
  8398. ;    RonB,12/23/83
  8399. ;  [1]    Add I/O support for the NEC Advanced Personal Computer
  8400. ;    RonB,12/23/83
  8401. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  8402.  
  8403. ; This module contains all the low level communications port I/O
  8404. ; routines.
  8405.  
  8406. ; The following is the I/O code for the DEC Rainbow.
  8407.  
  8408.         CSEG $
  8409.  
  8410. ; Clock rate *10 for timing loops    ;[19g]
  8411. clckrt    equ    48        ;[19g]  4.8 Mhz 
  8412.  
  8413. ; Interrupt vector locations, in data segment 
  8414. mnstat    EQU    042H        ;Status port.
  8415. mndata    EQU    040H        ;Data port.
  8416. mnctrl    EQU    002H        ;Control port.
  8417.  
  8418. ; Interrupt vector locations.  These are all in data segment 0.
  8419.  
  8420. mnoff    EQU    90H        ;Main data port interrupt routine offset.
  8421. mnseg    EQU    92H        ;Main data port interrupt routine segment.
  8422.  
  8423. output    EQU    04H        ;Bit for output ready.
  8424. input    EQU    01H        ;Bit for input ready.
  8425.  
  8426. outlmt    EQU    1000H        ;Number of times to check output status
  8427.                 ; before giving up on send.        ;[20d]
  8428.  
  8429.  
  8430. ; Input data from port.  Preserves all ACs and returns char in
  8431. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  8432. ; already there.
  8433.  
  8434. inchr:    push    bx
  8435.     cli            ;Disable interrupts while were are playing.
  8436.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  8437.     mov    bx, mnchop    ;Get the pointer into the buffer.
  8438.     inc    bx        ;Increment to the next char.
  8439.     cmp    bx, offset mnchrs+mnchnd ;Past the end?
  8440.     jb    inchr2
  8441.     mov    bx, offset mnchrs ;If so wrap around to the start.
  8442. inchr2:    mov    mnchop, bx    ;Save the updated pointer.
  8443.     mov    al, [bx]    ;Get the character.
  8444.     sti            ;All done, we can restore interrupts.
  8445.     pop    bx
  8446.     cmp    parflg,parnon    ;[par] no parity?
  8447.     je    inchr3        ;[par] yup, don't bother stripping
  8448.     and    al,7fh        ;[par] checking parity, strip off
  8449. inchr3:    cmp    floctl, floxon    ; do flow control?        [19a] start
  8450.     je    inchr4        ;If yes jump
  8451.     ret
  8452. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  8453.     je    inchr5        ;Jump if yes
  8454.     ret
  8455. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  8456.     jb    inchr6        ;yes - jump
  8457.     ret
  8458. inchr6:    push    ax        ;save current character
  8459.     mov    al, xon
  8460.     call    prtout        ;send an XON
  8461.     mov    xofsnt, false    ;turn off the flag
  8462.     pop    ax        ;get back character
  8463.     ret            ;                [19a] end
  8464.  
  8465.  
  8466. ; Output data to port. Trashes DX and prints char in AL.
  8467.  
  8468. outchr:    mov    dx, mndata
  8469.     out    dx, al
  8470.     ret
  8471.  
  8472.  
  8473. ; Test if data is available from port.
  8474.  
  8475. instat:    cmp    mnchrn, 0    ;Any chars in the buffer?
  8476.     jnz    inst2
  8477.      ret
  8478. inst2:    jmp    rskp
  8479.  
  8480.  
  8481. ; Test if port is ready to send next char.  Returns RETSKP if ready.
  8482. ; Trashes dx.
  8483.  
  8484. outwt:    cmp    floctl, floxon    ;are we doing flow-control?    [19a] start
  8485.     jne    outwta        ;no - go on
  8486.     cmp    xofrcv, true    ;are we being held?
  8487.     jne    outwta        ;no - ok go on
  8488.     ret            ;held - say we're busy.    [19a] end
  8489. outwta:    push    ax
  8490.     mov    dx, mnstat
  8491.     in    al, dx
  8492.     test    al, output
  8493.     pop    ax
  8494.     jnz    outwt2
  8495.      ret
  8496. outwt2:    jmp    rskp
  8497.  
  8498.  
  8499. ; Output the character, checking first to make sure the port is clear.
  8500.  
  8501. prtout:    call    dopar        ;[par]
  8502.     push    dx
  8503.     push    cx                        ;[20d] begin
  8504.     mov    cx,outlmt
  8505. prtou2:    call    outwt        ;Wait until the port is ready
  8506.      loop    prtou2        ; or too much time has passed.
  8507.      nop
  8508.     call    outchr        ;Output it.
  8509.     pop    cx                        ;[20d] end
  8510.     pop    dx
  8511.     ret
  8512.  
  8513.  
  8514. mnax    dw    0        ;Storage in CSEG        ;[28e] begin
  8515. mnsp    dw    0        ;  for use by interrupt handler
  8516. mnsseg    dw    0
  8517. mndseg    dw    0
  8518.  
  8519. ; This routine handles the interrupts on input.
  8520.  
  8521. mnint:    cli
  8522.     mov    cs:mnax, ax    ;Save interrupt stack location.
  8523.     mov    ax, sp
  8524.     mov    cs:mnsp, ax
  8525.     mov    ax, ss
  8526.     mov    cs:mnsseg, ax
  8527.     mov    ax, cs:mndseg    ;Switch to our internal stack.
  8528.     mov    ss, ax
  8529.     mov    sp, offset mnstk
  8530.     push    ds        ;Save all registers.
  8531.     push    es
  8532.     push    bp
  8533.     push    di
  8534.     push    si
  8535.     push    dx
  8536.     push    cx
  8537.     push    bx
  8538.     mov    ds, ax
  8539.     call    mnproc        ;Process the character.
  8540.     mov    dx, mnstat    ;Get the status port.
  8541.     mov    al, 38H
  8542.     out    dx, al        ;Tell the port we finished with the interrupt.
  8543.     pop    bx        ;Restore all registers.
  8544.     pop    cx
  8545.     pop    dx
  8546.     pop    si
  8547.     pop    di
  8548.     pop    bp
  8549.     pop    es
  8550.     pop    ds
  8551.     mov    ax, cs:mnsp    ;Restore the original stack.
  8552.     mov    sp, ax
  8553.     mov    ax, cs:mnsseg
  8554.     mov    ss, ax
  8555.     mov    ax, cs:mnax
  8556.     iret            ;Return from the interrupt.    ;[28e] end
  8557.  
  8558.  
  8559. ; This routine (called by MNINT) gets a char from the main port
  8560. ; and puts it in the infamous circular buffer.
  8561.  
  8562. mnproc:    mov    dx, mnstat
  8563.     in    al, dx        ;Get the port status.
  8564.     test    al, input    ;Any there?
  8565.     jnz    mnpro2        ;Yup, go take care of it.
  8566.  
  8567. ;[33] Begin addition
  8568. ; If not a received character, simulate an interrupt transferring
  8569. ; control to the CPM routine. Let it handle worrisome things like
  8570. ; someone turning on the printer.
  8571.  
  8572.      pushf            ; Save flags, like an int.
  8573.      callf dword ptr mnoldo    ; Call CPM's routine.
  8574.      ret            ; Now back to MNINT.
  8575.  
  8576. ;[33] End addition
  8577.  
  8578. mnpro2:    mov    al, 1        ;Point to RR1.
  8579.     out    dx, al
  8580.     in    al, dx        ;Read RR1.
  8581.     mov    ah, al        ;Save it.
  8582.     mov    al, 30H        ;Reset any errors.
  8583.     out    dx, al
  8584.     mov    dx, mndata
  8585.     in    al, dx        ;Read the char.
  8586.     cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  8587.     jne    mnpr2b        ;no - go on
  8588.     cmp    al, xoff    ;is it an XOFF?
  8589.     jne    mnpr2a        ;no - go on
  8590.     mov    xofrcv, true    ;set the flag
  8591.     ret
  8592. mnpr2a:    cmp    al, xon        ;an XON?
  8593.     jne    mnpr2b        ;no
  8594.     mov    xofrcv, false    ;clear the flag
  8595.     ret            ;                [19a] end
  8596. mnpr2b:    cmp    mnchrn, mnchnd    ;Is the buffer full?
  8597.     je    mnperr        ;If so, take care of the error.
  8598.     inc    mnchrn        ;Increment the character count.
  8599.     mov    bx, mnchip    ;Get the buffer input pointer.
  8600.     inc    bx        ;Increment it.
  8601.     cmp    bx, offset mnchrs+mnchnd ;Past the end?
  8602.     jb    mnpro3
  8603.     mov    bx, offset mnchrs ;Yes, point to the start again.
  8604. mnpro3:    mov    mnchip, bx    ;Save the pointer.
  8605.     mov    [bx], al    ;Put the character in the buffer.
  8606.     cmp    floctl, floxon    ;do flow control?        [19a] start
  8607.     je    mnpro4        ;If yes jump
  8608.     ret
  8609. mnpro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  8610.     jnz    mnpro5
  8611.     ret            ;return if we have
  8612. mnpro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  8613.     ja    mnpro6        ;yes - jump
  8614.     ret
  8615. mnpro6:    mov    al, xoff
  8616.     call    prtout        ;send an XOFF
  8617.     mov    xofsnt, true    ;set the flag
  8618.     ret            ;                [19a] End
  8619.  
  8620. mnperr:    ret            ;Just return on an error for now.
  8621.  
  8622.  
  8623. ; prtbrk - send a break        ;                [19e] start
  8624.  
  8625. prtbrk:                ;
  8626.     mov    dx, mnstat    ;status reg. address for port
  8627.     mov    al, 15H        ;select reg. 5
  8628.     out    dx, al        ;
  8629.     mov    al, 0FAH    ;8 bits, TX, Break, RTS, & DTR
  8630.     out    dx, al        ;Turn Break on
  8631.     mov    ax, 275        ;.. for 275 millisec's        [34]
  8632.     call    mswait        ;                [34]
  8633.     mov    al, 15H        ;select reg. 5
  8634.     out    dx, al        ;
  8635.     mov    al, 0EAH    ;same as above without Break
  8636.     out    dx, al        ;turn it off
  8637.     ret            ;                 [19e] end
  8638.  
  8639. mswait:                ;                [34] start
  8640.     mov    cx,5*clckrt    ; inner loop count for 1 millisec.
  8641. mswai1:
  8642.     sub    cx,1        ;** inner loop takes 20 clock cycles
  8643.     jnz    mswai1        ;**
  8644.     dec    ax        ; outer loop counter
  8645.     jnz    mswait        ; wait another millisecond
  8646.     ret            ;                [34] end
  8647. ;
  8648. ; Init the 7201 for 8 bits, no parity, and 1 stop bit.
  8649.  
  8650. serini:    call    ansmod        ;Switch from VT52 to ANSI mode    ;[30c]
  8651.  
  8652.     mov    ax, ds
  8653.     mov    cs:mndseg, ax    ;Save the data segment somewhere in CSEG.
  8654.     push    ds        ;Save the data segment.
  8655.     mov    ax, 0
  8656.     mov    ds, ax        ;We want DSEG = 0.
  8657.     cli            ;Turn off interrupts.
  8658.     mov    bx, .mnoff    ;[33] Get original interrupt offset.
  8659.     mov    es, .mnseg    ;[33] Get original interrupt segment.
  8660.     mov    ax, offset mnint;Point to the interrupt routine offset.
  8661.     mov    .mnoff, ax    ;Put in the main port interrupt offset addr.
  8662.     mov    ax, cs        ;Get our code segment.
  8663.     mov    .mnseg, ax    ;Put in the main port interrupt segment addr.
  8664.     sti            ;Restore interrupts.
  8665.     pop    ds        ;Restore data segment.
  8666.  
  8667.     mov    mnoldo, bx    ;[33] Stash original serial interrupt offset.
  8668.     mov    mnolds, es    ;[33] Stash original segment.
  8669.  
  8670.     mov    dx, mnstat    ;Point to status port.
  8671.     mov    al, 18H
  8672.     out    dx, al        ;Reset the port.
  8673.     mov    al, 14H
  8674.     out    dx, al        ;Select register 4.
  8675.     mov    al, 44H        ;16X clock, 1 stop bit, no parity.
  8676.     out    dx, al
  8677.     mov    al, 13H
  8678.     out    dx, al        ;Select register 3.
  8679.     mov    al, 0C1H    ;8 bits/char, RX enable.
  8680.     out    dx, al
  8681.     mov    al, 15H
  8682.     out    dx, al        ;Select register 5.
  8683.     mov    al, 0EAH    ;8 bits/char, TX enable, RTS and DTR.
  8684.     out    dx, al
  8685.     mov    al, 11H
  8686.     out    dx, al        ;Select register 1.
  8687.     mov    al, 18H
  8688.     out    dx, al        ;Enable interrupt processing on this port.
  8689.     mov    dx, mnctrl    ;point to comm control port
  8690.     mov    al, 0F0H    ;set RTS & DTR high
  8691.     out    dx, al
  8692.     ret
  8693.  
  8694. serfin:    
  8695.     call    clrscr        ;[19b] clear screen        ;[30c]
  8696.  
  8697.     ret            ;Nothing to deinitialize on Rainbow.
  8698.  
  8699. ; This routine clears the serial port input buffer.  It is called to
  8700. ; clear out excess NAKs that can result from server mode operation.
  8701.  
  8702. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  8703.     mov    mnchip, offset mnchrs-1+mnchnd ;Reset input pointer.
  8704.     mov    mnchop, offset mnchrs-1+mnchnd ;Reset output pointer.
  8705.     ret
  8706.  
  8707.     DSEG $
  8708.  
  8709. mnchnd    equ    256        ;[19a] Size of circular buffer.
  8710. mntrg1    equ    64        ;[19a] Low trigger point for Auto XON/XOFF
  8711. mntrg2    equ    192        ;[19a] High trigger point for Auto XON/XOFF
  8712.  
  8713. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  8714. xofsnt    db    0        ;[19a] set if XOFF was sent
  8715. xofrcv    db    0        ;[19a] set if XOFF was recieved
  8716.  
  8717. mnchrn    DW    0        ;[19a] Number of chars in the buffer.
  8718. mnchrs    RB    mnchnd        ;Circular character buffer for input.
  8719. mnchip    DW    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  8720. mnchop    DW    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  8721.  
  8722. mnoldo    RW    1        ;[33] CPM's 7201 interrupt vector offset
  8723. mnolds    RW    1        ;[33] and segment.
  8724.  
  8725.     rw    32        ;Interrupt stack        ;[28e]
  8726. mnstk    dw    0        ;bottom of stack        ;[28e]
  8727.  
  8728.  
  8729.     CSEG $
  8730.  
  8731. ; The following routines do the SET and SHOW for the machine dependent
  8732. ; features of Kermit.  At present there are only two:  baud rate setting
  8733. ; and port selection.
  8734.  
  8735. ;    This is the SET BAUD rate subcommand (not implemented in Rainbow)
  8736.  
  8737. bdset:    mov    ah, cmcfm
  8738.     call    comnd        ;Get a confirm.
  8739.      jmp    $+3        ; Didn't get a confirm.
  8740.     mov    dx, offset infms6 ;Tell user it's not implemented
  8741.     call    tcrmsg
  8742.     jmp    rskp
  8743.  
  8744. ;    This is the SET PORT subcommand (not implemented in Rainbow)
  8745.  
  8746. prtset:    mov    ah, cmcfm
  8747.     call    comnd        ;Get a confirm.
  8748.      jmp    $+3        ; Didn't get a confirm.
  8749.     mov    dx, offset infms6 ;Tell user it's not implemented
  8750.     call    tcrmsg
  8751.     jmp    rskp
  8752.  
  8753.  
  8754. ; The following procedures implement the SHOW command for the system
  8755. ; dependent features of baud rate and port selection.
  8756.  
  8757. shobd:    ret            ;Baud rate selection not implemented.
  8758.  
  8759. shoprt:    ret            ;Port selection not implemented.
  8760.  
  8761.  
  8762.  
  8763.  
  8764. ; The following routines do screen control.  These are isolated here because
  8765. ; the screen control sequences are likely to vary from system to system, even
  8766. ; though the Rainbow and APC (the only systems implemented to date) both use
  8767. ; ANSI sequences for this purpose.
  8768.  
  8769.     CSEG $
  8770.  
  8771. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  8772.  
  8773. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  8774.     mov    cl, 10
  8775.     mov    al, [bx]    ;Get row value
  8776.     sub    ah, ah
  8777.     div    cl        ;units digit in ah, tens digit in al
  8778.     add    ax, '00'    ;Convert both to ASCII
  8779.     mov    word ptr anspos+2, ax    ;Save reversed (al,ah)
  8780.     mov    al, 1[bx]    ;Do same for column value
  8781.     sub    ah, ah
  8782.     div    cl
  8783.     add    ax, '00'
  8784.     mov    word ptr anspos+5, ax
  8785.     mov    dx, offset anspos ;Print cursor positioning string.
  8786.     call    tmsg
  8787.     ret
  8788.  
  8789. ; CLRSCR - homes cursor and clears screen.
  8790.  
  8791. clrscr:    mov    dx, offset anscls
  8792.     call    tmsg
  8793.     ret
  8794.  
  8795. ; CLRLIN - clears from cursor to end of line.
  8796.  
  8797. clrlin:    mov    dl, cr        ;Go to beginning of line
  8798.     call    bout
  8799. clreol:    mov    dx, offset ansclr ;Clear from cursor to end of line
  8800.     call    tmsg
  8801.     ret
  8802.  
  8803. ; REVON - turns on reverse video display
  8804.  
  8805. revon:    mov    dx, offset ansron
  8806.     call    tmsg
  8807.     ret
  8808.  
  8809. ; REVOFF - turns off reverse video display
  8810.  
  8811. revoff:    mov    dx, offset ansrof
  8812.     call    tmsg
  8813.     ret
  8814.  
  8815. ; BLDON - turns on bold (highlighted) display
  8816.  
  8817. bldon:    mov    dx, offset ansbon
  8818.     call    tmsg
  8819.     ret
  8820.  
  8821. ; BLDOFF - turns off bold (highlighted) display
  8822.  
  8823. bldoff:    mov    dx, offset ansbof
  8824.     call    tmsg
  8825.     ret
  8826.  
  8827. ; ANSMOD - enters ANSI mode from VT52 mode
  8828.  
  8829. ansmod:    mov    dx, offset ansion
  8830.     call    tmsg
  8831.     ret
  8832.  
  8833.     DSEG $
  8834.  
  8835. anspos    db    esc,'[00;00H$'        ;Position cursor to row and column
  8836. anscls    db    esc,'[H',esc,'[J$'    ;Home cursor and clear screen
  8837. ansclr    db    esc,'[K$'        ;Clear from cursor to end of line
  8838. ansron    db    esc,'[7m$'        ;Turn on reverse video
  8839. ansrof    db    esc,'[m$'        ;Turn off reverse video
  8840. ansbon    db    esc,'[1m$'        ;Turn on bold (highlight) display
  8841. ansbof    db    esc,'[m$'        ;Turn off bold display
  8842. ansion    db    esc,'<$'        ;Enter ANSI mode
  8843.  
  8844. ; Here tab expansion is done if necessary.  If not, just return retskp.
  8845.  
  8846.     CSEG $
  8847. dotab:    jmp rskp
  8848.  
  8849.     DSEG $
  8850. delstr    db    ' ',10O,10O,'$'    ;Delete string.
  8851.  
  8852. system    db    '                DEC Rainbow-100$'
  8853.  
  8854. <<< c86xtx.a86 >>>
  8855. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  8856. ;    Tektronix 4170 version - TransEra Corporation
  8857. ;    Robert Raymond, 3707 North Canyon Road, Building 4, Provo, UT 84601
  8858. ; [31c] set default baud to 9600
  8859. ; [31b] Changes made for 4170 port hardware
  8860. ; [31a] Use ansi routines from 86keri.rb
  8861. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  8862. ; [30d] Add SET PORT command, currently unimplemented.
  8863. ; [30c] Isolate all machine dependencies in KERIO.
  8864. ; [30a] Add keyboard DEL key alteration for APC
  8865. ;    RonB, 04/18/84
  8866. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  8867. ; [28e] Switch to local stack on interrupts.
  8868. ;    RonB, 03/28/84
  8869. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  8870. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  8871. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  8872. ;    RonB,03/02/84
  8873. ; [19a] Add XON/XOFF type flow control
  8874. ; [19b]    Clear screen and beginning and end of program.
  8875. ; [19e]    Add PRTBRK to send break to port (Rainbow only)
  8876. ; [19g]    Put in EQU for clock rate for timing loops.
  8877. ;    Rg, 2/84     <Oc.Garland%CU20B@Columbia-20>
  8878. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  8879. ;  [par] Added calls to set parity, strip parity on input if
  8880. ;        other than none parity is called for.
  8881. ;     JD, 2/84
  8882. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  8883. ;  [2]    Add a de-initialization routine for the serial port, to restore
  8884. ;    changed interrupt vectors, etc.
  8885. ;    RonB,12/23/83
  8886. ;  [1]    Add I/O support for the NEC Advanced Personal Computer
  8887. ;    RonB,12/23/83
  8888. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  8889.  
  8890. ; This module contains all the low level communications port I/O
  8891. ; routines.
  8892.  
  8893. ; Here are the I/O routines for the TEK 4170.
  8894.  
  8895.     CSEG $
  8896.  
  8897. ; Clock rate *10 for timing loops    ;[19g]
  8898. clckrt    equ    49        ;[19g]  4.9 Mhz            ;[20b]
  8899.  
  8900. ; Interrupt vector locations, in data segment 0
  8901.  
  8902. mnioff    equ    200h        ;HO_In_Int interrupt offset    ;[31b]
  8903. mniseg    equ    202h        ;HO_In_Int interrupt segment    ;[31b]
  8904.  
  8905. ;
  8906. ; equates for 2661B chip -- host initialization parameters
  8907. ;
  8908.  
  8909. HO_Data    equ    0e0h
  8910. HO_Stat    equ    0e2h
  8911. HO_Mode    equ    0e4h
  8912. HO_Cmd    equ    0e6h
  8913.  
  8914. HOCLKRATE    equ    02h    ;sets async mode, 16x clock on host port
  8915. HOSB2    equ    0c0h    ;two stop bits
  8916. HOSB1    equ    040h    ;one stop bits
  8917. HOEVEN    equ    020h    ;select even parity, not odd parity
  8918. HOPENB    equ    010h    ;enable parity on the host
  8919.  
  8920. HOSTART    equ    037h    ;RTS, DTR set, Rx & Tx enabled, reset errors
  8921. HOBREAK equ    4    ; force break
  8922.  
  8923. HO_Thre    equ    01h    ;one on this indicates thre, 0 is thr busy
  8924. HO_DRdy    equ    02h    ;one indicates data ready, 0 no data
  8925.  
  8926.  
  8927.  
  8928. outlmt    EQU    1000H        ;Number of times to check output status
  8929.                 ; before giving up on send.        ;[20d]
  8930.  
  8931.  
  8932. ; Test if port is ready to send next char.  Returns RSKP if ready.
  8933. ; Trashes dx.
  8934.  
  8935. outwt:    cmp    floctl, floxon    ;are we doing flow-control?    [19a] start
  8936.     jne    outwta        ;no - go on
  8937.     cmp    xofrcv, true    ;are we being held?
  8938.     jne    outwta        ;no - ok go on
  8939.     ret            ;held - say we're busy.    [19a] end
  8940. outwta:    push    ax
  8941.     mov    dx,HO_Stat    ;[31b] begin
  8942.     in    al,dx
  8943.     test    al,HO_Thre    ;transmit holding register empty
  8944.     pop    ax
  8945.     jnz    outwt2
  8946.      ret
  8947. outwt2:    jmp    rskp        ;[31b] end
  8948.  
  8949.  
  8950. ; Output data to port. Trashes DX and prints char in AL.
  8951.  
  8952. outchr:    mov    dx,HO_Data    ;[31b] begin
  8953.     out    dx,al
  8954.                 ; don't ask me why we do this:
  8955.  
  8956.     mov    al,HO_START    ;rts and start scanning
  8957.     out    HO_Cmd,al    
  8958.     ret            ;[31b] end
  8959.  
  8960.  
  8961. ; Output the character in AL, checking first to make sure the port is clear.
  8962.  
  8963. prtout:    call    dopar        ;[par] set parity
  8964.     push    dx
  8965.     push    cx                        ;[20d] begin
  8966.     mov    cx,outlmt
  8967. prtou2:    call    outwt        ;Wait until the port is ready
  8968.      loop    prtou2        ; or too much time has passed.
  8969.      nop
  8970.     call    outchr        ;Output it.
  8971.     pop    cx                        ;[20d] end
  8972.     pop    dx
  8973.     ret
  8974.  
  8975.  
  8976. ; Test if data is available from port.
  8977.  
  8978. instat:    cmp    mnchrn,0    ;Any chars in the buffer?
  8979.     jnz    inst2
  8980.      ret
  8981. inst2:    jmp    rskp
  8982.  
  8983.  
  8984. ; Input data from port.  Preserves all registers and returns char in
  8985. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  8986. ; already there.
  8987.  
  8988. inchr:    push    bx
  8989.     cli            ;Disable interrupts while were are playing.
  8990.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  8991.     mov    bx,mnchop    ;Get the pointer into the buffer.
  8992.     inc    bx        ;Increment to the next char.
  8993.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  8994.     jb    inchr2
  8995.     lea    bx,mnchrs    ;If so wrap around to the start.
  8996. inchr2:    mov    mnchop,bx    ;Save the updated pointer.
  8997.     mov    al,[bx]        ;Get the character.
  8998.     sti            ;All done, we can restore interrupts.
  8999.     pop    bx
  9000.     cmp    parflg,parnon    ;[par] no parity?
  9001.     je    inchr3        ;[par] yup, don't bother stripping
  9002.     and    al,7fh        ;[par] checking parity, strip off
  9003. inchr3:    cmp    floctl, floxon    ;do flow-control?        [19a] start
  9004.     je    inchr4        ;If yes jump
  9005.     ret
  9006. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  9007.     je    inchr5        ;Jump if yes
  9008.     ret
  9009. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  9010.     jb    inchr6        ;yes - jump
  9011.     ret
  9012. inchr6:    push    ax        ;save current character
  9013.     mov    al, xon
  9014.     call    prtout        ;send an XON
  9015.     mov    xofsnt, false    ;turn off the flag
  9016.     pop    ax        ;get back character
  9017.     ret            ;                [19a] end
  9018.  
  9019.  
  9020.  
  9021. mnax    dw    0        ;Storage in CSEG        ;[28e] begin
  9022. mnsp    dw    0        ;  for use by interrupt handler
  9023. mnsseg    dw    0
  9024. mndseg    dw    0
  9025.  
  9026. ; This routine handles the interrupts on input.
  9027.  
  9028. mnint:    cli
  9029.     mov    cs:mnax, ax    ;Save interrupt stack location.
  9030.     mov    ax, sp
  9031.     mov    cs:mnsp, ax
  9032.     mov    ax, ss
  9033.     mov    cs:mnsseg, ax
  9034.     mov    ax, cs:mndseg    ;Switch to our internal stack.
  9035.     mov    ss, ax
  9036.     lea    sp, mnstk
  9037.     push    ds        ;Save all registers.
  9038.     push    es
  9039.     push    bp
  9040.     push    di
  9041.     push    si
  9042.     push    dx
  9043.     push    cx
  9044.     push    bx
  9045.     mov    ds, ax        ;Get our data segment address.
  9046.     call    mnproc        ;Process the character.
  9047.     pop    bx        ;Restore all registers.
  9048.     pop    cx
  9049.     pop    dx
  9050.     pop    si
  9051.     pop    di
  9052.     pop    bp
  9053.     pop    es
  9054.     pop    ds
  9055.     mov    ax, cs:mnsp    ;Restore the original stack.
  9056.     mov    sp, ax
  9057.     mov    ax, cs:mnsseg
  9058.     mov    ss, ax
  9059.     mov    ax, cs:mnax
  9060.     iret            ;Return from the interrupt.    ;[28e] end
  9061.  
  9062.  
  9063. ; This routine (called by MNINT) gets a char from the serial port
  9064. ; and puts it in the ring buffer.
  9065.  
  9066. mnproc:    mov    dx,HO_Stat    
  9067.     in    al,dx        ;Get the port status.        [31b] start
  9068.     test    al,HO_DRdy    ;Is a character waiting?
  9069.     jnz    mnpro2        ;   Yes, go take care of it.
  9070.      ret            ;   No, just a false alarm.
  9071.  
  9072. mnpro2:    mov    dx,HO_Data
  9073.     in    al,dx        ;Read the char.            [31b] end
  9074.     cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  9075.     jne    mnpr2b        ;no - go on
  9076.     cmp    al, xoff    ;is it an XOFF?
  9077.     jne    mnpr2a        ;no - go on
  9078.     mov    xofrcv, true    ;set the flag
  9079.     ret
  9080. mnpr2a:    cmp    al, xon        ;an XON?
  9081.     jne    mnpr2b        ;no
  9082.     mov    xofrcv, false    ;clear the flag
  9083.     ret            ;                [19a] end
  9084. mnpr2b:    cmp    mnchrn,mnchnd    ;Is the buffer full?
  9085.     je    mnperr        ;If so, take care of the error.
  9086.     inc    mnchrn        ;Increment the character count.
  9087.     mov    bx,mnchip    ;Get the buffer input pointer.
  9088.     inc    bx        ;Increment it.
  9089.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  9090.     jb    mnpro3
  9091.     lea    bx,mnchrs    ;Yes, point to the start again.
  9092. mnpro3:    mov    mnchip,bx    ;Save the pointer.
  9093.     mov    [bx],al        ;Put the character in the buffer.
  9094.     cmp    floctl, floxon    ;do flow-control?        [19a] start
  9095.     je    mnpro4        ;If yes jump
  9096.     ret
  9097. mnpro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  9098.     jnz    mnpro5
  9099.     ret            ;return if we have
  9100. mnpro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  9101.     ja    mnpro6        ;yes - jump
  9102.     ret
  9103. mnpro6:    mov    al, xoff
  9104.     call    prtout        ;send an XOFF
  9105.     mov    xofsnt, true    ;set the flag
  9106.     ret            ;                [19a] End
  9107.  
  9108. mnperr:    ret            ;Just return on an error for now.
  9109.  
  9110.  
  9111. ; prtbrk - send a break        ;                [31b] start
  9112.  
  9113. prtbrk:
  9114.     mov    dx,HO_Cmd    ;break goes to command port
  9115.     mov    al,HO_START+HO_BREAK    ;add break to normal command
  9116.     out    dx,al
  9117.     mov    cx, 25000    ;sit for a while
  9118. prtbk1:    loop    prtbk1
  9119.     mov    al,HO_START    ;normal command,RTS & DTR high, Rx & Tx enabled
  9120.     out    dx,al        ;return to normal setting
  9121.     ret
  9122.  
  9123.  
  9124. ; serini - This routine initializes all devices that need it.
  9125. ;       Called at the start of the program.
  9126.  
  9127. serini:    cmp    mninit,0FFh    ; must only do this initialization once
  9128.     je    serin2
  9129.     mov    mninit,0FFh
  9130.     call    ansmod        ; switch from tek mode to ansi mode
  9131.  
  9132.     push    es
  9133. ;code could be added here 
  9134. ;to tell the interrupt controller to diable host interrupt
  9135.     mov    ax,ds        ;save data segment in cseg
  9136.     mov    cs:mndseg,ax    ;   for use by the interrupt handler
  9137.  
  9138.     mov    ax,0        ;point to zero page to replace
  9139.     mov    es,ax        ;the sio interrupt vector
  9140.     mov    ax,es:.mniseg    ;after first saving the current vector
  9141.     mov    mnxseg,ax
  9142.     mov    ax,es:.mnioff
  9143.     mov    mnxoff,ax
  9144.     cli
  9145.     mov    ax,cs
  9146.     mov    es:.mniseg,ax
  9147.     mov    ax,offset mnint
  9148.     mov    es:.mnioff,ax
  9149.     sti
  9150.  
  9151.     call    stmode        ;set mode & baud to defaults
  9152.     call    stbaud
  9153.  
  9154.                 ;enable transmission of data
  9155.     mov    al,HOSTART    ;DTR high, Rx & Tx enabled, reset error
  9156.     out    HO_Cmd,al
  9157.  
  9158.     in    al,HO_Data    ;dummy read to clear buffer
  9159.  
  9160. ;code could be added here 
  9161. ;to tell the interrupt controller to re-enable host interrupt
  9162.     mov    dx,0ebh
  9163.     mov    al,24h            ;turn on host read interrupt
  9164.     out    dx,al                        ;[31b] end
  9165.  
  9166.     pop    es
  9167.  
  9168. serin2:    ret
  9169.  
  9170.  
  9171. ; serfin - this routine is used to "undo" what serini has done, called
  9172. ;       just before exiting back to cp/m.
  9173.  
  9174. serfin:
  9175.     call    clrscr        ;[19b] clear screen    ;[30c]
  9176.  
  9177.     cmp    mninit,0FFh    ;check if initialization has been done
  9178.     jne    serfn2        ;if not, don't de-initialize
  9179.     mov    mninit,0
  9180.  
  9181.     push    es
  9182.  
  9183.     cli
  9184. ;code could be added here to assure the interrupt controller
  9185. ;is restored to the state is was in when kermit started
  9186.     mov    ax,0
  9187.     mov    es,ax
  9188.     mov    ax,mnxseg    ;restore sio interrupt vector
  9189.     mov    es:.mniseg,ax
  9190.     mov    ax,mnxoff
  9191.     mov    es:.mnioff,ax
  9192.     sti
  9193.  
  9194.     pop    es
  9195.  
  9196. serfn2:    ret
  9197.  
  9198.  
  9199. ; This routine clears the serial port input buffer.  It is called to
  9200. ; clear out excess NAKs that can result from server mode operation.
  9201.  
  9202. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  9203.     mov    mnchip, OFFSET mnchrs-1+mnchnd ;Reset input pointer.
  9204.     mov    mnchop, OFFSET mnchrs-1+mnchnd ;Reset output pointer.
  9205.     ret
  9206.  
  9207. ; set the parity, number of data bits, and number of stop bits
  9208.  
  9209. stmode:    mov    dx,HO_Cmd                    ;[31b] start
  9210.     mov    al,0        ;reset 
  9211.     out    dx,al    
  9212.     in    al,dx        ;reset mode1/2 sequencer
  9213.     mov    dx,HO_Mode
  9214.     mov    al,HOCLKRATE    ;init async mode, 16x baud, no parity
  9215.     add    al,HOSB1    ;1 stop bit
  9216.     add    al,0ch        ;8 data bits
  9217.     out    dx,al                        ;[31b] end
  9218.     ret
  9219.  
  9220.  
  9221. ; set the baud rate
  9222.  
  9223. stbaud:    mov    dx,HO_Cmd                    ;[31b] start
  9224.     in    al,dx        ;reset mode1/2 sequencer
  9225.     mov    dx,HO_Mode
  9226.     in    al,dx        ;get mode1 register
  9227.  
  9228.                 ; can the next 4 lines be skipped? 
  9229.  
  9230.     mov    ah,al        ;save it
  9231.     in    al,dx        ;get mode2 register to reset sequence
  9232.     mov    al,ah        ; write back old contents of mode 1
  9233.     out    dx,al
  9234.                 ; next out will set mode 2 - baud rate
  9235.  
  9236.     mov    al,mnbaud    ;get the baud rate information
  9237.     cmp    al,15        ;check for valid range (0-15)
  9238.     ja    stb02
  9239.     or    al, 70h        ;internal baud clock, 16x
  9240.     out    dx,al                        ;[31b] end
  9241. stb02:    ret
  9242.  
  9243.     dseg $
  9244.  
  9245. ;    Serial port default parameters
  9246.  
  9247. mnbaud    db    0dh        ;9600 baud  [31c]
  9248.  
  9249. mninit    db    0        ;set to 0FFh if initialization has been done
  9250. mnxseg    dw    0        ;system host interrupt vector
  9251. mnxoff    dw    0
  9252.  
  9253. mnchnd    equ    512        ;Size of circular buffer.
  9254. mnchrs    rb    mnchnd        ;Circular character buffer for input.
  9255. mnchip    dw    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  9256. mnchop    dw    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  9257. mnchrn    dw    0        ;Number of chars in the buffer.
  9258.  
  9259. mntrg1    equ    128        ;[19a] Low trigger point for Auto XON/XOFF
  9260. mntrg2    equ    384        ;[19a] High trigger point for Auto XON/XOFF
  9261.  
  9262. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  9263. xofsnt    db    0        ;[19a] set if XOFF was sent
  9264. xofrcv    db    0        ;[19a] set if XOFF was recieved
  9265.  
  9266.     rw    32        ;Interrupt stack        ;[28e]
  9267. mnstk    dw    0        ;bottom of stack        ;[28e]
  9268.  
  9269.     CSEG $
  9270.  
  9271. ; The following routines do the SET and SHOW for the machine dependent
  9272. ; features of Kermit.  At present there are only two:  baud rate setting
  9273. ; and port selection.
  9274.  
  9275. ;    This is the SET BAUD rate subcommand
  9276.  
  9277. bdset:    lea    dx, bdtab
  9278.     lea    bx, bdhlp
  9279.     mov    ah, cmkey
  9280.     call    comnd
  9281.      jmp    r
  9282.     mov    temp1, bx
  9283.     mov    ah, cmcfm
  9284.     call    comnd        ;Get a confirm.
  9285.      jmp    r        ; Didn't get a confirm.
  9286.     mov    bx, temp1
  9287.     mov    mnbaud, bl    ;Set the baud rate table index.
  9288.     call    stbaud
  9289.     jmp    rskp
  9290.  
  9291. ;    This is the SET PORT subcommand (not implemented in TEK)
  9292.  
  9293. prtset:    mov    ah, cmcfm
  9294.     call    comnd        ;Get a confirm.
  9295.      jmp    $+3        ; Didn't get a confirm.
  9296.     lea    dx, infms6    ;Tell user it's not implemented
  9297.     call    tcrmsg
  9298.     jmp    rskp
  9299.  
  9300.  
  9301. ; The following procedures implement the SHOW command for the system
  9302. ; dependent features of baud rate and port selection.
  9303.  
  9304. shobd:    lea    dx, bdst    ;Baud rate string.
  9305.     call    tcrmsg
  9306.     mov    al, mnbaud    ;Print the keyword corresponding to the
  9307.     lea    bx, bdtab    ;   current value of mnbaud.
  9308.     call    tabprt
  9309.     ret
  9310.  
  9311. shoprt:    ret            ;Port selection not implemented.
  9312.  
  9313.  
  9314.     DSEG $
  9315.  
  9316. bdtab    db    16        ; 16 entries        ;[31d] begin
  9317.     db    3,'110$'
  9318.     dw    0003H
  9319.     db    4,'1200$'
  9320.     dw    0008H
  9321.     db    3,'135$'
  9322.     dw    0004H
  9323.     db    3,'150$'
  9324.     dw    0005H
  9325.     db    4,'1800$'
  9326.     dw    0009H
  9327.     db    5,'19200$'
  9328.     dw    000EH
  9329.     db    4,'2000$'
  9330.     dw    000AH
  9331.     db    4,'2400$'
  9332.     dw    000BH
  9333.     db    3,'300$'
  9334.     dw    0006H
  9335.     db    5,'38400$'
  9336.     dw    000FH
  9337.     db    2,'45$'
  9338.     dw    0000H
  9339.     db    4,'4800$'
  9340.     dw    000CH
  9341.     db    2,'50$'
  9342.     dw    0001H
  9343.     db    3,'600$'
  9344.     dw    0007H
  9345.     db    2,'75$'
  9346.     dw    0002H
  9347.     db    4,'9600$'
  9348.     dw    000DH
  9349.  
  9350. bdhlp    db    cr,lf,'    45    75    135    300    1200    2000    4800    19200'
  9351.     db    cr,lf,'    50    110    150    600    1800    2400    9600    38400$'
  9352.                                   ;[31d] end
  9353. ;[31a] begin -- to end of file
  9354.  
  9355. ; The following routines do screen control.  These are isolated here because
  9356. ; the screen control sequences are likely to vary from system to system, even
  9357. ; though the Rainbow and APC (the only systems implemented to date) both use
  9358. ; ANSI sequences for this purpose.
  9359.  
  9360.     CSEG $
  9361.  
  9362. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  9363.  
  9364. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  9365.     mov    cl, 10
  9366.     mov    al, [bx]    ;Get row value
  9367.     sub    ah, ah
  9368.     div    cl        ;units digit in ah, tens digit in al
  9369.     add    ax, '00'    ;Convert both to ASCII
  9370.     mov    word ptr anspos+2, ax    ;Save reversed (al,ah)
  9371.     mov    al, 1[bx]    ;Do same for column value
  9372.     sub    ah, ah
  9373.     div    cl
  9374.     add    ax, '00'
  9375.     mov    word ptr anspos+5, ax
  9376.     lea    dx, anspos    ;Print cursor positioning string.
  9377.     call    tmsg
  9378.     ret
  9379.  
  9380. ; CLRSCR - homes cursor and clears screen.
  9381.  
  9382. clrscr:    lea    dx, anscls
  9383.     call    tmsg
  9384.     ret
  9385.  
  9386. ; CLRLIN - clears from cursor to end of line.
  9387.  
  9388. clrlin:    mov    dl, cr        ;Go to beginning of line
  9389.     call    bout
  9390. clreol:    lea    dx, ansclr    ;Clear from cursor to end of line
  9391.     call    tmsg
  9392.     ret
  9393.  
  9394. ; REVON - turns on reverse video display
  9395.  
  9396. revon:    lea    dx, ansron
  9397.     call    tmsg
  9398.     ret
  9399.  
  9400. ; REVOFF - turns off reverse video display
  9401.  
  9402. revoff:    lea    dx, ansrof
  9403.     call    tmsg
  9404.     ret
  9405.  
  9406. ; BLDON - turns on bold (highlighted) display
  9407.  
  9408. bldon:    lea    dx, ansbon
  9409.     call    tmsg
  9410.     ret
  9411.  
  9412. ; BLDOFF - turns off bold (highlighted) display
  9413.  
  9414. bldoff:    lea    dx, ansbof
  9415.     call    tmsg
  9416.     ret
  9417.  
  9418. ; ANSMOD - enters ANSI mode from Tek mode
  9419.  
  9420. ansmod:    lea    dx, ansion
  9421.     call    tmsg
  9422.     ret
  9423.  
  9424.     DSEG $
  9425.  
  9426. anspos    db    esc,'[00;00H$'        ;Position cursor to row and column
  9427. anscls    db    esc,'[H',esc,'[J$'    ;Home cursor and clear screen
  9428. ansclr    db    esc,'[K$'        ;Clear from cursor to end of line
  9429. ansron    db    esc,'[7m$'        ;Turn on reverse video
  9430. ansrof    db    esc,'[m$'        ;Turn off reverse video
  9431. ansbon    db    esc,'[1m$'        ;Turn on bold (highlight) display
  9432. ansbof    db    esc,'[m$'        ;Turn off bold display
  9433. ansion    db    esc,'%!1$'        ;SelectCode Ansi mode
  9434.  
  9435. ; Here tab expansion is done if necessary.  If not, just return retskp.
  9436.  
  9437.     CSEG $
  9438. dotab:    jmp rskp
  9439.  
  9440.     DSEG $
  9441. delstr    db    ' ',10O,10O,'$'    ;Delete string.
  9442.  
  9443. system    db    '                 Tektronix 4170$'
  9444. <<< c86xv9.a86 >>>
  9445. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  9446. ; [35] Modify the Rainbow 100 version to handle the Victor 9000/Sirius
  9447. ; Eric Zurcher, Utah State University, Logan, Utah (REHABIV@USU.BITNET)
  9448. ; 07/07/86
  9449. ; * * * * * * * * * * * * * * *  version 2.8  * * * * * * * * * * * * * * *
  9450. ; [34] Insert milli-second wait-loop for Break-timing - label MSWAIT:
  9451. ; [33] Fix printer on hanging system problem by letting CP/M handle the
  9452. ;       interrupts from the 7201 that we don't care about.  Thanks to
  9453. ;       Paul Ford, U. of Chicago Graduate School of Business
  9454. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  9455. ; [30d] Add SET PORT command, currently unimplemented.
  9456. ; [30c] Isolate all machine dependencies in KERIO.
  9457. ;       RonB, 04/18/84
  9458. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  9459. ; [28e] Switch to local stack on interrupts.
  9460. ;       RonB, 03/28/84
  9461. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  9462. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  9463. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  9464. ;       RonB,03/02/84
  9465. ; [19a] Add XON/XOFF type flow control
  9466. ; [19b] Clear screen and beginning and end of program.
  9467. ; [19e] Add PRTBRK to send break to port (Rainbow only)
  9468. ; [19g] Put in EQU for clock rate for timing loops.
  9469. ;       Rg, 2/84        <Oc.Garland%CU20B@Columbia-20>
  9470. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  9471. ;  [par] Added calls to set parity, strip parity on input if
  9472. ;       other than none parity is called for.
  9473. ;        JD, 2/84
  9474. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  9475. ;  [2]  Add a de-initialization routine for the serial port, to restore
  9476. ;       changed interrupt vectors, etc.
  9477. ;       RonB,12/23/83
  9478. ;  [1]  Add I/O support for the NEC Advanced Personal Computer
  9479. ;       RonB,12/23/83
  9480. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  9481.  
  9482. ; This module contains all the low level communications port I/O
  9483. ; routines.
  9484.  
  9485. ; The following is the I/O code for the Victor 9000.
  9486.  
  9487.                 CSEG $
  9488.  
  9489. ; Clock rate *10 for timing loops       ;[19g]
  9490. clckrt  equ     48              ;[19g]  4.8 Mhz
  9491.  
  9492. ;[35a] begin
  9493. ; Offsets of memory-mapped Victor "ports" within segment 0E000H
  9494. mdmseg  EQU     0E000H          ;Segement for memory-mapped 7201 of Victor
  9495. mnstat  EQU     042H            ;Status port A.
  9496. mndata  EQU     040H            ;Data port A.
  9497. mnctl1  EQU     000H            ;Interrupt controller.
  9498. mnctl2  EQU     001H            ;Interrupt controller.
  9499. mnclk1  EQU     023H            ;For setting baud rate
  9500. mnclk2  EQU     020H            ;      "
  9501. ;[35a] end
  9502.  
  9503. ; Interrupt vector locations.  These are all in data segment 0.
  9504.  
  9505. mnoff   EQU     84H             ;Main data port interrupt routine offset.  [35]
  9506. mnseg   EQU     86H             ;Main data port interrupt routine segment. [35]
  9507.  
  9508. output  EQU     04H             ;Bit for output ready.
  9509. input   EQU     01H             ;Bit for input ready.
  9510.  
  9511. outlmt  EQU     1000H           ;Number of times to check output status
  9512.                                 ; before giving up on send.             ;[20d]
  9513.  
  9514.  
  9515. ; Input data from port.  Preserves all ACs and returns char in
  9516. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  9517. ; already there.
  9518.  
  9519. inchr:  push    bx
  9520.         cli                     ;Disable interrupts while were are playing.
  9521.         dec     mnchrn          ;Decrement the number of chars in the buffer.
  9522.         mov     bx, mnchop      ;Get the pointer into the buffer.
  9523.         inc     bx              ;Increment to the next char.
  9524.         cmp     bx, offset mnchrs+mnchnd ;Past the end?
  9525.         jb      inchr2
  9526.         mov     bx, offset mnchrs ;If so wrap around to the start.
  9527. inchr2: mov     mnchop, bx      ;Save the updated pointer.
  9528.         mov     al, [bx]        ;Get the character.
  9529.         sti                     ;All done, we can restore interrupts.
  9530.         pop     bx
  9531.         cmp     parflg,parnon   ;[par] no parity?
  9532.         je      inchr3          ;[par] yup, don't bother stripping
  9533.         and     al,7fh          ;[par] checking parity, strip off
  9534. inchr3: cmp     floctl, floxon  ; do flow control?              [19a] start
  9535.         je      inchr4          ;If yes jump
  9536.         ret
  9537. inchr4: cmp     xofsnt, true    ;Have we sent an XOFF
  9538.         je      inchr5          ;Jump if yes
  9539.         ret
  9540. inchr5: cmp     mnchrn, mntrg1  ;Under the low trigger point?
  9541.         jb      inchr6          ;yes - jump
  9542.         ret
  9543. inchr6: push    ax              ;save current character
  9544.         mov     al, xon
  9545.         call    prtout          ;send an XON
  9546.         mov     xofsnt, false   ;turn off the flag
  9547.         pop     ax              ;get back character
  9548.         ret                     ;                               [19a] end
  9549.  
  9550.  
  9551. ; Output data to port. Trashes DX and prints char in AL.
  9552.  
  9553. ;[35b] begin
  9554. outchr: push    es
  9555.         push    si
  9556.         mov     dx, mdmseg
  9557.         mov     es, dx
  9558.         mov     si, mndata
  9559.         mov     es:[si], al
  9560.         pop     si
  9561.         pop     es
  9562.         ret
  9563.  ;[35b] end
  9564.  
  9565. ; Test if data is available from port.
  9566.  
  9567. instat: cmp     mnchrn, 0       ;Any chars in the buffer?
  9568.         jnz     inst2
  9569.          ret
  9570. inst2:  jmp     rskp
  9571.  
  9572.  
  9573. ; Test if port is ready to send next char.  Returns RETSKP if ready.
  9574. ; Trashes dx.
  9575.  
  9576. outwt:  cmp     floctl, floxon  ;are we doing flow-control?     [19a] start
  9577.         jne     outwta          ;no - go on
  9578.         cmp     xofrcv, true    ;are we being held?
  9579.         jne     outwta          ;no - ok go on
  9580.         ret                     ;held - say we're busy. [19a] end
  9581. outwta: push    ax
  9582. ;[35c] begin
  9583.         push    es
  9584.         push    si
  9585.         mov     dx, mdmseg
  9586.         mov     es, dx
  9587.         mov     si, mnstat
  9588.         mov     al, es:[si]
  9589.         test    al, output
  9590.         pop     si
  9591.         pop     es
  9592. ;[35c] end
  9593.         pop     ax
  9594.         jnz     outwt2
  9595.          ret
  9596. outwt2: jmp     rskp
  9597.  
  9598.  
  9599. ; Output the character, checking first to make sure the port is clear.
  9600.  
  9601. prtout: call    dopar           ;[par]
  9602.         push    dx
  9603.         push    cx                                              ;[20d] begin
  9604.         mov     cx,outlmt
  9605. prtou2: call    outwt           ;Wait until the port is ready
  9606.          loop   prtou2          ; or too much time has passed.
  9607.          nop
  9608.         call    outchr          ;Output it.
  9609.         pop     cx                                              ;[20d] end
  9610.         pop     dx
  9611.         ret
  9612.  
  9613.  
  9614. mnax    dw      0               ;Storage in CSEG                ;[28e] begin
  9615. mnsp    dw      0               ;  for use by interrupt handler
  9616. mnsseg  dw      0
  9617. mndseg  dw      0
  9618.  
  9619. ; This routine handles the interrupts on input.
  9620.  
  9621. mnint:  cli
  9622.         mov     cs:mnax, ax     ;Save interrupt stack location.
  9623.         mov     ax, sp
  9624.         mov     cs:mnsp, ax
  9625.         mov     ax, ss
  9626.         mov     cs:mnsseg, ax
  9627.         mov     ax, cs:mndseg   ;Switch to our internal stack.
  9628.         mov     ss, ax
  9629.         mov     sp, offset mnstk
  9630.         push    ds              ;Save all registers.
  9631.         push    es
  9632.         push    bp
  9633.         push    di
  9634.         push    si
  9635.         push    dx
  9636.         push    cx
  9637.         push    bx
  9638.         mov     ds, ax
  9639.         mov     dx, mdmseg      ;[35]
  9640.         mov     es, dx          ;[35]
  9641.         call    mnproc          ;Process the character.
  9642. ;[35d] begin
  9643.         mov     si, mnctl1      ;Point to the interrupt controller
  9644.         mov     al, 061H
  9645.         mov     es:[si], al     ;Re-enable interrupts
  9646.         mov     si, mnstat      ;Get the status port.
  9647.         mov     al, 38H
  9648.         mov     es:[si], al     ;Tell the port we finished with the interrupt.
  9649. ;[35d] end
  9650.         pop     bx              ;Restore all registers.
  9651.         pop     cx
  9652.         pop     dx
  9653.         pop     si
  9654.         pop     di
  9655.         pop     bp
  9656.         pop     es
  9657.         pop     ds
  9658.         mov     ax, cs:mnsp     ;Restore the original stack.
  9659.         mov     sp, ax
  9660.         mov     ax, cs:mnsseg
  9661.         mov     ss, ax
  9662.         mov     ax, cs:mnax
  9663.         iret                    ;Return from the interrupt.     ;[28e] end
  9664.  
  9665.  
  9666. ; This routine (called by MNINT) gets a char from the main port
  9667. ; and puts it in the infamous circular buffer.
  9668.  
  9669. mnproc: mov     si, mnstat      ;[35] Check port status
  9670.         mov     al, es:[si]     ;[35]
  9671.         test    al, input       ;Any there?
  9672.         jnz     mnpro2          ;Yup, go take care of it.
  9673.  
  9674. ;[33] Begin addition
  9675. ; If not a received character, simulate an interrupt transferring
  9676. ; control to the CPM routine. Let it handle worrisome things like
  9677. ; someone turning on the printer.
  9678. ;[35e] begin
  9679. ;Unlike the Rainbow, Victor CP/M does not normally handle these interrupts.
  9680. ;Let's just return, lest we wreak havoc...
  9681. ;        pushf                  ; Save flags, like an int.
  9682. ;        callf dword ptr mnoldo ; Call CPM's routine.
  9683. ;[35e] end
  9684.          ret                    ; Now back to MNINT.
  9685.  
  9686. ;[33] End addition
  9687.  
  9688. ;[35f] begin
  9689. mnpro2: mov     al, 1           ;Point to RR1.
  9690.         mov     es:[si], al
  9691.         mov     al, es:[si]     ;Read RR1.
  9692.         mov     ah, al          ;Save it.
  9693.         mov     al, 30H         ;Reset any errors.
  9694.         mov     es:[si], al
  9695.         mov     si, mndata
  9696.         mov     al, es:[si]     ;Read the char.
  9697. ;[35f] end
  9698.         cmp     floctl, floxon  ;are we doing flow-control ?    [19a] start
  9699.         jne     mnpr2b          ;no - go on
  9700.         cmp     al, xoff        ;is it an XOFF?
  9701.         jne     mnpr2a          ;no - go on
  9702.         mov     xofrcv, true    ;set the flag
  9703.         ret
  9704. mnpr2a: cmp     al, xon         ;an XON?
  9705.         jne     mnpr2b          ;no
  9706.         mov     xofrcv, false   ;clear the flag
  9707.         ret                     ;                               [19a] end
  9708. mnpr2b: cmp     mnchrn, mnchnd  ;Is the buffer full?
  9709.         je      mnperr          ;If so, take care of the error.
  9710.         inc     mnchrn          ;Increment the character count.
  9711.         mov     bx, mnchip      ;Get the buffer input pointer.
  9712.         inc     bx              ;Increment it.
  9713.         cmp     bx, offset mnchrs+mnchnd ;Past the end?
  9714.         jb      mnpro3
  9715.         mov     bx, offset mnchrs ;Yes, point to the start again.
  9716. mnpro3: mov     mnchip, bx      ;Save the pointer.
  9717.         mov     [bx], al        ;Put the character in the buffer.
  9718.         cmp     floctl, floxon  ;do flow control?               [19a] start
  9719.         je      mnpro4          ;If yes jump
  9720.         ret
  9721. mnpro4: cmp     xofsnt, true    ;Have we sent an XOFF
  9722.         jnz     mnpro5
  9723.         ret                     ;return if we have
  9724. mnpro5: cmp     mnchrn, mntrg2  ;Past the High trigger point?
  9725.         ja      mnpro6          ;yes - jump
  9726.         ret
  9727. mnpro6: mov     al, xoff
  9728.         call    prtout          ;send an XOFF
  9729.         mov     xofsnt, true    ;set the flag
  9730.         ret                     ;                               [19a] End
  9731.  
  9732. mnperr: ret                     ;Just return on an error for now.
  9733.  
  9734.  
  9735. ; prtbrk - send a break         ;                               [19e] start
  9736.  
  9737. prtbrk:                         ;
  9738. ;[35g] begin
  9739.         push    es              ;save registers
  9740.         push    si
  9741.         mov     dx, mdmseg      ;Point to "port" segment
  9742.         mov     es, dx
  9743.         mov     si, mnstat      ;status reg. address for port
  9744.         mov     al, 15H         ;select reg. 5
  9745.         mov     es:[si], al
  9746.         mov     al, 0FAH        ;8 bits, TX, Break, RTS, & DTR
  9747.         mov     es:[si], al     ;Turn Break on
  9748.         mov     ax, 275         ;.. for 275 millisec's          [34]
  9749.         call    mswait          ;                               [34]
  9750.         mov     al, 15H         ;select reg. 5
  9751.         mov     es:[si], al
  9752.         mov     al, 0EAH        ;same as above without Break
  9753.         mov     es:[si], al     ;turn it off
  9754.         pop     si
  9755.         pop     es
  9756.         ret                     ;                                [19e] end
  9757. ;[35g] end
  9758. mswait:                         ;                               [34] start
  9759.         mov     cx,5*clckrt     ; inner loop count for 1 millisec.
  9760. mswai1:
  9761.         sub     cx,1            ;** inner loop takes 20 clock cycles
  9762.         jnz     mswai1          ;**
  9763.         dec     ax              ; outer loop counter
  9764.         jnz     mswait          ; wait another millisecond
  9765.         ret                     ;                               [34] end
  9766. ;
  9767. ; Init the 7201 for 8 bits, no parity, and 1 stop bit.
  9768.  
  9769. serini:  ;call ansmod ;Switch from VT52 to ANSI mode ;[30c][35] removed
  9770.  
  9771.         cmp     mninit, 0FFH
  9772.         je      serin2
  9773.         mov     mninit, 0FFH
  9774.         mov     ax, ds
  9775.         mov     cs:mndseg, ax   ;Save the data segment somewhere in CSEG.
  9776.         push    ds              ;Save the data segment.
  9777.         mov     ax, 0
  9778.         mov     ds, ax          ;We want DSEG = 0.
  9779.         cli                     ;Turn off interrupts.
  9780.         mov     bx, .mnoff      ;[33] Get original interrupt offset.
  9781.         mov     es, .mnseg      ;[33] Get original interrupt segment.
  9782.         mov     ax, offset mnint;Point to the interrupt routine offset.
  9783.         mov     .mnoff, ax      ;Put in the main port interrupt offset addr.
  9784.         mov     ax, cs          ;Get our code segment.
  9785.         mov     .mnseg, ax      ;Put in the main port interrupt segment addr.
  9786.         pop     ds              ;Restore data segment.
  9787.  
  9788.         mov     mnoldo, bx      ;[33] Stash original serial interrupt offset.
  9789.         mov     mnolds, es      ;[33] Stash original segment.
  9790.  
  9791. ;[35h] begin
  9792.         push    es              ;Save registers
  9793.         push    si
  9794.         mov     dx, mdmseg      ;Get "port" segment
  9795.         mov     es, dx
  9796.         mov     si, mnstat      ;Point to status port.
  9797.         mov     al, 18H         ;Reset the port.
  9798.         mov     es:[si], al
  9799.         mov     al, 14H         ;Select register 4.
  9800.         mov     es:[si], al
  9801.         mov     al, 48H         ;16X clock, 1.5 stop bits, no parity.
  9802.         mov     es:[si], al
  9803.         mov     al, 13H         ;Select register 3.
  9804.         mov     es:[si], al
  9805.         mov     al, 0C1H        ;8 bits/char, RX enable.
  9806.         mov     es:[si], al
  9807.         mov     al, 15H         ;Select register 5.
  9808.         mov     es:[si], al
  9809.         mov     al, 0EAH        ;8 bits/char, TX enable, RTS and DTR.
  9810.         mov     es:[si], al
  9811.         mov     al, 11H         ;Select register 1.
  9812.         mov     es:[si], al
  9813.         mov     al, 18H         ;Enable interrupt processing on this port.
  9814.         mov     es:[si], al
  9815.         mov     si, mnctl2      ;point to 8259 interrput controller
  9816.         mov     al,es:[si]
  9817.         and     al, 0FDH        ;Enable interrupt processing
  9818.         mov     es:[si], al
  9819.         mov     si, mnctl1
  9820.         mov     al, 061H
  9821.         mov     es:[si], al     ;Clears outstanding requests
  9822.         sti                     ;Restore interrupts.
  9823.         pop     si
  9824.         pop     es
  9825.         call    stbaud
  9826. serin2: ret
  9827.  
  9828. serfin:
  9829.         call    clrscr          ;[19b] clear screen             ;[30c]
  9830.         cmp     mninit, 0FFH
  9831.         jne     serfn2
  9832.         mov     mninit, 0
  9833.         cli
  9834.         push    es
  9835.         push    si
  9836.         mov     dx, mdmseg      ;Victor
  9837.         mov     es, dx          ;Victor
  9838.         mov     si, mnctl2      ;point to 8259 interrput controller
  9839.         mov     al,es:[si]      ;Enable interrupt processing
  9840.         or      al, 02H
  9841.         mov     es:[si], al
  9842.         mov     si, mnstat
  9843.         mov     al, 01
  9844.         mov     es:[si], al
  9845.         mov     al, 00
  9846.         mov     es:[si], al
  9847.         mov     ax, mnoldo      ;[33] Get original interrupt offset.
  9848.         mov     es, mnolds      ;[33] Get original interrupt segment.
  9849.         push    ds              ;Save the data segment.
  9850.         mov     dx, 0
  9851.         mov     ds, dx          ;We want DSEG = 0.
  9852.         mov     .mnoff, ax      ;Put in the main port interrupt offset addr.
  9853.         mov     .mnseg, es      ;Put in the main port interrupt segment addr.
  9854.         pop     ds              ;Restore data segment.
  9855.         pop     si
  9856.         pop     es
  9857.         sti
  9858.  
  9859. serfn2: ret
  9860. ;[35h] end
  9861.  
  9862. ; This routine clears the serial port input buffer.  It is called to
  9863. ; clear out excess NAKs that can result from server mode operation.
  9864.  
  9865. cfibf:  mov     mnchrn, 0       ;Say no characters in the buffer.
  9866.         mov     mnchip, offset mnchrs-1+mnchnd ;Reset input pointer.
  9867.         mov     mnchop, offset mnchrs-1+mnchnd ;Reset output pointer.
  9868.         ret
  9869.  
  9870.         DSEG $
  9871.  
  9872. mnchnd  equ     256             ;[19a] Size of circular buffer.
  9873. mntrg1  equ     64              ;[19a] Low trigger point for Auto XON/XOFF
  9874. mntrg2  equ     192             ;[19a] High trigger point for Auto XON/XOFF
  9875.  
  9876. floctl  db      1               ;[19a] If floctl=floxon do Auto XON/XOFF logic
  9877. xofsnt  db      0               ;[19a] set if XOFF was sent
  9878. xofrcv  db      0               ;[19a] set if XOFF was recieved
  9879.  
  9880. mnchrn  DW      0               ;[19a] Number of chars in the buffer.
  9881. mnchrs  RB      mnchnd          ;Circular character buffer for input.
  9882. mnchip  DW      mnchrs-1+mnchnd ;Input pointer into character buffer.
  9883. mnchop  DW      mnchrs-1+mnchnd ;Output pointer into character buffer.
  9884.  
  9885. mnoldo  RW      1               ;[33] CPM's 7201 interrupt vector offset
  9886. mnolds  RW      1               ;[33] and segment.
  9887. mninit  DB      0               ;set to 0FFH if initialization has been done
  9888.  
  9889.         rw      32              ;Interrupt stack                ;[28e]
  9890. mnstk   dw      0               ;bottom of stack                ;[28e]
  9891.  
  9892.  
  9893.         CSEG $
  9894.  
  9895. ; The following routines do the SET and SHOW for the machine dependent
  9896. ; features of Kermit.  At present there are only two:  baud rate setting
  9897. ; and port selection.
  9898.  
  9899. ;[35i] begin
  9900. ;       This is the SET BAUD rate subcommand
  9901.  
  9902. ; set the baud rate
  9903.  
  9904. stbaud: mov     al,mnbaud       ;get the baud rate information
  9905.         cmp     al,15           ;check for valid range (0-15)
  9906.         ja      stb02
  9907.         mov     bx,offset baudtb;get address of baud rate table
  9908.         add     al,al           ;compute word offset
  9909.         mov     ah,0
  9910.         add     bx,ax
  9911.         push    es
  9912.         push    si
  9913.         mov     ax, mdmseg
  9914.         mov     es, ax
  9915.         mov     si, mnclk1
  9916.         mov     al, 036H
  9917.         mov     es:[si], al
  9918.         mov     si, mnclk2
  9919.         mov     ax, [bx]
  9920.         mov     es:[si], al
  9921.         mov     es:[si], ah
  9922.         pop     si
  9923.         pop     es
  9924. stb02:  ret
  9925.  
  9926.         dseg $
  9927.  
  9928. ;       Serial port default parameters
  9929.  
  9930. mnbaud  db      13              ;9600 baud
  9931.  
  9932. ;       Interval Timer values (assumes 16x baud rate mode)
  9933.  
  9934. baudtb  dw      061Bh           ;50 baud        0
  9935.         dw      0412h           ;75 baud        1
  9936.         dw      02C6h           ;110 baud       2
  9937.         dw      0245h           ;135 baud       3
  9938.         dw      0209h           ;150 baud       4
  9939.         dw      0104h           ;300 baud       5
  9940.         dw      0082h           ;600 baud       6
  9941.         dw      0041h           ;1200 baud      7
  9942.         dw      002Bh           ;1800 baud      8
  9943.         dw      0027h           ;2000 baud      9
  9944.         dw      0021h           ;2400 baud      10
  9945.         dw      0016h           ;3600 baud      11
  9946.         dw      0010h           ;4800 baud      12
  9947.         dw      0008h           ;9600 baud      13
  9948.         dw      0004h           ;19200 baud     14
  9949.         dw      0002h           ;38400 baud     15
  9950.  
  9951.         CSEG $
  9952.  
  9953. bdset:  mov     dx, offset bdtab
  9954.         mov     bx, offset bdhlp
  9955.         mov     ah, cmkey
  9956.         call    comnd
  9957.          jmp    r
  9958.         mov     temp1, bx
  9959.         mov     ah, cmcfm
  9960.         call    comnd           ;Get a confirm.
  9961.          jmp    r               ; Didn't get a confirm.
  9962.         mov     bx, temp1
  9963.         mov     mnbaud, bl      ;Set the baud rate table index.
  9964.         call    stbaud
  9965.         jmp     rskp
  9966. ;[35i] end
  9967.  
  9968. ;This is the SET PORT subcommand (not implemented in Victor at this time)
  9969.  
  9970. prtset: mov     ah, cmcfm
  9971.         call    comnd           ;Get a confirm.
  9972.          jmp    $+3             ; Didn't get a confirm.
  9973.         mov     dx, offset infms6 ;Tell user it's not implemented
  9974.         call    tcrmsg
  9975.         jmp     rskp
  9976.  
  9977.  
  9978. ; The following procedures implement the SHOW command for the system
  9979. ; dependent features of baud rate and port selection.
  9980.  
  9981. ;[35j] begin
  9982. shobd:  mov     dx, offset bdst ;Baud rate string.
  9983.         call    tcrmsg
  9984.         mov     al, mnbaud      ;Print the keyword corresponding to the
  9985.         mov     bx, offset bdtab ; current value of mnbaud.
  9986.         call    tabprt
  9987.         ret
  9988.  
  9989.         DSEG $
  9990.  
  9991. bdtab   db      16              ;Thirteen entries               ;[6] begin
  9992.         db      3,'110$'
  9993.         dw      0002H
  9994.         db      4,'1200$'
  9995.         dw      0007H
  9996.         db      3,'135$'
  9997.         dw      0003H
  9998.         db      3,'150$'
  9999.         dw      0004H
  10000.         db      4,'1800$'
  10001.         dw      0008H
  10002.         db      5,'19200$'
  10003.         dw      000EH
  10004.         db      4,'2000$'
  10005.         dw      0009H
  10006.         db      4,'2400$'
  10007.         dw      000AH
  10008.         db      3,'300$'
  10009.         dw      0005H
  10010.         db      4,'3600$'
  10011.         dw      000BH
  10012.         db      5,'38400$'
  10013.         dw      000FH
  10014.         db      4,'4800$'
  10015.         dw      000CH
  10016.         db      2,'50$'
  10017.         dw      0000H
  10018.         db      3,'600$'
  10019.         dw      0006H
  10020.         db      2,'75$'
  10021.         dw      0001H
  10022.         db      4,'9600$'
  10023.         dw      000DH                                           ;[6] end
  10024.  
  10025. bdhlp:
  10026. db cr,lf,'      50      110     150     600     1800    2400    4800    19200'
  10027. db cr,lf,'      75      135     300     1200    2000    3600    9600    38400$'
  10028.  
  10029.         CSEG $
  10030. ;[35j] end
  10031. shoprt: ret                     ;Port selection not implemented.
  10032.  
  10033.  
  10034.  
  10035.  
  10036. ; The following routines do screen control.  These are isolated here because
  10037. ; the screen control sequences are likely to vary from system to system, even
  10038. ; though the Rainbow and APC (the only systems implemented to date) both use
  10039. ; ANSI sequences for this purpose.
  10040.  
  10041.         CSEG $
  10042.  
  10043. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  10044.  
  10045. ;[35k] begin
  10046. poscur:
  10047.         mov     si, dx
  10048.         mov     dx, offset anspos ; move prefix string
  10049.         mov     cl, prstr
  10050.         int     bdos
  10051.         xor     dx,dx
  10052.         mov     dl, [si]
  10053.         add     dl,01FH         ; this is the row
  10054.         mov     cl,dconio       ; no checking please
  10055.         int     bdos
  10056.         mov     dl, 1[si]
  10057.         add     dl,01FH         ; this is the column
  10058.         mov     cl,dconio
  10059.         int     bdos
  10060.         ret
  10061. ;[35k] end
  10062.  
  10063. ; CLRSCR - homes cursor and clears screen.
  10064.  
  10065. clrscr: mov     dx, offset anscls
  10066.         call    tmsg
  10067.         ret
  10068.  
  10069. ; CLRLIN - clears from cursor to end of line.
  10070.  
  10071. clrlin: mov     dl, cr          ;Go to beginning of line
  10072.         call    bout
  10073. clreol: mov     dx, offset ansclr ;Clear from cursor to end of line
  10074.         call    tmsg
  10075.         ret
  10076.  
  10077. ; REVON - turns on reverse video display
  10078.  
  10079. revon:  mov     dx, offset ansron
  10080.         call    tmsg
  10081.         ret
  10082.  
  10083. ; REVOFF - turns off reverse video display
  10084.  
  10085. revoff: mov     dx, offset ansrof
  10086.         call    tmsg
  10087.         ret
  10088.  
  10089. ; BLDON - turns on bold (highlighted) display
  10090.  
  10091. bldon:  mov     dx, offset ansbon
  10092.         call    tmsg
  10093.         ret
  10094.  
  10095. ; BLDOFF - turns off bold (highlighted) display
  10096.  
  10097. bldoff: mov     dx, offset ansbof
  10098.         call    tmsg
  10099.         ret
  10100.  
  10101. ; ANSMOD - enters ANSI mode from VT52 mode
  10102.  
  10103. ;[35l] begin    ; Just keep Victor in VT52 (actually Heath-19) mode
  10104. ansmod: ;mov    dx, offset ansion
  10105.         ;call   tmsg
  10106.         ret
  10107.  
  10108.         DSEG $
  10109.  
  10110. anspos  db      esc,'Y$'                ;Position cursor to row and column
  10111. anscls  db      esc,'H',esc,'J$'        ;Home cursor and clear screen
  10112. ansclr  db      esc,'K$'                ;Clear from cursor to end of line
  10113. ansron  db      esc,'p$'                ;Turn on reverse video
  10114. ansrof  db      esc,'q$'                ;Turn off reverse video
  10115. ansbon  db      esc,'($'                ;Turn on bold (highlight) display
  10116. ansbof  db      esc,')$'                ;Turn off bold display
  10117. ansion  db      '$'                     ;Enter ANSI mode
  10118. ;[35l] end
  10119.  
  10120. ; Here tab expansion is done if necessary.  If not, just return retskp.
  10121.  
  10122.         CSEG $
  10123. dotab:  jmp rskp
  10124.  
  10125.         DSEG $
  10126. delstr  db      ' ',10O,10O,'$' ;Delete string.
  10127.  
  10128. system  db      '                  Victor 9000$' ;[35]
  10129.