home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols100 / vol170 / comm725a.asm < prev    next >
Encoding:
Assembly Source File  |  1994-07-13  |  50.8 KB  |  2,111 lines

  1.  
  2. ; (comm725a.asm)
  3.  
  4. ; process primary option and process/validate secondary options (set
  5. ; 'uartctlb' to last declared operating mode.  usr remembers mode.)
  6.  
  7. PROCOPT    LXI    D,FCB+1
  8.     LDAX    D
  9.     STA    OPTION        ;primary option stored in 'option'
  10.     CPI    ' '        ;check if initial command-line option requested
  11.     RZ            ;blank --> no 'comm7.com' attribute entered
  12. OPTLP    INX    D
  13.     LDAX    D        ; 1st secondary option into a-reg
  14.     CPI    ' '        ;delimiter for filename-beginning flags..
  15.     JZ    END$OPT        ;..end of secondary option string. 
  16.     LXI    H,OPTBL
  17.     MVI    B,OPTBE-OPTBL    ; (test each character over table length)
  18. OPTCK    CMP    M
  19.     JNZ    OPTNO
  20.  
  21.      IF    PMMI OR MM100
  22.     CPI    'O'        ;originate mode?
  23.     MOV    C,A        ;preserve a-reg for 'a' test
  24.     LDA    ORIGMOD        ;get word structure and..
  25.     JZ    OPTCK2        ;branch if not
  26.     MOV    A,C        ;get a-reg for character test
  27.     CPI    'A'        ;answer mode?
  28.     JNZ    OPTCK3        ;no, neither mode requested.
  29.     LDA    ANSWMOD        ;yes, do..
  30.      ENDIF            ;pmmi or mm100
  31.  
  32.      IF    PMMI
  33. OPTCK2    STA    UARTCTLB    ;..store here.
  34.      ENDIF            ;pmmi
  35.  
  36.      IF    MM100
  37. OPTCK2    STA    MODCTLB
  38.      ENDIF            ;mm100
  39.  
  40. OPTCK3    MVI    M,0        ;zero-out options requested in table
  41.     JMP    OPTLP        ;loop 'till done
  42.     
  43. OPTNO    INX    H        ;see if..
  44.     DCR    B        ;..end..
  45.     JNZ    OPTCK        ;..of table string length.
  46.     JMP    BADCMD        ;option not valid, show message.
  47.  
  48. END$OPT    LDA    VSEEFLG        ;if 'viewing', suppress..
  49.     ORA    A        ;..all..
  50.     JNZ    SW3        ;..but..
  51.     STA    QFLG        ;..ascii-file text.
  52. SW3    LDA    OPTION        ;check primary option
  53.     CPI    'T'        ;terminal mode
  54.     RZ
  55.     CPI    'E'        ;return if echo (host computer) option
  56.     RZ
  57.     CPI    'M'        ;return to menu
  58.     RZ
  59.  
  60.      IF    PMMI OR MM100 OR US100
  61.     CPI    'C'        ;go to call (telephone) library or..
  62.     RZ
  63.     CPI    'D'        ;..disconnect the phone line
  64.     RZ
  65.      ENDIF            ;pmmi or mm100 or us100
  66.  
  67.     CPI    'S'        ;send a file
  68.     JZ    CKFILE
  69.     CPI    'R'        ;receive a file
  70.     JNZ    BADCMD
  71.     LDA    BATCHFLG    ;if multi-file mode, receive..
  72.     ORA    A        ;..option doesn't need filename.
  73.     RZ
  74.  
  75. ; enter command again if no filename specified
  76.  
  77. CKFILE    LDA    FCB2+1        ;option needs filename, check..
  78.     CPI    ' '        ;..to see if name exists.
  79.     RNZ            ;if none, request to do everything over.
  80. REENTER    CALL    ILPRTQ
  81.     DB    ESC,ETEOP,'Filename required (S/R fn.ft), '
  82.     DB    '<RETURN> continues: ',BELL,0
  83.     LXI    D,CMDBUF
  84.     CALL    INBUF        ;wait for keyboard input
  85.     LDA    CMDBUF+1    ;return to command line..
  86.     ORA    A        ;..if only..
  87.     JZ    MENU        ;..a <return> entered.
  88.     JMP    DOOPT        ;loop back 'till good response entered
  89.  
  90. ; t e r m i n a l   m o d e
  91.  
  92. ; terminal routine allowing memory save
  93.  
  94. DSKSAVE    LDA    DIRECTB        ;load direct bios flag
  95.     STA    DTYPE        ;and copy it into tempoary register
  96.     LDA    LSTRETF        ;was printer on before..
  97.     ORA    A        ;..entering command mode?
  98.     JZ    NOLIST        ;no, then branch. 
  99.     XRA    A        ;zero resets terminal return..
  100.     STA    LSTRETF        ;..flag for next time and sets..
  101.     STA    LISTFLG        ;..printer to list characters.
  102. NOLIST    CALL    CROSSCK        ;verify option compatibility
  103.     LDA    NFILFLG        ;if file open go..
  104.     ORA    A        ;..directly..
  105.     JZ    TERM        ;..to 'term' loop.
  106.     LXI    H,FCB        ;filename moved from fcb2 --> fcb by 'movefcb'
  107.     MVI    B,11        ;make sure..
  108. CKOKLP    INX    H        ;..no..
  109.     MOV    A,M        ;..wildcards..
  110.     CPI    '?'        ;..in filename.
  111.     JZ    NGMSG        ;if so, say so.
  112.     DCR    B
  113.     JNZ    CKOKLP        ;if not, check..
  114.     LDA    FCB+1        ;..if a filename..
  115.     CPI    ' '        ;..was declared.
  116.     JNZ    GOODNM        ;yes, name seems okay.
  117.     JMP    TERM        ; (no file being saved --> terminal mode)
  118.  
  119. CROSSCK    LDA    BATCHFLG    ;make sure..
  120.     ORA    A
  121.     JZ    BADCMD
  122.     LDA    QFLG        ;..primary and secondary options..
  123.     ORA    A
  124.     JZ    BADCMD
  125.     RET            ;..are fully compatible.
  126.  
  127. NGMSG    CALL    ILPRT
  128.     DB    ESC,ETEOP,BELL,' ++ WILDCARDS not allowed ++ ',0
  129.     JMP    MSGREAD
  130.  
  131. GOODNM    CALL    ERASFIL        ;see if file already exists.  erase?
  132.     JNZ    MENU        ;no, go to cmd mode.
  133.     CALL    MOVE2        ;shifts 1st 12 bytes of fcb to fcb3..
  134.     LXI    D,FCB3        ;..(fcb2 previously shifted to fcb).
  135.     MVI    C,MAKE        ;create and..
  136.     CALL    BDOS
  137.     LXI    D,FCB3
  138.     MVI    C,OPEN        ;..open new file.
  139.     CALL    BDOS
  140.     LXI    H,BOTTRAM    ;start address for file-save
  141.     SHLD    HLSAVE        ; 'hlsave' --> last byte into file.
  142.     XRA    A        ;zero'd so a file can be toggled for save..
  143.     STA    NFILFLG     ;..and 't' used for terminal return.
  144.  
  145. ; main terminal loop with file-save/transfer, output to printer,
  146. ; 'softkey' and other capabilities
  147.  
  148. TERM    CALL    LISTST        ;character for printer?
  149.     CALL    STAT        ;console keypress?
  150.     JZ    TERML        ;no, check line.
  151.     CALL    KEYIN        ;get char from kbd
  152.     MOV    B,A        ;save and..
  153.     LDA    CMDFLG        ;ignore next (ctrl) char locally..
  154.     ORA    A            ;..if zero flag not set.
  155.     MVI    A,0        ;clear for..
  156.     STA    CMDFLG        ;..next time.
  157.     MOV    A,B        ;..restore.
  158.     JZ    CHROUT        ;send character (control code out)
  159.  
  160. ; check for in-line terminal commands
  161.  
  162.      IF    TELE25TH    ;others don't have 25th line
  163.     PUSH    PSW        ;save a-reg and flags
  164.     CALL    ILPRT
  165.     DB    ESC,'h',0    ;turn off 25th line
  166.     POP    PSW
  167.      ENDIF            ;tele25th
  168.  
  169.      IF    ZENITH
  170.     PUSH    PSW
  171.     CALL    ILPRT
  172.     DB    ESC,'x1',0    ;turn off 25th line
  173.     POP    PSW
  174.      ENDIF            ;zenith
  175.  
  176.     MOV    B,A
  177.     LDA    CMDCHR        ; get command character
  178.     CMP    B        ; check it out
  179.     MOV    A,B
  180.     JZ    CHROUT1
  181.     CALL    UCASE        ;convert to uppercase
  182.     CPI    'E'        ;  e = exit terminal mode
  183.     JZ    ALERT        ;      (see if save memory file is wanted)
  184.     CPI    'T'        ;  t = transfer a file
  185.     CZ    TRANSFER
  186.     JZ    TERM
  187.  
  188.      IF    PMMI OR MM100
  189.     CPI    '@'-40h        ; ^@ = send a break (<break> on 'televideo'
  190.     JZ    BREAK        ;      equal to a ^@)
  191.      ENDIF            ;pmmi or mm100
  192.  
  193.      IF    PMMI OR MM100 OR US100
  194.     CPI    'D'        ;  d = disconnect and return to command mode
  195.     JZ    DISCON1        
  196.     CPI    'B'        ;  b = change baud rate
  197.     CZ    NEWBAUD        ;get baudrate request (returns with..
  198.     JZ    TERML        ;..flags set)
  199.      ENDIF            ;pmmi or mm100 or us100
  200.  
  201.      IF    SOFTKEY
  202.     CPI    'R'        ;  r = display softkey table
  203.     CZ    REVIEW        ;      yes, show current string-storage.
  204.     JZ    TERM        ;      continue looping
  205.     CPI    '0'        ;  0 - 9 are soft keys
  206.     JC    CHROUT        ;      less than 0
  207.     CPI    '9'+1        ;
  208.     CC    SOFTCMD        ;yes, we have a soft key
  209.     JZ    TERM        ;      then return to term loop
  210.      ENDIF            ;softkey
  211.  
  212.     CPI    'P'        ;  p = test for printer list
  213.     JNZ    SW6        ;no, by-pass toggle.
  214.     LDA    LISTFLG
  215.     STA    LSTRETF        ;set permanent toggle 'not'
  216.     CMA
  217.     STA    LISTFLG        ;set tempoary toggle
  218.     JMP    BELLOUT        ;audible printer toggle
  219.  
  220. SW6    CPI    'S'        ;  s = "colon-save"
  221.     JNZ    CHROUT        ;no toggle, it's a char to send.
  222.     LDA    NFILFLG        ;save not allowed if flag true
  223.     ORA    A
  224.     JNZ    TERML        ;check line for another character
  225.     MVI    A,TRUE
  226.     STA    ALERTFG        ; 1st time thru announces a save
  227.     LDA    SAVEFLG
  228.     CMA
  229.     STA    SAVEFLG        ;toggled by savechr
  230. BELLOUT    LDA    BELLFLG        ;do you want noisy bells?
  231.     ORA    A
  232.     JZ    TERML        ;no, so don't beep at me
  233.     MVI    A,BELL        ;otherwise, start/stop printer/file-save..
  234.     CALL    TYPE        ;..with audible toggle.
  235.     JMP    TERML        ;ck for another char from remote
  236.  
  237. ; exit character storage
  238.  
  239. EXTFLG    MVI    A,TRUE
  240.     STA    CMDFLG
  241.     JMP    TERML
  242.  
  243. ; character-out through modem port
  244.  
  245. COMMAND    MVI    A,TRUE
  246.     STA    CMDFLG        ;command next
  247.  
  248.      IF    TELE25TH OR ZENITH
  249.     MVI    A,255        ;turn off printer for a bit
  250.     STA    LISTFLG
  251.      ENDIF            ;tele25th or zenith
  252.  
  253.      IF    TELE25TH
  254.     CALL    ILPRT
  255.     DB    ESC,'f'        ;turn on 25th line
  256.      ENDIF
  257.  
  258.      IF    ZENITH
  259.     CALL    ILPRT
  260.     DB    ESC,'j',ESC,'x1',ESC,'Y8 '    ;turn on 25th line
  261.      ENDIF
  262.  
  263.      IF    TELE25TH OR ZENITH
  264. ;        '----5---10---15---20---25---30---35---40'
  265.     DB    'B>aud | D>isc | E>xit | P>rint | R>eview'
  266.     DB    ' | S>ave | T>ransfer | <break> | (0-9)'
  267.      ENDIF            ;tele25th or zenith
  268.  
  269.      IF    TELE25TH    ;restore cursor
  270.     DB    CR,ESC,'g',0
  271.      ENDIF            ;tele25th
  272.  
  273.      IF    ZENITH
  274.     DB    ESC,'Y  ',ESC,'k',0    ;restore cursor
  275.      ENDIF            ;zenith
  276.  
  277.      IF    TELE25TH OR ZENITH
  278.     LDA    LSTRETF        ;get permanent list flag
  279.     CMA            ;flip it
  280.     STA    LISTFLG        ;and restore the printer's condition
  281.      ENDIF            ;tele25th or zenith
  282.  
  283.     JMP    TERML        ;print message on 25th line
  284.  
  285. ; character-out through modem port -- full/half-duplex option from 'sel'
  286.  
  287. CHROUT    MOV    B,A
  288.     LDA    CMDCHR        ;get command character
  289.     CMP    B        ;check it out
  290.     MOV    A,B
  291.     JZ    COMMAND        ;it was a command, so show menu
  292. CHROUT1    CALL    OUTCHAR
  293.     MOV    B,A
  294.     LDA    HALFDUP        ;if half-duplex..
  295.     ORA    A
  296.     MOV    A,B
  297.     CNZ    TYPE        ;..show character locally.
  298.  
  299. ; character input from telephone line -- filter out control codes option
  300.  
  301. TERML    CALL    INSTAT
  302.     JNZ    TERM
  303.     CALL    INCHAR
  304.     ANI    7FH        ;strip parity
  305.     JZ    TERM        ;don't process nulls
  306.     MOV    B,A
  307.     LDA    FILBYTE        ;filter control codes out?
  308.     ORA    A
  309.     MOV    A,B
  310.     JZ    TERML1        ;no, process them.
  311.     CPI    ' '
  312.     JNC    TERML1
  313.     CPI    BS        ;print backspace,..
  314.     JZ    TERML1
  315.     CPI    HT        ;..horizontal tab..
  316.     JZ    TERML1
  317.     CPI    CR        ;..carriage return..
  318.     JZ    TERML1
  319.     CPI    LF        ;..and line feed.
  320.     JNZ    TERM
  321. TERML1    CALL    TYPE        ;print locally
  322.     MOV    B,A        ; save line character and..
  323.     LDA    SAVEFLG
  324.     ORA    A
  325.     JZ    TERM        ;branch if no-file-save
  326.     LHLD    HLSAVE        ;get address of last saved character
  327.     MOV    M,B        ;last character copied into ram, pointed..
  328.     INX    H        ;..to by 'hlsave-1'.
  329.     SHLD    HLSAVE
  330.     MOV    A,B        ; ..put back here.
  331.     CPI    LF        ; lf?  if yes,..
  332.     JNZ    NOCOLON        ;..type ":" after each line feed..
  333.     MVI    A,':'        ;..when memory save active.  (don't put into..
  334.     CALL    TYPEQ        ;..colon-save file or send to printer.)
  335. NOCOLON    LDA    SAVCCP
  336.     ORA    A
  337.     LDA    BDOS+2        ;check to see if..
  338.     JZ    SUB1
  339.     SUI    CCP+RING    ;..page below 'ccp+ring'..
  340. SUB1    DCR    A        ;..or 'bdos' has been..
  341.     CMP    H        ;..reached and disksave is needed.
  342.     JNZ    TERM        ;no, continue looping.  else fall-thru.
  343.  
  344. ; ramsave:  routine automatically stops remote computer when colon-save buffer
  345. ; is full and writing to disk is required.  after 'xoff' is sent, up to 'rbuf'
  346. ; characters are saved, if necessary, waiting for remote computer to stop
  347. ; sending.  if remote never stops, characters are lost during auto-write to
  348. ; disk.
  349.  
  350. RAMSAVE    MVI    A,XOFF        ;send a <ctrl-s>, 'xoff', to stop..
  351.     CALL    OUTCHAR        ;..remote computer sending.
  352.     MVI    D,RBUF        ;initialize for maximum ram buffer length
  353.     CALL    INMODEM        ;get characters received after sending 'xoff'
  354.     PUSH    D        ;protect d-reg counter
  355.     CALL    WRTDSK        ;write 'colon-save' memory to disk
  356.     POP    D        ;counter restore
  357.     LXI    H,BOTTRAM    ;reset 'colon-save' memory and..
  358.     LXI    B,LASTBYTE    ;..buffer areas.
  359. TORAMLP INR    D        ;bump 'till..
  360.     MOV    A,D        ;..at..
  361.     CPI    RBUF+1        ;..maximum.
  362.     JZ    CTRLQ        ;branch if at limit
  363.     LDAX    B        ;get character from buffer and..
  364.     MOV    M,A        ;..put in 'colon-save' memory area.
  365.     INX    H        ;ready for..
  366.     INX    B        ;..another character.
  367.     CALL    TYPE        ;show locally
  368.     JMP    TORAMLP        ;continue 'till d-reg tops out
  369.  
  370. CTRLQ    SHLD    HLSAVE        ; 'last character + one' position
  371.     MVI    A,XON        ;restart remote computer
  372.     CALL    OUTCHAR
  373.     JMP    TERM        ;continue terminal looping
  374.  
  375. INMODEM    LXI    B,LASTBYTE    ;set pointer to buffer begin-address
  376.     PUSH    B
  377. INMDM    LXI    B,104*MHZ    ;constand for 100 msec wait
  378. DELAYLP    CALL    INSTAT        ;character from line?  if yes, store..
  379.     JZ    GETBYTE        ;..received character after 'xoff' sent.
  380.     DCX    B
  381.     MOV    A,B
  382.     ORA    C
  383.     JNZ    DELAYLP        ;loop 'till time-out
  384.     POP    B        ;restore stack
  385.     RET            ;return if remote computer stops sending
  386.  
  387. GETBYTE    CALL    INCHAR
  388.     POP    B        ;get pointer to 'lastbyte' buffer and..
  389.     STAX    B        ;..store character there.
  390.     INX    B        ;increment pointer and..
  391.     PUSH    B        ;..save if a next time thru occurs.
  392.     DCR    D        ;bump character count.  at zero yet?
  393.     JNZ    INMDM        ;get more, if not.
  394.     POP    B        ;restore stack
  395.     RET            ;return if buffer full
  396.  
  397. ; routine to send 'break' (null) code -- used by to reboot some remotes
  398.  
  399.      IF    PMMI
  400. BREAK    LDA    MODCTLB        ;get modem control byte
  401.     ANI    BRK        ;set break bit low (active)
  402.      ENDIF            ;pmmi
  403.  
  404.      IF    MM100 OR US100
  405. BREAK    LDA    MODCTLB        ;get modem control byte
  406.     ORI    BRK        ;set break bit hi (active)
  407.      ENDIF            ;mm100 or us100
  408.  
  409.      IF    PMMI OR MM100 OR US100
  410.     CALL    OUTCTR2         ;send to modem
  411.     LXI    B,104*MHZ       ;constant for 100 msec wait
  412. BRKLP    CALL    INSTAT
  413.     JZ    FETCHEM
  414.     DCX    B
  415.     MOV    A,B
  416.     ORA    C
  417.     JNZ    BRKLP
  418.     LDA    MODCTLB        ;restore previous..
  419.     CALL    OUTCTR2        ;..modem condition if time-out.
  420.     LHLD    HLSAVE        ;last address written if colon-save active
  421.     LDA    SAVCCP
  422.     ORA    A
  423.     LDA    BDOS+2        ;check to see if..
  424.     JZ    SUB2
  425.     SUI    CCP+RING    ;..page below 'ccp+ring'..
  426. SUB2    DCR    A        ;..or 'bdos' has been..
  427.     CMP    H        ;..reached and disksave is needed.
  428.     JNZ    TERM        ;if a-reg not equal to h-reg continue
  429.     CALL    ILPRT        ;if equal, show msg and continue.
  430.     DB    CR,LF,'++ File buffer full ++',CR,LF,BELL,0
  431.     JMP    TERM
  432.  
  433. FETCHEM    CALL    INCHAR
  434.     ORA    A        ;check for nulls (cpi 0) but..
  435.     JZ    BRKLP        ;..don't process them.
  436.     ANI    7FH        ;strip parity
  437.     CALL    TYPE
  438.     MOV    B,A        ;copy line character here..
  439.     LDA    SAVEFLG
  440.     ORA    A
  441.     JZ    BRKLP
  442.     LHLD    HLSAVE        ;get last address of ram-saved character
  443.     MOV    M,B        ;..and here..
  444.     INX    H        ; update hl-pair, char by char..
  445.     SHLD    HLSAVE        ; ..and store in 'hlsave'.
  446.     MOV    A,B        ;..and put back here.
  447.     CPI    LF        ;lf?
  448.     JNZ    BRKLP        ;yes, type ":" after each line feed..
  449.     MVI    A,':'        ;..when memory-save active.
  450.     CALL    TYPE
  451.     JMP    BRKLP
  452.      ENDIF            ;pmmi or mm100 or us100
  453.  
  454. ; write ram to disk
  455.  
  456. ; determine # of records in file
  457.  
  458. RAMDISK    LHLD    HLSAVE        ;get 'colon-save' file-end address and..
  459.     MVI    M,EOFCHAR    ;..put cp/m terminator there.  then..
  460.     INX    H        ;..lengthen thru one record,  making..
  461.     LXI    D,127        ;..sure file-bytes..
  462.     DAD    D        ;..aren't chopped.
  463. WRTDSK    LXI    D,-(BOTTRAM)    ;subtract by adding 2's complement to..
  464.     DAD    D        ;..'hlsave' --> total bytes in ram-file.
  465.     MVI    B,7+1        ;set to divide total by 128 and return..
  466.     CALL    SHIFTLP        ;..with # of records in hl-pair.
  467.     LDA    WRT$FLG        ;allow zero-length if..
  468.     ORA    A        ;..at least..
  469.     JZ    NEXTWRT        ;..one buffer full..
  470.     XRA    A        ;..has been written.
  471.     STA    WRT$FLG
  472.  
  473. ; write records to disk
  474.  
  475.     LXI    D,BOTTRAM
  476.     LDAX    D        ;don't save zero-length..
  477.     CPI    EOFCHAR        ;..file.  delete..
  478.     JZ    ZEROMSG        ;..filename from directory.
  479. NEXTWRT    MVI    C,SETDMA
  480.     CALL    BDOSRET
  481.     PUSH    D
  482.     LXI    D,FCB3
  483.     MVI    C,WRITE
  484.     CALL    BDOSRET
  485.     POP    D
  486.     XCHG            ; (if you understand these..
  487.     PUSH    D
  488.     LXI    D,128        ;..lines, consider..
  489.     DAD    D
  490.     POP    D        ;..yourself..
  491.     XCHG
  492.     DCX    H        ;..a cp/m assembly..
  493.     MOV    A,H
  494.     ORA    L        ;..language programmer.)
  495.     JNZ    NEXTWRT        ;branch if not done
  496.     RET
  497.  
  498. ; zero-length file announcement and filename deletion
  499.  
  500. ZEROMSG CALL    ILPRT
  501.     DB    CR,ESC,ETEOP,'---> Zero-length file deleted ',0
  502.     MVI    B,20
  503.     CALL    TIMER
  504.     JMP    DELNEWF
  505.  
  506. ; close file at fcb3 -- bdos call with all registers saved and restored
  507.  
  508. CLOSE3    LXI    D,FCB3
  509.     MVI    C,CLOSE
  510. BDOSRET    PUSH    PSW
  511.     PUSH    B
  512.     PUSH    D
  513.     PUSH    H
  514. BDOSV    CALL    BDOS
  515.     POP    H
  516.     POP    D
  517.     POP    B
  518.     POP    PSW
  519.     RET
  520.  
  521. ; file transfer subroutine -- called with <ctrl-t> from terminal
  522. ; routine.  transfer cancelled while sending by using <ctrl-x>.
  523. ; choice of blind or protocol-send into receiving line-editor.  file
  524. ; may be transfered while another is being saved.
  525.  
  526. ; transfer fcb set-up
  527.  
  528. TRANSFER LXI    H,FCB4        ;hl-pair points to fcb..
  529.      CALL    INITFCB         ;..to be intialized.
  530.  
  531. ; process name of file (fn.ft) to transfer
  532.  
  533. GETFNFT    MVI    A,TRUE        ;turn off printer for a bit
  534.     STA    LISTFLG
  535.     CALL    ILPRT
  536.  
  537.      IF    TELE25TH
  538.     DB    ESC,'g',ESC,'f'
  539.      ENDIF            ;tele25th
  540.  
  541.      IF    NOT TELE25TH
  542.     DB    CR,LF
  543.      ENDIF            ;not tele25th
  544.  
  545.     DB    'Enter filename to transfer, '
  546.     DB    '<return> to terminal mode: ',0
  547.     LXI    D,CMDBUF
  548.     CALL    INBUF
  549.     LDA    CMDBUF+2    ;was file entered?
  550.     CPI    ' '
  551.     JZ    RETURN
  552.  
  553. ; set-up to transfer file bytes
  554.  
  555.     LXI    D,CMDBUF    ;move filename to..
  556.     LXI    H,FCB4        ;..fcb4..
  557.     CALL    CMDLINE        ;..and..
  558.     LXI    D,FCB4        ;..open file..
  559.     MVI    C,OPEN        ;..for..
  560.     CALL    BDOS        ;..reading.
  561.     INR    A        ; 0ffh --> 0 if no file found
  562.     JNZ    CONTIN0        ;continue, file found.
  563. TRANSL1 CALL    ILPRT
  564.     DB    CR,LF,'++ Unable to find file ++',CR,LF,0
  565.     JMP    RETURN
  566.  
  567. ; choice of blind-send or protocol-send
  568.  
  569. CONTIN0    CALL    ILPRT
  570.  
  571.      IF    TELE25TH
  572.     DB    ESC,'f'
  573.      ENDIF        ;tele25th
  574.  
  575.      IF    NOT TELE25TH
  576.     DB    CR,LF
  577.      ENDIF        ;not tele25th
  578.  
  579.     DB    'Delay between characters/lines sent?  (Y/N): ',0
  580.     CALL    RESPOND
  581.     CPI    'N'
  582.     JZ    CONTIN
  583.     XRA    A        ;zero line-editor flag
  584.     STA    LNEDFLG
  585.  
  586. CONTIN     IF    TELE25TH
  587.     CALL    ILPRT        ;turn off 25th line before printer goes on
  588.     DB    ESC,'h',0
  589.      ENDIF            ;tele25th
  590.  
  591.     LDA    LSTRETF        ;get printer flag
  592.     CMA            ;flip it
  593.     STA    LISTFLG
  594.     CALL    ILPRT        ;a fresh line before..
  595.     DB    CR,LF,LF,0    ;..reading file..
  596.     LXI    D,TBUF        ;..and away we go.
  597.     MVI    C,SETDMA
  598.     CALL    BDOS
  599.  
  600. ; get 128-byte data record
  601.  
  602. READMR    LXI    D,FCB4
  603.     MVI    C,READ        ;read 128 bytes
  604.     CALL    BDOS
  605.     ORA    A        ; eof?
  606.     JZ    SENDMR        ;no, branch.
  607. RETURNS    CALL    ILPRT        ;yes, show msg:
  608.     DB    CR,LF,'---> Transfer completed',CR,LF,BELL,0
  609.     JMP    RETURN
  610.  
  611. SENDMR    CALL    SEND80C
  612.     CPI    EOFCHAR        ; eof?
  613.     JZ    RETURNS        ;return if finished
  614.     CPI    CAN        ; (^x) cancellation?
  615.     JNZ    READMR        ;loop till 'eof' or <ctrl-x>
  616.     CALL    ILPRT
  617.     DB    CR,LF,'++ Transfer cancelled ++',CR,LF,0
  618.  
  619. RETURN
  620.      IF    TELE25TH    ;force printer off, turn off 25th line.
  621.     MVI    A,TRUE        ;turn off printer if it was on
  622.     STA    LISTFLG
  623.     CALL    ILPRT        ;turn off 25th line
  624.     DB    ESC,'h',0
  625.      ENDIF            ;tele25th
  626.  
  627.     LDA    LSTRETF        ;make sure printer is in right state
  628.     CMA
  629.     STA    LISTFLG
  630.     MVI    A,TRUE        ;sequential transfer default condition
  631.     STA    LNEDFLG
  632.     XRA    A        ;return with zero flag set
  633.     RET            ;xfer finished, continue loop thru 'term'.
  634.  
  635. ; send 128-byte record
  636.  
  637. SEND80C    MVI    A,80H        ;send 128 bytes
  638.     STA    CHARCNT        ;count characters
  639.     LXI    H,TBUF        ;points to cp/m 'tbuf'
  640. SENPLHR    LDA    LNEDFLG        ;is it line-editor prompted mode?
  641.     ORA    A
  642.     JZ    EDIT        ;yes..
  643.     MOV    A,M        ;..no, straight blind-send mode.
  644.     CALL    MODOUT
  645.     RZ            ;to 'sendmr' for finish
  646. GETNEXT    CALL    STAT        ;test for keypress
  647.     JZ    SKIP12
  648.     CALL    KEYIN
  649.     CPI    CAN        ; (^x) cancellation character
  650.     RZ            ;to readmr for cancel and exit
  651. SKIP12    INX    H        ;next character to send pointed to by..
  652.     LDA    CHARCNT
  653.     DCR    A        ;..bumping hl-pair, count in charcnt.
  654.     STA    CHARCNT
  655.     JNZ    SENPLHR        ;get next character
  656.     RET            ;to 'cpi eofchar' in 'sendmr' for 128 bytes
  657.  
  658. ; blind-send to line-editor (dumb protocol)
  659. ; sends at 85 words per minute and delays at end-of-line
  660.  
  661.      IF    DUMB
  662. EDIT    MOV    A,M
  663.     CPI    LF
  664.     JZ    PROMPT
  665.     CALL    MODOUT
  666.     RZ
  667.     LXI    B,375*MHZ    ;delay..
  668. CHRLOOP    DCX    B
  669.     MOV    A,B        ;..between..
  670.     ORA    C
  671.     JNZ    CHRLOOP        ;..characters.
  672.     JMP    GETNEXT        ;get next to send
  673.  
  674. PROMPT    CALL    MODOUT        ;send 'lf' to remote
  675.     MVI    B,7        ;delay at line-end after sending a 'cr'
  676.     CALL    TIMER        ; 100 msec in b-reg
  677.     JMP    GETNEXT
  678.  
  679. ; blind-send to remote (no protocol)
  680.  
  681. MODOUT    PUSH    PSW        ;save send-character in a-reg 
  682.     PUSH    H        ;protect 'tbuf' pointer
  683.     CALL    LISTST        ;character for printer?
  684.     POP    H
  685. MODLP    CALL    OUTSTAT        ;test if ready to send
  686.     JNZ    MODLP        ; (out at baudrate)
  687.     POP    PSW        ;character back into a-reg
  688.     CALL    OUTCHAR        ;char out modem
  689.     CPI    EOFCHAR        ;if (^z) don't send to..
  690.     RZ            ;..terminal, just return.  if..
  691.     JMP    TYPE        ;..not, print locally.
  692.      ENDIF            ;dumb
  693.  
  694. ; (experimental)
  695. ; smart-protocol send/receive to line-editor (receives echo before next
  696. ; send).  checks for bell near, and cursor return at, end-of-line.  waits
  697. ; for remote prompt(s) to be received before continuing send.
  698.  
  699.      IF    NOT DUMB
  700. EDIT    MOV    A,M        ;char to send into a-reg
  701.     CPI    CR        ;end of line?
  702.     JZ    WAITFOR        ;yes, get delay, else..
  703.     CALL    MODOUT2        ;..send chararcter out modem.
  704.     CPI    EOFCHAR        ;if eof then..
  705.     RZ            ;..finish up.
  706.     JMP    GETNEXT        ;get another character to send
  707.  
  708. ; wait for remote prompt(s) to be sent
  709.  
  710. WAITFOR    CALL    MODOUT2
  711.     MVI    B,10        ;wait window for bbs prompt(s)
  712.     CALL    TIMER        ; (100 msec timer)
  713.     CALL    CRLF        ; (crlf not received as echo)
  714.     JMP    GETNEXT        ;get another character
  715.  
  716. ; smart-send/receive to/from remote (special protocol)
  717.  
  718. MODOUT2    CALL    OUTCHAR        ;character out
  719.     CPI    EOFCHAR        ;eof?
  720.     RZ            ;yes, don't type.  ret & finish up.
  721. MODLP2    CALL    INSTAT
  722.     JNZ    MODLP2        ;(in at baudrate)
  723.     CALL    INCHAR        ;get echo
  724.     ANI    7FH        ;strip parity
  725.     RZ                  ;don't process null
  726.     CALL    TYPE        ;if not null, show locally.
  727.      CPI    BELL        ;bell?  if yes, delay till remote..
  728.     JZ    DELAY07        ;..is able to receive next char else..
  729.     RET            ;..ret and send next character.
  730.  
  731. ; delay sending after receiving bell (07H)
  732.  
  733. DELAY07    MVI    B,2        ; 200 msec wait before sending next..
  734.     CALL    TIMER        ;..character after near-end-of-line bell
  735.     RET            ;to caller of modout2
  736.      ENDIF            ;not dumb
  737.  
  738. ; softkey routine outputs stored text by pressing the lead-in
  739. ; character followed by a single numeral, 0,1,2,3, etc.  see skone
  740. ; db fields before start of program for the command and message
  741. ; strings (alter them as desired).  <lead-in> d displays the fields
  742. ; locally while in terminal mode.
  743.  
  744.      IF    SOFTKEY
  745. SOFTCMD    SUI    30H        ;ok, now convert ascii digit to binary.
  746.     RLC            ; *2 for table offset (0,1,2... --> 0,2,4...)
  747.     LXI    H,SKTBL        ;point to softkey table and.
  748.     MOV    E,A        ;..index down, factor in a-reg.
  749.     MVI    D,0        ;clear msb
  750.     DAD    D        ;add offset to table beginning address
  751.     MOV    E,M        ;get dw address in table
  752.     INX    H        ;fully fill de-pair
  753.     MOV    D,M        ;done, next..
  754.     XCHG            ;..point to desired db string in table.
  755. KEYSEND    MOV    A,M        ;put character in a-reg for sending
  756.     ORA    A        ;ck for null terminator
  757.     RZ
  758.     CALL    OUTCHAR        ;send character to remote
  759.     LXI    B,400*MHZ
  760. MDMINLP    CALL    INSTAT        ;test if echo character received
  761.     JZ    GETCHR        ;if not, delay..
  762.     DCX    B        ;..and..
  763.     MOV    A,B        ;..try..
  764.     ORA    C        ;..again..
  765.     JNZ    MDMINLP        ;..and again 'till timeout or char rcvd.
  766.     RET            ;ret to terminal loop
  767.  
  768. GETCHR    CALL    INCHAR        ;character received in a-reg
  769.     ANI    7FH        ;strip parity
  770.     JZ    NULSKIP        ;don't process if null
  771.     CALL    TYPE        ;display locally
  772. NULSKIP    INX    H        ;get next character to be sent
  773.     JMP    KEYSEND        ;loop till terminator
  774.  
  775. ; softkey dispatch table
  776.  
  777. SKTBL    DW    SKZERO        ;address of db text strings
  778.     DW    SKONE
  779.     DW    SKTWO
  780.     DW    SKTHREE
  781.     DW    SKFOUR
  782.     DW    SKFIVE
  783.     DW    SKSIX
  784.     DW    SKSEVEN
  785.     DW    SKEIGHT
  786.     DW    SKNINE        ; 0 to 9 presently permitted
  787.      ENDIF            ;softkey
  788.  
  789. ; e c h o   m o d e   (resemble a computer)
  790.  
  791. TERM$ECHO CALL    CROSSCK        ;comfirm option compatibility
  792. ECHOLP    CALL    INSTAT
  793.     JZ    LINECHR
  794.     CALL    STAT
  795.     JZ    ECHOLP
  796.     CALL    KEYIN
  797.     MOV    B,A        ;save character
  798.     LDA    CMDFLG        ;ignore next (ctrl) char locally..
  799.     ORA    A        ;..if zero flag not set.
  800.     MVI    A,0
  801.     STA    CMDFLG        ;clear for next time
  802.     MOV    A,B        ;restore character
  803.     JNZ    ECHOCMD        ;we are in command mode, check for command.
  804.     LDA    CMDCHR        ;get command character
  805.     CMP    B
  806.     MOV    A,B        ;put character back into A
  807.     JNZ    SW7        ;not command character, so send it out.
  808.     ORI    TRUE        ;set command mode
  809.     STA    CMDFLG
  810.     JMP    ECHOLP        ;go back to main echo loop
  811.  
  812. LINECHR    CALL    INCHAR
  813. SW7    CPI    CR        ;if cursor return..
  814.     JNZ    SW7A
  815.     CALL    OUTCHAR
  816.     CALL    TYPE        ;print locally
  817.     MVI    A,LF        ;..auto-output a linefeed.
  818. SW7A    CALL    OUTCHAR
  819.     CALL    TYPE
  820.     JMP    ECHOLP        ;loop for more
  821.  
  822. ECHOCMD    CALL    UCASE
  823.     CPI    'E'        ;exit to (re-enter) command mode
  824.     JZ    MENU
  825.  
  826.      IF    PMMI OR MM100 OR US100
  827.     CPI    'B'        ;same routines as in 'terminal mode'
  828.     CZ    NEWBAUD
  829.     JZ    ECHOLP
  830.     CPI    'D'        ;disconnect?
  831.     JZ    DISCON1
  832.      ENDIF            ;pmmi or mm100
  833.  
  834.     JMP    SW7        ;not a valid command, so send it
  835.  
  836. ; s e n d
  837.  
  838. SENDFIL     MVI    A,'C'        ;always force checksum..
  839.      STA    CRCFLG        ;..mode initially on send.
  840. SENDFIL1 LDA    BATCHFLG    ;check if multiple file..
  841.      ORA    A        ;..(batch) mode is set.
  842.      JNZ    SENPLF
  843.      CALL    ILPRTQ
  844.      DB    CR,LF,'Ready to send -- batch mode',0
  845. SENDFIL2 MVI    A,TRUE        ;indicate 'batch' send mode
  846.      STA    SENDFLG
  847.      LDA    FSTFLG        ;if first time thru..
  848.      ORA    A        ;..scan the command line..
  849.      CNZ    TNMBUF        ;..for multiple names.
  850.      CALL    SENDFN        ;sends filename to receiver
  851.      JNC    SENPLF        ;carry set means no more files
  852.      MVI    A,'B'        ;stop batch..
  853.      STA    BATCHFLG    ;..mode secondary option.
  854.      MVI    A,EOT        ;final file transfer indication
  855.      CALL    SEND
  856.      JMP    DONE
  857.  
  858. SENPLF    CALL    CNREC        ;get number of records
  859.     CALL    OPENFIL
  860.     MVI    E,90        ;waiting time-out
  861.     CALL    WAITNAK
  862. SENDLP    CALL    CKABORT        ; (manual abort?)
  863.     CALL    RDRECD        ;read a record
  864.     JC    SENDEOF        ;send 'eof' if done
  865.     CALL    INCRRNO        ;bump count
  866.     MVI    A,1             ;initialize error count for 1st error
  867.     STA    ERRCT
  868. SENDRPT    CALL    CKABORT        ;want to quit sending?
  869.     CALL    SENDHDR        ;send a header
  870.     CALL    SENDREC        ;send bytes of record
  871.     LDA    CRCFLG
  872.     ORA    A
  873.     CZ    SENPLRC        ;send phone line crc or..
  874.     CNZ    SENPLKS        ;..cksum.
  875.     CALL    GETACK        ;get the ack.  rets with carry..
  876.     JC    SENDRPT        ;..set if no ack received.
  877.     JMP    SENDLP        ;loop till 'eof'
  878.  
  879. SENDEOF    MVI    A,EOT
  880.     CALL    SEND        ;send an 'eot'
  881.     CALL    GETACK
  882.     JC    SENDEOF        ;loop if no ack
  883.     JMP    DONE        ;to 'finish up' routine
  884.  
  885. ; r e c e i v e
  886.  
  887. ; initial entry routine
  888.  
  889. RCVFIL    XRA    A        ;set initially..
  890.     STA    CRCFLG        ;..to 'crc' mode
  891. RCVFIL1    LDA    BATCHFLG    ;check if mult-file..
  892.     ORA    A        ;..(batch) mode.
  893.     JNZ    RCVC3
  894.     XRA    A        ;flag --> 'batch' receive..
  895.     STA    SENDFLG        ;..for next file transfer.
  896.     CALL    GETFN        ;get filename
  897.     JNC    RCVC2        ;carry set means no more files
  898.     MVI    A,'B'        ;stop batch..
  899.     STA    BATCHFLG    ;..mode option.
  900.     JMP    DONE        ;finish
  901.  
  902. RCVC2    CALL    CKCPM2
  903.     CALL    CKBAKUP
  904. RCVC3    CALL    ERASFIL        ;if file exists -- erase.  else use..
  905.     JNZ    MENU        ;..different filename, as desired.
  906.     CALL    MAKEFIL
  907.     LDA    BATCHFLG
  908.     ORA    A
  909.     JZ    RCVFST        ;no msg if in 'batch' mode..
  910.     CALL    ILPRTQ        ;..but shows in 'quiet'.
  911.     DB    CR,LF,'File open -- ready to receive',0
  912. RCVFST    LDA    CRCFLG        ;determine mode and..
  913.     ORA    A
  914.     JNZ    RCVFIL2        ; (do 'checksum')
  915.     CALL    ILPRTQ        ;..if 'crc', say:
  916.     DB    CR,LF,'CRC in effect',CR,LF,0
  917.     MVI    A,CRC
  918.     JMP    RCVCRCM        ;store 'c' (or 'nak')
  919.  
  920. RCVFIL2    CALL    ILPRTQ        ;else show this msg then..
  921.     DB    CR,LF,'Checksum in effect',CR,LF,0
  922.     MVI    A,NAK        ;..store..
  923. RCVCRCM    STA    ACKFLG        ;..'nak'.
  924.  
  925. ; main receive loop -- update record count, write, and close file
  926.  
  927. RCVLP    CALL    RCVRECD        ;get a record
  928.     JC    RCVEOT        ;get 'eot'
  929.     CALL    WRRECD        ;write the record
  930.     CALL    INCRRNO        ;bump count
  931.     MVI     A,ACK
  932.     STA    ACKFLG        ;store 'ack'
  933.     JMP    RCVLP        ;loop till 'ack'
  934.  
  935. RCVEOT    CALL    WRBLOCK        ;write last record
  936.     CALL    SENDACK        ;send 'ack'
  937.     CALL    CLOSFIL        ;close file
  938.     JMP    DONE        ;finished
  939.     
  940. ; subroutines used by batch mode
  941.  
  942. ; await 'nak' -- send 'ack'
  943.  
  944. SENDFN    CALL    ILPRT        ;don't show in quiet mode
  945.     DB    CR,LF,'Awaiting filename NAK',CR,LF,0
  946.     MVI    E,90
  947.     CALL    WAITNLP        ; (don't show 'awaiting ready signal')
  948.     MVI    A,ACK        ;got nak, send ack.
  949.     CALL    SEND
  950.     LXI    H,FILECT
  951.     DCR    M
  952.     JM    NOMRNM
  953.     LHLD    NBSAVE        ;get filename..
  954.     LXI    D,FCB        ;..into fcb.
  955.     MVI    B,12
  956.     CALL    MOVE
  957.     SHLD    NBSAVE
  958.     CALL    SENDNM        ;send it
  959.     ORA    A        ;clear carry
  960.     RET
  961.  
  962. NOMRNM    MVI    A,EOT
  963.     CALL    SEND
  964.     STC
  965.     RET
  966.  
  967. ; send filename
  968.  
  969. SENDNM    PUSH    H
  970. SENDNM1    MVI    D,11        ;count chars in name
  971.     MVI    C,0        ;init checksum
  972.     MOV    A,C
  973.     STA    FTYCNT        ;initialize filetype count
  974.     LXI    H,FCB+1        ;address name
  975. NAMLPS    MOV    A,M        ;send name
  976.     ANI    7FH        ;strip high order bit so cp/m 2..
  977.     CALL    SEND        ;..won't send r/o file designation.
  978.     LDA    QFLG        ;don't show filename..
  979.     ORA    A        ;..if in 'quiet' mode.
  980.     MOV    A,M
  981.     CNZ    FTYTST        ;type locally filename characters
  982. ACKLP    PUSH    B        ;save cksum
  983.     MVI    B,10        ;wait 1 sec for receiver..
  984.     CALL    RECV        ;..to acknowledge..
  985.     POP    B        ;..getting letter.
  986.     JC    SCKSER        ;cksum error --> time-out on receive
  987.     CPI    ACK
  988.     JNZ    ACKLP
  989.     INX    H        ;bump for next character
  990.     DCR    D
  991.     JNZ    NAMLPS
  992.     MVI    A,EOFCHAR     ;tell receiver end of name
  993.     CALL    SEND
  994.     CALL    CRLF        ; (doesn't show in quiet mode)
  995.     MOV    D,C        ;save checksum
  996.     MVI    B,10        ; 1-sec time-out
  997.     CALL    RECV        ;get checksum..
  998.     CMP    D        ;..from receiver.
  999.     JZ    NAMEOK
  1000. SCKSER    MVI    A,BDNMCH     ;bad name, tell receiver.
  1001.     CALL    SEND
  1002.     CALL    ILPRTQ
  1003.     DB    CR,LF,'++ Filename error ++',CR,LF,0
  1004.     MVI    E,90        ;do handshaking over
  1005.     CALL    WAITNLP        ;don't print 'awaiting filename nak' msg
  1006.     MVI    A,ACK
  1007.     CALL    SEND
  1008.     JMP    SENDNM1        ;re-send filename
  1009.  
  1010. NAMEOK    MVI    A,OKNMCH     ;successful filename sent and received,..
  1011.     CALL    SEND        ;..tell receiver.
  1012.     POP    H
  1013.     RET    
  1014.  
  1015. GETFN    LXI    H,FCB
  1016.     CALL    INITFCB+2     ;does not initialize drive
  1017.     CALL    ILPRTQ
  1018.     DB    CR,LF,'Ready to receive filename',CR,LF,0
  1019. GNAMELP    MVI    E,45        ; 90-seconds for receiving 'ack'
  1020.     CALL    HSNAK        ;get 'ack' or auto-abort
  1021.     CALL    GETNM        ;get the name
  1022.     CPI    EOT        ;if eot, then no more files.
  1023.     JZ    NOMRNMG
  1024.     ORA    A        ;clear carry
  1025.     RET
  1026.  
  1027. NOMRNMG    STC
  1028.     RET
  1029.  
  1030. GETNM    PUSH    H
  1031. GETNM1    MVI    C,0        ;initialize checksum
  1032.     MOV    A,C
  1033.     STA    FTYCNT        ;initiate count for filetype
  1034.     LXI    H,FCB+1
  1035. NAMELPG    MVI    B,50
  1036.     CALL    RECV        ;get char (5-sec time-out)
  1037.     JNC    GETNM3
  1038.     CALL    ILPRTQ
  1039.     DB    CR,LF,'Timeout receiving filename',CR,LF,0
  1040.     JMP    GCKSER
  1041.  
  1042. GETNM3    CPI    EOT        ;if 'eot', then no more files.
  1043.     JZ    GNRET
  1044.     CPI    EOFCHAR        ;got end of name
  1045.     JZ    ENDNAME
  1046.     MOV    M,A        ;put name in fcb
  1047.     CALL    FTYTST        ;show locally received filename
  1048.     PUSH    B        ;save cksum
  1049.     MVI    A,ACK        ; 'ack' getting letter
  1050.     CALL    SEND
  1051.     POP    B
  1052.     INX    H        ;get next char
  1053.     MOV    A,L        ;don't let noise...
  1054.     CPI    7FH        ;..cause overflow..
  1055.     JZ    GCKSER        ;..into program area.
  1056.     JMP    NAMELPG
  1057.  
  1058. ; show locally filename sent/received
  1059.  
  1060. FTYTST    LDA    FTYCNT        ;filetype counter
  1061.     INR    A
  1062.     STA    FTYCNT
  1063.     CPI    8+1        ;into filetype yet?
  1064.     JZ    SPCTST        ;go if so
  1065. ENDSPT    MOV    A,M
  1066.     CPI    ' '        ;test for space
  1067.     CNZ    TYPEQ        ;type if not
  1068.     RET
  1069.  
  1070. SPCTST    MOV    A,M        ; 'space' test
  1071.     CPI    ' '        ;test for space in first filetype byte
  1072.     RZ            ;don't output period if space
  1073.     MVI    A,'.'
  1074.     CALL    TYPEQ
  1075.     JMP    ENDSPT        ;output first filetype byte
  1076.  
  1077. ; verify 'goodname' recevied after sent
  1078.  
  1079. ENDNAME    CALL    CRLF        ; (not shown in quiet mode)
  1080.     MOV    A,C        ;send checksum
  1081.     CALL    SEND
  1082.     MVI    B,10        ; 1-sec time-out
  1083.     CALL    RECV           ;checksum good?
  1084.     CPI    OKNMCH           ;yes, if oknmch sent..
  1085.     JZ    GNRET           ;..else do over.
  1086. GCKSER    LXI    H,FCB           ;clear fcb (except drive) since it can be..
  1087.     CALL    INITFCB+2     ;..changed by too many characters.
  1088.     CALL    ILPRTQ
  1089.     DB    CR,LF,'++ Filename error ++',CR,LF,0
  1090. GCKSER1    MVI    E,45
  1091.     CALL    HSNAK        ;do handshaking over
  1092.     JMP    GETNM1
  1093.  
  1094. GNRET    POP    H
  1095.     RET
  1096.  
  1097. ; handshake 'nak'/'ack'
  1098.  
  1099. HSNAK    MVI    A,NAK        ;send nak until receiving..
  1100.     CALL    SEND        ;..'ack' or e-reg times out.
  1101.     CALL    CKABORT        ; (manual abort?)
  1102.     MVI    B,20        ;wait 2 seconds..
  1103.     CALL    RECV        ;..in receive.
  1104.     CPI    ACK        ;if ack, then..
  1105.     RZ            ;..return.
  1106.     DCR    E        ;time-out in e-reg
  1107.     JNZ    HSNAK        ;loop 'till time-out and..
  1108.     JMP    ABORT        ;..then abort.
  1109.  
  1110. ; load 'namebuf' with filename(s) to send
  1111.  
  1112. TNMBUF    XRA    A        ;call from 'sendfil' only once.
  1113.     STA    FSTFLG
  1114.     STA    FILECT
  1115.     CALL    SCANM
  1116.     LXI    H,NAMEBUF
  1117.     SHLD    NBSAVE        ;save addr of 1st name
  1118. TNLP1    CALL    TRTOBUF
  1119.     LXI    H,FCB
  1120.     LXI    D,FCBBUF
  1121.     CALL    CMDLINE        ;parse name to cp/m format
  1122. TNLP2    CALL    MFNAME        ;search for names (* format)
  1123.     JC    NEXTNM
  1124.     LDA    FCB+10        ;if cp/m 2 $sys file..
  1125.     ANI    80H        ;..don't send.
  1126.     JNZ    TNLP2
  1127.     LHLD    NBSAVE        ;get name
  1128.     LXI    D,FCB        ;move it to fcb
  1129.     XCHG
  1130.     MVI    B,12
  1131.     CALL    MOVE
  1132.     XCHG
  1133.     SHLD    NBSAVE         ;addr of next name
  1134.     LXI    H,FILECT     ;count files found
  1135.     INR    M
  1136.     JMP    TNLP2
  1137.  
  1138. NEXTNM    LXI    H,NAMECT     ;count names found
  1139.     DCR    M
  1140.     JNZ    TNLP1
  1141.     LXI    H,NAMEBUF     ;save start of buffer
  1142.     SHLD    NBSAVE
  1143.     LDA    FILECT
  1144.     CPI    64+1        ;no more than 64 transfers
  1145.     RC
  1146.     MVI    A,64        ;only x'fer first 64
  1147.     STA    FILECT
  1148.     RET
  1149.  
  1150. ; scan cmdbuf, counts names, and puts "space" after last name
  1151.  
  1152. SCANM    PUSH    H
  1153.     LXI    H,NAMECT
  1154.     MVI    M,0
  1155.     LXI    H,CMDBUF+1     ;find end of cmd line..
  1156.     MOV    C,M        ;..and put space there.
  1157.     MVI    B,0
  1158.     LXI    H,CMDBUF+2
  1159.     DAD    B
  1160.     MVI    M,' '        ;space
  1161.     LXI    H,CMDBUF+1
  1162.     MOV    B,M
  1163.     INR    B
  1164.     INR    B
  1165. SCANLP1    INX    H
  1166.     DCR    B
  1167.     JZ    DNSCAN
  1168.     MOV    A,M
  1169.     CPI    ' '
  1170.     JNZ    SCANLP1
  1171. SCANLP2    INX    H        ;eat extra spaces
  1172.     DCR    B
  1173.     JZ    DNSCAN
  1174.     MOV    A,M
  1175.     CPI    ' '
  1176.     JZ    SCANLP2
  1177.     SHLD    BGNMS        ;save start of names in cmdbuf
  1178.     INR    B
  1179.     DCX    H
  1180. SCANLP3    INX    H
  1181.     DCR    B
  1182.     JZ    DNSCAN
  1183.     MOV    A,M
  1184.     CPI    ' '
  1185.     JNZ    SCANLP3
  1186.     LDA    NAMECT        ;counts names
  1187.     INR    A
  1188.     STA    NAMECT
  1189. SCANLP4    INX    H        ;eat spaces
  1190.     DCR    B
  1191.     JZ    DNSCAN
  1192.     MOV    A,M
  1193.     CPI    ' '
  1194.     JZ    SCANLP4
  1195.     JMP    SCANLP3
  1196.  
  1197. DNSCAN    MVI    M,' '        ;space after last char
  1198.     POP    H
  1199.     RET
  1200.  
  1201. ; place next name in buffer so cpmline may parse it
  1202.  
  1203. TRTOBUF    LHLD    BGNMS
  1204.     MVI    B,0
  1205.     LXI    D,FCBBUF+2
  1206. TBLP    MOV    A,M
  1207.     CPI    ' '        ;space
  1208.     JZ    TRBFEND
  1209.     STAX    D
  1210.     INX    H
  1211.     INX    D
  1212.     INR    B        ;count chars in name
  1213.     JMP    TBLP
  1214.  
  1215. TRBFEND    INX    H
  1216.     MOV    A,M        ;eat extra spaces
  1217.     CPI    ' '
  1218.     JZ    TRBFEND
  1219.     SHLD    BGNMS
  1220.     LXI    H,FCBBUF+1     ;put # chars before name
  1221.     MOV    M,B
  1222.     RET
  1223.  
  1224. ; $r/o and $sys files changed to 'bak'
  1225.  
  1226. CKCPM2    LXI    D,TBUF        ;establish 'dma'
  1227.     MVI    C,SETDMA
  1228.     CALL    BDOS
  1229.     LXI    D,FCB
  1230.     MVI    C,SRCHF        ;search for file
  1231.     CALL    BDOS
  1232.     INR    A        ; 0ffh --> 0 means no file found
  1233.     RZ
  1234.     CALL    GETADDR        ;returns filename address in hl-pair
  1235.     DCX    H
  1236.     LXI    D,9
  1237.     DAD    D        ;point to 'r/o' attribute byte
  1238.     MOV    A,M
  1239.     ANI    80H        ;test msb
  1240.     JNZ    MKCHG        ;if set, make change.
  1241.     INX    H        ;check 'system' attribute byte
  1242.     MOV    A,M
  1243.     ANI    80H
  1244.     RZ            ;not $sys or $r/o
  1245.     DCX    H
  1246. MKCHG    LXI    D,-8
  1247.     DAD    D        ;point hl-pair to filename+1
  1248.     LXI    D,FCB+1        ;move directory name to fcb..
  1249.     MVI    B,11        ;..without changing drive.
  1250.     CALL    MOVE
  1251.     LXI    H,FCB+9        ; $r/o attribute is..
  1252.     MOV    A,M
  1253.     ANI    7FH        ;..stripped here and..
  1254.     MOV    M,A
  1255.     INX    H        ;..$sys attribute is..
  1256.     MOV    A,M
  1257.     ANI    7FH        ;..stripped here.
  1258.     MOV    M,A
  1259.     LXI    D,FCB
  1260.     MVI    C,30        ;set new file attributes in directory
  1261.     CALL    BDOS
  1262.     JMP    PLANCHG
  1263.  
  1264. ; check if backup required and change filetype to 'bak'
  1265.  
  1266. CKBAKUP    LDA    BAKUPBYTE
  1267.     ORA    A
  1268.     RZ
  1269.     MVI    C,SRCHF
  1270.     LXI    D,FCB
  1271.     CALL    BDOS
  1272.     INR    A        ; 0ffh --> 0 means..
  1273.     RZ            ;..file not found.
  1274. PLANCHG    LXI    H,FCB        ;change name to type 'bak'
  1275.     LXI    D,FCB2
  1276.     MVI    B,9        ;copy drive and filename (not filetype)
  1277.     CALL    MOVE
  1278.     LXI    H,FCB2+9    ;start of filetype in fcb2
  1279.     MVI    M,'B'
  1280.     INX    H
  1281.     MVI    M,'A'
  1282.     INX    H
  1283.     MVI    M,'K'
  1284.     LXI    D,FCB2
  1285.     MVI    C,ERASE        ;erase existing backup, if one.
  1286.     CALL    BDOS
  1287.     LXI    H,FCB2        ;fcb2 'dr' field should..
  1288.     MVI    M,0        ;..be 0 for rename.
  1289.     LXI    D,FCB
  1290.     MVI    C,REN        ;rename the file
  1291.     JMP    BDOS        ;ret to caller
  1292.  
  1293. ; receive 'cp/m file' routines
  1294.  
  1295. ; receive a record
  1296.  
  1297. RECVACK    MVI    A,ACK
  1298.     STA    ACKFLG        ;store 'ack' first
  1299. RCVRECD MVI    A,1        ;initialize error count for 1st error
  1300.     STA    ERRCT
  1301. RCVRPT    XRA    A        ;clear receive..
  1302.     STA    ERRCDE        ;..error code.
  1303.     CALL    CKABORT        ;ck keyboard for abort request
  1304.     CALL    ILPRT
  1305.      DB    CR,'Awaiting #',0
  1306.     PUSH    H        ;save it
  1307.     LHLD    RECDNO        ;get record number
  1308.     INX    H        ;bump it
  1309.     CALL    DECOUT        ;print record number in decimal
  1310.     CALL    ILPRT
  1311.     DB    ' (', 0
  1312.     CALL    DHXOUT        ; 16-bit hex conversion & output
  1313.     CALL    ILPRT
  1314.     DB    'H) ',0
  1315.     POP    H        ;restore it
  1316.     LDA    ACKFLG        ;send 'ack' or..
  1317.     CALL    SEND        ;..'nak' now.
  1318.  
  1319. ;---->    rcvsq:
  1320. ;    if 'crc' is in effect, there is a 10-second timeout to first
  1321. ;    'soh'.  rountine tries 'errcrc' times to let sender know system
  1322. ;    is capable of receiving a crc check.  At the end of that time
  1323. ;    a 'nak' is sent which tells sender to use checksum checking
  1324. ;    instead of crc.  thus automatic compatability with systems
  1325. ;    implementing crc (cyclic redundancy checking) is provided.
  1326.  
  1327. RCVSQ    MVI    B,100-10    ; 10 (-1) second timeout
  1328.     CALL    RECV        ;get line character
  1329.     JC    RCVSTOT        ;indicate 'timeout' occurred
  1330.     CALL    RCVERR        ;check for receive errors (fop) and report
  1331.     CPI    SOH        ;a start of header?
  1332.     JZ    RCVSOH        ;branch, if yes.
  1333.     ORA    A        ;character a null?
  1334.     JZ    RCVSQ        ; (disregard)
  1335.     CPI    CRC        ;was it a 'crc' we sent?
  1336.     JZ    RCVSQ        ; (disregard)
  1337.     CPI    NAK        ;or a checksum 'nak'?
  1338.     JZ    RCVSQ        ; (disregard)
  1339.     CPI    EOT        ;or an end of text?
  1340.     STC            ;if yes, done -- return..
  1341.     RZ            ;..with carry set.
  1342.     MOV    B,A        ;save received character..
  1343.     CALL    ILPRT
  1344.     DB    CR,LF,'++ ',0
  1345.     MOV    A,B
  1346.     CALL    HEXO        ;..to display on console as hex value.
  1347.     CALL    ILPRT
  1348.     DB    'h received, not SOH - ',0
  1349. RCVPRN    CALL    SHOWERR        ;display error count
  1350. RCVSERR    MVI    B,10        ;wait up to 1 second..
  1351.     CALL    RECV        ;..with no character received.
  1352.     JNC    RCVSERR        ;loop until sender done
  1353.     CALL    CKABORT        ;want to stop receiving now?
  1354.     LDA    CRCFLG        ;get 'crc' flag
  1355.     ORA    A        ; 'crc' in effect?
  1356.     MVI    A,NAK        ;put 'nak' in accumulator
  1357.     JNZ    RCVSER1        ;no, store the 'nak'.
  1358.     LDA    FIRSTME        ;first soh..
  1359.     ORA    A        ;..been received?
  1360.     MVI    A,NAK        ;put 'nak' in accumulator
  1361.     JZ    RCVSER1        ;yes, then store 'nak'.
  1362.     MVI    A,CRC        ;tell sender 'crc' is in effect
  1363. RCVSER1 STA    ACKFLG        ;store the 'nak' or 'crc' request
  1364.     LDA    ERRCT        ;include this error..
  1365.     INR    A        ;..in the error count.
  1366.     STA    ERRCT        ;abort if at limit
  1367.     CPI    ERRLIM+1    ; (started out with count at 1)
  1368.     JC    RCVRPT        ;no, try again.
  1369.     JMP    ABORT        ;auto-abort at error limit
  1370.  
  1371. ; cancel file-receive and erase unfinished file
  1372.  
  1373. RCVSABT    LXI    SP,STACK    ;start anew
  1374.     CALL    CLOSFIL        ;save records received then..
  1375.     CALL    NOASK        ;..delete the partial file.
  1376.     CALL    ILPRTQ
  1377.     DB    CR,LF,'Routine cancelled -- '
  1378.     DB    'Unfinished file deleted' ,CR,LF,LF,BELL,0
  1379.     JMP    DONETCA        ;to (tc) 'transfer completed' routine
  1380.  
  1381. ; get error count and show locally
  1382.  
  1383. SHOWERR    PUSH    H
  1384.     LHLD    ERRCT        ;load 8-bit error count and..
  1385.     MVI    H,0        ;..zero high byte, then..
  1386.     CALL    DECOUT        ;..display in decimal.
  1387.     POP    H
  1388.     CALL    ILPRT
  1389.     DB    ' ++',CR,LF,0    ;add trailer and start newline
  1390.     RET
  1391.  
  1392. ; time-out announcement -- routine switches from 'crc' to 'checksum' if
  1393. ; 'errct' reaches 'errcrc' and 'firstme' is true
  1394.  
  1395. RCVSTOT    CALL    ILPRT
  1396.     DB    CR,LF,'++ Timeout ',0
  1397.     CALL    SHOWERR
  1398.     LDA    ERRCT
  1399.     CPI    ERRCRC        ;number of tries for crc/checksum soh
  1400.     JC    RCVSERR
  1401.     LDA    FIRSTME
  1402.     ORA    A
  1403.     JZ    RCVSERR
  1404.     LDA    CRCFLG
  1405.     ORA    A
  1406.     JNZ    RCVSERR
  1407.     MVI    A,'C'        ;show now in checksum mode
  1408.     STA    CRCFLG
  1409.     CALL    ILPRTQ
  1410.     DB    'Switching to Checksum mode',CR,LF,BELL,0
  1411.     JMP    RCVSERR
  1412.  
  1413. ;---->    rcverr:
  1414. ;    checks for framing, overrun, and parity (fop) errors.
  1415. ;      1. error code (errcde) was set in 'recv' routine.
  1416. ;      2. errcde = 0 for no errors, errcde <> 0 for errors.
  1417. ;      3. on an error, routine jumps to rcvderr for display.
  1418. ;         but if no error, simply rets to caller.
  1419.  
  1420. RCVERR     MOV    B,A        ;save received character and..
  1421.      LDA    ERRCDE        ;get receive error code
  1422.      ORA    A        ;is it zero?
  1423.      JNZ    RCVDERR        ;no, get receive error.
  1424.      MOV    A,B        ;..put it back here.
  1425.      RET
  1426.  
  1427. ;---->    rcvderr:  checks for receive error and displays appropriate error
  1428. ;    message.  then goes to 'rcvprn' to show error count, purge line,
  1429. ;    and send 'nak'.
  1430.  
  1431. RCVDERR     POP    PSW        ;balance stack from call to 'rcverr'
  1432.  
  1433.       IF    (NOT PMMI) AND (NOT MM100) AND (NOT US100)
  1434.      JMP    RCVRPT
  1435.       ENDIF            ;neither pmmi or mm100 or us100
  1436.  
  1437.       IF    US100
  1438.      LDA    MODCTLB        ;reset 'fop' error..
  1439.      CALL    OUTCTRL        ;..flags in 8251a.
  1440.       ENDIF            ;us100
  1441.  
  1442.       IF    PMMI OR MM100 OR US100
  1443.      LDA    ERRCDE         ;get receive error code
  1444.      ANI    FE         ;was there a framing error?
  1445.      JZ    RCVDERR2     ;no, go check for overrun.
  1446.      CALL    ILPRT        ;show error type then..
  1447.      DB    CR,LF,'++ Framing error ',0
  1448.      JMP    RCVPRN      ;..print error number.
  1449.  
  1450. RCVDERR2 LDA    ERRCDE
  1451.      ANI    OE         ;was there an overrun?
  1452.      JZ    RCVDERR3     ;no, go check for parity error.
  1453.      CALL    ILPRT
  1454.      DB    CR,LF,'++ Overrun error ',0
  1455.      JMP    RCVPRN
  1456.  
  1457. RCVDERR3 LDA    ERRCDE
  1458.      ANI    PE        ;parity error?
  1459.      JZ    RCVRPT        ;no, get another character.
  1460.      CALL    ILPRT
  1461.      DB    CR,LF,'++ Parity error ',0
  1462.      JMP    RCVPRN
  1463.       ENDIF            ;pmmi or mm100 or us100
  1464.  
  1465. ; got soh -- get record # and its complement
  1466.  
  1467. RCVSOH    XRA    A
  1468.     STA    FIRSTME        ;indicate first soh was recevied
  1469.     MVI    B,10        ; 1-sec time-out
  1470.     CALL    RECV        ;receive character routine
  1471.     JC    RCVSTOT     ;indicate time-out
  1472.     CALL    RCVERR        ;check for receive (fop) error and report
  1473.     MOV    D,A        ;save record # for..
  1474.     MVI    B,10
  1475.     CALL    RECV
  1476.     JC    RCVSTOT
  1477.     CALL    RCVERR
  1478.     CMA            ;..comparsion with..        
  1479.     CMP    D        ;..its complement.
  1480.     JZ    RCVDATA        ;okay, get 128-byte record.
  1481.     CALL    ILPRT
  1482.     DB    CR,LF,'++ Invalid record # in header - ',0
  1483.     JMP    RCVPRN        ;display error count
  1484.  
  1485. RCVDATA    MOV    A,D
  1486.     STA    RCVRNO
  1487.     MVI    A,1        ;set to 'show' data if in..
  1488.     STA    DATAFLG        ;..'view' mode.
  1489.     MVI    C,0
  1490.     CALL    CLRCRC        ;clear crc counter
  1491.     LXI    H,TBUF
  1492. RCVCHR    MVI    B,10        ; 1-sec time-out
  1493.     CALL    RECV        ;receive character routine
  1494.     JC    RCVSTOT     ;indicate time-out
  1495.     CALL    RCVERR        ;check for receive (fop) error
  1496.     MOV    M,A        ;store rcvd char in ram
  1497.     INR    L        ;loop for 128 bytes
  1498.     JNZ    RCVCHR
  1499.     XRA    A        ;indicate don't 'show' if in..
  1500.     STA    DATAFLG        ;..'view' mode.
  1501.     LDA    CRCFLG
  1502.     ORA    A
  1503.     JZ    RCVCRC
  1504.     MOV    D,C
  1505.     MVI    B,10
  1506.     CALL    RECV
  1507.     JC    RCVSTOT
  1508.     CALL    RCVERR
  1509.     CMP    D
  1510.     JNZ    RCVCERR        ;indicate checksum error
  1511. CK$R$NM    LDA    RCVRNO        ;compare record..
  1512.     MOV    B,A
  1513.     LDA    RECDNO
  1514.     CMP    B        ;..numbers.
  1515.     JZ    RECVACK
  1516.     INR    A
  1517.     CMP    B
  1518.     JNZ    ABORT
  1519.     RET
  1520.  
  1521. RCVCRC    MVI    E,2        ;nr of crc bytes
  1522. RCVCRC2    MVI    B,10
  1523.     CALL    RECV
  1524.     JC    RCVSTOT
  1525.     CALL    RCVERR
  1526.     DCR    E
  1527.     JNZ    RCVCRC2
  1528.     CALL    CHKCRC
  1529.     ORA    A
  1530.     JZ    CK$R$NM
  1531.     CALL    ILPRT
  1532.     DB    CR,LF,'++ CRC error ',0
  1533.     JMP    RCVPRN        ;display error count
  1534.  
  1535. RCVCERR    CALL    ILPRT
  1536.     DB    CR,LF,'++ Checksum error ',0
  1537.     JMP    RCVPRN
  1538.  
  1539. ; send 'cp/m file' routines
  1540.  
  1541. ; send start-of-header, record #, and its complement
  1542.  
  1543. SENDHDR    CALL    ILPRT
  1544.     DB    CR,'Sending #',0
  1545.     PUSH    H
  1546.     LHLD    RECDNO        ;get record number
  1547.     CALL    DECOUT        ;display in decimal and..
  1548.     CALL    ILPRT
  1549.     DB    ' (',0
  1550.     CALL    DHXOUT        ;..in hexidecimal.
  1551.     CALL    ILPRT
  1552.     DB    ' Hex) ',0
  1553.     POP    H
  1554. SENDHNM    MVI    A,SOH        ;send soh..
  1555.     CALL    SEND
  1556.     LDA    RECDNO        ;..record # and..
  1557.     CALL    SEND
  1558.     LDA    RECDNO
  1559.     CMA
  1560.     JMP    SEND        ;..its complement.
  1561.  
  1562. ; send-record loop
  1563.  
  1564. SENDREC    MVI    A,1        ;ready to 'show' data if in..
  1565.     STA    DATAFLG        ;..'view' mode.
  1566.     MVI    C,0
  1567.     CALL    CLRCRC
  1568.     LXI    H,TBUF        ;point to characters to send
  1569. SENPL    MOV    A,M        ;get one chararcter from ram
  1570.     CALL    SEND
  1571.     INR    L        ;loop 'till 128 bytes..
  1572.     JNZ    SENPL        ;..are sent.
  1573.     XRA    A        ;stop possibility..
  1574.     STA    DATAFLG        ;;..of 'viewing'.
  1575.     RET
  1576.  
  1577. ; send (phone line) checksum
  1578.  
  1579. SENPLKS    MOV    A,C
  1580.     JMP    SEND
  1581.  
  1582. ; send 2-byte 'crc'
  1583.  
  1584. SENPLRC    PUSH    H
  1585.     LHLD    CRCVAL
  1586.     MOV    A,H
  1587.     CALL    SEND
  1588.     MOV    A,L
  1589.     CALL    SEND
  1590.     POP    H
  1591.     XRA    A
  1592.     RET
  1593.  
  1594. ; receive either 'acknowledge' or error character
  1595.  
  1596. GETACK    MVI    B,100        ; 10-sec time-out
  1597.     CALL    RECVDG        ;enter clearing noise char
  1598.     JC    GETATOT        ;indicate timeout occurred
  1599.     CPI    ACK
  1600.     RZ            ; 'ack' received -- return.
  1601.     MOV    B,A
  1602.     CALL    ILPRT
  1603.     DB    CR,LF,'++ ',0
  1604.     MOV    A,B
  1605.     CPI    NAK        ;if 'nak'..
  1606.     JZ    PRTNAK        ;..say so.
  1607.     CALL    HEXO        ;else show hex value..
  1608.     CALL    ILPRT
  1609.     DB    'h',0        ;..received instead of 'nak'.
  1610.     JMP    ACKERR0
  1611. PRTNAK    CALL    ILPRT
  1612.     DB    'NAK',0
  1613. ACKERR0    CALL    ILPRT
  1614.     DB    ' received, not ACK - ',0
  1615.  
  1616. ; acknowledge and keep track of errors (for send-file)
  1617.  
  1618. ACKERR    CALL    SHOWERR        ;display error count and line tail
  1619.     LDA    ERRCT        ;update error counter
  1620.     INR    A
  1621.     STA    ERRCT
  1622.     CPI    ERRLIM+1    ;reached the error limit yet?
  1623.     RC            ;if not, back to work.
  1624.     CALL    ERXIT
  1625.     DB    '---> File send cancelled','@'
  1626.  
  1627. ; time-out message
  1628.  
  1629. GETATOT    CALL    ILPRT
  1630.     DB    CR,LF,'++ Timeout on ACK - ',0
  1631.     JMP    ACKERR
  1632.  
  1633. ; check for request to abort
  1634.  
  1635. CKABORT    LDA    VSEEFLG        ;abort permitted in 'view' and other..
  1636.     ORA    A
  1637.     JZ    CKABRT1
  1638.     LDA    QFLG
  1639.     ORA    A
  1640.     RZ            ;..modes but not in quiet mode.
  1641. CKABRT1    CALL    STAT
  1642.     RZ
  1643.     CALL    KEYIN
  1644.     CPI    CAN
  1645.     RNZ            ;if zero, abort.
  1646.  
  1647. ; cancellation routines
  1648.  
  1649. ABORT    LXI    SP,STACK
  1650. ABORTL    MVI    B,10        ; 1-second timeout to clear input here..
  1651.     CALL    RECV
  1652.     JNC    ABORTL
  1653.     MVI    A,CAN
  1654.     CALL    SEND
  1655. ABORTW    MVI    B,10        ;..and here.
  1656.     CALL    RECV
  1657.     JNC    ABORTW        ;loop
  1658.     MVI    A,' '
  1659.     CALL    SEND
  1660.     MVI    A,'B'         ;turn multi-file mode..
  1661.     STA    BATCHFLG     ;..off so routine ends.
  1662.     MVI    A,TRUE       ;show abort..
  1663.     STA    ABORTFLG    ;..was requested.
  1664.     LDA    OPTION        ;receiving a file now?
  1665.     CPI    'R'
  1666.     JZ    RCVSABT        ;if yes, cancel the unfinished file.
  1667.     CALL    ILPRT
  1668.     DB    CR,LF,'---> Routine cancelled',CR,LF,LF,BELL,0
  1669.     JMP    DONETCB
  1670.  
  1671. ; increment record number
  1672.  
  1673. INCRRNO    PUSH    H
  1674.     LHLD    RECDNO        ;get record number
  1675.     INX    H        ;bump it
  1676.     SHLD    RECDNO        ;store it
  1677.     MOV    A,L
  1678.     POP    H
  1679.     RET
  1680.  
  1681. ; erase file routine with question
  1682.  
  1683. ERASFIL    LDA    BATCHFLG    ;don't ask for erase..
  1684.     ORA    A         ;..in multi-file mode..
  1685.     JZ    NOASK         ;..just do it.
  1686.     LXI    D,FCB
  1687.     MVI    C,SRCHF
  1688.     CALL    BDOS
  1689.     INR    A        ; 0ffh --> 0 if file not found
  1690.     RZ            ;ok to create file
  1691.     CALL    ILPRT
  1692.     DB    CR,LF,'File exists - erase?  (Y/N): ',BELL,0
  1693.     CALL    RESPOND
  1694.     CPI    'Y'        ;anything else..
  1695.     RNZ            ;..rets to caller/cmd mode.
  1696.     CALL    CRLF
  1697. NOASK    LXI    D,FCB
  1698.     MVI    C,ERASE
  1699.     JMP    BDOS
  1700.  
  1701. ; create a cp/m file
  1702.  
  1703. MAKEFIL    LXI    D,FCB
  1704.     MVI    C,MAKE
  1705.     CALL    BDOS
  1706.     INR    A
  1707.     RNZ
  1708.     CALL    ERXIT
  1709.     DB    '++ Unable to make file - directory '
  1710.     DB    'may be full ++','@'
  1711.  
  1712. ; determine file record count and save in rcnt
  1713.  
  1714. CNREC    MVI    C,COMPSZ    ;compute file size function
  1715.     LXI    D,FCB        ;point to file control block
  1716.     CALL    BDOS
  1717.     LHLD    FCB+33        ;get record count
  1718.     SHLD    RCNT        ;store it
  1719.     LXI    H,0        ;zero hl-pair
  1720.     SHLD    FCB+33        ;reset random record in fcb
  1721.     RET
  1722.  
  1723. ; open file and ready to send
  1724.  
  1725. OPENFIL    LXI    D,FCB
  1726.     MVI    C,OPEN
  1727.     CALL    BDOS
  1728.     INR    A
  1729.     JNZ    OPENOK
  1730.     CALL    ERXIT
  1731.     DB    '++ Unable to find file ++','@'
  1732.  
  1733. OPENOK    CALL    ILPRT
  1734.     DB    CR,LF,'File open: ',0
  1735.     LHLD    RCNT        ;get record count
  1736.     CALL    DECOUT        ;print decimal number of records
  1737.     CALL    ILPRT
  1738.     DB    ' (',0
  1739.     CALL    DHXOUT        ;print records in hex
  1740.     CALL    ILPRT
  1741.     DB    ' Hex) records   (^X cancels)',CR,LF
  1742.     DB    'Send time: ',0
  1743.     LXI    H,BTABLE    ;point to baud factor table
  1744.     MVI    D,0        ;clear msb
  1745.     LDA    MSPEED        ;load speed indicator
  1746.     MOV    E,A        ;set up for table access
  1747.     DAD    D        ;index to required factor
  1748.     MOV    A,M        ;put factor in a-reg
  1749.     LHLD    RCNT        ;get number of records
  1750.     CALL    DIVHLA        ;divide hl-pair by value in a (rec/min)
  1751.     PUSH    H        ;save remainder then..
  1752.     MVI    H,0        ;..clear msb of hl-pair.
  1753.     CALL    DECOUT        ;show minutes
  1754.     CALL    ILPRT
  1755.     DB    ' minutes, ',0
  1756.     LXI    H,SECTBL    ;divisor table for seconds calc
  1757.     MVI    D,0
  1758.     LDA    MSPEED        ;speed factor
  1759.     MOV    E,A
  1760.     DAD    D        ;index into table
  1761.     MOV    A,M        ;get multiplier
  1762.     POP    H        ;get remainder
  1763.     CALL    MULHA        ;multiply contents of h-reg by a-reg
  1764.     CALL    SHIFTHL        ;shift hl-pair four bits right
  1765.     MVI    H,0
  1766.     CALL    DECOUT        ;show seconds
  1767.     CALL    ILPRT
  1768.     DB    ' seconds at ',0
  1769.     LXI    H,SPTBL        ;baudrate text table
  1770.     MVI    D,0
  1771.     LDA    MSPEED        ;baudrate factor
  1772.     RLC            ; *4 offset into..
  1773.     RLC            ;..baudrate table.
  1774.     MOV    E,A        ;put speed factor in de-pair
  1775.     DAD    D        ;add to hl-pair and..
  1776.     CALL    TEXTOUT        ;..show baudrate.
  1777.     CALL    ILPRT        ;add tailer
  1778.     DB    ' baud',CR,LF,0
  1779.     RET
  1780.  
  1781. ; time-to-send and baudrate tables
  1782.  
  1783. BTABLE    DB    5,13,19,25,29,49
  1784. SECTBL    DB    192,74,51,38,33,20
  1785. SPTBL    DB    '110@','300@','450@','600@','710@','1200@'
  1786.  
  1787. ; close cp/m file
  1788.  
  1789. CLOSFIL    LXI    D,FCB        ;point to filename
  1790.     MVI    C,CLOSE
  1791.     CALL    BDOS
  1792.     INR    A        ; 0ffh --> 00 if close not okay
  1793.     RNZ            ;return if close successful
  1794.     MVI    A,'Q'        ;reset quiet flag..
  1795.     STA    QFLG        ;..and..
  1796.     JMP    ERXIT1        ;..abort operation.
  1797.     
  1798. ; update record read
  1799.  
  1800. RDRECD    LDA    RECINBF        ;records in buffer
  1801.     DCR    A
  1802.     STA    RECINBF
  1803.     JM    RDBLOCK
  1804.     LHLD    RECPTR
  1805.     LXI    D,80H
  1806.     CALL    MOVE128
  1807.     SHLD    RECPTR        ;buffer pointer
  1808.     RET
  1809.  
  1810. ; buffer empty -- read in another block (128 records)
  1811.  
  1812. RDBLOCK    LDA    EOFLG
  1813.     CPI    1
  1814.     STC
  1815.     RZ
  1816.     MVI    C,0
  1817.     LXI    D,DBUF
  1818. RDRECLP    PUSH    B
  1819.     PUSH    D
  1820.     MVI    C,SETDMA
  1821.     CALL    BDOS
  1822.     LXI    D,FCB
  1823.     MVI    C,READ
  1824.     CALL    BDOS
  1825.     POP    D
  1826.     POP    B
  1827.     ORA    A        ;record read okay?
  1828.     JZ    RDRECOK        ;yes
  1829.     DCR    A        ; 'eof'?
  1830.     JZ    REOF        ;yes
  1831.     CALL    ERXIT
  1832.     DB    '++ File read error ++','@'
  1833. RDRECOK    LXI    H,80H
  1834.     DAD    D
  1835.     XCHG
  1836.     INR    C
  1837.     MOV    A,C
  1838.     CPI    DBUFSIZ*8    ;buffer size (128 128-byte records)
  1839.     JZ    RDBFULL        ;read-buffer full?
  1840.     JMP    RDRECLP        ;no, loop for another record.
  1841.  
  1842. REOF    MVI    A,1
  1843.     STA    EOFLG
  1844.     MOV    A,C
  1845.  
  1846. ; buffer full or received 'eof'
  1847.  
  1848. RDBFULL    STA    RECINBF
  1849.     LXI    H,DBUF
  1850.     SHLD    RECPTR
  1851.     LXI    D,TBUF
  1852.     MVI    C,SETDMA
  1853.     CALL    BDOS
  1854.     JMP    RDRECD
  1855.  
  1856. ; update record write
  1857.  
  1858. WRRECD    LHLD    RECPTR
  1859.     XCHG
  1860.     LXI    H,80H
  1861.     CALL    MOVE128
  1862.     XCHG
  1863.     SHLD    RECPTR
  1864.     LDA    RECINBF
  1865.     INR    A
  1866.     STA    RECINBF
  1867.     CPI    DBUFSIZ*8     ;buffer size
  1868.     RNZ            ;ret if not full block
  1869.  
  1870. ; write block to disk (128 records)
  1871.  
  1872. WRBLOCK    LDA    RECINBF
  1873.     ORA    A
  1874.     RZ
  1875.     MOV    C,A
  1876.     LXI    D,DBUF
  1877. DKWRLP    PUSH    H
  1878.     PUSH    D
  1879.     PUSH    B
  1880.     MVI    C,SETDMA
  1881.     CALL    BDOS
  1882.     LXI    D,FCB
  1883.     MVI    C,WRITE
  1884.     CALL    BDOS
  1885.     POP    B
  1886.     POP    D
  1887.     POP    H
  1888.     ORA    A
  1889.     JNZ    WRERR        ;write error
  1890.     LXI    H,80H
  1891.     DAD    D
  1892.     XCHG
  1893.     DCR    C
  1894.     JNZ    DKWRLP
  1895.     XRA    A        ;reset record..
  1896.     STA    RECINBF        ;..counter.
  1897.     LXI    H,DBUF        ;reset buffer..
  1898.     SHLD    RECPTR        ;..pointer.
  1899.     RET
  1900.  
  1901. WRERR    MVI    C,CAN
  1902.     CALL    SEND
  1903.     CALL    ERXIT
  1904.     DB    '++ File write error ++','@'
  1905.  
  1906. ; recv: receive a character.  time-out is in b, in tenth-seconds.
  1907. ; entry via 'recvdg' deletes line-noise characters.  for example,
  1908. ; having just sent a record, calling 'recvdg' deletes a line noise
  1909. ; induced character long before the ack/nak is received.
  1910.  
  1911. ; time-out routine -- delete line-noise character -- check for abort
  1912.  
  1913. RECVDG    CALL    CLR$L        ;clear noise from line
  1914. RECV    PUSH    D
  1915. RECMSEC    LXI    D,113*MHZ    ;makes b-reg tenth-seconds
  1916.     CALL    CKABORT
  1917. RECWLP    CALL    INSTAT         ;test if character received
  1918.     JZ    RECEIVE        ;get character from line
  1919.     DCX    D
  1920.     MOV    A,D
  1921.     ORA    E
  1922.     JNZ     RECWLP
  1923.     DCR    B        ;timeout value
  1924.     JNZ     RECMSEC
  1925.     POP     D
  1926.     STC             ;carry means time-out occurred
  1927.     RET
  1928.  
  1929. ; receive character from modem
  1930.  
  1931. RECEIVE    
  1932.      IF    PMMI OR MM100 OR US100
  1933.     CALL    INCTRL         ;get error-status byte
  1934.     ANI    ERRCDM       ;check for parity, overrun or framing..
  1935.     STA    ERRCDE           ;..errors, save results.
  1936.      ENDIF            ;pmmi or mm100 or us100
  1937.  
  1938. MCHAR    CALL    INCHAR
  1939.     POP    D
  1940.     PUSH    PSW
  1941.     CALL    UPDCRC        ;calculate crc value
  1942.     ADD    C        ;update..
  1943.     MOV    C,A        ;..checksum.
  1944.     LDA    RSEEFLG        ;show data and error msg if zero'd
  1945.     ORA    A
  1946.     JZ    MONIN
  1947.     LDA    VSEEFLG        ;suppress status messages..
  1948.     ORA    A        ;..if zero'd, but view ascii text.
  1949.     JNZ    NOMONIN
  1950.     LDA    DATAFLG
  1951.     ORA    A
  1952.     JZ    NOMONIN
  1953. MONIN    POP    PSW
  1954.     PUSH    PSW
  1955.      CALL    SHOW        ;display character on crt
  1956. NOMONIN    POP    PSW
  1957.     ORA    A
  1958.     RET
  1959.  
  1960. ; send character out thru modem
  1961.  
  1962. SENDACK    MVI    A,ACK        ;send acknowledge
  1963. SEND    PUSH    PSW
  1964.     LDA    SSEEFLG        ;show file as sent
  1965.     ORA    A
  1966.     JZ    MONOUT
  1967.     LDA    VSEEFLG        ;view ascii file as sent but..
  1968.     ORA    A        ;..without status messages.
  1969.     JNZ    NOMONOT
  1970.     LDA    DATAFLG
  1971.     ORA    A
  1972.     JZ    NOMONOT
  1973. MONOUT    POP    PSW
  1974.     PUSH    PSW
  1975.     CALL    SHOW
  1976. NOMONOT    POP    PSW
  1977.     PUSH    PSW
  1978.     CALL    UPDCRC        ;calculate crc value
  1979.     ADD    C        ;update..
  1980.     MOV    C,A        ;..checksum.
  1981. SENDW    CALL    OUTSTAT        ;test if ready to send
  1982.     JNZ    SENDW        ;out at baudrate
  1983.     POP    PSW
  1984.     JMP    OUTCHAR        ;send character
  1985.  
  1986. ; waits for 1st received chararcter (time-out in e-reg) in send mode
  1987.  
  1988. WAITNAK    LDA    QFLG        ;add 'crlf' and ready msg..
  1989.     ORA    A        ;..if..
  1990.     JNZ    WTNAK1        ;..in quiet mode.
  1991.     CALL    ILPRTQ        ;print crlf
  1992.     DB    CR,LF,0
  1993. WTNAK1    CALL    ILPRTQ
  1994.     DB    'Awaiting ready signal ',0
  1995. WAITNLP    CALL    CKABORT
  1996.     MVI    B,10        ; 1-sec time-out
  1997.     CALL    RECV
  1998.     CPI    NAK        ;checksum (or name nak) or..
  1999.     JZ    WAITCK        ; (show checksum msg, if not batch mode.)
  2000.     CPI    CRC        ;..crc request?
  2001.     JZ    WAITCRC        ;set crc flag and show msg
  2002.     DCR    E        ;e-reg in seconds
  2003.     JNZ    WAITNLP        ;loop 'till time-out then..
  2004.     JMP    ABORT        ;..abort.
  2005.  
  2006. WAITCRC    CALL    ILPRT
  2007.     DB    '-- CRC request received',CR,LF,0
  2008.     XRA    A
  2009.     STA    CRCFLG
  2010.     RET
  2011.  
  2012. WAITCK    LDA    BATCHFLG    ;don't show..
  2013.     ORA    A        ;..if in batch mode.
  2014.     RZ
  2015.     CALL    ILPRT
  2016.     DB    '-- Checksum received',CR,LF,0
  2017.     RET
  2018.  
  2019. ; file transfer completed
  2020.  
  2021. DONE    LDA    BATCHFLG
  2022.     ORA    A
  2023.     JNZ    DONETC        ;branch if wasn't batch mode
  2024.  
  2025. ; prepare for next file transfer
  2026.  
  2027.     LDA    FCB          ;save drive #
  2028.     STA    DISKNO
  2029.     LXI    H,FCB          ;blank out file control block
  2030.     CALL    INITFCB
  2031.     LDA    DISKNO          ;put drive number back
  2032.     STA    FCB
  2033.     LXI    H,RESTRN      ;restore record numbers..
  2034.     LXI    D,RECDNOB     ;..for new file transfer.
  2035.     MVI    B,RECDNOE-RECDNOB
  2036.     CALL    MOVE
  2037.     LDA    SENDFLG          ;go to either send or..
  2038.     ORA    A          ;..receive file, controlled by..
  2039.     JNZ    SENDFIL2      ;..the routine setting flag..
  2040.     JMP    RCVFIL1          ;..in multi-file (batch) mode.
  2041.  
  2042. ; end-of-transfer routine
  2043.  
  2044. DONETC    MVI    A,TRUE        ;reset multi-file..
  2045.     STA    FSTFLG        ;..transfer mode.
  2046.     CALL    ILPRTQ
  2047.     DB    CR,LF,'---> Transfer completed',CR,LF,BELL,0
  2048.  
  2049. DONETCA
  2050.      IF    PMMI OR MM100 OR US100
  2051.     LDA    EXITFLG        ;exit to cp/m with..
  2052.     ORA    A        ;..disconnect and reboot?
  2053.     JZ    PEXIT        ;branch, if yes.
  2054.     LDA    DISCFLG        ;disconnect when finished?
  2055.     ORA    A        ;yes, if zero.  disconnect..
  2056.     JZ    DISCON1        ;..and go to command line.
  2057.      ENDIF            ;pmmi or mm100 or us100
  2058.  
  2059. DONETCB    MVI    A,CRC
  2060.     STA    CRCFLG        ;turn off 'crc' option
  2061.     MVI    A,'Q'        ;reset the flag to normal
  2062.     STA    QFLG
  2063.     MVI    A,TRUE
  2064.     STA    FIRSTME        ;set 'first-time' flag
  2065.     LDA    ABORTFLG    ;came here from a timeout?
  2066.     ORA    A
  2067.     JNZ    MENU        ;if yes, go to command mode.
  2068.     LDA    TERMFLG        ;see if return to..
  2069.     ORA    A        ;..terminal mode..
  2070.     JZ    TERM        ;..after x'fer.
  2071.     JMP    MENU        ;else, go to cmd line.
  2072.  
  2073. ; c p m
  2074.  
  2075. ; leave comm7 program
  2076.  
  2077. PREEXIT    
  2078.      IF    PMMI OR MM100 OR US100
  2079.     LDA    LINEFLG        ;simply exit if..
  2080.     ORA    A        ;..line not..
  2081.     JZ    EXIT        ;..connected.
  2082.     CALL    ILPRT
  2083.     DB    CR,LF,LF,'Exit to CP/M with telephone line '
  2084.     DB    'connected?  (Y/N): ',0
  2085.     CALL    RESPOND
  2086.     CPI    'N'        ;exit with line connected?
  2087.     JNZ    EXIT        ;no, with line disconnected.  any..
  2088. PEXIT    CALL    DISCONN        ;..other character simply exits to cp/m.
  2089.      ENDIF            ;pmmi or mm100 or us100
  2090.  
  2091. EXIT    LDA    O$USR        ;restore original..
  2092.     CALL    SET$USR        ;..user area and..
  2093.     LXI    D,TBUF        ;..tidy up before..
  2094.     MVI    C,SETDMA
  2095.     CALL    BDOS        ;..leaving comm7.
  2096.     CALL    STAT        ;flush any character..
  2097.     MVI    C,RDCON        ;..remaining..
  2098.     CNZ    BDOS        ;..in bdos.
  2099.     CALL    CRLF        ;exit to cp/m with a fresh line
  2100.     LDA    EXITFLG        ;warm boot if 'e' secondary..
  2101.     ORA    A        ;..option..
  2102.     JZ    WBOOT        ;..requested.
  2103.     LDA    SAVCCP        ;see if 'ccp' saved
  2104.     ORA    A
  2105.     JZ    WBOOT        ;no, noisily warm boot.  else..
  2106.     LHLD    STACK        ;..restore cp/m stack by..
  2107.     SPHL            ;..hl/sp-pair swap then..
  2108.     RET            ;..return quickly to cp/m 'ccp'.
  2109.  
  2110.     LINK    COMM725B    ;chains to 'comm725b.asm' using lasm.com
  2111.