home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / NUBYE / NUKMD111.ARK / NUKMD111.FL1 < prev    next >
Text File  |  1987-02-03  |  80KB  |  3,532 lines

  1. ; -------------------
  2. ; PROGRAM STARTS HERE
  3. ; -------------------
  4. ;
  5. ; Save CP/M stack, initialize new one for NUKMD and check to see if
  6. ; NUBYE is available before continuing.
  7. ;
  8. BEGIN:    LXI    H,0
  9.     DAD    SP
  10.     SHLD    STACK        ; Save current return to CCP address
  11.     LXI    SP,STACK    ; Reset the stack
  12. ;
  13. ; Show program name and version number
  14. ;
  15.     CALL    ILPRT
  16.     DB    CR,LF,'NUKMD v',MAIN+'0','.'
  17.     DB    VERS/10+'0',VERS MOD 10+'0',' - '
  18.     DB    MONTH/10+'0',MONTH MOD 10+'0','/'
  19.     DB    DAY/10+'0',DAY MOD 10+'0','/'
  20.     DB    YEAR/10+'0',YEAR MOD 10+'0',' '
  21.     DB    CR,LF,0
  22. ;
  23.     MVI    C,32
  24.     MVI    E,241
  25.     CALL    BDOS        ; See if NUBYE is running
  26.     CPI    77
  27.     JZ    BEGIN1        ; We're ok
  28.     CALL    ILPRT
  29.     DB    CR,LF,BELL
  30.     DB    '** NUBYE Unavailable -- Initiating Test Mode **'
  31.     DB    CR,LF,0
  32.     JMP    OPTERR
  33. ;
  34. ; Save the current d/u area
  35. ;
  36. BEGIN1:    MVI    E,0FFH
  37.     CALL    USRSET
  38.     STA    OLDUSR        ; Save for now
  39.     MVI    C,CURDRV
  40.     CALL    BDOS
  41.     STA    OLDDRV
  42. ;
  43.      IF    WRTLOC        ; Set write lock?
  44.     MVI    C,75
  45.     MVI    E,1
  46.     CALL    BDOS        ; Set the WRTLOC flag
  47.      ENDIF
  48. ;
  49.      IF    RESUSR
  50.     MVI    C,85        ; Access flags byte
  51.     MVI    E,255
  52.     CALL    BDOS        ; Byte returned in 'A'
  53.     STA    AFBYTE        ; Store it
  54.      ENDIF
  55. ;
  56.      IF    TIMEON OR CLOCK
  57.     CALL    TIME        ; Get user's time and status from NUBYE
  58.      ENDIF
  59. ;
  60. ; Gobble up garbage characters from the line prior to receive or send
  61. ;
  62.     CALL    CATCH
  63. ;
  64. ; Check option for send or receive
  65. ;
  66.     LXI    H,FCB+1
  67.     MOV    A,M        ; Get the main option
  68.     STA    OPTSAV        ; Save it for later use
  69.     STA    CRCFLG        ; Insure in CRC mode now
  70. ;
  71.      IF    LOGCAL
  72.     STA    LOGOPT        ; Save for the station's log file
  73.      ENDIF
  74. ;
  75.     CPI    'L'        ; Download an .LBR member?
  76.     JZ    SETLAM
  77.     CPI    'A'        ; Download an .ARK/.ARC member?
  78.     JZ    SETLAM
  79.     CPI    'S'        ; Download a normal file?
  80.     JZ    CHKSND
  81.     CPI    'R'        ; Upload a file?
  82.     JNZ    OPTERR        ; None of these, show help guide
  83. ;
  84.     LDA    MSPEED
  85.     CPI    5        ; <1200 bps?
  86.     JC    CKROPT        ; Skip 1k stuff if so
  87.     STA    KFLG        ; Set the 1k flag for now
  88. ;
  89. ; Check for possible receive options
  90. ;
  91. CKROPT:    INX    H
  92.     MOV    A,M        ; Get the receive option, if any
  93.     CPI    'P'        ; Want a private upload?
  94.     JZ    SETPRV
  95. ;
  96.      IF    RESUSR AND PUPOPT
  97.     CPI    'W'        ; Special privileged xfr request?
  98.     JNZ    CKROP1        ; No, continue
  99.     MVI    A,1
  100.     STA    PUPFLG        ; Show privileged xfr requested
  101.     JMP    CKROP2        ; Check for more options
  102.      ENDIF
  103. ;
  104. CKROP1:     IF    MSGFIL
  105.     CPI    'M'        ; Message file?
  106.      ENDIF
  107. ;
  108.     JNZ    CKROP3        ; None of these, it's not special
  109. ;
  110.      IF    MSGFIL
  111.     STA    MSGFLG        ; Else set the message flag
  112.     MVI    A,'P'        ; ...and...
  113.      ENDIF
  114. ;
  115. SETPRV:    STA    PRVTFL        ; Set the private flag
  116. ;
  117. CKROP2:    INX    H
  118.     JMP    CKROP4
  119. ;
  120. CKROP3:     IF    DESCRIB    OR SETAREA
  121.     PUSH    H
  122.     CALL    WHAT        ; Get category and/or drive/user area now
  123.     POP    H
  124.      ENDIF
  125. ;
  126. CKROP4:    MOV    A,M        ; Get additional receive option, if any
  127.     CPI    ' '        ; Next column a space character?
  128.     JZ    RCKBCH        ; If yes, see if requesting batch
  129.     CPI    'B'        ; For batch mode
  130.     JZ    RCKBCH
  131.     CPI    'C'        ; Want checksum?
  132.     JZ    RCKSM
  133.     CPI    'X'        ; Want 128-character blocks?
  134.     JNZ    RK        ; No, so check for Ymodem request
  135. ;
  136. R128:    XRA    A        ; Reset the 1k block flag
  137.     STA    KFLG
  138.     JMP    RCRC
  139. ;
  140. RK:    LDA    MSPEED
  141.     CPI    5        ; <1200 bps?
  142.     JC    R128        ; Skip 1k stuff if so
  143.     MOV    A,M        ; ...else, get it back
  144.     CPI    'K'        ; Want Ymodem?
  145.     JNZ    OPTERR        ; None of these, it's an error
  146.     CALL    YMDMSG        ; Show protocol
  147.     JMP    RCVFL
  148. ;
  149. ; -----
  150. ;
  151. SETLAM:    STA    LBRARC        ; Set .LBR/.ARK/.ARC extraction flag
  152. ;
  153. CHKSND:    INX    H        ; Point to next command line character
  154.     MOV    A,M        ; Get it
  155.     CPI    ' '        ; Anything?
  156.     JZ    SNDFL        ; No, finished checking
  157.     CPI    'X'        ; 'X'modem protocol?
  158.     JNZ    CHKSND1        ; No, continue checking
  159.     CALL    XMDMSG        ; Show protocol
  160.     JMP    SNDFL
  161. ;
  162. CHKSND1:CPI    'K'        ; Force 1k transmissions?
  163.     JNZ    CHKSND2        ; No, continue checking
  164.     LDA    MSPEED        ; Check speed being used
  165.     CPI    5
  166.     JC    SNDFL        ; Don't allow 1k blocks if 300 bps
  167.     STA    KFLG        ; Else set the 1k flag
  168.     CALL    YMDMSG        ; Show protocol
  169.     JMP    SNDFL
  170. ;
  171. CHKSND2:LDA    LBRARC
  172.     ORA    A        ; Member extraction?
  173.     JNZ    SNDFL        ; Yes, ignore 'S'pecial and 'B'atch
  174.     MOV    A,M        ; Get character back
  175.     CPI    'B'        ; Batch request?
  176.     JNZ    CHKSND3        ; No, continue checking
  177.     STA    YMODEM        ; Prep for Ymodem batch send
  178.     JMP    SBCH        ; Go send batch
  179. ;
  180. CHKSND3: IF    ALTSEC
  181.     CPI    'S'        ; 'S'pecial download?
  182.     JNZ    CHKSND4        ; No, continue checking
  183.     STA    SPLFL1        ; Set "special send" flag
  184.     STA    SPLFL        ; Set "private download" flag
  185.     JMP    CHKSND        ; Loop for more options
  186.      ENDIF
  187. ;
  188. CHKSND4:CPI    'P'        ; 'P'rivate?
  189.     JNZ    CHKSND        ; No, loop for more options
  190.     STA    SPLFL        ; Set the "private download" flag
  191.     JMP    CHKSND        ; Loop for more options
  192. ;
  193. ; Allows batch mode to private area if R, RB or RPB is typed
  194. ;
  195. RCKBCH:    LDA    FCB1+1
  196.     CPI    ' '        ; File requested?
  197.     JNZ    RCRC        ; Yes, can't use filename request in batch
  198.     INR    A        ; Will set batch flag to non-zero
  199.     STA    INBTCH        ; For MSGDSC
  200.     CALL    BCHMSG        ; Show batch enabled message
  201.     JMP    RCVFL
  202. ;
  203. RCRC:    MVI    A,1
  204.     STA    CRCFLG        ; Show in CRC mode
  205.     CALL    XMDMSG        ; Show protocol
  206.     JMP    RCVFL
  207. ;
  208. RCKSM:    XRA    A
  209.     STA    CRCFLG
  210.     STA    KFLG        ; Can't use 1k blocks with checksum
  211.     CALL    ILPRT
  212.     DB    CR,LF,'(Xmodem Checksum / 128-byte packets)',CR,LF,0
  213.     JMP    RCVFL
  214. ;
  215. ; Displays the Batch enabled message for send
  216. ;
  217. SBCH:    LDA    SPLFL        ; Sending from the private area?
  218.     ORA    A
  219.     JNZ    SNDFL        ; If yes, skip batch message
  220.     INR    A        ; To set the batch flag to non-zero
  221.     CALL    BCHMSG        ; Display the batch message
  222.     JMP    SNDFL
  223. ;
  224. BCHMSG:    STA    BCHFLG        ; Set the batch flag
  225.     LDA    MSPEED        ; Check speed being used
  226.     CPI    5
  227.     JC    XMDMSG        ; 1k packets not used at 300 bps
  228.     CALL    ILPRT
  229.     DB    CR,LF,'(Ymodem Batch CRC / 1k packets)',CR,LF,0
  230.     RET
  231. ;
  232. XMDMSG:    CALL    ILPRT
  233.     DB    CR,LF,'(Xmodem CRC / 128-byte packets)',CR,LF,0
  234.     RET
  235. ;
  236. YMDMSG:    CALL    ILPRT
  237.     DB    CR,LF,'(Ymodem CRC / 1k packets)',CR,LF,0
  238.     RET
  239. ;
  240. ; -----
  241. ;
  242. ; Show user available upload space when KMD A is entered
  243. ;
  244. SPACE:     IF    NOT SETAREA
  245.     CALL    ILPRT
  246.     DB    CR,LF
  247.     DB    'Public uploads received on any disk/user area.',CR,LF
  248.     DB    'Use DIR to determine available free space.....',CR,LF,0
  249.      ENDIF
  250. ;
  251.      IF    SETAREA    AND USEMENU
  252.     CALL    WHAT        ; Give area/description options
  253.      ENDIF
  254. ;
  255.      IF    SETAREA
  256.     CALL    ILPRT
  257.     DB    CR,LF,LF
  258.     DB    'Normal  Uploads > ',0
  259.     LDA    XDRV
  260.     CALL    CTYPE
  261.     LDA    XUSR
  262.     MVI    H,0
  263.     MOV    L,A
  264.     CALL    DECOUT
  265.     MVI    A,':'
  266.     CALL    CTYPE
  267.     CALL    ILPRT
  268.     DB    '  (',0
  269.     LDA    XDRV
  270.     STA    KDRV
  271.     CALL    KSHOW
  272.     MVI    A,')'
  273.     CALL    CTYPE
  274.      ENDIF
  275. ;
  276.     CALL    ILPRT
  277.     DB    CR,LF
  278.     DB    'Private Uploads > ',0
  279.     LDA    XPRDRV
  280.     CALL    CTYPE
  281.     LDA    XPRUSR
  282.     MVI    H,0
  283.     MOV    L,A
  284.     CALL    DECOUT
  285.     MVI    A,':'
  286.     CALL    CTYPE
  287. ;
  288.      IF    SETAREA
  289.     LDA    XPRDRV
  290.     MOV    B,A
  291.     LDA    XDRV
  292.     CMP    B        ; Both drives the same?
  293.     JZ    NOSHO1        ; Yes, don't show free space twice
  294.      ENDIF
  295. ;
  296.     CALL    ILPRT
  297.     DB    '  (',0
  298.     LDA    XPRDRV
  299.     STA    KDRV
  300.     CALL    KSHOW
  301.     MVI    A,')'
  302.     CALL    CTYPE
  303. ;
  304. NOSHO1:    CALL    ILPRT
  305.     DB    CR,LF,0
  306.     RET
  307. ;
  308. ; -----
  309. ;
  310. ; Help guide
  311. ;
  312. ; NUKMD entered by itself or incorrect command was given...
  313. ;
  314. OPTER0:    CALL    MORE
  315. OPTERR:    CALL    ILPRT
  316.     DB    CR,LF,LF
  317.     DB    ' << NUKMD HELP/INFORMATION MENU >>',CR,LF,LF
  318.     DB    '  1)  Downloading',CR,LF
  319.     DB    '  2)  Uploading',CR,LF
  320.     DB    '  3)  Downloading .LBR/.ARK/.ARC file members',CR,LF
  321.     DB    '  4)  General Information',CR,LF
  322.     DB    '  5)  Check Available Disk Space',CR,LF
  323.     DB    '  6)  EXIT to system',CR,LF,LF
  324.     DB    '  Your choice : ',0
  325. ;
  326. OPTER1:    CALL    INPUT        ; Get a character
  327.     CPI    '1'        ; <1?
  328.     JC    OPTER1
  329.     JNZ    OPTER2        ; Not 1, so continue
  330.     CALL    TYPE
  331. ;
  332. ; This section displays examples for DOWNLOAD.
  333. ;
  334. HELP1:    CALL    ILPRT
  335.     DB    CR,LF,LF
  336.     DB    'DOWNLOADS (from this system to you)'
  337.     DB    CR,LF,LF
  338.     DB    '   NUKMD S   EXAMPLE.LBR      Normal file download'
  339.     DB    CR,LF
  340.     DB    '   NUKMD S   B1:EXAMPLE.DQC   From a named d/u area'
  341.     DB    CR,LF
  342.     DB    '   NUKMD SB  EXAMPLE.*        1k Ymodem Batch mode'
  343.     DB    CR,LF
  344.     DB    '   NUKMD SK  EXAMPLE.LBR      Force 1k Ymodem protocol'
  345.     DB    CR,LF
  346.     DB    '   NUKMD SX  EXAMPLE.LBR      Force Xmodem protocol'
  347.     DB    CR,LF,0
  348.     JMP    OPTER0
  349. ;
  350. OPTER2:    CPI    '6'+1        ; >5?
  351.     JNC    OPTER1        ; Wait for correct input
  352.     CALL    TYPE        ; Echo character typed
  353.     CPI    '2'
  354.     JNZ    OPTER3
  355. ;
  356. ; This section displays examples for UPLOAD.
  357. ;
  358. HELP2:    CALL    ILPRT
  359.     DB    CR,LF,LF
  360.     DB    'UPLOADS   (from you to this system)'
  361.     DB    CR,LF,LF
  362.     DB    '   NUKMD R   EXAMPLE.OBJ      Normal file upload'
  363.     DB    CR,LF
  364.     DB    '   NUKMD RC  EXAMPLE.LBR      Force checksum'
  365.     DB    CR,LF
  366.     DB    '   NUKMD RP  EXAMPLE.AQM      Private upload'
  367.     DB    CR,LF
  368.     DB    '   NUKMD RPC EXAMPLE.DQC      Force checksum'
  369.     DB    CR,LF
  370.     DB    '   NUKMD R                    1k Ymodem Batch mode'
  371.     DB    CR,LF
  372. ;
  373. ; This section displays example for special message file upload.
  374. ;
  375.      IF    MSGFIL
  376.     DB    LF
  377.     DB    'MESSAGE FILE UPLOAD  (special function)'
  378.     DB    CR,LF,LF
  379.     DB    '   NUKMD RM  UPLOAD.MSG       Pre-formatted msg file xfr'
  380.     DB    CR,LF
  381.      ENDIF
  382. ;
  383.     DB    0
  384.     JMP    OPTER0
  385. ;
  386. OPTER3:    CPI    '3'
  387.     JNZ    OPTER4
  388. ;
  389. ; This section displays examples for downloading individual .LBR members,
  390. ; as well as a miscellaneous example for determining available upload space.
  391. ;
  392. HELP3:    CALL    ILPRT
  393.     DB    CR,LF,LF
  394.     DB    'DOWNLOADS (Special Command Option)'
  395.     DB    CR,LF,LF
  396.     DB    '   The "L" and "A" options are used to download single'
  397.     DB    CR,LF
  398.     DB    '   file members from within .LBR/.ARK/.ARC files.  The'
  399.     DB    CR,LF
  400.     DB    '   .LBR/.ARK/.ARC extensions are not required.'
  401.     DB    CR,LF,LF
  402.     DB    'EXAMPLES:'
  403.     DB    CR,LF,LF
  404.     DB    '   NUKMD L  NUBYE101 NUBYE101.AQM  {.LBR file}'
  405.     DB    CR,LF
  406.     DB    '   NUKMD LX NUBYE101 NUBYE.HQS     Force Xmodem protocol'
  407.     DB    CR,LF,LF
  408.     DB    '   NUKMD A  LIST556  L.DOC         {.ARC/.ARK file}'
  409.     DB    CR,LF
  410.     DB    '   NUKMD AK LIST556  L.DOC         Force 1k Ymodem protocol'
  411.     DB    CR,LF,0
  412.     JMP    OPTER0
  413. ;
  414. OPTER4:    CPI    '4'
  415.     JNZ    OPTER5
  416. ;
  417. ; This section displays general features and comments about KMD.
  418. ;
  419. HELP4:    CALL    ILPRT
  420.     DB    CR,LF,LF
  421.     DB    'General Features/Comments:'
  422.     DB    CR,LF,LF
  423.     DB    '  1)  NUKMD provides 100% support for Xmodem and'
  424.     DB    CR,LF
  425.     DB    '        Ymodem protocols.'
  426.     DB    CR,LF
  427.     DB    '  2)  NUKMD uses automatic protocol detection and will'
  428.     DB    CR,LF
  429.     DB    '        determine which mode to use for a transfer:'
  430.     DB    CR,LF
  431.     DB    '           Xmodem = 128-byte records (CRC or checksum)'
  432.     DB    CR,LF
  433.     DB    '           Ymodem = 1k-byte records  (CRC only)'
  434.     DB    CR,LF
  435.     DB    '  3)  Ymodem BATCH transfers are also supported.'
  436.     DB    CR,LF
  437.     DB    '  4)  Individual file members may be extracted from'
  438.     DB    CR,LF
  439.     DB    '        .ARK (CP/M) and .ARC (MS-DOS) file collections'
  440.     DB    CR,LF
  441.     DB    '        via the "A" download option and from .LBR (both'
  442.     DB    CR,LF
  443.     DB    '        CP/M and MS-DOS) files via the "L" option.'
  444.     DB    CR,LF,0
  445.     JMP    OPTER0
  446. ;
  447. OPTER5:    CPI    '5'
  448.     JZ    OPTER6
  449.     CALL    ILPRT
  450.     DB    CR,LF,0
  451.     JMP    EXIT        ; Wants to exit
  452. ;
  453. OPTER6:    CALL    SPACE        ; Show free space
  454.     JMP    OPTER0
  455. ;
  456. ; ===============================
  457. ;    ---> SNDFL  --  DOWNLOAD
  458. ;   (from RCP/M system TO USER)
  459. ; ===============================
  460. ;
  461. ; The file specified in the NUKMD command line is transferred over the
  462. ; phone from the RCP/M system to another computer via modem using
  463. ; the "S" (send) option.  The data is sent one record at a time, with
  464. ; headers and checksums and retransmissions on errors.
  465. ;
  466. SNDFL:     IF    (MBBS OR PBBS) AND RESUSR
  467.     LDA    SPLFL        ; Requesting private download?
  468.     ORA    A
  469.     JNZ    SNDOK        ; Yes, so ignore access level
  470.     LDA    AFBYTE
  471.     ANI    20H        ; Test bit 5 for download access
  472.     JZ    DENIED
  473.      ENDIF
  474. ;
  475. SNDOK:    XRA    A
  476.     STA    SNDFLG        ; Show in send mode
  477.     LDA    BCHFLG        ; Batch mode requested?
  478.     ORA    A
  479.     JNZ    SBTCH        ; If yes, go handle batch mode
  480.     CALL    LOGDU
  481. ;
  482. SNDFL1:    LDA    LBRARC
  483.     ORA    A        ; Member extraction?
  484.     CZ    CNREC        ; No, compute record count
  485. ;
  486. SNDFL2:    CALL    OPNFIL        ; Open the file
  487.     CALL    RDBLK1        ; Put up to 16k from file into buffer
  488.     CALL    CATCH        ; Clear the decks
  489.     MVI    E,60        ; Wait up to 1 minute for initial 'NAK'
  490.     CALL    WAITNAK
  491.     CALL    SETFLG        ; Can't use 1k if not 8 records in file
  492. ;
  493. ; Loops back to this point after a successful transmission for next one
  494. ;
  495. SNDLP:    CALL    GTRATIO        ; Check the ACK ratio if using 1k blocks
  496.     CALL    RDRECD        ; Read a record
  497.     JC    SNDEOF        ; Send 'EOF' if done
  498.     CALL    INCRNO        ; Bump record number if sent ok
  499.     CALL    SNDABT        ; Check for local abort
  500.     XRA    A        ; Initialize error count to zero
  501.     STA    ERRCT
  502. ;
  503. ; Comes back here to repeat previous transmission if no ACK was received
  504. ;
  505. SNDRPT:    CALL    CKABORT        ; Check for remote abort
  506.     CALL    FUNCHK        ; Check the function keys
  507.     CALL    SNDABT        ; Check for local abort
  508.     CALL    SNDHDR        ; Send a header
  509.     CALL    SNDREC        ; Send data record
  510.     CALL    SNDCHK        ; Send CRC or checksum value
  511.     CALL    GTACK        ; Get the 'ACK'
  512.     JC    SNDRPT        ; No 'ACK', repeat transmission
  513.     CALL    SETPTR        ; Successful record so increase pointers
  514.     LDA    LBRARC
  515.     ORA    A        ; Member extraction?
  516.     JZ    SNDLP        ; No, exit
  517. ;
  518. SNDRP1:    CALL    SETLBR        ; Set library pointers and size left
  519.     LHLD    RCNT        ; See if anything was actually sent
  520.     MOV    A,H
  521.     ORA    L        ; See if L and H both zero now
  522.     JNZ    SNDLP        ; Not done, yet
  523. ;
  524. ; File sent, send EOT but do local log-keeping first
  525. ;
  526. SNDEOF:     IF    LOGLDS
  527.     LDA    DNLDS        ; Get Downloads Counter
  528.     INR    A        ; One more download since log in
  529.     STA    DNLDS        ; And update counter
  530.      ENDIF
  531. ;
  532.      IF    LOGCAL
  533.     CALL    LOGCALL        ; Write log entries first
  534.      ENDIF
  535. ;
  536. EOF1:    CALL    EOFSND
  537. ;
  538.      IF    TIMEON AND (NOT    CLOCK)
  539.     CALL    ADDTON        ; Update NUBYE's time-on-system byte
  540.      ENDIF
  541. ;
  542.     CALL    ALLDON
  543.     JMP    DONE
  544. ;
  545. ; Sends batch mode
  546. ;
  547. SBTCH:    LDA    FSTFLG        ; If first time through
  548.     ORA    A
  549.     JNZ    SBTCH1        ; If not first time, exit
  550.     CALL    ILPRT
  551.     DB    CR,LF
  552.     DB    'Locating selection(s)...',0
  553.     CALL    LOGDU        ; Check disk, user
  554.     CALL    TNMBUF        ; Put all requested files into NAMBUF
  555. ;
  556. ; Total number of files, total records and total length is shown, user
  557. ; then gets up to 5 seconds to abort.
  558. ;
  559.     CALL    ILPRT
  560.     DB    CR
  561.     DB    'Number of files found   > ',0
  562.     LDA    FILCNT        ; Get total files
  563.     STA    SHOCNT
  564.     PUSH    PSW
  565.     MOV    L,A
  566.     MVI    H,0
  567.     CALL    DECOUT        ; Show remote # of files
  568.     POP    PSW
  569.     ORA    A        ; Abort if no files to send
  570.     JZ    NOFILE
  571.     CALL    ILPRT
  572.     DB    CR,LF
  573.     DB    'Xmodem 128-byte packets > ',0
  574.     LHLD    TOTREC        ; Get total records - all files
  575.     PUSH    H
  576.     CALL    DECOUT        ; Show remote
  577.     CALL    ILPRT
  578.     DB    CR,LF
  579.     DB    'Ymodem 1k packets       > ',0
  580.     POP    H
  581.     CALL    DIVREC        ; Divide number of records by 8
  582.     CALL    DECOUT        ; Show # of k
  583.     CALL    ILPRT
  584.     DB    CR,LF
  585.     DB    'Disk space you need     > ',0
  586.     LHLD    BLOKK        ; Get k required on remote disk for 2k
  587.     XCHG            ; Block size
  588.     LHLD    BLOKK
  589.     DAD    D        ; Double the size for 2k blocks
  590.     CALL    DECOUT        ; Print it
  591.     CALL    ILPRT
  592.     DB    'k (2k blocks)',0
  593. ;
  594. SBTCH1:    LDA    FILCNT
  595.     ORA    A
  596.     JZ    SBTCH2
  597.     LDA    FSTFLG
  598.     ORA    A        ; Past first batch file?
  599.     JZ    SHOREM        ; No, else show local
  600. ;
  601.      IF    CLRSCR
  602.     CALL    PRINTL
  603.     DB    CLRCH1,CLRCH2,CLRCH3,CLRCH4,CLRCH5,CLRCH6,'$'
  604.      ENDIF
  605. ;
  606.     CALL    ILPRTL        ; Local display from here on...
  607.     DB    CR,LF
  608.     DB    'Remaining transfer time > ',0
  609.     JMP    SKPREM
  610. ;
  611. SHOREM:    CALL    ILPRT
  612.     DB    CR,LF,LF
  613.     DB    'Total transfer time     > ',0
  614. ;
  615. SKPREM:    LXI    H,KTABLE
  616.     LDA    MSPEED        ; Get speed indicator
  617.     MVI    D,0
  618.     MOV    E,A        ; Set up for table access
  619.     DAD    D        ; Index to proper factor
  620.     DAD    D
  621.     MOV    E,M
  622.     INX    H
  623.     MOV    D,M
  624.     LHLD    TOTREC        ; Get number of records
  625.     CALL    FILTIM1
  626.     CALL    OPNOK4
  627.     CALL    ILPRT
  628.     DB    CR,LF,0
  629.     LDA    FSTFLG
  630.     ORA    A        ; Past first batch file?
  631.     JZ    NOXTRA        ; No, else give extra CR, LF
  632.     CALL    ILPRT
  633.     DB    CR,LF,0
  634.     CALL    CATCH        ; Get stray garbage
  635. ;
  636. NOXTRA:    LDA    FSTFLG
  637.     ORA    A
  638.     JNZ    SBTCH2
  639.     INR    A        ; Now show we have been this way
  640.     STA    FSTFLG
  641.     CALL    ILPRT
  642.     DB    CR,LF,'Your selection(s) ready to Download'
  643.     DB    CR,LF,'   Abort: CTRL-X <pause> CTRL-X'
  644.     DB    CR,LF,LF,0
  645.     CALL    ILPRTL        ; Local display from here on...
  646.     DB    '[ waiting ]',0
  647. ;
  648. SBTCH2:    CALL    CKABORT
  649.     CALL    FUNCHK        ; Check the function keys
  650.     CALL    SNDABT        ; Check for local abort
  651.     CALL    SNDFN        ; Sends file name to user
  652.     JC    SBTCH4        ; No more files, exit
  653.     CALL    SHOWFIL        ; Show the batch filename
  654.     JMP    SNDFL1        ; Send the file
  655. ;
  656. SBTCH4:    LDA    GOTONE        ; Did we actually send at least one?
  657.     ORA    A
  658.     JZ    ABORT        ; If not, don't act like we did
  659.     CALL    EOFSND        ; No more files so send EOT to finish
  660.     CALL    XFRDON
  661.     CALL    WAIT1
  662.     JMP    EXIT
  663. ;
  664. NOFILE:    CALL    ERXIT
  665.     DB    CR,LF,'++ No matching filename(s) ++','$'
  666. ;
  667. EOFSND:    MVI    A,EOT        ; Send an 'EOT'
  668.     CALL    SEND
  669.     LDA    CHKEOT        ; Did not get an ACK, try again
  670.     INR    A
  671.     STA    CHKEOT        ; Limit number of retries to 10
  672.     CPI    10        ;    (to prevent possible 'lock-up')
  673.     RNC            ; Quit if already sent 10 or more
  674.     CALL    GTACK        ; Get the ACK
  675.     JC    EOFSND        ; Resend if carry is set
  676.     RET
  677. ;
  678. ALLDON:    LDA    BCHFLG        ; In batch mode?
  679.     ORA    A
  680.     RNZ            ; If yes, ignore message
  681. ;
  682. XFRDON:    CALL    ILPRT
  683.     DB    CR,LF,LF
  684.     DB    '[ Transfer Completed ]',CR,LF,0
  685.     RET
  686. ;
  687. SNDABT:    LDA    SYSABT
  688.     ORA    A        ; Local abort?
  689.     JNZ    ABORT        ; Yes, else return
  690.     RET
  691. ;
  692. ; ================================
  693. ;    ---> RCVFL  --  UPLOAD
  694. ;  (from USER to RCP/M System)
  695. ; ================================
  696. ;
  697. ; The file specified in the NUKMD command line is transferred over the
  698. ; phone from the user's computer to the RCP/M system via modem using
  699. ; the "R" (receive) option.  The data is sent one record at a time,
  700. ; with headers and checksums and retransmissions on errors.
  701. ;
  702. RCVFL:     IF    MBBS AND MSGFIL
  703.     LDA    MSGFLG
  704.     ORA    A        ; Message file upload?
  705.     JZ    RCVOK1        ; No, so skip the rest
  706.      ENDIF
  707. ;
  708.      IF    MBBS AND RESUSR    AND MSGFIL
  709.     LDA    AFBYTE
  710.     ANI    8        ; Test for write access (bit 3)
  711.     JZ    DENIED
  712.      ENDIF
  713. ;
  714.      IF    MBBS AND ZCPR AND MSGFIL
  715.     LDA    WHEEL
  716.     ORA    A        ; WHEEL set?
  717.     JZ    RCVOK4        ; No, so skip next
  718.     XRA    A
  719.     STA    WHEEL        ; Turn off WHEEL
  720.     CALL    ILPRT
  721.     DB    'The WHEEL has been turned OFF for "RM" function....'
  722.     DB    CR,LF,0
  723.      ENDIF
  724. ;
  725.      IF    MBBS AND RESUSR    AND MSGFIL
  726.     JMP    RCVOK4
  727.      ENDIF
  728. ;
  729. RCVOK1:     IF    RESUSR AND PUPOPT
  730.     LDA    PUPFLG
  731.     ORA    A        ; Privileged xfr option request?
  732.     JZ    RCVOK2        ; No
  733.      ENDIF
  734. ;
  735.      IF    (MBBS OR PBBS) AND RESUSR AND PUPOPT
  736.     LDA    AFBYTE
  737.     ANI    80H        ; Test for privileged user access (bit 7)
  738.      ENDIF
  739. ;
  740.      IF    (NOT MBBS) AND (NOT PBBS) AND ZCPR AND RESUSR AND PUPOPT
  741.     LDA    WHEEL
  742.     ORA    A        ; WHEEL set?
  743.      ENDIF
  744. ;
  745.      IF    RESUSR AND PUPOPT
  746.     JZ    DENIED
  747.      ENDIF
  748. ;
  749. RCVOK2:     IF    (MBBS OR PBBS) AND RESUSR
  750.     LDA    AFBYTE
  751.     ANI    40H        ; Test bit 6 for upload access
  752.     JZ    DENIED
  753.      ENDIF
  754. ;
  755. RCVOK3:    LDA    BCHFLG        ; Requesting batch mode?
  756.     ORA    A
  757.     JNZ    RCVBCH        ; If yes, exit
  758. ;
  759. RCVOK4:    CALL    RCVFL1        ; Find drive/user/filetype permitted
  760.     CALL    RCVFL6        ; Display drive/user area
  761.     CALL    CONTIN        ; Display drive/user area
  762.     CALL    MAKEFIL        ; Open the file, ready to receive
  763. ;
  764. RCVLP:    CALL    RCVRECD        ; Get a record
  765.     JC    RCVEOT        ; Exit if 'EOT' for end of current file
  766.     CALL    INCRNO        ; Bump record number, if received ok
  767.     CALL    WRRECD        ; Write the record
  768.     CALL    SNDACK        ; Ack the record
  769.     JMP    RCVLP        ; Loop until 'EOF'
  770. ; -----
  771. ;
  772. ; Using batch so reset flags
  773. ;
  774. RCVBCH:    XRA    A
  775.     STA    FRSTIM        ; Needs to be reset for each new file
  776.     MVI    A,1
  777.     STA    SNDFLG        ; Shows we are in receive batch mode
  778.     LDA    FSTFLG
  779.     ORA    A        ; First file received, yet?
  780.     JNZ    RCVBC1        ; Yes, so skip next section
  781.     INR    A
  782.     STA    FSTFLG        ; Show past first file
  783.     CALL    ILPRT
  784.     DB    CR,LF
  785.     DB    'Batch uploads limit  > ',0
  786.     LXI    H,0
  787.     MVI    A,BLIMIT
  788.     MOV    L,A
  789.     CALL    DECOUT        ; Show BLIMIT
  790.     CALL    ILPRT
  791.     DB    ' files',0
  792.     CALL    RCVFL1        ; Find drive/user/filetype permitted
  793.     CALL    CONTIN        ; Display drive/user area
  794.     LXI    H,NAMBUF
  795.     SHLD    NBSAVE
  796. ;
  797. RCVBC1:    CALL    RCVFN        ; Get the batch file name and display
  798.     JC    RCVBC2        ; If all done, exit
  799.     CALL    RCVFL6        ; Change file extent if needed
  800.     CALL    CHEKFIL        ; Already have a file with that name?
  801.     CALL    MAKEFIL
  802.     CALL    BCHINR
  803.     CALL    ILPRTL        ; Display local from here on...
  804.     DB    CR,LF,LF,'[ waiting ]',0
  805.     MVI    A,CRC
  806.     CALL    SEND
  807.     MVI    A,KSND        ; Request 1k blocks
  808.     CALL    SEND
  809.     JMP    RCVLP        ; Start receiving the file
  810. ;
  811. RCVBC2:    XRA    A        ; Zero the batch mode flag
  812.     STA    BCHFLG
  813.     LDA    GOTONE        ; Were there any files received?
  814.     ORA    A
  815.     JZ    ABORT
  816.     CALL    XFRDON        ; Show transmission is finished
  817.     CALL    WAIT1        ; Delay to let remote get into ter. mode
  818.     JMP    CRED3        ; Ask for descriptions
  819. ;
  820. ; -----
  821. ;
  822. ; Check on what drive/user area the file(s) will go into
  823. ;
  824. RCVFL1:    CALL    LOGDU        ; Select drive/user for upload
  825. ;
  826.      IF    RESUSR AND PUPOPT
  827.     LDA    PUPFLG        ; Place "RW" file as needed
  828.     ORA    A        ; Can only be set if user is privileged
  829.     JNZ    RCVFLA        ; Privileged, else check if Sysop...
  830.      ENDIF
  831. ;
  832.      IF    ZCPR
  833.     LDA    WHEEL        ; Let Sysop put file wherever he wants
  834.     ORA    A
  835.     JZ    RCVFL5        ; If WHEEL byte not set, stay normal
  836.      ENDIF
  837. ;
  838. RCVFLA:     IF    ZCPR
  839.     LDA    RCVDRV
  840.     ORA    A
  841.     JZ    RCVFL2
  842.     SUI    'A'        ; Convert ASCII drive to binary
  843.     JMP    RCVFL3
  844. ;
  845. RCVFL2:    LDA    OLDDRV
  846. ;
  847. RCVFL3:    INR    A
  848.     STA    FCB
  849.     ADI    'A'-1        ; Convert binary to ASCII
  850.     STA    XDRV        ; Drive
  851.     LDA    RCVDRV
  852.     ORA    A        ; Drive requested?
  853.     LDA    OLDUSR        ; Current user
  854.     JZ    RCVFL4        ; No, use current user
  855.     LDA    RCVUSR        ; Else get requested user
  856. ;
  857. RCVFL4:    STA    XUSR        ; User
  858.     INR    A        ; Make sure it is a positive number
  859.     STA    RWHEEL
  860.     RET
  861.      ENDIF            ; ZCPR
  862. ;
  863. RCVFL5:     IF    SETAREA
  864.     LDA    XDRV
  865.     SUI    40H
  866.     STA    FCB
  867.      ENDIF
  868. ;
  869.     LDA    PRVTFL        ; Receiving to a private area?
  870.     ORA    A
  871.     RZ            ; If not, exit
  872.     LDA    XPRDRV        ; Private area takes precedence
  873.     SUI    40H        ; Convert to binary
  874.     STA    FCB        ; Store drive to be used
  875.     RET
  876. ;
  877. ; Changes the name of certain type of files such a .COM to .OBJ, ect.
  878. ;
  879. RCVFL6:    LDA    RWHEEL        ; Wheel byte set for SYSOP?
  880.     ORA    A
  881.     RNZ            ; Yes, don't change any file extents
  882. ;
  883.      IF    CHGNAM
  884.     LXI    H,FCB+9        ; Point to filetype
  885.     MVI    A,'C'        ; 1st letter
  886.     CMP    M        ; Is it 'C' ?
  887.     JNZ    RCVFL7        ; If not, continue normally
  888.     INX    H        ; Get 2nd letter
  889.     MVI    A,'O'        ; 2nd letter
  890.     CMP    M        ; Is it 'O' ?
  891.     JNZ    RCVFL7        ; If not, continue normally
  892.     INX    H        ; Get 3rd letter
  893.     MVI    A,'M'        ; 3rd letter
  894.     CMP    M        ; Is it 'M' ?
  895.     JNZ    RCVFL7        ; If not, continue normally
  896.     CALL    ILPRT
  897.     DB    'Renaming file to ".OBJ"',CR,LF,0
  898.     LXI    H,FCB+9
  899.     MVI    M,'O'
  900.     INX    H
  901.     MVI    M,'B'
  902.     INX    H
  903.     MVI    M,'J'
  904.     RET
  905. ;
  906. RCVFL7:    LXI    H,FCB+9        ; Point to filetype
  907.     MVI    A,'P'        ; 1st letter
  908.     CMP    M        ; Is it 'P' ?
  909.     JNZ    RCVFL8        ; If not, continue normally
  910.     INX    H        ; Get 2nd letter
  911.     MVI    A,'R'        ; 2nd letter
  912.     CMP    M        ; Is it 'R' ?
  913.     JNZ    RCVFL8
  914.     INX    H        ; Get 3rd letter
  915.     MVI    A,'L'        ; 3rd letter
  916.     CMP    M        ; Is it 'L' ?
  917.     JNZ    RCVFL8
  918.     CALL    ILPRT
  919.     DB    'Renaming file to ".OBP"',CR,LF,0
  920.     LXI    H,FCB+9
  921.     MVI    M,'O'
  922.     INX    H
  923.     MVI    M,'B'
  924.     INX    H
  925.     MVI    M,'P'
  926.     RET
  927.      ENDIF            ; NOCMR
  928. ;
  929. RCVFL8:     IF    ZCPR
  930.     LXI    H,FCB+9        ; Point to filetype
  931.     MVI    A,'N'        ; 1st letter
  932.     CMP    M        ; Is it 'N' ?
  933.     JNZ    RCVFL9        ; If not, continue normally
  934.     INX    H        ; Get 2nd letter
  935.     MVI    A,'D'        ; 2nd letter
  936.     CMP    M        ; Is it 'D' ?
  937.     JNZ    RCVFL9        ; If not, continue normally
  938.     INX    H        ; Get 3rd letter
  939.     MVI    A,'R'        ; 3rd letter
  940.     CMP    M        ; Is it 'R' ?
  941.     JZ    RCVFL11        ; If yes, print error message and abort
  942. ;
  943. RCVFL9:    LXI    H,FCB+9        ; Point to filetype
  944.     MVI    A,'R'        ; 1st letter
  945.     CMP    M        ; Is it R ?
  946.     JNZ    RCVFL10        ; If not, continue normally
  947.     INX    H        ; Get 2nd letter
  948.     MVI    A,'C'        ; 2nd letter
  949.     CMP    M        ; Is it C ?
  950.     JNZ    RCVFL10        ; If not, continue normally
  951.     INX    H        ; Get 3rd letter
  952.     MVI    A,'P'        ; 3rd letter
  953.     CMP    M        ; Is it P ?
  954.     JZ    RCVFL11        ; Else play error message
  955. ;
  956. RCVFL10:LXI    H,FCB+9        ; Point to filetype
  957.     MVI    A,'S'        ; 1st letter
  958.     CMP    M        ; Is it S ?
  959.     RNZ            ; If not, continue normally
  960.     INX    H        ; Get 2nd letter
  961.     MVI    A,'Y'        ; 2nd letter
  962.     CMP    M        ; Is it Y ?
  963.     RNZ            ; If not, continue normally
  964.     INX    H        ; Get 3rd letter
  965.     MVI    A,'S'        ; 3rd letter
  966.     CMP    M        ; Is it S ?
  967.     JZ    RCVFL11        ; Else play error message
  968.     RET            ; If not, continue normally
  969. ;
  970. RCVFL11:CALL    ERXIT        ; Print renaming message
  971.     DB    CR,LF,'++ Select a different filename extension ++','$'
  972.      ENDIF            ; ZCPR
  973. ;
  974.     RET            ; Just in case ZCPR not used, etc.
  975. ;
  976. ; Displays where the file(s) will go, opens the file and shows the name
  977. ;
  978. CONTIN:    CALL    ILPRT        ; Print the message
  979.     DB    CR,LF
  980.     DB    'Uploads received on  > ',0
  981.     LDA    PRVTFL        ; Going to store in the private area?
  982.     ORA    A
  983.     JZ    CONT1        ; If not, exit
  984.     LDA    XPRDRV        ; Get private drive
  985.     SUI    40H        ; Convert ASCII to binary
  986.     STA    FCB
  987.     LDA    XPRDRV
  988.     JNZ    CONT2        ; If yes, it takes priority
  989. ;
  990. CONT1:     IF    RESUSR AND PUPOPT
  991.     LDA    PUPFLG        ; Get privileged upload status
  992.     ORA    A        ; Privileged xfr option request?
  993.     LDA    XDRV
  994.     JNZ    CONT2        ; Yes, exit, takes next priority
  995.      ENDIF
  996. ;
  997.      IF    ZCPR
  998.     LDA    WHEEL        ; Get WHEEL status
  999.     ORA    A        ; Set?
  1000.     LDA    XDRV
  1001.     JNZ    CONT2        ; Yes, exit, takes next priority
  1002.      ENDIF
  1003. ;
  1004.      IF    SETAREA
  1005.     LDA    XDRV        ; Setarea uses a specified drive
  1006.      ENDIF
  1007. ;
  1008.      IF    NOT SETAREA
  1009.     LDA    OLDDRV        ; Otherwise get current drive
  1010.     ADI    'A'        ; Convert to ASCII
  1011. ;
  1012. NOTDRV:    DB    0,0        ; Filled in by 'GETDU' if requested
  1013.      ENDIF
  1014. ;
  1015. CONT2:    STA    KDRV        ; Save drive for KSHOW
  1016.     CALL    CTYPE        ; Print the drive to store on
  1017.     LDA    PRVTFL        ; Going to store in the private area?
  1018.     ORA    A
  1019.     JZ    NOPRVL        ; If nope, skip ahead
  1020. ;
  1021.      IF    LOGCAL
  1022.     MVI    A,'P'        ; If private upload
  1023.     STA    LOGOPT        ; Show "P" as option
  1024.      ENDIF
  1025. ;
  1026.     LDA    XPRUSR        ; Get private user area
  1027.     JMP    CONT3        ; It takes priority
  1028. ;
  1029. NOPRVL:     IF    SETAREA
  1030.     LDA    XUSR        ; Setarea takes next precedence
  1031.      ENDIF
  1032. ;
  1033.      IF    NOT SETAREA
  1034.     LDA    OLDUSR        ; Get current drive for default
  1035. ;
  1036. NOTUSR:    DB    0,0        ; Filled in by 'GETDU' if requested
  1037.      ENDIF
  1038. ;
  1039. CONT3:    MVI    H,0
  1040.     MOV    L,A
  1041.     CALL    DECOUT        ; Print the user area
  1042.     CALL    ILPRT
  1043.     DB    ':',0
  1044.     CALL    ILPRT
  1045.     DB    CR,LF
  1046.     DB    'Disk space available > ',0
  1047.     CALL    KSHOW        ; Show available space remaining
  1048.     CALL    ILPRT
  1049.     DB    CR,LF,0
  1050.     CALL    CHEKFIL        ; See if file exists
  1051.     CALL    ILPRT
  1052.     DB    CR,LF
  1053.     DB    'Ready to receive your Upload',CR,LF
  1054.     DB    'Abort: CTRL-X <pause> CTRL-X',CR,LF,0
  1055.     LDA    PRVTFL        ; To the private area?
  1056.     ORA    A
  1057.     RNZ            ; Yes, don't mention descriptions
  1058. ;
  1059.      IF    (MSGDSC    OR DESCRIB) AND    RESUSR AND PUPOPT
  1060.     LDA    PUPFLG
  1061.     ORA    A        ; Privileged xfr option request?
  1062.     JZ    CONT5        ; No
  1063. ;
  1064. CONT4:    CALL    ILPRT
  1065.     DB    CR,LF,'No description - PRIVILEGED upload mode',CR,LF,0
  1066.     JMP    CONT6
  1067.      ENDIF
  1068. ;
  1069.      IF    MSGDSC OR DESCRIB
  1070. CONT5:    CALL    ILPRT
  1071.     DB    CR,LF,'Description(s) required after upload',CR,LF,0
  1072.      ENDIF
  1073. ;
  1074. CONT6:    CALL    ILPRTL        ; Display local from here on...
  1075.     DB    CR,LF,LF,'[ waiting ]',0
  1076.     RET
  1077. ;
  1078. ; Got EOT on record so flush buffers then done
  1079. ;
  1080. RCVEOT:    LHLD    RECDNO        ; Check for zero length file
  1081.     MOV    A,H        ; If no records, no file
  1082.     ORA    L
  1083.     JZ    RCVSABT        ; Abort and erase the zero length file
  1084.     CALL    SNDACK        ; Ack the record
  1085.     CALL    WRBLOCK        ; Write the last block
  1086.     CALL    CLOSFIL        ; Close the file
  1087. ;
  1088. ; Write record to log file if LOGCAL is YES
  1089. ;
  1090. RCVEO1:     IF    LOGCAL
  1091.     LHLD    RECDNO        ; If yes, get # of records
  1092.     SHLD    RCNT        ; And stuff in RCNT
  1093.     CALL    XTIM        ; Calculate appoximate transfer time
  1094.     CALL    STORTIM        ; Store the time
  1095.      ENDIF
  1096. ;
  1097.      IF    MSGDSC OR MSGFIL OR LOGCAL
  1098.     CALL    LOGCALL
  1099.      ENDIF
  1100. ;
  1101.      IF    LOGLDS
  1102.     LDA    UPLDS        ; Get Upload Counter
  1103.     INR    A        ; One more upload since log in
  1104.     STA    UPLDS        ; Update Counter
  1105.      ENDIF
  1106. ;
  1107.     CALL    ALLDON        ; If not batch, print xfer complete
  1108. ;
  1109. ; --------------------------------------
  1110. ;
  1111. ; Credit routine
  1112. ;
  1113.      IF    CREDIT
  1114.     LDA    BCHFLG        ; In batch mode now?
  1115.     ORA    A
  1116.     JNZ    CRED1        ; Yes, so skip the rest
  1117.      ENDIF
  1118. ;
  1119.      IF    MBBS AND CREDIT    AND MSGFIL
  1120.     LDA    MSGFLG
  1121.     ORA    A        ; Message file uploaded?
  1122.     JNZ    CRED4        ; Yes, so skip thanks, credit and description
  1123.      ENDIF
  1124. ;
  1125.      IF    CREDIT AND RESUSR AND PUPOPT
  1126.     LDA    PUPFLG        ; Get privileged xfr option flag
  1127.     ORA    A        ; Requested?
  1128.     JNZ    CRED4        ; Else, skip thx, credit and description
  1129.      ENDIF
  1130. ;
  1131.      IF    CREDIT AND ZCPR
  1132.     LDA    WHEEL
  1133.     ORA    A        ; Sysop?
  1134.     JNZ    CRED3        ; Yes, skip the thanks and credit, only
  1135.      ENDIF
  1136. ;
  1137.      IF    CREDIT
  1138.     CALL    ILPRTB        ; Switch remote display on
  1139.     DB    CR,LF,'Thank you for the upload!',CR,LF,0
  1140.     LDA    TLIMIT
  1141.     ORA    A        ; Special user?
  1142.     JZ    CRED3        ; Yes, else say...
  1143. ;
  1144. CRED0:    CALL    ILPRT
  1145.     DB    CR,LF,'The time you took to upload has been added'
  1146.     DB    CR,LF,'to your remaining system time for today.'
  1147.     DB    CR,LF,0
  1148. ;
  1149. CRED1:    LDA    TLIMIT        ; Get user status/MXTIME
  1150.     ORA    A
  1151.     JZ    CRED2        ; Special user -- don't credit
  1152.     LDA    TLIMIT        ; Get MXTIME once more
  1153.     PUSH    PSW        ; Set aside for now
  1154.     LHLD    RECDNO
  1155.     SHLD    RCNT
  1156.     CALL    XTIM        ; Determine upload time
  1157.     POP    PSW        ; Get MXTIME back
  1158.     INR    A        ; Round up 1 minute
  1159.     ADD    C        ; Credit the upload time
  1160.     STA    TLIMIT        ; Save new MXTIME
  1161. ;
  1162. CRED2:    MVI    A,1        ; Set to local display only
  1163.     STA    CONONL
  1164.      ENDIF
  1165. ;
  1166. ; If not still in batch mode, ask for file description
  1167. ;
  1168.     LDA    BCHFLG        ; In batch receive?
  1169.     ORA    A
  1170.     JNZ    CRED4        ; If yes, skip asking for a description
  1171. ;
  1172. ; end of credit routine
  1173. ; ---------------------
  1174. ;
  1175. CRED3:     IF    MSGDSC OR DESCRIB
  1176.     LHLD    1
  1177.     DCX    H
  1178.     MOV    D,M
  1179.     DCX    H
  1180.     MOV    E,M
  1181.     LXI    H,12
  1182.     DAD    D
  1183.     XRA    A
  1184.     MOV    M,A
  1185.     CALL    ASK        ; If yes, ask for description of file
  1186.      ENDIF
  1187. ;
  1188. CRED4:     IF    TIMEON AND (NOT    CLOCK)
  1189.     CALL    ADDTON        ; Update NUBYE's time-on-system byte
  1190.      ENDIF
  1191. ;
  1192.     JMP    DONE
  1193. ;
  1194. ; ===================
  1195. ; BATCH MODE ROUTINES
  1196. ; ===================
  1197. ;
  1198. ; If in batch receive, gets a file name from the buffer then asks for a
  1199. ; description.
  1200. ;
  1201. BCHDCR:    LDA    FILCNT
  1202.     DCR    A
  1203.     STA    FILCNT
  1204. ;
  1205. BCHD1:    LHLD    NBSAVE        ; Get address of next batch filename
  1206.     LXI    D,FCB        ; Where to put it
  1207.     MVI    B,12
  1208.     CALL    MOVE
  1209.     SHLD    NBSAVE        ; Store address for next filename
  1210.     RET
  1211. ;
  1212. ; If receiving batch, increment the file count, store the filename so we
  1213. ; can later ask for a description.
  1214. ;
  1215. BCHINR:    LHLD    NBSAVE        ; Where to put the name
  1216.     LXI    D,FCB        ; Where to get the name
  1217.     XCHG
  1218.     MVI    B,12        ; Move the current file name into buffer
  1219.     CALL    MOVE
  1220.     XCHG
  1221.     SHLD    NBSAVE        ; Store address for next filename
  1222.     LDA    FILCNT        ; Increment the file count
  1223.     INR    A
  1224.     STA    FILCNT
  1225.     RET
  1226. ;
  1227. BCHINR1:LDA    FILCNT
  1228.     CPI    BLIMIT        ; Reached batch xfr limit?
  1229.     RC
  1230.     CALL    ILPRTL
  1231.     DB    CR,LF
  1232.     DB    '++ Batch uploads limit has been reached ++',CR,LF,0
  1233.     XRA    A
  1234.     STA    BCHFLG        ; Reset the batch mode flag to zero
  1235.     POP    H        ; Reset stack from "CALL BCHINR"
  1236.     JMP    CRED4        ; Update TOS byte and exit
  1237. ;
  1238. ; Loads a command line addressed by 'DE' registers (max # characters in
  1239. ; line in 'DE', number of characters in line in DE+1, line starts in
  1240. ; DE+2) into FCB addressed by 'HL' registers.  The FCB should be at
  1241. ; least 33 bytes in length.  The command line buffer must have a maxi-
  1242. ; mum length at least one more than the greatest number of characters
  1243. ; that will be needed.
  1244. ;
  1245. CMDLINE:PUSH    PSW
  1246.     PUSH    B
  1247.     PUSH    D
  1248.     PUSH    H
  1249.     CALL    INITIAL        ; Fills FCBs with blanks and nulls
  1250.     XCHG            ; Get start of command line in HL
  1251.     INX    H        ; Address # bytes in command line
  1252.     MOV    E,M        ; Load DE pair with # bytes
  1253.     MVI    D,0
  1254.     INX    H
  1255.     DAD    D        ; Point to byte after last character
  1256.     MVI    M,CR        ; In command line and store delimiter
  1257.     POP    H        ; Restore HL and DE
  1258.     POP    D
  1259.     PUSH    D
  1260.     PUSH    H
  1261.     INX    D        ; Address start of command
  1262.     INX    D
  1263.     CALL    DRIVEX
  1264.     MVI    C,8        ; Transfer first filename to FCB
  1265.     CALL    TRANS
  1266.     CPI    CR
  1267.     JZ    DONEL
  1268.     CPI    ' '        ; If space, then start of 2nd filename
  1269.     JZ    NAME1
  1270.     POP    H        ; Filetype starts after 8th byte
  1271.     PUSH    H
  1272.     LXI    B,9
  1273.     DAD    B
  1274.     MVI    C,3        ; Transfer type of first file
  1275.     CALL    TRANS
  1276.     CPI    CR
  1277.     JZ    DONEL
  1278. ;
  1279. NAME1:    LDAX    D        ; Eat multiple spaces between names
  1280.     CPI    ' '
  1281.     JNZ    NAME2
  1282.     INX    D
  1283.     JMP    NAME1
  1284. ;
  1285. NAME2:    POP    H        ; Second name starts in 16th byte
  1286.     PUSH    H        ; Point HL to this byte
  1287.     LXI    B,16
  1288.     DAD    B
  1289.     CALL    DRIVEX
  1290.     MVI    C,8
  1291.     CALL    TRANS
  1292.     CPI    CR
  1293.     JZ    DONEL
  1294.     POP    H        ; Second file type starts in 25th byte
  1295.     PUSH    H
  1296.     LXI    B,25
  1297.     DAD    B
  1298.     MVI    C,3
  1299.     CALL    TRANS
  1300. ;
  1301. DONEL:    POP    H
  1302.     PUSH    H
  1303.     INX    H        ; Point to 1st char of 1st name in FCB
  1304.     CALL    SCANL        ; Check for * (ambiguous names)
  1305.     POP    H
  1306.     PUSH    H
  1307.     LXI    B,17        ; To 1st character of second name in FCB
  1308.     DAD    B
  1309.     CALL    SCANL
  1310.     POP    H
  1311.     POP    D
  1312.     POP    B
  1313.     POP    PSW
  1314.     RET
  1315. ;
  1316. ; Subroutines for CMDLINE section
  1317. ;
  1318. INITIAL:PUSH    H        ; Initializes FCB with 1 null for first
  1319.     PUSH    B        ;  drive with 11 blanks, 4 nulls, 1
  1320.     MVI    M,0        ;  null for second drive with 11 blanks
  1321.     INX    H        ;  and 4 nulls
  1322.     MVI    B,11
  1323.     MVI    A,' '
  1324.     CALL    INITFILL
  1325.     MVI    B,5
  1326.     XRA    A
  1327.     CALL    INITFILL
  1328.     MVI    B,11
  1329.     MVI    A,' '
  1330.     CALL    INITFILL
  1331.     MVI    B,4
  1332.     XRA    A
  1333.     CALL    INITFILL
  1334.     POP    B
  1335.     POP    H
  1336.     RET
  1337. ;
  1338. INITFILL:
  1339.     MOV    M,A
  1340.     INX    H
  1341.     DCR    B
  1342.     JNZ    INITFILL
  1343.     RET
  1344. ;
  1345. ; Show batch files remaining after this one is sent
  1346. ;
  1347. CUMSTS:    CALL    ILPRTL
  1348.     DB    CR,LF
  1349.     DB    'Files remaining                > ',0
  1350.     LDA    SHOCNT        ; Get cumulative files
  1351.     DCR    A
  1352.     STA    SHOCNT        ; Less one
  1353.     MOV    L,A
  1354.     MVI    H,0
  1355.     CALL    DECOUT
  1356.     CALL    ILPRT
  1357.     DB    CR,LF
  1358.     DB    'Xmodem packets remaining       > ',0
  1359.     LHLD    RCNT        ; Get this file's record count again
  1360.     XCHG            ; Put in DE
  1361.     LHLD    TOTREC        ; Total records remaining
  1362.     MOV    A,L
  1363.     SUB    E
  1364.     MOV    L,A
  1365.     MOV    A,H
  1366.     SBB    D
  1367.     MOV    H,A
  1368.     JNC    $+6
  1369.     LXI    H,0        ; In case of a slightly negative number
  1370.     SHLD    TOTREC
  1371.     PUSH    H
  1372.     CALL    DECOUT        ; Show remaining records
  1373.     CALL    ILPRT
  1374.     DB    CR,LF
  1375.     DB    'Ymodem packets remaining       > ',0
  1376.     POP    H
  1377.     CALL    DIVREC        ; Divide number of records by 8
  1378.     CALL    DECOUT
  1379.     CALL    ILPRT
  1380.     DB    CR,LF,0
  1381.     RET
  1382. ;
  1383. ; -----
  1384. ;
  1385. DRIVEX:    INX    D        ; Check 2nd byte of filename.  if it..
  1386.     LDAX    D        ; Is a ":", then drive was specified..
  1387.     DCX    D
  1388.     CPI    ':'
  1389.     JNZ    DEFDR        ; Else zero for default drive
  1390.     LDAX    D        ; ('INIT' put zero)
  1391.     ANI    5FH
  1392.     SUI    40H        ; Calculate drive (A=1, B=2,...)
  1393.     MOV    M,A        ; Place it in FCB
  1394.     INX    D        ; Address first byte in command line
  1395.     INX    D
  1396. ;
  1397. DEFDR:    INX    H        ; And name field in FCB
  1398.     RET
  1399. ;
  1400. ; -----
  1401. ;
  1402. ; Clears the FCB area
  1403. ;
  1404. INITFCB:MVI    M,0        ; Clears the drive
  1405. ;
  1406. INITFCB1:
  1407.     INX    H
  1408.     MVI    B,11        ; Clears the filename and extent area
  1409. ;
  1410. LOOP11:    MVI    M,' '
  1411.     INX    H
  1412.     DCR    B
  1413.     JNZ    LOOP11
  1414.     MVI    B,21        ; Clears the rest with zeros
  1415. ;
  1416. LOOP21:    MVI    M,0
  1417.     INX    H
  1418.     DCR    B
  1419.     JNZ    LOOP21
  1420.     RET
  1421. ;
  1422. ; Finished with the file transfer
  1423. ;
  1424. DONE:    LDA    BCHFLG        ; In batch mode now?
  1425.     ORA    A
  1426.     JZ    EXIT        ; If not, all done so go finish up
  1427.     LDA    OLDDRV        ; Restore the original drive
  1428.     CALL    RECDRX
  1429.     LDA    OLDUSR        ; Restore the original number
  1430.     CALL    RECARE
  1431.     CALL    RSTDMA        ; Reset to default DMA
  1432.     MVI    B,12        ; Zero out DONE6
  1433.     LXI    H,DONE6
  1434. ;
  1435. ; Null the batch file name buffer
  1436. ;
  1437. DONE1:    MVI    M,0        ; Zero the memory location
  1438.     INX    H
  1439.     DCR    B
  1440.     JNZ    DONE1        ; Zero all 12 locations
  1441. ;
  1442. ; Now fill in the batch file name
  1443. ;
  1444.     MVI    B,12        ; Put file name in DONE6
  1445.     LXI    H,FCB+1
  1446.     LXI    D,DONE6
  1447. ;
  1448. DONE2:    MVI    A,4        ; Start of file type?
  1449.     CMP    B
  1450.     JZ    DONE4        ; Put in period if so
  1451.     MOV    A,M
  1452.     CPI    ' '        ; Don't put in space
  1453.     JZ    DONE3
  1454.     STAX    D        ; Store in DONE6
  1455.     INX    D
  1456. ;
  1457. DONE3:    INX    H
  1458.     DCR    B
  1459.     MOV    A,B
  1460.     ORA    A        ; End of file name?
  1461.     JZ    DONE5        ; Display file name
  1462.     JMP    DONE2        ; Loop for another character
  1463. ;
  1464. DONE4:    MOV    A,M
  1465.     CPI    ' '        ; Is file type empty?
  1466.     JZ    DONE5        ; Go if so
  1467.     MVI    A,'.'        ; Else put period in message
  1468.     STAX    D
  1469.     INX    D
  1470.     DCR    B
  1471.     JMP    DONE2
  1472. ;
  1473. DONE5:    MVI    A,1        ; Display filename locally only
  1474.     STA    GOTONE        ; Indicates there was a file handled
  1475.     CALL    ILPRTL        ; Display the file name locally only
  1476.     DB    CR,LF
  1477. ;
  1478. DONE6:    DB    0,0,0,0,0,0,0
  1479.     DB    0,0,0,0,0,0
  1480.     CALL    ILPRTL
  1481.     DB    ' transferred',CR,LF,LF,0
  1482. ;
  1483. ; Now reset some flags for another possible batch file
  1484. ;
  1485.     XRA    A
  1486.     STA    EOFLG        ; Clear end of file flag
  1487.     STA    EOTFLG        ; And end of transmission flag
  1488.     STA    CHKEOT        ; And the "resend EOT" flag
  1489.     LXI    H,0
  1490.     SHLD    ACCERR        ; Reset the accumulate error count
  1491.     SHLD    RECNBF        ; Zero number of records in the buffer
  1492.     SHLD    RECDNO        ; Zero the current record number
  1493.     SHLD    RCDCNT        ; Zero the transmit record counter
  1494.     LXI    H,DBUF        ; Reset buffer pointers
  1495.     SHLD    RECPTR
  1496.     LDA    SNDFLG        ; Goes to either send or
  1497.     ORA    A        ; Receive file, depending
  1498.     JZ    SNDFL        ; Upon which routine set
  1499.     CALL    BCHINR1        ; Store filename, increment count, chk limit
  1500.     JMP    RCVFL        ; The flag in multi-file mode
  1501. ;
  1502. ; -----
  1503. ;
  1504. ; Multi-file access subroutine.  Allows processing of multiple files
  1505. ; (i.e., *.ASM) from disk.  Builds the correct name in the FCB each time
  1506. ; it is called.  The command is used in programs to process single or
  1507. ; multiple files.  The FCB is set up with the next name, ready to do
  1508. ; normal processing (open, read, etc.) when routine is called.    Carry is
  1509. ; set if no more names are found.
  1510. ;
  1511. MFNAM:    PUSH    B
  1512.     PUSH    D
  1513.     PUSH    H
  1514.     CALL    RSTDMA        ; Reset to default DMA
  1515.     POP    H
  1516.     POP    D
  1517.     POP    B
  1518.     XRA    A
  1519.     STA    FCBEXT
  1520.     LDA    MFFLG1
  1521.     ORA    A
  1522.     JNZ    MFNAM1
  1523.     MVI    A,1
  1524.     STA    MFFLG1
  1525.     LXI    H,FCB
  1526.     LXI    D,MFNAM5
  1527.     LXI    B,12
  1528.     CALL    MOVER
  1529.     LDA    FCB
  1530.     STA    MFNAM6        ; Save disk in current FCB
  1531.     LXI    H,MFNAM5
  1532.     LXI    D,FCB
  1533.     LXI    B,12
  1534.     CALL    MOVER
  1535.     PUSH    B
  1536.     PUSH    D
  1537.     PUSH    H
  1538.     CALL    FILSCH
  1539.     POP    H
  1540.     POP    D
  1541.     POP    B
  1542.     JMP    MFNAM2
  1543. ;
  1544. MFNAM1:    LXI    H,MFNAM6
  1545.     LXI    B,12
  1546.     LXI    D,FCB
  1547.     CALL    MOVER
  1548.     PUSH    B
  1549.     PUSH    D
  1550.     PUSH    H
  1551.     CALL    FILSCH
  1552.     POP    H
  1553.     POP    D
  1554.     POP    B
  1555.     LXI    H,MFNAM5
  1556.     LXI    B,12
  1557.     LXI    D,FCB
  1558.     CALL    MOVER
  1559.     PUSH    B
  1560.     PUSH    D
  1561.     PUSH    H
  1562.     MVI    C,SRCHN
  1563.     CALL    FCBSET
  1564.     POP    H
  1565.     POP    D
  1566.     POP    B
  1567. ;
  1568. MFNAM2:    INR    A
  1569.     STC
  1570.     JNZ    MFNAM3
  1571.     STA    MFFLG1
  1572.     RET
  1573. ;
  1574. MFNAM3:    DCR    A
  1575.     ANI    3
  1576.     ADD    A
  1577.     ADD    A
  1578.     ADD    A
  1579.     ADD    A
  1580.     ADD    A
  1581.     ADI    81H
  1582.     MOV    L,A
  1583.     MVI    H,0
  1584.     PUSH    H        ; Save name pointer
  1585.     LXI    D,MFNAM6+1
  1586.     LXI    B,11
  1587.     CALL    MOVER
  1588.     POP    H
  1589.     LXI    D,FCB+1
  1590.     LXI    B,11
  1591.     CALL    MOVER
  1592.     XRA    A
  1593.     STA    FCBEXT
  1594.     STA    FCBRNO
  1595.     RET
  1596. ;
  1597. MOVER:
  1598. MFNAM4:    MOV    A,M        ; Used if an 8080 CPU is active
  1599.     STAX    D
  1600.     INX    H
  1601.     INX    D
  1602.     DCX    B
  1603.     MOV    A,B
  1604.     ORA    C
  1605.     JNZ    MFNAM4
  1606.     RET
  1607. ;
  1608. ; end of multi-file access routine
  1609. ; --------------------------------
  1610. ;
  1611. ; NUKMD receive batch mode
  1612. ;
  1613. RCVFN:    LXI    H,FCB
  1614.     CALL    INITFCB1    ; Does not initialize drive
  1615.     XRA    A
  1616.     STA    RCVTRY
  1617.     INR    A        ; Set to local display only
  1618.     STA    CONONL
  1619. ;
  1620. RNUK1:    CALL    CKABORT        ; Check for user abort
  1621.     MVI    B,3        ; Wait up to 3 sec. for SOH from remote
  1622.     CALL    RECV
  1623.     JC    RNUK2        ; No character, decrement counter
  1624.     CPI    CANCEL        ; ^X?
  1625.     JZ    ABORTX        ; Abort if yes
  1626.     CPI    SOH
  1627.     JZ    RNUK4        ; Got SOH
  1628.     JMP    RNUK1        ; None of these, wait some more
  1629. ;
  1630. RNUK2:    MVI    A,CRC        ; Send a 'C'
  1631.     CALL    SEND
  1632. ;
  1633. RNUK3:    LDA    RCVTRY
  1634.     INR    A
  1635.     STA    RCVTRY
  1636.     CPI    33
  1637.     JC    RNUK1
  1638.     JMP    ABORT        ; Quit and try to force him to quit also
  1639. ;
  1640. RNUK4:    MVI    B,5        ; 5 seconds to get sector number
  1641.     CALL    RECV
  1642.     JC    NUKTOT
  1643.     MOV    D,A        ; Save sector number in D
  1644.     ORA    A        ; Must be a 0 if sending batch
  1645.     JNZ    NUKHDR
  1646.     MVI    B,5        ; 5 seconds to get reciprocal
  1647.     CALL    RECV
  1648.     JC    NUKTOT
  1649.     CMA            ; Invert it and compare to sector #
  1650.     CMP    D
  1651.     JNZ    NUKCRC        ; Bad match
  1652.     LXI    H,0
  1653.     SHLD    CRCVAL        ; Clear CRC counter
  1654.     MVI    E,128        ; Expecting a 128 character block
  1655.     LHLD    RECPTR        ; Point to the buffer address
  1656. ;
  1657. RNUK5:    MVI    B,5        ; 5 seconds to get 128 byte header block
  1658.     CALL    RECV        ; Get the character
  1659.     JC    NUKTOT        ; Exit if no character
  1660.     MOV    M,A        ; Store the character
  1661.     INX    H        ; Point to next buffer location
  1662.     DCR    E        ; One less to go
  1663.     JNZ    RNUK5        ;
  1664.     MVI    E,2        ; Number of CRC bytes to get
  1665. ;
  1666. RNUK6:    MVI    B,5
  1667.     CALL    RECV        ; Get CRC bytes
  1668.     JC    NUKTOT
  1669.     DCR    E        ; Done?
  1670.     JNZ    RNUK6        ; No
  1671.     CALL    CRCCHK        ; Compare CRC received against ours
  1672.     ORA    A        ; Ok?
  1673.     JNZ    NUKCRC        ; No
  1674.     CALL    SNDACK        ; Yes, acknowledge to remote
  1675. ;
  1676. ; Decode pathname into CPM format
  1677. ;
  1678.     LXI    D,FCB+1        ; Where to put it
  1679.     LHLD    RECPTR        ; Where to get it
  1680.     MVI    B,8        ; Filename length
  1681. ;
  1682. RNUK7:    MOV    A,M        ; Get the character from the buffer
  1683.     ORA    A        ; 0?
  1684.     JZ    RNUK12        ; If yes, all done
  1685.     CPI    '.'        ; Delimiter?
  1686.     JZ    RNUK9        ; Yes
  1687. ;
  1688. RNUK8:    CALL    UCASE        ; Insure name is in upper case
  1689.     CPI    '_'        ; Underline?
  1690.     JNZ    RNUK8A        ; No, else...
  1691.     MVI    A,'-'        ; Change to dash for CP/M
  1692. ;
  1693. RNUK8A:    STAX    D        ; Store filename character in FCB
  1694.     INX    D        ; Increment pointers
  1695.     INX    H
  1696.     DCR    B        ; One less to go
  1697.     JNZ    RNUK7        ; If not 8, keep going
  1698.     MOV    A,M        ; Get the character back
  1699.     ORA    A        ; 0?
  1700.     JZ    RNUK11        ; Yes, all done
  1701.     JMP    RNUK10        ; Else must be a '.'
  1702. ;
  1703. RNUK9:    MVI    A,' '        ; Spaces to make up 8 spaces for name
  1704.     STAX    D        ; Store space character in FCB
  1705.     INX    D        ; Increment pointers
  1706.     DCR    B        ; One less to go
  1707.     JNZ    RNUK9        ; Keep going until in extent area
  1708. ;
  1709. RNUK10:    INX    H        ; Skip the '.' position
  1710.     MVI    B,3        ; Extent length
  1711. ;
  1712. RNUK11:    MOV    A,M        ; Get the character from the buffer
  1713.     ORA    A        ; 0?
  1714.     JZ    RNUK12        ; Yes, all done
  1715.     CALL    UCASE        ; Insure extent is in upper case
  1716.     STAX    D        ; Store extent character
  1717.     INX    D        ; Increment pointers
  1718.     INX    H
  1719.     DCR    B        ; One less to go
  1720.     JNZ    RNUK11        ; Keep going until finished
  1721. ;
  1722. RNUK12:    LDA    FCB+1
  1723.     CPI    ' '        ; Any filename?
  1724.     STC            ; Set carry flag
  1725.     RZ            ; No, all done, no more files
  1726.     CALL    ILPRTL
  1727.     DB    CR,'Name of this file              > ',0
  1728.     LHLD    RECPTR        ; Print filename
  1729. ;
  1730. RNUK13:    MOV    A,M
  1731.     ORA    A
  1732.     JZ    RNUK14
  1733.     CALL    UCASE
  1734.     CALL    CTYPE
  1735.     INX    H
  1736.     JMP    RNUK13
  1737. ;
  1738. RNUK14:    LHLD    BUFSTR        ; Get the file length, if provided
  1739.     MOV    A,H
  1740.     ORA    L
  1741.     JZ    RNUK15        ; If both zero, length not provided
  1742.     SHLD    RCNT        ; Store the file length
  1743.     CALL    OPNOK3
  1744.     CALL    ILPRT
  1745.     DB    CR,LF
  1746.     DB    'Ymodem transfer time           > ',0
  1747.     CALL    KTIM
  1748.     CALL    OPNOK4
  1749. ;
  1750. RNUK15:    CALL    ILPRT
  1751.     DB    CR,LF,0        ; Finish the filename line
  1752.     XRA    A        ; Reset the carry flag
  1753.     STA    RCVTRY        ; Reset the error counter
  1754.     RET
  1755. ;
  1756. NUKCRC:    CALL    ILPRTL
  1757.     DB    '++ CRC error ++',CR,LF,0
  1758.     JMP    NUKXFR
  1759. ;
  1760. NUKHDR:    CALL    ILPRTL
  1761.     DB    '++ Wrong header type ++',CR,LF,0
  1762.     JMP    NUKXFR
  1763. ;
  1764. NUKTOT:    CALL    ILPRTL
  1765.     DB    ' ++ Timeout receiving filename ++',CR,LF,0
  1766. ;
  1767. NUKXFR:    CALL    WAIT1        ; Make sure sender has stopped
  1768.     CALL    WAIT1
  1769.     MVI    A,NAK
  1770.     CALL    SEND        ; Tell sender not successful
  1771.     LDA    RCVTRY        ; Get error counter
  1772.     INR    A        ; Increment it
  1773.     STA    RCVTRY        ; Store it
  1774.     CPI    33
  1775.     JC    RNUK3        ; Send a NAK and tell him to try again
  1776.     JMP    ABORT        ; Else abort
  1777. ;
  1778. ; end of get batch file name
  1779. ; --------------------------
  1780. ;
  1781. ; NUKMD send batch mode
  1782. ;
  1783. SNDFN:
  1784. SNDNUK:    LXI    H,FCB
  1785.     CALL    INITFCB1    ; Does not initialize drive
  1786.     XRA    A
  1787.     STA    ERRCT        ; Reset the error count
  1788.     CALL    CATCH        ; Clear the decks for action
  1789.     MVI    E,60        ; Wait up to 60 seconds to abort
  1790. ;
  1791. CCHECK:    CALL    CKABORT        ; Manually requesting an abort?
  1792.     MVI    B,1        ; Wait up to 1 second for a character
  1793.     CALL    RECV
  1794.     JC    CCHECK1        ; No character, decrement counter
  1795.     CPI    CANCEL        ; If they sent a ^X, abort now
  1796.     JZ    ABORT
  1797.     CPI    CRC        ; If they sent a CRC, go to work
  1798.     JZ    SNUK0
  1799.     JMP    CCHECK        ; None of these, wait some more
  1800. ;
  1801. CCHECK1:DCR    E        ; One less to go
  1802.     JNZ    CCHECK
  1803.     JMP    ACKMSG        ; Abort if timed out and no character
  1804. ;
  1805. SNUK0:    MVI    A,1
  1806.     STA    CRCFLG        ; Make sure in CRC mode
  1807.     LDA    FILCNT        ; Get the file count
  1808.     DCR    A        ; Decrement it for this one
  1809.     STA    FILCNT
  1810.     JM    NUKEND        ; If no more files, abort
  1811.     CALL    BCHD1        ; Get the name into FCB
  1812.     LHLD    RECPTR        ; Where to load the 0 block
  1813.     XCHG            ; Put into DE
  1814.     LXI    H,FCB+1        ; Get the start of the filname in HL
  1815.     MVI    B,8
  1816. ;
  1817. SNUK1:    MOV    A,M
  1818.     ANI    7FH        ; Strip any high bit set
  1819.     ORA    A
  1820.     JZ    SNUK6        ; Null pathname
  1821.     CPI    ' '
  1822.     JZ    SNUK3
  1823. ;
  1824. SNUK2:    CALL    LCASE        ; Put file name in lower case for UNIX
  1825.     STAX    D
  1826.     INX    H
  1827.     INX    D
  1828.     DCR    B
  1829.     JNZ    SNUK1
  1830.     JMP    SNUK4
  1831. ;
  1832. SNUK3:    INX    H        ; Skip over spaces if short name
  1833.     DCR    B
  1834.     JNZ    SNUK3
  1835. ;
  1836. SNUK4:    MOV    A,M
  1837.     CPI    ' '
  1838.     JZ    SNUK6        ; Missing file type field
  1839.     MVI    A,'.'        ; Send name-type seperator
  1840.     STAX    D
  1841.     INX    D
  1842.     MVI    B,3
  1843. ;
  1844. SNUK5:    MOV    A,M
  1845.     ANI    7FH        ; Strip any high bit set
  1846.     CPI    ' '
  1847.     JZ    SNUK6
  1848.     CALL    LCASE        ; Put in lower case for UNIX
  1849.     STAX    D
  1850.     INX    H
  1851.     INX    D
  1852.     DCR    B
  1853.     JNZ    SNUK5
  1854. ;
  1855. SNUK6:    XCHG            ; Get the address back to HL
  1856. ;
  1857. SNUK7:    MVI    M,0        ; Fill rest of block with zeroes
  1858.     INR    L
  1859.     JNZ    SNUK7
  1860.     CALL    CNREC        ; Get number of records in this file
  1861.     LHLD    RCNT
  1862.     SHLD    BUFSTR        ; Store the file length at end of block
  1863.     XRA    A        ; Make sure the header starts with Zero
  1864.     STA    RCDCNT
  1865. ;
  1866. ; Now send the 128-byte file name record
  1867. ;
  1868. SNUK8:    XRA    A
  1869.     STA    KFLG
  1870.     MVI    A,SOH        ; Send SOH
  1871.     CALL    SEND
  1872.     CALL    SNDHNM        ; Send header (record number, inverse)
  1873.     CALL    SNDREC        ; Send a 128 byte record
  1874.     CALL    SNDCRC        ; Send a two byte CRC
  1875.     MVI    B,5
  1876.     CALL    RECV        ; Get acknowledgement of good send
  1877.     CPI    ACK
  1878.     JNZ    NUKBAD        ; Bad name send
  1879.     LDA    MSPEED        ; Check speed being used
  1880.     CPI    5
  1881.     JC    SNUK9        ; Don't allow 1k blocks if 300 bps
  1882.     LDA    NOISY
  1883.     ORA    A        ; Has noise caused a step-down?
  1884.     JNZ    SNUK9        ; Yes, else
  1885.     MVI    A,1
  1886.     STA    KFLG        ; Change to 1k for Ymodem
  1887. ;
  1888. SNUK9:    XRA    A        ; Clear the carry flag
  1889.     STA    ERRCT        ; Start fresh for the main file
  1890.     RET
  1891. ;
  1892. NUKBAD:    CPI    CANCEL        ; Cancel (^X)?
  1893.     JZ    ABORT        ; Yes, abort
  1894.     CALL    ILPRTL        ; Bad name block
  1895.     DB    '++ CRC error ++',CR,LF,0
  1896.     LDA    ERRCT        ; Increment the error counter
  1897.     INR    A
  1898.     STA    ERRCT
  1899.     CPI    10        ; Timed out?
  1900.     JC    SNUK8        ; No, try again
  1901.     JMP    ACKMSG        ; Else abort
  1902. ;
  1903. NUKEND:    XRA    A        ; Reset the pointers
  1904.     LHLD    RECPTR
  1905.     MOV    M,A
  1906.     STA    RCDCNT        ; Reset the record counter
  1907.     STA    KFLG        ; Show in 128 size now
  1908.     MVI    A,SOH        ; Send a start of header
  1909.     CALL    SEND
  1910.     CALL    SNDHNM        ; This header is a zero count
  1911.     CALL    SNDREC        ; Send an empty record
  1912.     CALL    SNDCRC        ; Send the CRC for the empty record
  1913.     STC            ; Set the carry flag to show all done
  1914.     RET
  1915. ;
  1916. ; end of send batch name
  1917. ; ----------------------
  1918. ;
  1919. ; Scans CMDBUF counting names and putting delimiter (space) after last
  1920. ; name
  1921. ;
  1922. SCAN:    LXI    D,CMDBUF    ; Save original TBUF contents in CMDBUF
  1923.     LXI    H,TBUF
  1924.     MVI    B,128
  1925.     CALL    MOVE
  1926.     LXI    H,CMDBUF
  1927.     MOV    C,M
  1928.     MVI    B,0
  1929.     INX    H
  1930.     DAD    B        ; Now pointing at space after last char
  1931.     MVI    M,' '        ; Put in the space
  1932.     LXI    H,CMDBUF    ; Get the count again
  1933.     MOV    B,M
  1934.     INX    H        ; Skip the first space
  1935.     INR    B
  1936. ;
  1937. SCAN1:    INX    H        ; On first entry HL points to 1st char
  1938.     DCR    B        ; 1st go-thru B is count to last space
  1939.     JZ    SCAN5
  1940.     MOV    A,M        ; Look for the first space
  1941.     CPI    ' '
  1942.     JNZ    SCAN1
  1943. ;
  1944. SCAN2:    INX    H        ; Eat extra spaces
  1945.     DCR    B
  1946.     JZ    SCAN5
  1947.     MOV    A,M
  1948.     CPI    ' '
  1949.     JZ    SCAN2
  1950.     SHLD    BGNMS        ; Save start of names in TBUFF
  1951.     INR    B
  1952.     DCX    H
  1953. ;
  1954. SCAN3:    INX    H
  1955.     DCR    B
  1956.     JZ    SCAN5
  1957.     MOV    A,M
  1958.     CPI    ' '
  1959.     JNZ    SCAN3
  1960.     LDA    NAMECT        ; Counts names
  1961.     INR    A
  1962.     STA    NAMECT
  1963. ;
  1964. SCAN4:    INX    H        ; Eat spaces
  1965.     DCR    B
  1966.     JZ    SCAN5
  1967.     MOV    A,M
  1968.     CPI    ' '
  1969.     JZ    SCAN4
  1970.     JMP    SCAN3
  1971. ;
  1972. SCAN5:    LDA    NAMECT        ; Were there any names?
  1973.     ORA    A
  1974.     RNZ            ; Yes
  1975.     POP    H        ; Remove calls from stack
  1976.     POP    H
  1977.     JMP    OPTERR        ; Bail out to avoid BDOS error
  1978. ;
  1979. SCANL:    MVI    B,8        ; Scan file name addressed by HL
  1980. ;
  1981. TSTNAM:    MOV    A,M
  1982.     CPI    '*'        ; If '*' found, fill in rest of field
  1983.     JZ    FILL1        ; With '?' for ambiguous name.
  1984.     INX    H
  1985.     DCR    B
  1986.     JNZ    TSTNAM
  1987.     JMP    FILL2
  1988. ;
  1989. FILL1:    CALL    FILL4
  1990. ;
  1991. FILL2:    MVI    B,3        ; Scan and fill name 'type' field
  1992. ;
  1993. FILL3:    MOV    A,M        ; Specified above
  1994.     CPI    '*'
  1995.     JZ    FILL4
  1996.     INX    H
  1997.     DCR    B
  1998.     JNZ    FILL3
  1999.     RET
  2000. ;
  2001. FILL4:    MVI    M,'?'        ; Routine transfers '?'
  2002.     INX    H
  2003.     DCR    B
  2004.     JNZ    FILL4
  2005.     RET
  2006. ;
  2007. ; -----
  2008. ;
  2009. ; Show the file name (locally) as stored in the FCB but in CP/M format
  2010. ;
  2011. SHOWFIL:CALL    ILPRTL
  2012.     DB    CR,'Name of this file              > ',0
  2013.     LXI    H,FCB+1
  2014.     XRA    A
  2015.     STA    FTYCNT
  2016.     MVI    C,11
  2017. ;
  2018. PRNAM:    CALL    FTYTST
  2019.     INX    H
  2020.     DCR    C
  2021.     JNZ    PRNAM
  2022.     RET
  2023. ;
  2024. FTYTST:    LDA    FTYCNT
  2025.     INR    A
  2026.     STA    FTYCNT
  2027.     CPI    9        ; Are we at the file type?
  2028.     JZ    SPCTST        ; Go if so
  2029. ;
  2030. ENDSPT:    MOV    A,M
  2031.     CPI    ' '        ; Test for space
  2032.     CNZ    CTYPE        ; Type if not
  2033.     RET
  2034. ;
  2035. SPCTST:    MOV    A,M
  2036.     CPI    ' '        ; Test for space in 1st file type byte
  2037.     RZ            ; Do not output period if space
  2038.     MVI    A,'.'
  2039.     CALL    CTYPE
  2040.     JMP    ENDSPT        ; Output 1st file type byte
  2041. ;
  2042. ; -----
  2043. ;
  2044. ; Loads the batch file names into the storage buffer
  2045. ;
  2046. TNMBUF:    XRA    A
  2047.     STA    FILCNT        ; Reset the file count
  2048.     CALL    SCAN
  2049.     LXI    H,NAMBUF    ; Start of buffer into NBSAVE
  2050.     SHLD    NBSAVE        ; Save address of 1st name
  2051. ;
  2052. TNLP1:    CALL    TRTOBUF        ; Move a filename into FCBBUF
  2053.     LXI    H,FCB
  2054.     LXI    D,FCBBUF
  2055.     CALL    CMDLINE        ; Parse name to CP/M format
  2056. ;
  2057. TNLP2:    CALL    MFNAM        ; Search for names (wildcard format)
  2058.     JC    NEXTNM
  2059.     MVI    C,FILSIZ
  2060.     CALL    FCBSET
  2061.     LHLD    RANDOM        ; Get number of records in this file
  2062.     MOV    A,H
  2063.     ORA    L
  2064.     JZ    TNLP2        ; If no records, don't copy this file
  2065.     SHLD    DIRSIZ        ; Save temporarily
  2066. ;
  2067.      IF    ZCPR
  2068.     LDA    WHEEL
  2069.     ORA    A        ; WHEEL byte set for SYSOP use?
  2070.     JNZ    TNLP3        ; If yes, let him transfer any file
  2071.      ENDIF
  2072. ;
  2073.     LDA    FCB+1        ; Tagged library file to not send?
  2074.     ANI    80H
  2075.     JNZ    TNLP2        ; If set, do not send
  2076.     LDA    FCB+2        ; Special tag?
  2077.     ANI    80H
  2078.     JNZ    TNLP2        ; If set, do not send
  2079.     LDA    FCB+10        ; It is a .SYS file?
  2080.     ANI    80H
  2081.     JNZ    TNLP2        ; If set, do not send
  2082. ;
  2083.      IF    SNDWILD    OR SNDCOM
  2084.     LXI    H,FCB+11    ; Last character in the file extent
  2085.     MOV    A,M
  2086.     ANI    7FH        ; Strip off the high bit
  2087.      ENDIF
  2088. ;
  2089.      IF    SNDWILD
  2090.     CPI    '#'        ; Wildcard designator (? or *)?
  2091.     JZ    TNLP2        ; Yes, so don't send
  2092.      ENDIF
  2093. ;
  2094.      IF    SNDCOM
  2095.     CPI    'M'        ; M?
  2096.     JNZ    TNLP3        ; If not, file is ok to send
  2097.     DCX    H
  2098.     MOV    A,M
  2099.     ANI    7FH        ; strip any high bit
  2100.     CPI    'O'        ; O?
  2101.     JNZ    TNLP3        ; If not, file is ok to send
  2102.     DCX    H
  2103.     MOV    A,M
  2104.     ANI    7FH        ; Strip off any high bit set
  2105.     CPI    'C'        ; C?
  2106.     JZ    TNLP2        ; If yes, ignore file
  2107.      ENDIF
  2108. ;
  2109. TNLP3:    LHLD    NBSAVE        ; Get the filename
  2110.     LXI    D,FCB        ; Move it to FCB
  2111.     XCHG
  2112.     MVI    B,12
  2113.     CALL    MOVE
  2114.     XCHG
  2115.     SHLD    NBSAVE        ; Address of next name
  2116.     LDA    FILCNT        ; Count files found
  2117.     INR    A
  2118.     STA    FILCNT
  2119. ;
  2120. ; Add up the total records for all files to be sent
  2121. ;
  2122.     LHLD    DIRSIZ        ; Get number of records in this file
  2123.     PUSH    H        ; Save for later
  2124.     XCHG            ; Put record count into 'DE'
  2125.     LHLD    TOTREC        ; Get record count up to this file
  2126.     DAD    D        ; Add this file to previous total
  2127.     SHLD    TOTREC        ; New total record count
  2128.     POP    H        ; Get the length of this file
  2129.     LXI    D,15        ; Bring up to closest 2k size
  2130.     DAD    D
  2131.     INX    D        ; Divide result by 16
  2132.     CALL    DVHLDE        ; Divide HL by DE
  2133.     MOV    H,B
  2134.     MOV    L,C
  2135. ;
  2136. NOREM:    XCHG
  2137.     LHLD    BLOKK        ; Current number of 2k blocks needed
  2138.     DAD    D
  2139.     SHLD    BLOKK
  2140.     JMP    TNLP2
  2141. ;
  2142. NEXTNM:    LXI    H,NAMECT    ; Count names found
  2143.     DCR    M
  2144.     JNZ    TNLP1
  2145.     LXI    H,NAMBUF    ; Save start of buffer
  2146.     SHLD    NBSAVE
  2147.     RET
  2148. ;
  2149. ; -----
  2150. ;
  2151. TRANS:    LDAX    D        ; Transfer from command line to FCB
  2152.     INX    D        ;  up to number of chars specified
  2153.     CPI    CR        ;  by 'C' reg.    Keep scanning field
  2154.     RZ            ;  without transfer until a delimiting
  2155.     CPI    '.'        ;  field char such as '.', blank, or
  2156.     RZ            ;  CR (for end of commmand line).
  2157.     CPI    ' '
  2158.     RZ
  2159.     DCR    C
  2160.     JM    TRANS        ; Once C-reg is less than zero, keep
  2161.     MOV    M,A        ;  reading command line but do not
  2162.     INX    H        ;  transfer to FCB.
  2163.     JMP    TRANS
  2164. ;
  2165. ; -----
  2166. ;
  2167. ; Places next name in buffer so 'CMDLINE' may parse it
  2168. ;
  2169. TRTOBUF:LHLD    BGNMS
  2170.     MVI    B,0
  2171.     LXI    D,FCBBUF+2
  2172. ;
  2173. TBLP:    MOV    A,M
  2174.     CPI    ' '
  2175.     JZ    TRBFEND
  2176.     STAX    D
  2177.     INX    H
  2178.     INX    D
  2179.     INR    B        ; Count chars in name
  2180.     JMP    TBLP
  2181. ;
  2182. TRBFEND:INX    H
  2183.     MOV    A,M        ; Eat extra spaces
  2184.     CPI    ' '
  2185.     JZ    TRBFEND
  2186.     SHLD    BGNMS
  2187.     LXI    H,FCBBUF+1    ; Put # chars before name
  2188.     MOV    M,B
  2189.     RET
  2190. ;
  2191. ; -----
  2192. ;
  2193. LCASE:    CPI    41H        ; If less than capital 'A' ignore
  2194.     RC
  2195.     CPI    5AH+1        ; If more than capital Z' ignore
  2196.     RNC
  2197.     ORI    20H        ; Change to lower case
  2198.     RET
  2199. ;
  2200. UCASE:    CPI    61H        ; Changes lower case character..
  2201.     RC            ; In 'A'reg. to upper case.
  2202.     CPI    7AH+1        ; See if more than small 'Z'
  2203.     RNC
  2204.     ANI    5FH
  2205.     RET
  2206. ;
  2207. ; ===========
  2208. ; SUBROUTINES
  2209. ; ===========
  2210. ;
  2211. ; Sets drive/user area (if SETAREA is YES) according to user input and your
  2212. ; setting of MAXDUS and DRVx/USRx EQUates.
  2213. ;
  2214. ; MENU #1
  2215. ;
  2216. WHAT:     IF    (DESCRIB OR SETAREA) AND USEMENU AND (NOT ALTMENU)
  2217.     XRA    A
  2218.     STA    CHOICE        ; Clear for loop
  2219.      ENDIF
  2220. ;
  2221.      IF    (DESCRIB OR SETAREA) AND USEMENU
  2222.     STA    KIND
  2223.      ENDIF
  2224. ;
  2225.      IF    (DESCRIB OR SETAREA) AND USEMENU AND ALTMENU
  2226.     LXI    D,MENU4        ; Load alternate menu
  2227.     CALL    PRTSET        ; Show it
  2228.      ENDIF
  2229. ;
  2230.      IF    (DESCRIB OR SETAREA) AND USEMENU AND (NOT ALTMENU)
  2231.     LXI    D,MENU1        ; Load category/area uploads table
  2232.     CALL    PRTSET        ; Show it
  2233.     CALL    WELL        ; Wait for response
  2234.      ENDIF
  2235. ;
  2236. WHAT0:     IF    (DESCRIB OR SETAREA) AND USEMENU AND ALTMENU
  2237.     XRA    A
  2238.     STA    CHOICE        ; Clear for loop
  2239.      ENDIF
  2240. ;
  2241.      IF    (DESCRIB OR SETAREA) AND USEMENU
  2242.     CALL    INPUT        ; Get a character
  2243.     CALL    UCASE        ; Upper case if alpha
  2244.      ENDIF
  2245. ;
  2246.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND (NOT ALTMENU)
  2247.     CPI    'B'        ; Menu #2?
  2248.     JZ    WHAT2        ; Yes, else continue
  2249.      ENDIF
  2250. ;
  2251.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND (NOT ALTMENU)
  2252.     CPI    'C'        ; Menu #3?
  2253.     JZ    WHAT4        ; Yes, else continue
  2254.      ENDIF
  2255. ;
  2256. WHAT0A:     IF    (DESCRIB OR SETAREA) AND USEMENU AND ALTMENU
  2257.     CPI    '1'        ; Quit?
  2258.      ENDIF
  2259. ;
  2260.      IF    (DESCRIB OR SETAREA) AND USEMENU AND (NOT ALTMENU)
  2261.     CPI    'Q'        ; Quit?
  2262.      ENDIF
  2263. ;
  2264.      IF    (DESCRIB OR SETAREA) AND USEMENU
  2265.     JNZ    WHAT0B        ; No
  2266.     CALL    TYPE
  2267.     JMP    EXIT
  2268.      ENDIF
  2269. ;
  2270. WHAT0B:     IF    (DESCRIB OR SETAREA) AND USEMENU AND ALTMENU
  2271.     CPI    'A'        ; <?
  2272.     JC    WHAT0        ; Yes
  2273.     CPI    5BH        ; >'Z'?
  2274.     JNC    WHAT0        ; Yes
  2275.      ENDIF
  2276. ;
  2277.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2278.     CPI    'K'        ; >'J'?
  2279.     JNC    WHAT2        ; Yes
  2280.      ENDIF
  2281. ;
  2282.      IF    (DESCRIB OR SETAREA) AND USEMENU AND ALTMENU
  2283.     SUI    11H        ; 0-9 only
  2284.      ENDIF
  2285. ;
  2286.      IF    (DESCRIB OR SETAREA) AND USEMENU
  2287.     CPI    '0'        ; <0?
  2288.     JC    WHAT0        ; Yes, so loop
  2289.     STA    KIND
  2290.     JNZ    WHAT1        ; Not 0, so skip
  2291.      ENDIF
  2292. ;
  2293.      IF    (DESCRIB OR SETAREA) AND USEMENU AND ALTMENU
  2294.     ADI    11H        ; Alpha only
  2295.      ENDIF
  2296. ;
  2297.      IF    (DESCRIB OR SETAREA) AND USEMENU
  2298.     CALL    TYPE        ; Show response
  2299.     LDA    XDRV1
  2300.     STA    XDRV
  2301.     LDA    XUSR1
  2302.     STA    XUSR
  2303.     RET
  2304. ;
  2305. WHAT1:    CPI    MAXDU1+1    ; >MAXDU1?
  2306.     JNC    WHAT0        ; Yes, so loop
  2307.      ENDIF
  2308. ;
  2309.      IF    (DESCRIB OR SETAREA) AND USEMENU AND ALTMENU
  2310.     PUSH    PSW        ; Save A
  2311.     ADI    11H        ; Alpha only
  2312.      ENDIF
  2313. ;
  2314.      IF    (DESCRIB OR SETAREA) AND USEMENU
  2315.     CALL    TYPE
  2316.      ENDIF
  2317. ;
  2318.      IF    (DESCRIB OR SETAREA) AND USEMENU AND ALTMENU
  2319.     POP    PSW
  2320.      ENDIF
  2321. ;
  2322.      IF    DESCRIB    AND (NOT SETAREA) AND USEMENU
  2323.     RET
  2324.      ENDIF
  2325. ;
  2326.      IF    SETAREA    AND USEMENU
  2327.     CALL    WHAT8        ; Get d/u offset
  2328.     LXI    H,DUTBL1    ; Point to the d/u table
  2329.     JMP    WHAT7        ; Set drive/user
  2330.      ENDIF
  2331. ;
  2332. ; MENU #2
  2333. ;
  2334. WHAT2:     IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2335.     PUSH    PSW        ; Save A
  2336.     MVI    A,'B'
  2337.      ENDIF
  2338. ;
  2339.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1
  2340.     STA    CHOICE
  2341.      ENDIF
  2342. ;
  2343.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2344.     POP    PSW        ; Restore A
  2345.      ENDIF
  2346. ;
  2347.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND (NOT ALTMENU)
  2348.     CALL    TYPE
  2349.     LXI    D,MENU2        ; Load category/area uploads table
  2350.     CALL    PRTSET        ; Show it
  2351.     CALL    WELL        ; Wait for response
  2352. ;
  2353. WHAT2A:    CALL    INPUT        ; Get a character
  2354.     CALL    UCASE        ; Upper case if alpha
  2355.     CPI    'A'        ; Menu #1?
  2356.     JNZ    WHAT2B        ; No
  2357.     CALL    TYPE
  2358.     JMP    WHAT        ; Menu #1
  2359.      ENDIF
  2360. ;
  2361. WHAT2B:     IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND (NOT ALTMENU)
  2362.     CPI    'C'        ; Menu #3?
  2363.     JZ    WHAT4        ; Yes, else continue
  2364.      ENDIF
  2365. ;
  2366.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND (NOT ALTMENU)
  2367.     CPI    'Q'        ; Quit?
  2368.     JNZ    WHAT2C        ; No
  2369.     CALL    TYPE
  2370.     JMP    EXIT
  2371.      ENDIF
  2372. ;
  2373.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND ALTMENU
  2374.     CPI    'U'        ; >'T'?
  2375.     JNC    WHAT4        ; Yes
  2376.      ENDIF
  2377. ;
  2378.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2379.     SUI    1BH        ; 0-9 only
  2380.      ENDIF
  2381. ;
  2382.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1
  2383. WHAT2C:    CPI    '0'        ; <0?
  2384.      ENDIF
  2385. ;
  2386.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND (NOT ALTMENU)
  2387.     JC    WHAT2A        ; Yes, so loop
  2388.      ENDIF
  2389. ;
  2390.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1
  2391.     STA    KIND
  2392.     JNZ    WHAT3        ; Not '0', so continue
  2393.      ENDIF
  2394. ;
  2395.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2396.     ADI    1BH        ; Alpha only
  2397.      ENDIF
  2398. ;
  2399.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1
  2400.     CALL    TYPE
  2401.     LDA    XDRV2
  2402.     STA    XDRV
  2403.     LDA    XUSR2
  2404.     STA    XUSR
  2405.     RET
  2406. ;
  2407. WHAT3:    CPI    MAXDU2+1    ; >MAXDU2?
  2408.      ENDIF
  2409. ;
  2410.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2411.     JNC    WHAT0        ; Yes, so loop
  2412.      ENDIF
  2413. ;
  2414.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND (NOT ALTMENU)
  2415.     JNC    WHAT2A        ; Yes, so loop
  2416.      ENDIF
  2417. ;
  2418.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2419.     PUSH    PSW        ; Save A
  2420.     ADI    1BH        ; Alpha only
  2421.      ENDIF
  2422. ;
  2423.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1
  2424.     CALL    TYPE
  2425.      ENDIF
  2426. ;
  2427.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2428.     POP    PSW        ; Restore A
  2429.      ENDIF
  2430. ;
  2431.      IF    DESCRIB    AND (NOT SETAREA) AND USEMENU AND XTRA1
  2432.     RET
  2433.      ENDIF
  2434. ;
  2435.      IF    SETAREA    AND USEMENU AND    XTRA1
  2436.     CALL    WHAT8        ; Get d/u offset
  2437.     LXI    H,DUTBL2    ; Point to the d/u table
  2438.     JMP    WHAT7        ; Set drive/user
  2439.      ENDIF
  2440. ;
  2441. ; MENU #3
  2442. ;
  2443. WHAT4:     IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2444.     PUSH    PSW        ; Save A
  2445.     MVI    A,'C'
  2446.      ENDIF
  2447. ;
  2448.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2
  2449.     STA    CHOICE
  2450.      ENDIF
  2451. ;
  2452.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA1 AND ALTMENU
  2453.     POP    PSW        ; Restore A
  2454.      ENDIF
  2455. ;
  2456.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND (NOT ALTMENU)
  2457.     CALL    TYPE
  2458.     LXI    D,MENU3        ; Load category/area uploads table
  2459.     CALL    PRTSET        ; Show it
  2460.     CALL    WELL        ; Wait for response
  2461. ;
  2462. WHAT4A:    CALL    INPUT        ; Get a character
  2463.     CALL    UCASE        ; Upper case if alpha
  2464.     CPI    'A'        ; Menu #1?
  2465.     JNZ    WHAT4B        ; No
  2466.     CALL    TYPE
  2467.     JMP    WHAT        ; Menu #1
  2468. ;
  2469. WHAT4B:    CPI    'B'        ; Menu #2?
  2470.     JNZ    WHAT4C        ; No
  2471.     CALL    TYPE
  2472.     JMP    WHAT2        ; Menu #2
  2473. ;
  2474. WHAT4C:    CPI    'Q'        ; Quit?
  2475.     JNZ    WHAT4D        ; No
  2476.     CALL    TYPE
  2477.     JMP    EXIT
  2478.      ENDIF
  2479. ;
  2480.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND ALTMENU
  2481.     SUI    25H        ; 0-5 only
  2482.      ENDIF
  2483. ;
  2484.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2
  2485. WHAT4D:    CPI    '0'        ; <0?
  2486.      ENDIF
  2487. ;
  2488.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND (NOT ALTMENU)
  2489.     JC    WHAT4A        ; Yes, so loop
  2490.      ENDIF
  2491. ;
  2492.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2
  2493.     STA    KIND
  2494.     JNZ    WHAT6        ; Not '0', so continue
  2495.      ENDIF
  2496. ;
  2497.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND ALTMENU
  2498.     ADI    25H        ; Alpha only
  2499.      ENDIF
  2500. ;
  2501.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2
  2502.     CALL    TYPE
  2503.     LDA    XDRV3
  2504.     STA    XDRV
  2505.     LDA    XUSR3
  2506.     STA    XUSR
  2507.      ENDIF
  2508. ;
  2509.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2
  2510.     RET
  2511. ;
  2512. WHAT6:    CPI    MAXDU3+1    ; >MAXDU2?
  2513.      ENDIF
  2514. ;
  2515.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND ALTMENU
  2516.     JNC    WHAT0        ; Yes, so loop
  2517.      ENDIF
  2518. ;
  2519.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND (NOT ALTMENU)
  2520.     JNC    WHAT4A        ; Yes, loop
  2521.      ENDIF
  2522. ;
  2523.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND ALTMENU
  2524.     PUSH    PSW        ; Save A
  2525.     ADI    25H        ; Alpha only
  2526.      ENDIF
  2527. ;
  2528.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2
  2529.     CALL    TYPE
  2530.      ENDIF
  2531. ;
  2532.      IF    (DESCRIB OR SETAREA) AND USEMENU AND XTRA2 AND ALTMENU
  2533.     POP    PSW
  2534.      ENDIF
  2535. ;
  2536.      IF    DESCRIB    AND (NOT SETAREA) AND USEMENU AND XTRA2
  2537.     RET
  2538.      ENDIF
  2539. ;
  2540.      IF    SETAREA    AND USEMENU AND    XTRA2
  2541.     CALL    WHAT8        ; Get d/u offset
  2542.     LXI    H,DUTBL3    ; Point to the d/u table
  2543.      ENDIF
  2544. ;
  2545.      IF    SETAREA    AND USEMENU
  2546. WHAT7:    DAD    D
  2547.     MOV    A,M
  2548.     STA    XDRV        ; Set drive
  2549.     INX    H
  2550.     MOV    A,M
  2551.     STA    XUSR        ; Set user
  2552.     CALL    ILPRT
  2553.     DB    CR,LF,0
  2554.     RET
  2555. ;
  2556. ; Set d/u area
  2557. ;
  2558. WHAT8:    SUI    '1'        ; Get offset for d/u table
  2559.     RAL
  2560.     MVI    D,0
  2561.     MOV    E,A
  2562.     RET
  2563.      ENDIF
  2564. ;
  2565. ; Display DE and ask for input
  2566. ;
  2567.      IF    (DESCRIB OR SETAREA) AND USEMENU AND (NOT ALTMENU)
  2568. WELL:    CALL    ILPRT
  2569.     DB    CR,LF
  2570.     DB    'Your choice : ',0
  2571.     RET
  2572.      ENDIF
  2573. ;
  2574. ;
  2575. ; Add the time of the last up/download to NUBYE's time-on-system byte
  2576. ;
  2577.      IF    TIMEON AND (NOT    CLOCK)
  2578. ADDTON:    MVI    C,79
  2579.     CALL    BDOS        ; Get value of TON and RTC address
  2580.     LXI    D,7        ; Offset from RTC to TON
  2581.     DAD    D        ; HL now contains TON address
  2582.     PUSH    H        ; Save for now
  2583.     LHLD    RECDNO
  2584.     SHLD    RCNT
  2585.     CALL    XTIM        ; Calculate transfer time
  2586.     POP    H        ; Get TON address
  2587.     MOV    A,M        ; And current value
  2588.     INR    A        ; Bump it one
  2589.     ADD    C        ; Add transfer time
  2590.     MOV    M,A        ; And put it in NUBYE
  2591.     RET
  2592.      ENDIF
  2593. ;
  2594. ; Catches anything on the modem input and ignores, so can wait for what
  2595. ; we expect to receive
  2596. ;
  2597. CATCH:    CALL    MDINST        ; Check modem status for any characters
  2598.     RZ            ; If none, all checked
  2599.     CALL    MDINP        ; Else get the garbage character
  2600.     JMP    CATCH        ; Keep going until none remaining
  2601. ;
  2602. ; Check next character to see if a space or non-space, file name error
  2603. ; if no ASCII character.
  2604. ;
  2605. CHKFSP:    LDA    BCHFLG        ; Requesting batch mode now?
  2606.     ORA    A
  2607.     JZ    CHKFSP2        ; Exit if not
  2608.     LDA    SNDFLG        ; Sending batch?
  2609.     ORA    A
  2610.     JZ    CHKFSP2        ; If yes, exit
  2611.     DCR    B
  2612.     JZ    CHKFSP1
  2613.     INR    B
  2614.     JMP    CHKFSP2
  2615. ;
  2616. CHKFSP1:POP    H        ; Do not return to LOGDU
  2617.     RET            ; Return instead to SNDFL
  2618. ;
  2619. CHKFSP2:DCR    B
  2620.     JZ    NFN        ; Error if end of chars.
  2621.     MOV    A,M
  2622.     CPI    ' '+1
  2623.     RNC            ; Ok if valid character so return
  2624.     INX    H
  2625.     LDA    BCHFLG        ; Requesting batch mode?
  2626.     ORA    A
  2627.     JZ    CHKFSP2        ; If not, loop
  2628.     LDA    SNDFLG        ; Sending batch mode now?
  2629.     ORA    A
  2630.     JZ    CHKFSP2        ; If yes, loop
  2631.     DCR    B        ; Else look at next character
  2632.     JZ    CHKFSP1
  2633.     INR    B
  2634.     JMP    CHKFSP2
  2635. ;
  2636. ; Check next character to see if a space or non-space, go to menu if a
  2637. ; command error.
  2638. ;
  2639. CHKSP:    LDA    BCHFLG        ; Requesting batch mode?
  2640.     ORA    A
  2641.     JZ    CHKSP2        ; Exit if not
  2642.     LDA    SNDFLG        ; Sending in batch mode now?
  2643.     ORA    A
  2644.     JZ    CHKSP2        ; If yes, exit
  2645.     DCR    B
  2646.     JZ    CHKSP1
  2647.     INR    B
  2648.     JMP    CHKSP2
  2649. ;
  2650. CHKSP1:    POP    H        ; Don't return to LOGDU
  2651.     RET            ; Return to SNDFIL
  2652. ;
  2653. CHKSP2:    DCR    B
  2654.     JZ    OPTERR
  2655.     INX    H
  2656.     MOV    A,M        ; Get the character there
  2657.     CPI    ' '        ; Space character?
  2658.     RET            ; JZ = space, JNZ = non-space
  2659. ;
  2660. ; -----
  2661. ;
  2662. ****
  2663. ; Assorted BDOS functions
  2664. ;
  2665. CLOSEF:    MVI    C,CLOSE        ; Close file
  2666.     JMP    BDSRET
  2667. ;
  2668. DELDES:    LXI    D,DEST        ; Destination file
  2669. DELFIL:    MVI    C,DELET        ; Delete
  2670.     JMP    BDSRET
  2671. ;
  2672. DRVSET:    MVI    C,SELDSK    ; Select drive
  2673.     JMP    BDSRET
  2674. ;
  2675. FILSCH:    MVI    C,SRCHF
  2676.     LXI    D,FCB
  2677.     JMP    BDSRET
  2678. ;
  2679. OPENIT:    MVI    C,OPEN
  2680.     JMP    BDSRET
  2681. ;
  2682. PRTSET:    MVI    C,PRINT
  2683.     JMP    BDSRET
  2684. ;
  2685. REDFCB:    MVI    C,READ
  2686. FCBSET:    LXI    D,FCB
  2687.     JMP    BDSRET
  2688. ;
  2689. RRANDM:    MVI    C,RRDM
  2690.     JMP    BDSRET
  2691. ;
  2692. RSTDMA:    LXI    D,TBUF        ; Default buffer
  2693. DMASET:    MVI    C,STDMA        ; Set to DMA
  2694.     JMP    BDSRET
  2695. ;
  2696. USRSET:    MVI    C,SETUSR
  2697.     JMP    BDSRET
  2698. ;
  2699. BDSRET:    CALL    BDOS
  2700.     RET
  2701. ;
  2702. ; I/O drivers using NUBYE's extended BDOS calls
  2703. ;
  2704. CONIN:    PUSH    B
  2705.     PUSH    D
  2706.     PUSH    H        ; Save the registers
  2707.     MVI    C,67        ; Console input call
  2708.     CALL    BDOS        ; Character returned in 'A'
  2709.     CPI    CANCEL        ; Local abort requested?
  2710.     JNZ    CONIN1        ; No, else
  2711.     STA    SYSABT        ; Store it
  2712. ;
  2713. CONIN1:    JMP    BDOSX1        ; Restore registers
  2714. ;
  2715. CONOUT:    PUSH    B
  2716.     PUSH    D
  2717.     PUSH    H
  2718.     MVI    C,68        ; Console output call (char is in 'E')
  2719.     JMP    BDOSEX
  2720. ;
  2721. CONSTAT:PUSH    B
  2722.     PUSH    D
  2723.     PUSH    H
  2724.     MVI    C,66        ; Console status call
  2725.     JMP    BDOSEX
  2726. ;
  2727. MDCARCK:PUSH    B
  2728.     PUSH    D
  2729.     PUSH    H
  2730.     MVI    C,65        ; Carrier check
  2731.     JMP    BDOSEX
  2732. ;
  2733. MDINP:    PUSH    B
  2734.     PUSH    D
  2735.     PUSH    H
  2736.     MVI    C,64        ; Modem input
  2737.     JMP    BDOSEX
  2738. ;
  2739. MDINST:    PUSH    B
  2740.     PUSH    D
  2741.     PUSH    H
  2742.     MVI    C,61        ; Modem input status
  2743.     JMP    BDOSEX
  2744. ;
  2745. MDOUTP:    PUSH    B
  2746.     PUSH    D
  2747.     PUSH    H
  2748.     MVI    C,63        ; Modem output
  2749.     MOV    E,A        ; Put character in 'E'
  2750.     JMP    BDOSEX
  2751. ;
  2752. MDOUTST:PUSH    B
  2753.     PUSH    D
  2754.     PUSH    H
  2755.     MVI    C,62        ; Modem output status
  2756. ;
  2757. BDOSEX:    CALL    BDOS
  2758. ;
  2759. BDOSX1:    POP    H
  2760.     POP    D
  2761.     POP    B
  2762.     RET            ; Restore registers and return
  2763. ;
  2764. LSTCLR:    PUSH    B        ; Save the registers
  2765.     PUSH    D
  2766.     MVI    C,80        ; LCDATA BDOS call in NUBYE
  2767.     CALL    BDOS
  2768.     POP    D        ; Restore the registers
  2769.     POP    B
  2770.     RET
  2771. ;
  2772. ; -----
  2773. ;
  2774. ; Finished, clean up and return to CP/M (via MBBS/MFMSG if necessary).
  2775. ;
  2776. EXIT:     IF    WRTLOC        ; Did we set the WRTLOC?
  2777.     MVI    C,75
  2778.     MVI    E,0
  2779.     CALL    BDOS        ; Reset wrtloc flag
  2780.      ENDIF
  2781. ;
  2782.      IF    TIMEON AND CLOCK AND DTOS
  2783.     CALL    MDCARCK        ; Still have a carrier?
  2784.     JZ    EXIT1        ; If not can't use "RECV:"
  2785.     CALL    WAIT1        ; Insures other end is finished
  2786.     MVI    C,83
  2787.     CALL    BDOS        ; Tell NUBYE to print time-on-system
  2788.      ENDIF
  2789. ;
  2790. EXIT1:    LDA    OLDDRV        ; Restore the original drive
  2791.     CALL    RECDRX
  2792.     LDA    OLDUSR        ; Restore the original number
  2793.     CALL    RECARE
  2794.     CALL    RSTDMA        ; Reset to default DMA
  2795. ;
  2796. EXIT2:     IF    TIMEON
  2797.     LDA    TLIMIT        ; Restore MXTIME/status
  2798.     MVI    C,81
  2799.     MOV    E,A
  2800.     CALL    BDOS
  2801.      ENDIF
  2802. ;
  2803. EXIT3:    XRA    A        ; Clear the register and carry bit
  2804.     LHLD    STACK        ; Get original return adress back
  2805.     SPHL            ; Put on the stack pointer
  2806. ;
  2807.      IF    MSGDSC OR MSGFIL
  2808.     LDA    DSCFLG
  2809.     ORA    A        ; Normal file with description?
  2810.     JNZ    EXIT4        ; Yes, so skip next check
  2811.     LDA    MSGFLG
  2812.     ORA    A        ; Message file upload?
  2813.     RZ            ; No
  2814. ;
  2815. EXIT4:    CALL    ILPRTB        ; Show to remote also
  2816.     DB    CR,LF,LF
  2817.     DB    '++ Loading special message/description file handler ++'
  2818.     DB    CR,LF,LF,0
  2819.     STA    CONONL        ; Set to local display only
  2820.      ENDIF
  2821. ;
  2822.      IF    MSGFIL
  2823.     LDA    MSGFLG
  2824.     ORA    A        ; Message file upload?
  2825.     JNZ    EXIT6        ; Yes, skip rest
  2826.      ENDIF
  2827. ;
  2828.      IF    MSGDSC
  2829.     LDA    INBTCH        ; Batch?
  2830.     ORA    A
  2831.     JNZ    EXIT6        ; Yes, so skip next section
  2832.      ENDIF
  2833. ;
  2834.     IF    MSGDSC AND RESUSR AND PUPOPT
  2835.     LDA    PUPFLG
  2836.     ORA    A        ; Privileged xfr option request?
  2837.     JZ    EXIT5        ; No
  2838.     LDA    AFBYTE
  2839.     ANI    80H        ; Test for privileged user access (bit 7)
  2840.     RNZ            ; Return, privileged user ok'd
  2841.      ENDIF
  2842. ;
  2843. EXIT5:     IF    MSGDSC
  2844.     LDA    PRVTFL        ; Upload status (Public or Private)
  2845.     STA    TBUF        ; Stuff into page zero (80H)
  2846.     MVI    C,0        ; Number of characters (stuff at TBUF)
  2847.     LXI    D,TBUF+2    ; Buffer starts at 82H
  2848.     LXI    H,MBDSH        ; "NEW UPLOAD:" heading
  2849. ;
  2850. MBDSHP:    MOV    A,M        ; Get character
  2851.     ORA    A        ; End?
  2852.     JZ    MBDFS        ; Yes, else...
  2853.     CALL    MBDPUT        ; Stuff it into DE
  2854.     INX    H        ; Increment to next position
  2855.     JMP    MBDSHP        ; Loop until done
  2856. ;
  2857. MBDFS:    CALL    MBDFIL        ; Get du: info
  2858.     STA    TBUF+1        ; Save number of characters in 81H
  2859.     MVI    A,0CAH        ; Stuff JZ instruction
  2860.     STA    0
  2861.     XRA    A
  2862.     JMP    0
  2863.      ENDIF
  2864. ;
  2865.      IF    MSGDSC OR MSGFIL
  2866. EXIT6:    MVI    C,0        ; Number of characters (stuff at TBUF)
  2867.     LXI    D,TBUF+1    ; Start of buffer
  2868.     CALL    MBDFIL
  2869.     STA    TBUF        ; Save number of characters in TBUF
  2870.     MVI    A,0C2H        ; Stuff JNZ instruction
  2871.     STA    0        ; ..in 0, so NUBYE loads/runs MFMSG utility
  2872.     ORA    A        ; Make sure NZ flag set so JNZ will jump
  2873.     JMP    0
  2874.      ENDIF
  2875. ;
  2876.      IF    (NOT MSGFIL) AND (NOT MSGDSC)
  2877.     RET
  2878.      ENDIF
  2879. ;
  2880.      IF    MSGDSC OR MSGFIL
  2881. MBDFIL:    LDA    DSKSAV        ; Get current drive
  2882.     INR    A
  2883. ;
  2884. MWDRV:    ADI    'A'-1
  2885.     CALL    MBDPUT        ; Stuff in command line buffer
  2886.     LDA    USRSAV        ; Get current user
  2887.     CPI    10        ; <10?
  2888.     JC    US0        ; Yes
  2889.     ORA    A        ; Clear flags
  2890.     DAA            ; Decimal adjust
  2891.     RAR            ; Shift down tens digit
  2892.     RAR
  2893.     RAR
  2894.     RAR
  2895.     ANI    0FH        ; Mask out tens digit
  2896.     ADI    '0'        ; Make it ASCII
  2897.     CALL    MBDPUT
  2898.     LDA    USRSAV
  2899.     ORA    A        ; Clear flags
  2900.     DAA            ; Decimal adjust
  2901.     ANI    0FH        ; Mask out singles digit
  2902. ;
  2903. US0:    ADI    '0'        ; Make it ASCII
  2904.     CALL    MBDPUT
  2905.     MVI    A,':'        ; Put in a colon
  2906.     CALL    MBDPUT
  2907.     LDA    DSCFLG
  2908.     ORA    A        ; Normal file with description?
  2909.     JZ    US1        ; No, so skip next lines
  2910.     LDA    INBTCH        ; Batch?
  2911.     ORA    A
  2912.     JZ    US1        ; Normal upload, use its filename, else...
  2913.     LXI    H,FILE+1    ; Stuff in UPLOADS filename
  2914.     JMP    $+6        ; ...and skip next line
  2915. US1:    LXI    H,FCB+1        ; Stuff in filename
  2916.     MVI    B,8
  2917. ;
  2918. DESNM:    MOV    A,M
  2919.     CPI    ' '
  2920.     CNZ    MBDPUT
  2921.     INX    H
  2922.     DCR    B
  2923.     JNZ    DESNM
  2924.     MVI    A,'.'
  2925.     CALL    MBDPUT
  2926.     MVI    B,3
  2927. ;
  2928. DESNM3:    MOV    A,M
  2929.     CPI    ' '
  2930.     JZ    DESGO
  2931.     CPI    0
  2932.     JZ    DESGO
  2933.     CALL    MBDPUT
  2934.     INX    H
  2935.     DCR    B
  2936.     JNZ    DESNM3
  2937. ;
  2938. DESGO:    MOV    A,C
  2939.     RET
  2940. ;
  2941. MBDPUT:    STAX    D        ; Short routine to stuff A in (DE) and
  2942.     INX    D        ; Increment pointer and character count
  2943.     INR    C
  2944.     RET
  2945.      ENDIF            ; MSGFIL OR MSGDSC
  2946. ;
  2947. ; Check to see if SYSOP has typed a function key
  2948. ;
  2949. FUNCHK:    PUSH    PSW
  2950.     CALL    CONSTAT        ; See if SYSOP has typed a key
  2951.     ORA    A
  2952.     CNZ    CONIN        ; Yes, treat as function key
  2953.     POP    PSW
  2954.     RET
  2955. ;
  2956. ; Get Disk and User from DUSAVE and log in if valid.
  2957. ;
  2958. GETDU:    LDA    BCHFLG        ; Requesting batch mode?
  2959.     ORA    A
  2960.     JZ    GETDU1        ; If not, exit
  2961.     LDA    SNDFLG        ; Sending batch?
  2962.     ORA    A
  2963.     JNZ    GETDU2        ; If not, exit
  2964. ;
  2965. GETDU1:    CALL    CHKFSP        ; See if a file name is included
  2966.     SHLD    SAVEHL        ; Save location of the filename
  2967. ;
  2968. GETDU2:    LDA    PRVTFL        ; Uploading to a private area?
  2969.     ORA    A
  2970.     JNZ    TRAP1        ; If yes, going to a specified area
  2971.     LXI    H,DUSAVE    ; Point to drive/user
  2972.     LDA    OLDDRV        ; Get current drive
  2973.     STA    DUD
  2974.     ADI    'A'
  2975.     STA    RCVDRV
  2976.     MOV    A,M        ; Get 1st character
  2977.     CPI    '0'
  2978.     JC    GETDU3
  2979.     CPI    '9'+1
  2980.     JC    NUMER1
  2981. ;
  2982. GETDU3:    STA    RCVDRV        ; Allows Sysop/Privileged user any drive
  2983.     CPI    'A'-1
  2984.     JC    NUMER        ; Satisfied with current drive
  2985.     SUI    'A'
  2986.     STA    DUD
  2987. ;
  2988.      IF    RESUSR AND PUPOPT
  2989.     LDA    PUPFLG        ; Privileged user upload request?
  2990.     ORA    A
  2991.     LDA    DUD        ; Get value back
  2992.     JNZ    GETDU4        ; Yes
  2993.      ENDIF
  2994. ;
  2995.      IF    ZCPR
  2996.     LDA    WHEEL        ; Sysop using the system?
  2997.     ORA    A
  2998.     LDA    DUD        ; Get the value back
  2999.     JNZ    GETDU4
  3000.      ENDIF
  3001. ;
  3002.      IF    NOT USEMAX
  3003.     CPI    MAXDRV
  3004.     JNC    ILLDU        ; Drive selection not available
  3005.      ENDIF
  3006. ;
  3007.      IF    USEMAX
  3008.     PUSH    H
  3009.     LXI    H,DRIVMAX    ; Point to max drive byte
  3010.     INR    M
  3011.     CMP    M        ; And check it
  3012.     PUSH    PSW        ; Save flags from the CMP
  3013.     DCR    M        ; Restore max drive to normal
  3014.     POP    PSW        ; Restore flags from the CPM
  3015.     JNC    ILLDU
  3016.     POP    H
  3017.      ENDIF
  3018. ;
  3019. GETDU4:    INX    H        ; Get 2nd character
  3020. ;
  3021. NUMER:    MOV    A,M
  3022.     CPI    ':'
  3023.     JZ    OK4        ; Colon for drive only, no user number
  3024.     CALL    CKNUM        ; Check if numeric
  3025.     MOV    B,A        ; Save character
  3026.     LDA    BCHFLG        ; Using batch mode?
  3027.     ORA    A
  3028.     JZ    NUMER1        ; Skip next part if not using batch
  3029.     LDA    SNDFLG        ; Receiving in batch?
  3030.     ORA    A
  3031.     JNZ    NUMER1        ; Yes, can use normal drive/user
  3032. ;
  3033. NODU:    CALL    ERXIT
  3034.     DB    '++ Batch downloads only from this d/u area ++','$'
  3035. ;
  3036. NUMER1:    MOV    A,B        ; Get the value back
  3037.     SUI    '0'        ; Convert ASCII to binary
  3038.     STA    DUU        ; Save it
  3039.     INX    H        ; Get 3rd character if any
  3040.     MOV    A,M
  3041.     CPI    ':'
  3042.     JZ    OK1
  3043.     LDA    DUU
  3044.     CPI    1        ; Is first number a '1'?
  3045.     JNZ    ILLDU
  3046.     MOV    A,M
  3047.     CALL    CKNUM
  3048.     SUI    '0'-10
  3049.     STA    DUU
  3050.     INX    H        ; Get 4th (and last character) if any
  3051.     MOV    A,M
  3052.     CPI    ':'
  3053.     JNZ    ILLDU
  3054. ;
  3055. OK1:    LDA    OPTSAV        ; Get the option back
  3056.     CPI    'R'        ; Receiving a file?
  3057.     LDA    DUU        ; Get desired user area
  3058.     JZ    OK2        ; Yes, can not use special download area
  3059.     LDA    DUD        ; Get desired drive
  3060.     CPI    SPLDRV-'A'    ; Special download drive requested?
  3061.     LDA    DUU        ; Get user area requested
  3062.     JNZ    OK2        ; If none, exit
  3063.     CPI    SPLUSR        ; Special download area requested?
  3064.     JZ    OK3        ; If yes, process request
  3065. ;
  3066. OK2:     IF    ZCPR
  3067.     LDA    WHEEL        ; SYSOP using the system?
  3068.     ORA    A
  3069.     LDA    DUU        ; Restore desired user area
  3070.     STA    RCVUSR        ; Allows SYSOP to upload anywhere
  3071.     JNZ    OK3        ; If yes, let him have all user areas
  3072.      ENDIF
  3073. ;
  3074.      IF    NOT USEMAX
  3075.     CPI    MAXUSR+1    ; Check for maximum user download area
  3076.     JNC    ILLDU        ; Error if more (and not special area)
  3077.      ENDIF
  3078. ;
  3079.      IF    USEMAX
  3080.     PUSH    H
  3081.     LXI    H,USRMAX    ; Point at maximum user byte
  3082.     CMP    M        ; And check it
  3083.     JNC    ILLDU
  3084.     POP    H
  3085.      ENDIF
  3086. ;
  3087. OK3:    MOV    E,A
  3088. ;
  3089.      IF    NOT SETAREA
  3090.     STA    NOTUSR+1    ; Store requested user area
  3091.     MVI    A,3EH        ; 'MVI A,--' instruction
  3092.     STA    NOTUSR
  3093.      ENDIF
  3094. ;
  3095.     CALL    USRSET        ; Set to requested user area
  3096. ;
  3097. OK4:    LDA    DUD        ; Get drive
  3098.     MOV    E,A
  3099. ;
  3100.      IF    NOT SETAREA
  3101.     ADI    'A'
  3102.     STA    NOTDRV+1    ; Store requested drive
  3103.     MVI    A,3EH        ; 'MVI A,--' instruction
  3104.     STA    NOTDRV
  3105.      ENDIF
  3106. ;
  3107. OK5:    CALL    DRVSET        ; Set to requested drive
  3108.     PUSH    B
  3109.     CALL    WAIT1        ; 1 sec delay
  3110.     POP    B
  3111.     JMP    TRAP1        ; Now find file selected
  3112. ;
  3113. ; Set drive/user for special download request
  3114. ;
  3115. SETSPL:     IF    ALTSEC
  3116.     LDA    SPLFL1
  3117.     ORA    A        ; Special download request (alternate)
  3118.     JNZ    SETSP1        ; Yes
  3119.      ENDIF
  3120. ;
  3121.     MVI    E,SPLUSR    ; Get the special download user area
  3122.     CALL    USRSET        ; Set to it
  3123.     MVI    C,SELDSK
  3124.     MVI    E,SPLDRV-'A'    ; Get the special download drive
  3125.     JMP    BDOS        ; Set to requested drive, return
  3126. ;
  3127.      IF    ALTSEC
  3128. SETSP1:    MVI    E,ALTUSR        ; Get the special alternate download user area
  3129.     CALL    USRSET        ; Set to it
  3130.     MVI    C,SELDSK
  3131.     MVI    E,ALTDRV-'A'    ; Get the special alternate download drive
  3132.     JMP    BDOS        ; Set to requested drive, return
  3133.      ENDIF
  3134. ;
  3135. ; Shows available space on upload disk/area.  Uses KDRV data area which
  3136. ; must be loaded before calling this routine.  (So KSHOW will work with
  3137. ; user specified disk if SETAREA equate is not set YES.)
  3138. ;
  3139. ; Print the free space remaining for the received file
  3140. ;
  3141. CPMVER    EQU    0CH
  3142. CURDPB    EQU    1FH
  3143. GALLOC    EQU    1BH
  3144. SELDSK    EQU    0EH
  3145. GETFRE    EQU    46
  3146. ;
  3147. KDRV:    DB    0        ; Drive stored here before calling KSHOW
  3148. ;
  3149. KSHOW:    LDA    KDRV        ; Get drive ('A','B','C',etc.)
  3150.     SUI    41H        ; Convert to numeric (0,1,2,etc.)
  3151.     MOV    E,A        ; Stuff in E for BDOS call
  3152.     CALL    DRVSET        ; Set to proper drive
  3153.     MVI    C,CURDPB    ; It's 2.X or MP/M...request DPB
  3154.     CALL    BDOS
  3155.     INX    H
  3156.     INX    H
  3157.     MOV    A,M        ; Get block shift
  3158.     STA    BLKSHF
  3159.     INX    H        ; Bump to block mask
  3160.     MOV    A,M
  3161.     INX    H
  3162.     INX    H
  3163.     MOV    E,M        ; Get max block #
  3164.     INX    H
  3165.     MOV    D,M
  3166.     XCHG
  3167.     SHLD    BLKMAX        ; Save it
  3168.     XCHG
  3169.     INX    H
  3170.     MOV    E,M        ; Get directory size
  3171.     INX    H
  3172.     MOV    D,M
  3173.     XCHG
  3174. ;
  3175. ; Calculate # of K free on selected drive now so that the FREE figure
  3176. ; will not reflect either the creation or additions to the SD.DIR file
  3177. ; (which we would probably erase or move anyway).
  3178. ;
  3179.     MVI    C,CPMVER    ; Get CP/M version number
  3180.     CALL    BDOS
  3181.     MOV    A,L        ; Get returned version number
  3182.     CPI    30H        ; 3.0?
  3183.     JC    FREE20        ; Use old method if not
  3184.     LDA    KDRV        ; Get drive #
  3185.     SBI    'A'        ; Change from ASCII to binary
  3186.     MVI    C,GETFRE
  3187.     MOV    E,A        ; Use new Compute Free Space BDOS call
  3188.     CALL    BDOS
  3189.     MVI    C,3        ; Answer is a 24-bit integer
  3190. ;
  3191. FRE3L1:    LXI    H,80H+2        ; Answer is in 1st 3 bytes of DMA adr
  3192.     MVI    B,3        ; Convert it from sectors to K
  3193.     ORA    A        ; By dividing by 8
  3194. ;
  3195. FRE3L2:    MOV    A,M
  3196.     RAR
  3197.     MOV    M,A
  3198.     DCX    H
  3199.     DCR    B
  3200.     JNZ    FRE3L2        ; Loop for 3 bytes
  3201.     DCR    C
  3202.     JNZ    FRE3L1        ; Shift 3 times
  3203.     LHLD    80H        ; Now get result in K
  3204.     JMP    SAVFRE        ; Go store it
  3205. ;
  3206. FREE20:    MVI    C,GALLOC    ; Get address of allocation vector
  3207.     CALL    BDOS
  3208.     XCHG
  3209.     LHLD    BLKMAX        ; Get its length
  3210.     INX    H
  3211.     LXI    B,0        ; Init block count to 0
  3212. ;
  3213. GSPBYT:    PUSH    D        ; Save alloc address
  3214.     LDAX    D
  3215.     MVI    E,8        ; Set to process 8 blocks
  3216. ;
  3217. GSPLUP:    RAL            ; Test bit
  3218.     JC    NOTFRE
  3219.     INX    B
  3220. ;
  3221. NOTFRE:    MOV    D,A        ; Save bits
  3222.     DCX    H        ; Count down blocks
  3223.     MOV    A,L
  3224.     ORA    H
  3225.     JZ    ENDALC        ; Quit if out of blocks
  3226.     MOV    A,D        ; Restore bits
  3227.     DCR    E        ; Count down 8 bits
  3228.     JNZ    GSPLUP        ; Do another bit
  3229.     POP    D        ; Bump to next byte..
  3230.     INX    D        ; Of alloc. vector
  3231.     JMP    GSPBYT        ; Process it
  3232. ;
  3233. ENDALC:    POP    D        ; Clear stack of allocation vector ptr.
  3234.     MOV    L,C        ; Copy block to HL
  3235.     MOV    H,B
  3236.     LDA    BLKSHF        ; Get block shift factor
  3237.     SUI    3        ; Convert from sectors to K
  3238.     JZ    SAVFRE        ; Skip shifts if 1K blocks...
  3239. ;                ; Return free in HL
  3240. FREKLP:    DAD    H        ; Multiply blocks by K/BLK
  3241.     DCR    A
  3242.     JNZ    FREKLP
  3243. ;
  3244. ; Print the amount of free space remaining on the selected drive
  3245. ;
  3246. SAVFRE:    CALL    DECOUT
  3247.     CALL    ILPRT
  3248.     DB    'k free',0
  3249.     RET
  3250. ;
  3251. ; Log into drive and user (if specified).  If none mentioned, it falls
  3252. ; through to 'TRAP' routine for normal use.
  3253. ;
  3254. LOGDU:    LXI    H,TBUF        ; Point to default buffer command line
  3255.     MOV    B,M        ; Store number of characters in command
  3256.     INR    B        ; Add in current location
  3257. ;
  3258. LOG1:    CALL    CHKSP        ; Skip spaces to find 1st command
  3259.     JZ    LOG1
  3260. ;
  3261. LOG2:    CALL    CHKSP        ; Skip 1st command (non-spaces)
  3262.     JNZ    LOG2
  3263.     INX    H
  3264.     CALL    CHKFSP        ; Skip spaces to find 2nd command
  3265.     SHLD    SAVEHL        ; Save start address of the 2nd command
  3266. ;
  3267. ; Now point to the first byte in the argument, i.e., if it was of format
  3268. ; similar to:  B6:HELLO.DOC then we point at the drive character 'B'.
  3269. ;
  3270.     LXI    D,DUSAVE
  3271.     MVI    C,4        ; Drive/user is 4 characters maximum
  3272. ;
  3273. CPLP:    MOV    A,M
  3274.     CPI    ' '+1        ; Space or return, finished
  3275.     JC    TRAP
  3276.     STAX    D
  3277.     INX    H
  3278.     INX    D
  3279.     CPI    ':'
  3280.     JZ    GETDU        ; If colon, get drive/user and log in
  3281.     DCR    B        ; One less position to check
  3282.     DCR    C        ; One less to go
  3283.     JNZ    CPLP
  3284. ;
  3285. ; Check for no file name or ambiguous name
  3286. ;
  3287. TRAP:    LDA    SPLFL        ; Downloading from a private area?
  3288.     ORA    A
  3289.     CNZ    SETSPL        ; If yes, set special drive/user area
  3290. ;
  3291. TRAP1:    CALL    MOVEFCB        ; Move the filename into the file block
  3292.     LXI    H,FCB+1        ; Point to file name
  3293.     MOV    A,M        ; Get first character of file name
  3294.     CPI    ' '        ; Any there?
  3295.     JZ    NFN        ; If not, display error messagename
  3296.     MVI    B,11        ; 11 characters to check
  3297. ;
  3298. TRLOOP:    MOV    A,M        ; Get char from FCB
  3299.     CPI    '?'        ; Ambiguous?
  3300.     JZ    TRERR        ; Yes, exit with error message
  3301.     CPI    '*'        ; Even more ambiguous?
  3302.     JZ    TRERR        ; Yes, exit with error message
  3303.     INX    H        ; Point to next character
  3304.     DCR    B        ; One less to go
  3305.     JNZ    TRLOOP        ; Not done, check some more
  3306.     RET
  3307. ;
  3308. NFN:    CALL    ERXIT        ; Print message, exit
  3309.     DB    '++ Specify a filename ++','$'
  3310. ;
  3311. TRERR:    LDA    BCHFLG
  3312.     ORA    A
  3313.     RNZ            ; Wildcards are ok in batch mode
  3314.     CALL    ERXIT        ; Print message, exit
  3315.     DB    '++ Wild-cards accepted in batch mode only ++','$'
  3316. ;
  3317. CKNUM:    CPI    '0'
  3318.     JC    ILLDU        ; Error if less than ascii '0'
  3319.     CPI    '9'+1
  3320.     RC            ; Error if more than ascii '9'
  3321. ;
  3322. ILLDU:    CALL    ERXIT
  3323.     DB    '++ Improper drive/user combination ++','$'
  3324. ;
  3325. ; Receive a record - returns with carry bit set if EOT received
  3326. ;
  3327. RCVRECD:XRA    A        ; Initialize error count to zero
  3328.     STA    ERRCT
  3329. ;
  3330. RCVRPT:    CALL    FUNCHK        ; Check function keys
  3331.     LDA    SYSABT
  3332.     ORA    A        ; Local abort?
  3333.     JNZ    RCVSABT        ; Yes, else...
  3334.     MVI    B,10        ; 10-seconds to get first character
  3335.     LDA    FRSTIM        ; Have we started, yet?
  3336.     ORA    A
  3337.     JNZ    NOCHR        ; No, so skip next line
  3338.     MVI    B,3+1        ; Check every 4 seconds until started
  3339. ;
  3340. NOCHR:    CALL    RECV        ; Get any character received
  3341.     JC    RCVSTOT        ; Timeout error if no character received
  3342.     CPI    SOH        ; See if it is SOH
  3343.     JZ    RCVSOH        ; Got SOH, get record
  3344.     CPI    STX        ; See if it is STX for 1k blocks
  3345.     JZ    RCVSTX        ; Got STR, get record
  3346.     CPI    CANCEL        ; ^X to abort?
  3347.     JZ    CKCAN        ; Yes, check for aborting
  3348.     ORA    A        ; Null?
  3349.     JZ    RCVRPT        ; Yes, get another character
  3350.     CPI    7BH        ; V.22 synch character?
  3351.     JZ    RCVRPT        ; Yes, ignore
  3352.     CPI    0FBH        ; V.22 synch character with high bit set?
  3353.     JZ    RCVRPT        ; Yes, ignore
  3354.     CPI    EOT        ; End of transmission?
  3355.     JNZ    RCVRP1        ; No, continue
  3356.     LDA    EOTFLG        ; Get EOT flag status
  3357.     ORA    A        ; Second EOT?
  3358.     STC            ; Set carry, in case second EOT received
  3359.     RNZ            ; Yes, so all done
  3360.     MVI    A,NAK
  3361.     STA    EOTFLG        ; Show EOT received
  3362.     CALL    SEND        ; Send NAK for double check of EOT
  3363.     JMP    RCVLP        ; Continue with receive
  3364. ;
  3365. RCVRP1:    CPI    CRC        ; Ignore our own character coming back
  3366.     JZ    RCVRPT
  3367.     CPI    KSND        ; Ignore our own character coming back
  3368.     JZ    RCVRPT
  3369.     CPI    NAK        ; Ignore our own character coming back
  3370.     JZ    RCVRPT
  3371.     CALL    ILPRTL        ; Show locally only
  3372.     DB    CR,LF,0
  3373.     MOV    A,B
  3374.     CALL    HEXO
  3375.     CALL    ILPRT
  3376.     DB    'H received not SOH ',CR,LF,0
  3377. ;
  3378. ; Didn't get SOH or EOT or did not get valid header so purge the line,
  3379. ; then send NAK.
  3380. ;
  3381. RCVSR:    CALL    WAIT1        ; Get anything coming in and discard
  3382.     CALL    CKABORT        ; Want to quit now?
  3383.     LDA    FRSTIM        ; Get first time switch
  3384.     ORA    A        ; Has first 'SOH' been received?
  3385.     MVI    A,NAK
  3386.     JNZ    RCVSR1        ; Yes, then send 'NAK'
  3387.     LDA    CRCFLG        ; Get the 'CRC' flag
  3388.     ORA    A        ; 'CRC' in effect?
  3389.     MVI    A,NAK        ; Put 'NAK' in 'A' register
  3390.     JZ    RCVSR1        ; No, send the 'NAK' for checksum
  3391.     MVI    A,CRC        ; Tell sender we have 'CRC'
  3392.     CALL    SEND
  3393.     LDA    KFLG        ; Requesting 1k transmissions?
  3394.     ORA    A
  3395.     JZ    RCVSR1        ; If not, exit
  3396.     MVI    A,KSND        ; Tell sender we also have 1k capability
  3397. ;
  3398. RCVSR1:    CALL    SEND        ; Checksum (NAK) or CRC (X/Ymodem) request
  3399.     LDA    ERRCT        ; Get the error count
  3400.     INR    A        ; Increment error count
  3401.     STA    ERRCT        ; Store new value
  3402.     MOV    B,A        ; Keep the error count for now
  3403.     LDA    FRSTIM        ; Have we gotten under way yet?
  3404.     ORA    A
  3405.     MOV    A,B        ; get the value back
  3406.     JZ    RCVSR2        ; If not, exit
  3407.     CPI    10        ; 10 errors the limit, once under way
  3408.     JNC    RCVSABT        ; Abort if over the limit
  3409.     CALL    RDCOUNT        ; Display record count before repeating
  3410.     JMP    RCVRPT        ; Less than 10, keep going
  3411. ;
  3412. RCVSR2:    CPI    10        ; 10 times for 1k/CRC yet? (40 seconds)
  3413.     JC    RCVRPT        ; Keep trying if less
  3414.     XRA    A        ; Else flip to checksum mode
  3415.     STA    CRCFLG
  3416.     MOV    A,B        ; Get the count back
  3417.     CPI    15        ; Another 5 times for checksum?
  3418.     JC    RCVRPT        ; If less, try again, quit at 60 seconds
  3419. ;
  3420. ; Error limit exceeded, so abort
  3421. ;
  3422. RCVSABT:XRA    A
  3423.     STA    CONONL        ; Clear the console-only flag
  3424.     LXI    SP,STACK    ; Clear the stack just in case
  3425.     CALL    CLOSFIL        ; Keep whatever we got
  3426.     CALL    ILPRT
  3427.     DB    CR,LF,LF
  3428.     DB    '   ++ Upload has been cancelled ++',0
  3429.     CALL    DELFILE        ; Delete received file
  3430.     CALL    ERXIT        ; Print second half of message
  3431.     DB    '++ Incomplete file has been deleted ++','$'
  3432. ;
  3433. ; Deletes the received file (used if receive aborts)
  3434. ;
  3435. DELFILE:LXI    D,FCB        ; Point to file
  3436.     CALL    DELFIL        ; Delete it
  3437.     INR    A        ; Delete ok?
  3438.     RNZ            ; Yes, return
  3439.     CALL    ERXIT        ; No, abort
  3440.     DB    CR,LF
  3441.     DB    '++ No file or can''t delete received file ++','$'
  3442. ;
  3443. ; Aborts with 1 ^X if first time flag is not set, two otherwise
  3444. ;
  3445. CKCAN:    LDA    FRSTIM        ; First time flag set yet?
  3446.     ORA    A
  3447.     JZ    RCVSABT        ; If not, Abort and close file
  3448.     MVI    B,2        ; Maximum of 2 seconds for extra ^X
  3449.     CALL    RECV
  3450.     JC    RCVRPT        ; No additional character, ignore ^X
  3451.     CPI    CANCEL        ; If a 2nd ^X, abort and close file
  3452.     JZ    RCVSABT
  3453.     JMP    RCVRPT        ; Else wait for a STX, SOH or timeout
  3454. ;
  3455. ; Timed out on receive
  3456. ;
  3457. RCVSTOT:CALL    EOTCHK        ; See if EOT has been received
  3458.     LDA    FRSTIM        ; First time flag set yet?
  3459.     ORA    A
  3460.     JZ    RCVSR        ; If not, don't show an error
  3461.     CALL    ILPRTL        ; Show locally only
  3462.     DB    '++ Timeout waiting for character ++',CR,LF,0
  3463.     JMP    RCVSR        ; Bump error count, etc.
  3464. ;
  3465. ; Got a STX - set KFLG for 1k
  3466. ;
  3467. RCVSTX:    STA    KFLG        ; Set the 1k flag
  3468.     STA    CRCFLG        ; Insure in CRC mode for 1k blocks
  3469.     JMP    RCVS1
  3470. ;
  3471. ; Got SOH - get block number, block number complemented
  3472. ;
  3473. RCVSOH:    XRA    A
  3474.     STA    KFLG        ; If SOH, clear the 1k flag
  3475. ;
  3476. RCVS1:    MVI    B,5        ; Timeout = 5 seconds
  3477.     MOV    A,B        ; Get something to store
  3478.     STA    FRSTIM        ; Indicate first 'SOH' or 'STX' recvd.
  3479.     CALL    RECV        ; Get block number
  3480.     JC    RCVSTOT        ; Got timeout
  3481.     MOV    D,A        ; Save block number
  3482.     MVI    B,5        ; Timeout = 5 seconds
  3483.     CALL    RECV        ; Get complimented record number
  3484.     JC    RCVSTOT        ; Timeout
  3485.     CMA            ; Get the complement
  3486.     CMP    D        ; Same as original block number?
  3487.     JZ    RCVDATA        ; Yes, get data
  3488. ;
  3489. ; Got bad record number in header
  3490. ;
  3491.     CALL    ILPRTL        ; Show locally only
  3492.     DB    '++ Error in header ++',CR,LF,0
  3493.     JMP    RCVSR        ; Go check error limit and send NAK
  3494. ;
  3495. RCVDATA:MOV    A,D        ; Get record number
  3496.     STA    RCVCNT        ; Save it
  3497.     MVI    C,0        ; Initialize checksum
  3498.     LXI    H,0        ; Initialize CRC
  3499.     SHLD    CRCVAL        ; Clear CRC counter
  3500.     LXI    D,128        ; For 128 character blocks
  3501.     LDA    KFLG        ; Using 1k blocks?
  3502.     ORA     A
  3503.     JZ    $+6        ; If not, skip next line
  3504.     LXI    D,1024        ; If using 1k blocks
  3505.     LHLD    RECPTR        ; Get buffer address
  3506. ;
  3507. RCVCHR:    MVI    B,5        ; 5 sec timeout
  3508.     CALL    RECV        ; Get the character
  3509.     JC    RCVSTOT        ; Timeout
  3510.     MOV    M,A        ; Store the character
  3511.     INX    H        ; Point to next character
  3512.     DCX    D        ; One less to go
  3513.     MOV    A,D        ; See if 'D' and 'E' are both empty
  3514.     ORA    E
  3515.     JNZ    RCVCHR        ; No, get next character
  3516.     LDA    CRCFLG        ; Using 'CRC'?
  3517.     ORA    A
  3518.     JNZ    RCVCRC        ; If yes go get 'CRC'
  3519. ;
  3520. ; Verify checksum
  3521. ;
  3522.     MOV    D,C        ; Save checksum
  3523.     MVI    B,5        ; Timeout length
  3524.     CALL    RECV        ; Get checksum
  3525.     JC    RCVSTOT        ; Timeout
  3526.     CMP    D        ; Checksum ok?
  3527.     JZ    CHKSNUM        ; Yes, exit
  3528.     CALL    ILPRTL        ; Show locally only
  3529.     DB    '++ Checksum error ++',CR,LF,0
  3530.     JMP    RCVSR        ; Go check the error limit and send NAK
  3531. ;
  3532.