home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / sigmv068.ark / PLINK65.ASM < prev    next >
Assembly Source File  |  1984-04-29  |  24KB  |  1,158 lines

  1. ;                    PLINK.ASM  ver 6.5
  2. ;              (revised 6/26/81)
  3. ;
  4. ;PLINK is a CP/M transient command which allows the user to
  5. ;establish a communications link with a remote computer.
  6. ;
  7. ;This program currently supports the following modems or computers
  8. ;via conditional assembly:
  9. ;
  10. ; 1. PMMI modem
  11. ; 2. Any serial I/O board (TUART included)
  12. ; 3. TRS-80 model 1
  13. ; 4. TRS-80 model 2
  14. ; 5. Heath H8/H89 with 8250 uart at port 330Q
  15. ; 6. D.C.Hayes 80-103A or Micromodem 100
  16. ; 7. MITS 2SI/O board, ports 10h &11h = console, 12h & 13h = modem
  17. ; 8. Intel SBC or National BLC multi-bus boards using 8251 USART
  18. ;
  19. ;Originally written by L.E. Hughes (EDCAM) in July, 1977.  Many
  20. ;modifications have been made since this time, as shown in the
  21. ;following summary.
  22. ;
  23. ;Fixes/updates (in reverse order to minimize reading time):
  24. ;
  25. ; June 26, 1981. Added message when exiting if last buffer was
  26. ; not saved.  Ted Shapin.
  27. ;
  28. ;June 14, 1981, by Keith Petersen, W8SDZ.  Changed port
  29. ;equate to 'equ' instead of 'set'.  ASM doesn't like 'set'
  30. ;when later conditionals are based on a label defined that
  31. ;way.
  32. ;
  33. ;June 7, 1981, by Tom Jorgenson (CP-MIG).  Changed CP/M 
  34. ;origin from being via SETs to referenced to BASE, added
  35. ;TRUE/FALSE rather than numeric values (for readability),
  36. ;changed ^Q function to ^W (write) because some systems
  37. ;(notably Micronet) use ^S/^Q to suspend/resume output,
  38. ;changed page 0 references in TRS routines to use
  39. ;BASE equate properly, changed PORT equates to default
  40. ;to TRUE, reinserted Heath equates, and cleaned up code
  41. ;in several places.
  42. ;
  43. ;June 7, 1981, by Keith Petersen, W8SDZ.  Fixed problem with
  44. ;equates which prevented assembly by 'ASM' when TUART option
  45. ;was selected.
  46. ;
  47. ;June 6, 1981, by Keith Petersen, W8SDZ.  Added version number,
  48. ;cleaned up file.
  49. ;
  50. ;May 12, 1981, by T. Shapin.  Added code for 8251 USART on Intel 
  51. ;SBC or National BLC multibus board with modified CP/M origin.  
  52. ;Added prompt to signon. Added toggle to ^Y to save or ignore 
  53. ;incoming text. Added ^C abort on file name response.
  54. ;
  55. ;November 10, 1980, by Kelly Smith.  Added conditional assembly 
  56. ;switch for MITS 2SI/O board, using "standard" MITS ports 10 and
  57. ;11 hex for the console, and 12 and 13 hex for the modem.
  58. ;
  59. ;October 18, 1980, by Keith Petersen, W8SDZ.
  60. ;
  61. ;Heath equates added by Tom Jorgenson.
  62. ;
  63. ;TRS-80 model 1 mods by Steve Vinokuroff, Vancouver CBBS.
  64. ;
  65. ;Optional trigger characters by Steve Vinokuroff.
  66. ;
  67. ;TRS-80 mods by Dennis Breckenridge, Burnaby CBBS.
  68. ;
  69. ;D.C.Hayes mods by Bruce Ratoff, Iselin New Jersey Remote CP/M.
  70. ;
  71. ;NOTE: If you add improvements or otherwise update
  72. ;this program, please modem a copy of the new file
  73. ;to "TECHNICAL CBBS" in Dearborn, Michigan - phone
  74. ;313-846-6127 (110, 300, 450 or 600 baud).  Use the
  75. ;filename PLINKXX.NEW.
  76. ;
  77. ;PLINK currently supports two way transfer of text files between
  78. ;the CP/M disk and the remote computer. The following control
  79. ;codes may be initiated from the console keyboard:
  80. ;
  81. ;Control-E      Exit PLINK to CP/M "warm-boot".
  82. ;
  83. ;Control-T      Transmit ASCII file to remote system, asks for
  84. ;               drive (A, B, etc.) and filename.typ.
  85. ;
  86. ;Control-C      Aborts transmission of file to remote system.
  87. ;
  88. ;Control-Y      Switches between saving and ignoring
  89. ;        incoming ASCII data in RAM buffer,
  90. ;        for later transfer to disk.
  91. ;
  92. ;Control-W      Writes RAM buffer to disk, and asks for drive
  93. ;               and filename.typ.
  94. ;
  95. ;Del (delete)   Backspace when in command mode (e.g. ^T or ^W).
  96. ;
  97. ;Control-U      Aborts current line when in command mode.
  98. ;
  99. ;(Note: all other control codes are passed to modem output, and
  100. ;may be interpreted by the remote system as various control
  101. ;functions.)
  102. ;
  103. ;TRUE/FALSE definitions
  104. ;
  105. FALSE    equ    0
  106. TRUE    equ    NOT FALSE
  107. ;
  108. ;Conditional assembly switches <<-- set for your system
  109. ;(select only one as true) - (NOTE: use TUART for other
  110. ;serial ports not defined).
  111. ;
  112. MITSIO    equ    FALSE    ;true, if MITS 2SI/O board
  113. H84    equ    FALSE    ;true, if you have H8/H8-4 or H89
  114. TUART    equ    FALSE     ;true, if Cromenco TUART or OTHER SERIAL
  115. PMMI    equ    TRUE    ;true, if PMMI (set INITREQ true only
  116.             ;if orig mode and parity is required)
  117. DCH    equ    FALSE    ;true, if D.C.Hayes
  118. TRS1    equ    FALSE    ;true, if TRS-80 model 1
  119. TRSPT    equ    FALSE    ;true, if TRS-80 model 2
  120.             ;using pickles & trout CP/M 2.x
  121. MULTI   equ     FALSE    ;true, if SBC or BLC 8251 USART
  122. ;
  123. INITREQ equ    FALSE    ;true, if port initialization required
  124. ;
  125.     IF    NOT TRSPT
  126. PORT    equ    TRUE     ;true, on most systems
  127.     ENDIF
  128. ;
  129.     IF    TRSPT
  130. PORT    equ    FALSE    ;this is the oddball
  131.     ENDIF
  132. ;
  133. ;bdos entry point and function codes
  134. ;
  135. base    equ    0    ;<<-- set to offset of CP/M for your
  136.             ;system, standard systems are 0, some
  137.             ;'alternate' systems are 4200H
  138. ;
  139. bdos    equ    base+5
  140. resdsk    equ    13    ;reset disk system
  141. offc    equ    15    ;open file
  142. cffc    equ    16    ;close file
  143. dffc    equ    19    ;delete file
  144. rrfc    equ    20    ;read record
  145. wrfc    equ    21    ;write record
  146. mffc    equ    22    ;make file
  147. ;
  148. ;TRS80 pickles and trout sio calls
  149. ;offset by -3 that is add 3 to all calls
  150. ;
  151. setsio    equ    30h    ;set up z80 sio
  152. siotst    equ    33h    ;read sio status
  153. sioinp    equ    36h    ;input a char
  154. sioout    equ    39h    ;output a char
  155. ;
  156.      IF    MULTI
  157. mods      equ    0DDH    ;modem control
  158. mtbe      equ    1    ;bit to test for send
  159. mrda      equ    2    ;bit to test for receive
  160. mxor      equ    3    ;mask to make MTBE and MRDA 'low true'
  161. modd      equ    0DCH    ;modem data port
  162.     ENDIF
  163. ;
  164. ;default fcb and field definitions
  165. ;
  166. fcb    equ    base+5ch
  167. fn    equ    1    ;file name field (rel)
  168. ft    equ    9    ;file type field (rel)
  169. ex    equ    12    ;file extent field (rel)
  170. nr    equ    32    ;next record field (rel)
  171. dbuf    equ    base+80h ;default disk buffer address
  172. ;
  173. ;ascii control characters
  174. ;
  175. cr    equ    0dh    ;carriage return
  176. lf    equ    0ah    ;line feed
  177. del    equ    7fh    ;delete (rubout)
  178. bell    equ    07h    ;bell signal
  179. tab    equ    09h    ;horizontal tab
  180. xon    equ    11h    ;x-on character
  181. null    equ    00h    ;null char
  182. ;
  183. ;the following "trigger" equate is set to "lf" (linefeed)
  184. ;by default. an optional trigger char may be passed via fcb1
  185. ;
  186. ; ie:  PLINK B        will set trigger to "bell"
  187. ;
  188. ;the following options are allowed
  189. ;
  190. ;    1. B = bell  07h
  191. ;    2. X = xon   11h
  192. ;    3. U = upload no trigger check at all
  193. ;
  194. ;any other ascii character may be passed through fcb1
  195. ;
  196. ;
  197. trigger    equ    LF    ;default value
  198. ;
  199. ;
  200. ;warning character for low memory
  201. ;
  202. wrnsig    equ    BELL    ;if you have one, put 'BELL' here
  203.             ;...else put '*' here.
  204. ;
  205. ;modem i/o port addresses
  206. ;
  207.     IF    MITSIO
  208. modd    equ    13h    ;modem data port
  209. mods    equ    12h    ;modem status port
  210. modrset    equ    03h    ;6850 ACIA reset
  211. modinit    equ    11h    ;8 data, no parity, 2 stop
  212.     ENDIF
  213. ;
  214.     IF    H84
  215. modd    equ    330Q    ;modem data port
  216. mods    equ    335Q    ;modem status port
  217.     ENDIF
  218. ;
  219.     IF    PMMI
  220. modd    equ    0c1h    ;modem data port
  221. mods    equ    0c0h    ;modem status port
  222. modinit    equ    29h    ;initialize byte originate,
  223.             ;7 data, even parity, 1 stop
  224.     ENDIF
  225. ;
  226.     IF    DCH
  227. modd    equ    90h    ;modem data port
  228. mods    equ    91h    ;modem status port
  229. modinit    equ    05h    ;7 data, even parity, 1 stop
  230.     ENDIF
  231. ;
  232.     IF    TRS1
  233. modd    equ    0ebh    ;TRS80 mod 1 rs232 data port
  234. mods    equ    0eah    ; and the rs232 status port
  235.     ENDIF
  236. ;
  237.     IF    TUART
  238. modd    equ    0d6h    ;<<--modify for yours
  239. mods    equ    0d7h    ;<<--modify for yours
  240.     ENDIF
  241. ;
  242. ;modem status port bit definitions
  243. ;
  244.     IF    H84
  245. mtbe    equ    40Q    ;modem THRE transmit ready bit
  246. mrda    equ    01Q    ;modem RDA rec'd data bit
  247. mxor    equ    41Q    ;mask to make mtbe and mrda 'negative logic'
  248.     ENDIF
  249. ;
  250.     IF    PMMI
  251. mtbe    equ    01h    ;modem trans. buffer ready flag
  252. mrda    equ    02h    ;modem receive data avail. flag
  253. mxor    equ    03h    ;mask to make mtbe and mrda "low true"
  254.     ENDIF
  255. ;
  256.     IF    DCH or MITSIO
  257. mtbe    equ    02h    ;modem trans. buffer ready flag
  258. mrda    equ    01h    ;modem receive data avail. flag
  259. mxor    equ    03h
  260.     ENDIF
  261. ;
  262.     IF    TRS1
  263. mtbe    equ    40h    ;TRS80 mod1 rs232 buffer ready
  264. mrda    equ    80h    ;modem receive data avail.
  265. mxor    equ    0c0h
  266.     ENDIF
  267. ;
  268.     IF    TUART    ;<<--or any other serial i/o
  269. mtbe    equ    1    ;<<--modify for yours
  270. mrda    equ    2    ;<<--modify for yours
  271. mxor    equ    3    ;<<--modify for yours
  272.     ENDIF
  273. ;
  274. ;    **main program**
  275. ;
  276.     org    base+100h
  277. ;
  278. link:    lxi    sp,stack+64 ;create local stack
  279.     lhld    base+1    ;point to CP/M jmp table
  280.     lxi    d,3    ;get ready to add 3
  281.     dad    d    ;point to con status jmp
  282.     shld    citcal+1 ;modify call adrs
  283.     dad    d    ;point to con in jmp
  284.     shld    rccal+1    ;modify call adrs
  285.     dad    d    ;point to con out jmp
  286.     shld    wccal+1    ;modify call adrs
  287.     lda    fcb+1    ;see if optional trigger char
  288.     cpi    20h    ;blank.. ?
  289.     jz    skp    ;..blank so use default "lf"
  290.     cpi    'B'    ;bell wanted
  291.     jz    trgbel
  292.     cpi    'X'    ;xon wanted
  293.     jz    trgxon
  294.     cpi    'U'    ;uploading no checking for trigger
  295.     jz    trgupl
  296. ;
  297. settrg    sta    overly+1 ;store the character as is then
  298.     jmp    skp
  299. ;
  300. trgbel    mvi    a,bell
  301.     jmp    settrg
  302. ;
  303. trgxon    mvi    a,xon
  304.     jmp    settrg
  305. ;
  306. trgupl    xra    a     ;zero out jump
  307.     sta    overl1+1 ;change check for c/r to null
  308.     sta    overl2+1 ;and send linefeeds as well
  309.     jmp    skp
  310. ;
  311. skp:    equ    $
  312. ;
  313.     IF    MITSIO
  314.     mvi    a,modrset
  315.     out    mods
  316.     mvi    a,modinit
  317.     out    mods
  318.     ENDIF
  319. ;
  320.     IF    H84
  321.     mvi    a,80h    ;set dlab bit in 8250 uart
  322.     out    0dbh    ;8250 at port d8h (330q)
  323.     nop ! nop ! nop
  324.     nop ! nop
  325.     mvi    a,01h    ;msb of baud rate divisor
  326.     out    0d9h    ;...to uart
  327.     nop ! nop ! nop
  328.     nop ! nop
  329.     mvi    a,80h    ;lsb of baud rate divisor
  330.     out    0d8h    ;...to uart
  331.     nop ! nop ! nop
  332.     nop ! nop
  333.     mvi    a,03h    ;8 bits, 1 stop bit, no parity, dlab reset
  334.     out    0dbh    ;...to uart
  335.     nop ! nop ! nop
  336.     nop ! nop
  337.     mvi    a,0    ;reset control register
  338.     out    0dch    ;...to uart
  339.     jmp    cont
  340.     ENDIF
  341. ;
  342.     IF    INITREQ and (NOT H84) and (NOT MITSIO)
  343.     mvi    a,modinit
  344.     out    mods    ;initialize modem port
  345.     ENDIF
  346. ;
  347.     IF    INITREQ and TUART
  348.     mvi    a,80h    ;dsr on bit 7 parl port b
  349.     out    54h
  350.     ENDIF
  351. ;
  352.     IF    TRSPT    ;must set up serial channel
  353. reset:    lxi    h,initr    ;store return address
  354.     push    h
  355.     lhld    1
  356.     lxi    d,setsio ;sio setup routine
  357.     dad    d
  358.     push    h    ;store on stack
  359.     mvi    c,00h    ;no parity chan-a
  360.     mvi    d,0e6h    ;8 bits ,1 stop
  361.     mvi    e,3    ;300 baud
  362.     mvi    l,00h    ;disable ext/ack sio functions
  363.     mvi    h,'S'-40h ;control s (x-on)
  364.     ret        ;trough setup prog
  365. ;
  366. initr    nop        ;do it to it
  367.     ENDIF
  368. ;
  369.     IF    TRS1    ;init for TRS80 mod1 rs232
  370.     out    0e8h    ;reset rs232
  371.     in    0e9h    ;read the switches
  372.     ani    0f8h
  373.     ori    5
  374.     out    0eah    ;set dsr and cts
  375.     mvi    a,55h    ;300 baud
  376.     out    0e9h
  377.     ENDIF
  378. ;
  379.     IF    PORT
  380.     in    modd    ;clear modem uart read buffers
  381.     in    modd
  382.     ENDIF
  383. ;
  384.     IF    MULTI    ;initialize 8251
  385.     xra    a
  386.     out    mods
  387.     out    mods
  388.     out    mods
  389.     mvi    a,40h
  390.     out    mods
  391.     mvi    a,0cfh    ;300 baud (this depends on strapping)
  392.     out    mods
  393.     mvi    a,37h
  394.     out    mods
  395.     ENDIF
  396. ;
  397. cont:    xra    a    ;clear char buffers
  398.     sta    inch
  399.     sta    outch
  400.     sta    flag    ;clear text save flag
  401.     lxi    h,tbuf    ;set ptr to tbuf
  402.     shld    ptr
  403.     lxi    h,0    ;size = 0
  404.     shld    size
  405.     lxi    h,linkms  ;print sign-on message
  406.     call    wcs
  407. ;
  408. ;main loop
  409. ;
  410. link3:    call    citest    ;jump if no data from console
  411.     jz    link4
  412.     call    rcc    ;else read console data
  413.     cpi    20h
  414.     cc    pcc    ;call pcc if control char
  415.     jc    link4    ;jump if pcc handled char
  416.     ori    80h    ;else set valid data bit
  417.     sta    inch    ;and store in input char buffer
  418. ;
  419. link4:    lda    outch    ;jump if no data for console
  420.     ora    a
  421.     jp    link5
  422.     ani    7fh    ;else discard valid data bit
  423.     call    wcc    ;send char to console
  424.     xra    a    ;then clear output char buffer
  425.     sta    outch
  426. ;
  427. link5:    call    mitest    ;jump if no data from modem
  428.     jz    link6
  429.     call    rmc2    ;else read modem data
  430.     call    save    ;save char in text buffer if flag on
  431.     ori    80h    ;set data valid bit
  432.     sta    outch    ;store in output char buffer
  433. ;
  434. link6:    call    motest    ;jump if modem xmit buffer busy
  435.     jz    link7
  436.     lda    inch    ;jump if no data for modem
  437.     ora    a
  438.     jp    link7
  439.     ani    7fh    ;discard valid data bit
  440. ;
  441.     IF    PORT
  442.     out    modd    ;output char to modem
  443.     ENDIF
  444. ;
  445.     IF    TRSPT
  446.     push    b    ;store registers
  447.     push    h
  448.     push    d
  449.     call    wmc    ;send char
  450.     pop    d
  451.     pop    h
  452.     pop    b
  453.     ENDIF
  454. ;
  455.     xra    a    ;...then clear input char buffer
  456.     sta    inch
  457. ;
  458. link7:    jmp    link3    ;end of main loop
  459. ;
  460. linkms:    db    cr,lf,'PLINK ver 6.5'
  461.     db    cr,lf,cr,lf
  462.     db    '[^T]ransmit, [^Y]ank, [^W]rite, [^E]xit, [^C]ancel'
  463.     db    cr,lf,'Ready',cr,lf,lf,0
  464. ;
  465. ;pcc - process control character
  466. ;
  467. pcc:    cpi    'E'-40h    ;jump out if ctrl e
  468.     jnz    pcc1
  469.     push    h
  470.     lhld    size    ; check for something in text buffer
  471.     mov    a,l    ; and give warning
  472.     ora    h
  473.     jz    pccex    ; before exit
  474.     lxi    h,ays    ;print 'do you want to save...
  475.     call    wcs
  476.     pop    h
  477.     call    rcc    ;get answer
  478.     call    wcc    ;echo it
  479.     ani    5fh    ;make upper case
  480.     cpi    'Y'    ;yes?
  481.     cz    wtb    ; write out buffer
  482.     jmp    pccex    ;exit
  483. ;    call    wccr    ;crlf
  484. ;    stc        ;tell plink to ignore this character
  485. ;
  486.     IF    TRSPT
  487.     pop    psw    ;gobble up call address
  488.     jmp    reset    ;re-initialize sio
  489.     ENDIF
  490. ;
  491.     IF    PORT
  492.     ret
  493.     ENDIF
  494. ;
  495. pcc1:    cpi    'T'-40h    ;jump if not control-t
  496.     jnz    pcc2
  497.     call    stf    ;transmit text file to modem
  498.     stc        ;tell plink to ignore this character
  499.     ret
  500. ;
  501. pcc2:    cpi    'Y'-40h    ;jump if not control-y
  502.     jnz    pcc3
  503.     lda    flag
  504.     dcr    a    ;was it zero?
  505.     jnz    pcc2a    ;yes
  506.     sta    flag    ;no, was 1, now 0
  507.     lxi    h,pcmnix ;print ignore incoming stuff
  508.     jmp    pcc2b
  509. ;
  510. pcc2a:    mvi    a,1    ;turn on text save flag
  511.     sta    flag
  512.     lxi    h,pccmr    ;print 'saving incoming text in memory'
  513. ;
  514. pcc2b:    call    wcs
  515.     stc        ;tell plink to ignore this character
  516.     ret
  517. ;
  518. pcc3:    cpi    'W'-40h    ;jump if not control-W
  519.     jnz    pcc4
  520.     xra    a    ;turn off text save flag
  521.     sta    flag
  522.     call    wtb    ;write text buffer to disk
  523.     stc
  524.     ret
  525. ;
  526. pcc4:    stc        ;let plink handle all other cont. codes
  527.     cmc
  528.     ret
  529. ;
  530. pccex:    lxi    h,disms    ;print 'modem not disconnected'
  531.     call    wcs
  532.     jmp    base    ;exit to warm boot
  533. ;
  534. ays:    db    cr,lf,'Do you want to save the stuff in'
  535.     db    cr,lf,'the buffer before exit to CP/M (Y or N)? ',0
  536. ;
  537.     IF    PMMI or DCH
  538. disms:    db    cr,lf,'Don''t forget - the modem '
  539.     db    'is not disconnected',cr,lf
  540.     db    'use "MODEM D" to disconnect',0
  541.     ENDIF
  542. ;
  543.     IF    (NOT PMMI) and (NOT DCH)
  544. disms:    db    cr,lf,'+++ Exit to CP/M +++',cr,lf,0
  545.     ENDIF
  546. ;
  547. pccmr:    db    cr,lf,'Saving incoming text in memory',cr,lf,0
  548. pcmnix:    db    cr,lf,'Ignoring incoming text',cr,lf,0
  549. ;
  550. ;stf - send text file (to modem)
  551. ;
  552. stf:    call    gfn    ;get name of disk file to send
  553.     jc    stf6    ;jump if file name error
  554.     call    open    ;try to open specified file
  555.     cpi    255    ;jump if file not found
  556.     jz    stf7
  557. ;
  558. stf1:    call    read    ;read next record into dbuf
  559.     cpi    1    ;jump if end-of-file
  560.     jz    stf5
  561.     lxi    h,dbuf     ;point to disk buffer
  562.     mvi    c,128
  563. ;
  564. stf2:    mov    a,m    ;fetch next char from dbuf
  565.     inx    h
  566.     cpi    'Z'-40h    ;jump if end-of-file character
  567.     jz    stf5
  568. ;
  569. overl2    cpi    lf    ;ignore line feeds
  570.     jz    stf4
  571.     call    wmc    ;write character to modem
  572.     call    wcc    ;write character to console
  573. ;
  574. overl1    cpi    cr    ;jump if not carriage return
  575.     jnz    stf4
  576. ;
  577. stf3:    call    citest    ;check console data ready
  578.     jz    stf3a    ;no data there
  579.     call    rcc    ;get console character
  580.     cpi    'C'-40h    ;control c aborts it
  581.     jz    stf8
  582. ;
  583. stf3a:    call    mitest    ;wait for next modem character
  584.     jz    stf3
  585.     call    rmc2    ;check modem for trigger char.
  586. ;
  587. overly    cpi    trigger
  588.     jnz    stf3
  589.     call    wccr    ;send crlf to console
  590. ;
  591. stf4:    dcr    c    ;loop thru rest of dbuf
  592.     jnz    stf2
  593.     jmp    stf1    ;go get next record from disk
  594. ;
  595. stf5:    lxi    h,stfsm    ;print 'file send complete'
  596.     call    wcs
  597.     ret
  598. ;
  599. stf6:    lxi    h,stfs1    ;print 'file name error'
  600.     call    wcs
  601.     ret
  602. ;
  603. stf7:    lxi    h,stfs2    ;print 'file not found'
  604.     call    wcs
  605.     ret
  606. ;
  607. stf8:    lxi    h,stfsa    ;print 'file send aborted'
  608.     call    wcs
  609.     ret
  610. ;
  611. stfsm:    db    'File send complete',cr,lf,0
  612. stfs1:    db    'File name error or abort',cr,lf,0
  613. stfs2:    db    'File not found',cr,lf,0
  614. stfsa:    db    cr,lf,'File send aborted',cr,lf,0
  615. ;
  616. ;save - save char in text buffer if flag on
  617. ;
  618. ;  entry conditions
  619. ;     a - character to save
  620. ;
  621. save:    push    psw
  622.     lda    flag
  623.     ora    a
  624.     jnz    save1
  625.     pop    psw
  626.     ret
  627. ;
  628. save1:    pop    psw
  629.     cpi    del    ;rubout (del) ?
  630.     rz        ;yes, ignore it
  631.     cpi    20h    ;test for control characters
  632.     jnc    save2    ;jump if not control char.
  633.     cpi    cr    ;allow cr to be saved
  634.     jz    save2
  635.     cpi    lf    ;allow lf to be saved
  636.     jz    save2
  637.     cpi    tab    ;allow tab to be saved
  638.     jz    save2
  639.     ret        ;ignore all other control chars.
  640. ;
  641. save2:    push    h
  642.     lhld    size    ;size = size + 1
  643.     inx    h
  644.     shld    size
  645.     lhld    ptr
  646.     mov    m,a
  647.     inx    h
  648.     shld    ptr
  649.     push    psw
  650.     lda    base+7    ;get system size
  651.     sui    1    ;so we dont crash CP/M
  652.     cmp    h    ;are we out of room?
  653.     jz    saveab    ;yes, abort
  654.     sui    4    ;leave some room (1k)
  655.     cmp    h
  656.     mvi    a,wrnsig  ;signal console running out of space
  657.     cc    wcc
  658.     pop    psw
  659.     pop    h
  660.     ret
  661. ;
  662. ;saveab - ran out of room, issue message and flow
  663. ;      through to disk save routine
  664. ;
  665. savend:    db    bell,cr,lf,'Aborting - no room left',0
  666. ;
  667. saveab:    lxi    sp,stack+64  ;reinitialize stack
  668.     lxi    h,savend  ;print 'aborting - no room left'
  669.     call    wcs
  670.     lxi    h,link    ;set up return address
  671.     push    h    ;leave it on the stack
  672. ;
  673. ;wtb - write text buffer to disk
  674. ;
  675. wtb:    lhld    size    ;jump if text buffer empty
  676.     mov    a,l
  677.     ora    h
  678.     jz    wtb5
  679.     mvi    c,resdsk ;reset in case read-only
  680.     call    bdos
  681.     call    gfn    ;get file name
  682.     jc    wtb6    ;jump if file name error
  683.     call    delt    ;delete old file, if any
  684.     call    make    ;make new file
  685.     lhld    size    ;de = tbuf size
  686.     xchg
  687.     lxi    h,dbuf    ;top of stack points to dbuf
  688.     push    h
  689.     lxi    h,tbuf    ;hl points to tbuf
  690. ;
  691. wtb1:    mvi    c,128    ;disk buffer size
  692. ;
  693. wtb2:    mov    a,m    ;fetch next byte of tbuf
  694.     inx    h
  695.     xthl
  696.     mov    m,a    ;store in dbuf
  697.     inx    h
  698.     xthl
  699.     dcx    d    ;size = size - 1
  700.     mov    a,d    ;exit loop if size = 0
  701.     ora    e
  702.     jz    wtb3
  703.     dcr    c    ;loop until dbuf full
  704.     jnz    wtb2
  705.     call    write    ;write full dbuf to disk
  706.     xthl        ;top of stack points to dbuf
  707.     lxi    h,dbuf
  708.     xthl
  709.     jmp    wtb1    ;loop until end of tbuf
  710. ;
  711. wtb3:    pop    h    ;hl points to current place in dbuf
  712. ;
  713. wtb4:    mvi    m,'Z'-40h ;store eof code
  714.     inx    h
  715.     dcr    c    ;loop thru rest of dbuf
  716.     jnz    wtb4
  717.     call    write    ;write last sector to disk
  718.     call    close    ;clean up act and go home
  719.     lxi    h,tbuf    ;clear text buffer
  720.     shld    ptr
  721.     lxi    h,0
  722.     shld    size
  723.     lxi    h,wtbsm    ;print 'buffer saved on disk'
  724.     call    wcs
  725.     ret
  726. ;
  727. wtb5:    lxi    h,wtbs1    ;print 'text buffer empty'
  728.     call    wcs
  729.     ret
  730. ;
  731. wtb6:    lxi    h,wtbs2    ;print 'file name error'
  732.     call    wcs
  733.     ret
  734. ;
  735. wtbsm:    db    cr,lf,'Buffer saved on disk',cr,lf
  736.     db    'Memory save cancelled',cr,lf,0
  737. wtbs1:    db    'Text buffer empty',cr,lf,0
  738. wtbs2:    db    'File name error or abort',cr,lf,0
  739. ;
  740. ;wcs - write console string
  741. ;
  742. ;  entry conditions
  743. ;     hl - points to string (term by zero byte)
  744. ;
  745. wcs:    mov    a,m
  746.     inx    h
  747.     ora    a
  748.     rz
  749.     call    wcc
  750.     jmp    wcs
  751. ;
  752. ;wccr - write console carriage return (and line feed)
  753. ;
  754. wccr:    mvi    a,cr
  755.     call    wcc
  756.     mvi    a,lf
  757. ;
  758. ;wcc - write console character
  759. ;
  760. ;  entry conditions:
  761. ;     a - character to write
  762. ;
  763. wcc:    push    psw
  764.     push    b
  765.     push    d
  766.     push    h
  767.     mov    c,a    ;get character for cbios
  768. wccal:    call    $-$    ;modified by init.
  769.     pop    h
  770.     pop    d
  771.     pop    b
  772.     pop    psw
  773.     ret
  774. ;
  775. ;rcs - read console string (with echo)
  776. ;
  777. ;  exit conditions
  778. ;     b - number of characters read (<255)
  779. ;    hl - points to last char stored (cr)
  780. ;
  781. rcs:    lxi    h,ibuf
  782.     mvi    b,0
  783. ;
  784. rcs1:    call    rcc    ;read next char from console
  785.     cpi    del    ;jump if not del
  786.     jnz    rcs2
  787.     inr    b    ;ignore del if ibuf already empty
  788.     dcr    b
  789.     jz    rcs1
  790.     dcx    h    ;else discard last char
  791.     mov    a,m    ;echo discarded char to console
  792.     call    wcc
  793.     dcr    b    ;decrement count
  794.     jmp    rcs1    ;    and loop
  795. ;
  796. rcs2:    cpi    'U'-40h    ;jump if not control u
  797.     jnz    rcs3
  798.     call    wccr    ;else abort current line
  799.     jmp    rcs    ;    and start over
  800. ;
  801. rcs3:    call    wcc    ;echo char to console
  802.     mov    m,a    ;store char in ibuf
  803.     inr    b    ;increment count
  804.     cpi    cr    ;jump if carriage return
  805.     jz    rcs4
  806.     inx    h    ;else advance pointer
  807.     jmp    rcs1    ;    and loop
  808. ;
  809. rcs4:    mvi    a,lf    ;issue line feed and return
  810.     call    wcc
  811.     ret
  812. ;
  813. ;rcc - read console character
  814. ;
  815. ;  exit conditions
  816. ;     a - character read
  817. ;
  818. rcc:    push    b
  819.     push    d
  820.     push    h
  821. rccal:    call    $-$    ;modified by init.
  822.     pop    h
  823.     pop    d
  824.     pop    b
  825.     ret
  826. ;
  827. ;wmc - write modem character
  828. ;
  829. ;  entry conditions
  830. ;     a - character to write
  831. ;
  832. ;
  833.     IF    PORT
  834. wmc:    push    psw
  835. ;
  836. wmcl:    in    mods
  837.     xri    mxor
  838.     ani    mtbe
  839.     jnz    wmcl
  840.     pop    psw
  841.     ani    7fh    ;strip parity bit
  842.     out    modd
  843.     ret
  844.     ENDIF
  845. ;
  846.     IF    TRSPT
  847. wmc:    push    h
  848.     push    d
  849.     push    psw
  850. ;
  851. wmcl:    call    motest    ;test status
  852.     jz    wmcl    ;loop till tx empty
  853.     pop    psw    ;restore char
  854.     ani    7fh    ;strip parity
  855.     push    b    ;store b
  856.     mov    c,a    ;put char into c
  857.     mvi    b,00h    ;channel a
  858.     lxi    h,wmcre    ;store return address
  859.     push    h
  860.     lhld    base+1    ;get base address
  861.     lxi    d,sioout
  862.     dad    d
  863.     pchl        ;jump to it
  864. ;
  865. wmcre:    pop    b    ;restore it
  866.     pop    d
  867.     pop    h
  868.     ret
  869.     ENDIF
  870. ;
  871. ;rmc - read modem character
  872. ;
  873. ;  exit conditions:
  874. ;     a - character read
  875. ;
  876. ;
  877.     IF    PORT
  878. rmc:    in    mods
  879.     xri    mxor
  880.     ani    mrda
  881.     jnz    rmc
  882. ;
  883. rmc2:    in    modd
  884.     ani    7fh
  885.     ret
  886.     ENDIF
  887. ;
  888.     IF    TRSPT
  889. rmc:    call    mitest    ;char available
  890.     jz    rmc    ;loop if not ready
  891. ;
  892. rmc2:    push    b    ;store b
  893.     push    d
  894.     push    h
  895.     mvi    b,00h    ;channel a
  896.     lxi    h,rmcre    ;return address
  897.     push    h
  898.     lhld    1
  899.     lxi    d,sioinp
  900.     dad    d
  901.     pchl
  902. ;
  903. rmcre:    pop    h
  904.     pop    d
  905.     pop    b
  906.     ani    7fh    ;strip parity
  907.     ret
  908.     ENDIF
  909. ;
  910. ;gfn - get file name
  911. ;
  912. gfn:    lxi    h,gfnsd    ;print 'which drive?'
  913.     call    wcs
  914.     call    rcc    ;get answer from console
  915.     call    wcc    ;echo it to console
  916.     ani    5fh    ;make upper case
  917.     cpi    'C'-40h    ;^C means abort
  918.     jz    gfn6
  919.     sui    'A'-1
  920.     jc    gfn    ;require alphabetic
  921.     jz    gfn
  922.     cpi    17    ;allow 16 drives (as in CP/M 2.x)
  923.     jnc    gfn
  924.     sta    fcb
  925. ;
  926. gfnb:    lxi    h,gfns1    ;print 'filename? '
  927.     call    wcs
  928.     call    rcs    ;read response into ibuf
  929.     lxi    h,fcb+fn  ;blank fill fn and ft fields
  930.     mvi    c,11
  931. ;
  932. gfn1:    mvi    m,' '
  933.     inx    h
  934.     dcr    c
  935.     jnz    gfn1
  936.     lxi    h,ibuf    ;point to input buffer
  937.     lxi    d,fcb+fn  ;scan off fn field
  938.     mvi    c,9
  939. ;
  940. gfn2:    mov    a,m    ;fetch next char from ibuf
  941.     inx    h
  942.     cpi    61h    ;if lc, convert to uc
  943.     jc    gfn2a
  944.     sui    20h
  945. ;
  946. gfn2a:    cpi    cr    ;jump if end of line
  947.     jz    gfn5
  948.     cpi    '.'    ;jump if end of name
  949.     jz    gfn3
  950.     stax    d    ;else store char in fn field
  951.     inx    d
  952.     dcr    c    ;loop if 8 or less chars so far
  953.     jnz    gfn2
  954.     jmp    gfn6    ;else take error exit
  955. ;
  956. gfn3:    lxi    d,fcb+ft  ;scan off ft field
  957.     mvi    c,4
  958. ;
  959. gfn4:    mov    a,m    ;fetch next char from ibuf
  960.     inx    h
  961.     cpi    61h    ;if lc, convert to uc
  962.     jc    gfn4a
  963.     sui    20h
  964. ;
  965. gfn4a:    cpi    cr    ;jump if end of line
  966.     jz    gfn5
  967.     stax    d    ;else store char in ft field
  968.     inx    d
  969.     dcr    c    ;loop if 3 or less chars so far
  970.     jnz    gfn4
  971.     jmp    gfn6    ;else take error exit
  972. ;
  973. gfn5:    xra    a
  974.     sta    fcb+ex    ;set extent number to zero
  975.     sta    fcb+nr    ;set record number to zero
  976.     stc        ;clear error flag and return
  977.     cmc
  978.     ret
  979. ;
  980. gfn6:    stc        ;set error flag and return
  981.     ret
  982. ;
  983. gfnsd:    db    cr,lf,'Which drive? ',0
  984. gfns1:    db    cr,lf,'Filename? ',0
  985. ;
  986. ;open - open disk file
  987. ;
  988. open:    push    h
  989.     push    d
  990.     push    b
  991.     lxi    d,fcb
  992.     mvi    c,offc
  993.     call    bdos
  994.     pop    b
  995.     pop    d
  996.     pop    h
  997.     ret
  998. ;
  999. ;read - read record from disk file
  1000. ;
  1001. read:    push    h
  1002.     push    d
  1003.     push    b
  1004.     lxi    d,fcb
  1005.     mvi    c,rrfc
  1006.     call    bdos
  1007.     pop    b
  1008.     pop    d
  1009.     pop    h
  1010.     ret
  1011. ;
  1012. ;close - close disk file
  1013. ;
  1014. close:    push    h
  1015.     push    d
  1016.     push    b
  1017.     lxi    d,fcb
  1018.     mvi    c,cffc
  1019.     call    bdos
  1020.     pop    b
  1021.     pop    d
  1022.     pop    h
  1023.     ret
  1024. ;
  1025. ;delt - delete disk file
  1026. ;
  1027. delt:    push    h
  1028.     push    d
  1029.     push    b
  1030.     lxi    d,fcb
  1031.     mvi    c,dffc
  1032.     call    bdos
  1033.     pop    b
  1034.     pop    d
  1035.     pop    h
  1036.     ret
  1037. ;
  1038. ;write - write record to disk
  1039. ;
  1040. write:    push    h
  1041.     push    d
  1042.     push    b
  1043.     lxi    d,fcb
  1044.     mvi    c,wrfc
  1045.     call    bdos
  1046.     pop    b
  1047.     pop    d
  1048.     pop    h
  1049.     ret
  1050. ;
  1051. ;make - make new disk file
  1052. ;
  1053. make:    push    h
  1054.     push    d
  1055.     push    b
  1056.     lxi    d,fcb
  1057.     mvi    c,mffc
  1058.     call    bdos
  1059.     pop    b
  1060.     pop    d
  1061.     pop    h
  1062.     ret
  1063. ;
  1064. ;citest - check console input status
  1065. ;
  1066. citest:    push    b
  1067.     push    d
  1068.     push    h
  1069. citcal:    call    $-$    ;modified by init.
  1070.     ora    a    ;set zero flag
  1071.     pop    h
  1072.     pop    d
  1073.     pop    b
  1074.     ret        ;zero flag carries answer
  1075. ;
  1076. ;mitest - check modem input status
  1077. ;
  1078.     IF    PORT
  1079. mitest:    in    mods    ;get modem uart status
  1080.     xri    mxor    ;invert high-true bits
  1081.     ani    mrda    ;any data available?
  1082.     mvi    a,0
  1083.     jnz    mitst1
  1084.     cma
  1085. ;
  1086. mitst1:    ora    a
  1087.     ret        ;zero flag carries answer
  1088.     ENDIF
  1089. ;
  1090.     IF    TRSPT
  1091. ;
  1092. mitest:    push    b
  1093.     push    h
  1094.     push    d
  1095.     mvi    b,00    ;channel a
  1096.     lxi    h,mitstr
  1097.     push    h
  1098.     lhld    base+1
  1099.     lxi    d,siotst
  1100.     dad    d
  1101.     pchl
  1102. ;
  1103. mitstr:    pop    d
  1104.     pop    h
  1105.     ani    01    ;tx empty
  1106.     pop    b
  1107.     ret        ;zero flag holds the answer
  1108.     ENDIF
  1109. ;
  1110. ;motest - check modem output status
  1111. ;
  1112.     IF    PORT
  1113. motest:    in    mods    ;get modem uart status
  1114.     xri    mxor    ;invert high-true bits
  1115.     ani    mtbe    ;uart ready for character?
  1116.     mvi    a,0
  1117.     jnz    motst1    ;zero flag carries answer
  1118.     cma
  1119. ;
  1120. motst1:    ora    a    ;set zero flag if ready
  1121.     ret
  1122.     ENDIF
  1123. ;
  1124.     IF    TRSPT
  1125. motest:    push    b
  1126.     push    h
  1127.     push    d
  1128.     mvi    b,00    ;channel a
  1129.     lxi    h,motstr
  1130.     push    h
  1131.     lhld    1
  1132.     lxi    d,siotst
  1133.     dad    d
  1134.     pchl
  1135. ;
  1136. motstr:    ani    02    ;buffer empty
  1137.     pop    d
  1138.     pop    h
  1139.     pop    b
  1140.     ret
  1141.     ENDIF
  1142. ;
  1143. ;data area
  1144. ;
  1145. inch:    ds    1    ;input char buffer (to cyber)
  1146. outch:    ds    1    ;output char buffer (from ciber)
  1147. stack:    ds    80    ;local stack
  1148. ibuf:    ds    256    ;input buffer
  1149. ;
  1150. ;text buffer
  1151. ;
  1152. flag:    ds    1    ;text save flag
  1153. ptr:    ds    2    ;text buffer pointer
  1154. size:    ds    2    ;text buffer size
  1155. tbuf:    equ    $    ;start of text buffer
  1156. ;
  1157.     end
  1158.