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 / KERMIT / CP411SRC.ARK / cpxcom.asm < prev    next >
Assembly Source File  |  1991-04-23  |  16KB  |  487 lines

  1. IF NOT lasm
  2. .printx * CPXCOM.ASM *
  3. ENDIF    ; NOT lasm
  4. ;       KERMIT - (Celtic for "FREE")
  5. ;
  6. ;       This is the CP/M-80 implementation of the Columbia University
  7. ;       KERMIT file transfer protocol.
  8. ;
  9. ;       Version 4.0
  10. ;
  11. ;       Copyright June 1981,1982,1983,1984,1985
  12. ;       Columbia University
  13. ;
  14. ; Originally written by Bill Catchings of the Columbia University Center for
  15. ; Computing Activities, 612 W. 115th St., New York, NY 10025.
  16. ;
  17. ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
  18. ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
  19. ; others.
  20. ;
  21. ;       This file contains part common code required for most if not all
  22. ;    systems.  Specifiacally, SYSINIT, INIADR, MOVER, and DELAY to name
  23. ;    the most important ones.
  24. ;
  25. ; revision history:
  26. ;
  27. ; edit 1, 21st July 1987 by OBSchou.  Regretably, I have had to include
  28. ;    some system dependent IFs, mainly for CRT, TORCH and OSI.  Inclusion
  29. ;    here means simpler family files later on. (Regrettably, the delay
  30. ;    loop for APMMDM differs too.)
  31. ;
  32. ; Set the fuzzy timeout value.  Range is 1 (VERY short) through 0ffffH to zero
  33. ; (maximum).  The actual duration is a function of the loop length and the
  34. ; processor speed.  For now, we'll make it zero for everybody, but feel free
  35. ; to change it for your system.
  36. ; [OBS] make it a little less than max, say 1000H.  More useful.
  37. fuzval  EQU     1000H
  38.  
  39. ;
  40. ;       System-dependent initialization
  41. ;       Called once at program start.
  42. sysinit:
  43. ;
  44. ; [13]  Had to move this call to here, as the prtstr routine needs this
  45. ; before the config message is sent out.  It has only been moved.
  46. ;
  47.     call    iniadr    ;Initialize the BIOS addresses
  48.     mvi    c,gtiob    ;Get current I/O byte
  49.     call    bdos    ;From CP/M
  50.     sta    coniob    ;Remember where console is
  51.     mvi    c,getvnm    ; get the BDOS version number (e.g. 22H, 31H)
  52.     call    bdos
  53.     mov    a,l
  54.     sta    bdosvr        ; and store it away for future reference
  55.     lxi    d,cfgmsg    ; "configured for "
  56.     call    prtstr
  57.     lxi    d,sysver    ; get configuration we're configured for
  58.     call    prtstr        ; print it.
  59. ;
  60. ;       If we're set up to do special terminal handling, say what kind
  61. ;       of terminal we expect... (unless it's the generic 'crt')
  62. IF termin
  63.     lxi    d,witmsg    ; " with "
  64.     call    prtstr
  65.     lxi    d,ttytyp    ; terminal type
  66.     call    prtstr
  67. ENDIF;termin
  68.     call    prcrlf        ; print CR/LF
  69. ;
  70. ; now, to work...
  71. ;
  72. ; locate large buffer for multi-sector I/O
  73. ; What we want to do here is find the ccp.  Space between ovlend and the ccp
  74. ; is available for buffering, except we don't want to use more than maxsec
  75. ; buffers (if we use too many, the remote end could time out while we're
  76. ; writing to disk).  maxsec is system-dependent, but for now we'll just
  77. ; use 8Kbytes.  If you get retransmissions and other protocol errors after
  78. ; transferring the first maxsec sectors, lower maxsec.
  79.  
  80. maxsec    EQU    (8*1024)/bufsiz    ; 8K / number of bytes per sector
  81.  
  82.     lxi    h,ovlend    ; get start of buffer
  83.     shld    bufadr        ; store in linkage section
  84.     mvi    a,maxsec    ; get size of buffer, in sectors
  85.     sta    bufsec        ; store that, too.
  86.  
  87.     call    sysxin        ; call system specific init code
  88.  
  89.     ret            ; return from system-dependent routine
  90.  
  91. bdosvr:    ds    1        ; space to save the BDOS version number
  92. IF NOT iobyt
  93. coniob:    ds    1        ; space to save copy of IO byte
  94. ENDIF    ;NOT iobyt
  95. ;
  96. ;       This one is hopefully the last "improvement" in view of GENERIC
  97. ;Kermit. It uses for Character-I/O the BIOS-routines ( instead of the
  98. ;"normal" BDOS routines. What does it give us (hopefully) : More speed,
  99. ;higher chance of success ( I/O byte implemented in BIOS [if at all]),
  100. ;but no "extra" device handling - that's done by BDOS.
  101. ;
  102. ;       How do we "get" the call-adresses?  Location 0 has a JMP Warm-Boot
  103. ;in CP/M which points into the second location of the BIOS JMP-Vector.  The
  104. ;next three locations of the JMP-Vector point to the CONSTAT,CONIN,CONOUT
  105. ;BIOS-routines.  CONOUT wants the character in C.
  106. ;
  107. ;- Bernie Eiben
  108.  
  109. iniadr:    lhld    1        ;get BIOS Warmstart-address
  110.     lxi    d,3        ;next adress is CONSTAT in BIOS
  111.     dad    d
  112.     shld    bconst+1    ;stuff it into the call-instruction
  113.     lxi    d,3        ;next adress is CONIN in BIOS
  114.     dad    d
  115.     shld    bconin+1    ;
  116.     lxi    d,3        ;next adress is CONOUT in BIOS
  117.     dad    d
  118.     shld    bcnout+1
  119.     lxi    d,3        ;next address is LIST in BIOS
  120.     dad    d
  121.     shld    blsout+1
  122.     lxi    d,10*3        ; get printer status routine
  123.     dad    d
  124.     shld    bprtst
  125.     ret            ;And return
  126.  
  127. bconst:    jmp    $-$        ;Call BIOS directly (filled in by iniadr)
  128.  
  129. bconin:    jmp    $-$        ;Call BIOS directly (filled in by iniadr)
  130.  
  131. bcnout:    jmp    $-$        ;Call BIOS directly (filled in by iniadr)
  132.  
  133. blsout:    jmp    $-$        ; ....
  134.  
  135. bprtst:    jmp    $-$        ; Call BIOS directly for printer status
  136.  
  137. IF NOT apmmdm    ; Shame about this, but the Apple needs a different delay
  138. ;
  139. ;[cjc]  Delay routine.  Called with time (hundredths of seconds) in A.
  140. ;       The inner loop delays 1001 T-states, assuming no wait states are
  141. ;       inserted; this is repeated CPUSPD times, for a total delay of just
  142. ;       over 0.01 second. (CPUSPD should be set to the system clock rate,
  143. ;       in units of 100KHz: for an unmodified Kaypro II, that's 25 for
  144. ;       2.5 MHz.  Some enterprising soul could determine whether or not the
  145. ;       Kaypro actually inserts a wait state on instruction fetch (a common
  146. ;       practice); if so, the magic number at delay2 needs to be decreased.
  147. ;       (We also neglect to consider time spent at interrupt level).
  148. ;
  149. ;       called by: sendbr
  150. ;       destroys BC
  151.  
  152. delay:    mvi    c,cpuspd    ; Number of times to wait 1000 T-states to
  153.                 ;  make .01 second delay
  154. delay2:    mvi    b,70        ; Number of times to execute inner loop to
  155.                 ;  make 1000 T-state delay
  156. delay3:    dcr    b        ; 4 T-states (* 70 * cpuspd)
  157.     jnz    delay3        ; 10 T-states (* 70 * cpuspd)
  158.     dcr    c        ; 4 T-states (* cpuspd)
  159.     jnz    delay2        ; 10 T-states (* cpuspd)
  160.                 ; total delay: ((14 * 70) + 14) * cpuspd
  161.                 ;  = 1001 * cpuspd
  162.     dcr    a        ; 4 T-states
  163.     jnz    delay        ; 10 T-states
  164.     ret            ; grand total: ((1001 * cpuspd) + 14) * a
  165. ENDIF    ; NOT apmmdm
  166. ;
  167. ;
  168. ;       Set up screen display for file transfer
  169. ;       called with kermit version in DE
  170. ;
  171. sysscr: push    d               ; save version for a bit
  172.         lxi     d,outlin        ; clear screen, position cursor
  173.         call    prtstr          ; do it
  174.         pop     d               ; get Kermit's version
  175. IF NOT (osi OR crt)             ; got cursor control?
  176.         call    prtstr          ; print it
  177.         mvi     e,'['           ; open bracket
  178.         call    outcon          ; print it (close bracket is in outln2)
  179.         lxi     d,sysver        ; get name and version of system module
  180.         call    prtstr
  181.         lxi     d,outln2        ; yes, print field names
  182.         call    prtstr
  183.         lda     dbgflg          ; is debugging enabled?
  184.         ora     a
  185.         rz                      ; finished if no debugging
  186.         lxi     d,outln3        ; set up debugging fields
  187.         call    prtstr
  188. ENDIF;NOT (osi OR crt)
  189.         ret
  190. ;
  191. ;       Calculate free space for current drive
  192. ;       returns value in HL
  193. sysspc:
  194.         lda     bdosvr          ;cpm3's alloc vect may be in another bank
  195.         cpi     30H             ;cpm3 or later?
  196.         jm      cp2spc          ;no: use cp/m 2 algorithm
  197.         lda     fcb             ;If no drive, get
  198.         ora     a               ; logged in drive
  199.         jz      dir180
  200.         dcr     a               ;FCB drive A=1 normalize to be A=0
  201.         jmp     dir18a
  202.  
  203. dir180: mvi     c,rddrv
  204.         call    bdos
  205. dir18a: mov     e,a             ;drive in e
  206.         mvi     c,getfs         ;get free space BDOS funct
  207.         call    bdos            ;returns free recs (3 bytes in buff..buff+2)
  208.         mvi     b,3             ;conv recs to K by 3 bit shift
  209. dir18b: xra     a               ;clear carry
  210.         mvi     c,3             ;for 3 bytes
  211.         lxi     h,buff+3        ;point to addr + 1
  212. dir18c: dcx     h               ;point to less sig. byte
  213.         mov     a,m             ;get byte
  214.         rar                     ;carry -> A -> carry
  215.         mov     m,a             ;put back byte
  216.         dcr     c               ;for all bytes (carry not mod)
  217.         jnz     dir18c
  218.         dcr     b               ;shift 1 bit 3 times
  219.         jnz     dir18b
  220.         mov     e,m             ;get least sig byte
  221.         inx     h
  222.         mov     d,m             ;get most sig byte
  223.         xchg                    ;get K free in HL
  224.         ret
  225.  
  226. ; the rest are CP/M 2.2 systems, so use the alloc vector
  227. cp2spc: mvi     c,getalv        ;Address of CP/M Allocation Vector
  228.         call    bdos
  229.         xchg                    ;Get its length
  230.         lhld    bmax
  231.         inx     h
  232.         lxi     b,0             ;Initialize Block count to zero
  233. dir19:  push    d               ;Save allocation address
  234.         ldax    d
  235.         mvi     e,8             ;set to process 8 blocks
  236. dir20:  ral                     ;Test bit
  237.         jc      dir20a
  238.         inx     b
  239. dir20a: mov     d,a             ;Save bits
  240.         dcx     h
  241.         mov     a,l
  242.         ora     h
  243.         jz      dir21           ;Quit if out of blocks
  244.         mov     a,d             ;Restore bits
  245.         dcr     e               ;count down 8 bits
  246.         jnz     dir20           ;do another bit
  247.         pop     d               ;Bump to next count of Allocation Vector
  248.         inx     d
  249.         jmp     dir19           ;process it
  250.  
  251. dir21:  pop     d               ;Clear Allocation vector from stack
  252.         mov     l,c             ;Copy block to 'HL'
  253.         mov     h,b
  254.         lda     bshiftf         ;Get Block Shift Factor
  255.         sui     3               ;Convert from records to thousands
  256.         rz                      ;Skip shifts if 1K blocks
  257. dir22:  dad     h               ;Multiply blocks by 'K per Block'
  258.         dcr     a
  259.         jnz     dir22
  260.         ret
  261.  
  262. ;      +----|----|----|----|----|----|----|...
  263. ;    1 |
  264. ;    2 |                Kermit-80 v4.0 [system]
  265. ;    3 |
  266. ;    4 |Number of packets: ____
  267. ;    5 |Number of retries: ____
  268. ;    6 |File name: ____________
  269. ;    7 |<error>...
  270. ;    8 |<status>...
  271. ;    9 |RPack: ___(if debugging)...
  272. ;   10 |
  273. ;   11 |SPack: ___(if debugging)...
  274. ;   12 |
  275. ;   13 |Kermit-80  A:>  (when finished)
  276. ;
  277. ; For the PX-8, the display looks like:
  278. ;           5    10   15   20   25   30   35   40   45   50   55
  279. ;      +----|----|----|----|----|----|----|----|----|----|----|----|----
  280. ;    1 |Kermit-80 v4.05 [Epson PX-8]            Number of retries: ____
  281. ;    2 |Number of packets: ____                 File name: ________.___
  282. ;    3 |<error>...
  283. ;    4 |<status>...
  284. ;    5 |RPack: ___ (if debugging)...
  285. ;    6 |
  286. ;    7 |SPack: ___ (if debugging)...
  287. ;    8 |
  288. ;    9 |Kermit-80 A:> (when finished)
  289. ;
  290.  
  291. IF NOT px8 ; [29]
  292. nppos   EQU     4*100h+20
  293. rtpos   EQU     5*100h+20
  294. fnpos   EQU     6*100h+12
  295. errlin  EQU     7
  296. stlin   EQU     8
  297. rplin   EQU     9
  298. splin   EQU     11
  299. prplin  EQU     13
  300. ENDIF ; NOT px8
  301.  
  302. IF px8
  303. nppos   EQU     2*100h+20
  304. rtpos   EQU     1*100h+59
  305. fnpos   EQU     2*100h+51
  306. errlin  EQU     3
  307. stlin   EQU     4
  308. rplin   EQU     5
  309. splin   EQU     7
  310. prplin  EQU     9
  311. ENDIF ; px8 [29]
  312.  
  313.  
  314. IF NOT (osi OR crt );[26]
  315. scrnp:  lxi     b,nppos
  316.         jmp     csrpos
  317.  
  318. scrnrt: lxi     b,rtpos
  319.         jmp     csrpos
  320.  
  321. scrfln: lxi     b,fnpos
  322.         call    csrpos
  323. clreol:
  324.         lxi     d,tk
  325.         jmp     prtstr
  326.  
  327. screrr: lxi     b,errlin*100H+1
  328.         call    csrpos
  329.         jmp     clreol
  330.  
  331. scrst:  lxi     b,stlin*100H+1
  332.         call    csrpos
  333.         jmp     clreol
  334.  
  335. rppos:  lxi     b,rplin*100H+8
  336.         call    csrpos
  337.         jmp     clreol
  338.  
  339. sppos:  lxi     b,splin*100H+8
  340.         call    csrpos
  341.         jmp     clreol
  342.  
  343. ; [29] Modify scrend to make the cursor line conditional on use of debugging
  344. ; This means that in most cases the entire file transfer will fit on PX-8 lcd
  345. scrend: lda     dbgflg
  346.         ora     a
  347.         jz      scr1nd
  348.         lxi     b,prplin*100H+1 ; debugging in use [29]
  349.         jmp     scr2nd
  350. scr1nd: lxi     b,rplin*100H+1  ; no debugging
  351. scr2nd: call    csrpos
  352. clreos: lxi     d,tj
  353.         jmp     prtstr
  354. ; [29]  and nop out the rest for now...
  355. ;
  356. ;scrend:        lxi     b,prplin*100H+1
  357. ;       call    csrpos
  358. ;clreos:        lxi     d,tj
  359. ;       jmp     prtstr
  360. ENDIF;NOT (osi OR crt ) [26]
  361.  
  362.  
  363. IF osi OR crt   ; no cursor control
  364. scrnp:  mvi     e,' '
  365.         jmp     outcon
  366.  
  367. scrnrt: mvi     e,' '
  368.         call    outcon
  369.         mvi     e,'%'
  370.         jmp     outcon
  371.  
  372. scrfln:
  373. screrr:
  374. scrst:
  375. scrend: jmp     prcrlf          ;Print CR/LF    [Toad Hall]
  376.  
  377. rppos:  lxi     d,prpack
  378.         jmp     prtstr
  379.  
  380. sppos:  lxi     d,pspack
  381.         jmp     prtstr
  382. ENDIF;osi OR crt
  383.  
  384. ; Some frequently-used routines (duplicates of those in CPSMIT):
  385. ;       prcrlf - output a CR/LF
  386. ;       prtstr - output string in DE
  387. ;       rskp - return, skipping over error return
  388. prcrlf: lxi     d,crlf
  389. prtstr:
  390. ;  [17] added this  to avoid prtstr.. emulate function 9 call.
  391. ;    Works on most machines.
  392. IF (torch OR px8 OR z80mu)
  393. ;
  394. ;       Modified print string as the CP/N (for Nut) system traps control
  395. ;       characters in a function 9 call.. rot its cotton socks.
  396.         push    h
  397.         push    d
  398.         push    b
  399. prtst1:
  400.         ldax    d
  401.         inx     d
  402.         cpi     '$'             ; if a dollar then end of string
  403.         jz      prtst2
  404.         push    d
  405.         mov     e,a
  406.     mov    c,a        ; also to c if its via conout in BIOS
  407.         call    outcon          ; send it to the screen
  408.         pop     d
  409.         jmp     prtst1
  410.  
  411. prtst2: pop     b
  412.         pop     d
  413.         pop     h
  414.         ret                     ; regs restored.. just in case
  415. ENDIF    ;(torch OR px8 OR z80mu)
  416.  
  417. IF NOT (torch OR px8 or z80mu)        ;ie any machine that can send ctrl chrs via dos call 9
  418.     PUSH    H
  419.     PUSH    D
  420.         push    b
  421.         mvi     c,9     ; Dos call 9 (print a string)
  422.         call    bdos
  423.         pop     b
  424.     POP    D
  425.     POP    H
  426.         ret             ; all done for good machines
  427. ENDIF   ;NOT (torch OR px8 OR z80mu)
  428.  
  429. ;
  430. ;    rskp - return to calling address + 3.
  431. rskp:   pop     h               ; Get the return address
  432.         inx     h               ; Increment by three
  433.         inx     h
  434.         inx     h
  435.         pchl
  436.  
  437. ;       Copy block of data
  438. ;       source in HL, destination in DE, byte count in BC
  439. ;       called by: cpxsys, mfname
  440. ;
  441. mover:
  442. ;IF NOT z80              ; 8080's have to do it the hard way
  443. ;OBS assume its an 8080 for now - this will work on Z80s anyway.
  444.         mov     a,m
  445.         stax    d
  446.         inx     h
  447.         inx     d
  448.         dcx     b
  449.         mov     a,b
  450.         ora     c
  451.         jnz     mover
  452. ;ENDIF;NOT z80
  453. ;IF z80
  454. ;       db      0EDh,0B0h       ; Z80 LDIR instruction
  455. ;ENDIF;z80
  456.         ret
  457.  
  458. ;
  459. ;       Miscellaneous messages
  460. ;
  461. crlf:   db      cr,lf,'$'
  462. cfgmsg: db      'configured for $'
  463. witmsg:    db    ' with $'    ; Its included if we get here ('with terminal')
  464.  
  465. IF NOT (osi OR crt OR px8)    ; [29] got cursor control?
  466. outln2:    db    ']',cr,lf,cr,lf,'Number of packets:'
  467.     db    cr,lf,'Number of retries:'
  468.     db    cr,lf,'File name:$'
  469. ENDIF;NOT (osi OR crt OR px8)
  470.  
  471. IF px8    ; [29]
  472. outln2:    db    ']           Number of retries:', cr, lf
  473.     db    'Number of packets:                     File name:$'
  474. ENDIF ; px8 [29]
  475.  
  476. IF NOT (osi OR crt) ; [29]
  477. outln3:    db    cr,lf,cr,lf    ; debugging messages
  478.     db    cr,lf,'Rpack:'
  479.     db    cr,lf        ; Blank line in case of long packet
  480.     db    cr,lf,'Spack:$'
  481. ENDIF ; NOT (osi OR crt) [29]
  482.  
  483. IF lasm
  484. LINK CPXSWT.ASM
  485. ENDIF    ;lasm
  486.  
  487.