home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccdos / ccscom.asm < prev    next >
Assembly Source File  |  2020-01-01  |  53KB  |  1,152 lines

  1.         NAME    ccscom
  2. ; File CCSCOM.ASM
  3.  
  4. ;CHINESE
  5. ifdef   MSDOS
  6.         include msscom.dat
  7. else
  8.         include ccscom.dat
  9. endif
  10.  
  11. code    segment public 'code'
  12.         extrn   prtchr:near, clrbuf:near, outchr:near, isdev:near
  13.         extrn   sppos:near, stpos:near, biterr:near, intmsg:near
  14.         extrn   clearl:near, rppos:near, errpack:near, prtscr:near
  15.         extrn   pktcpt:near, strlen:near, pcwait:near
  16.  
  17.         assume  cs:code, ds:datas
  18.  
  19. ;       Packet routines
  20.  
  21. ; Send_Packet
  22. ; This routine assembles a packet from the arguments given and sends it
  23. ; to the host.
  24. ;
  25. ; Expects the following:
  26. ;       AH     - Type of packet (D,Y,N,S,I,R,E,F,Z,other)
  27. ;       PACK.SEQNUM - Packet sequence number
  28. ;       PACK.DATLEN - Number of data characters
  29. ; Returns: +1 always
  30. ; Packet construction areas:
  31. ;       Prolog (8 bytes)                        Data     null  Data
  32. ;+----------------------------------------+---------------+---------------+
  33. ;| SOH,LEN,SEQ,TYPE,Xlen(2-3),Xlen chksum | packet's data | chksum,EOL,HS |
  34. ;+----------------------------------------+---------------+---------------+
  35. ; where Xlen is 2 byte (Long) or 3 byte (Extra Long) count of bytes to follow.
  36. ;
  37. SPKT    PROC    NEAR
  38.  
  39. spack:  push    ax              ; save packet type (in ah)
  40.         call    clrbuf          ; clear serial port input buffer
  41.         call    prtchr          ; exercise receiver
  42.          nop
  43.          nop
  44.          nop
  45.         call    clrbuf          ; clear serial  port input buffer
  46.         mov     spkcnt,0        ; number of bytes sent in this packet
  47.         add     fsta.pspkt,1    ; statistics, count a packet being sent
  48.         adc     fsta.pspkt+2,0  ;  ripple carry
  49.         mov     al,spause       ; Wait spause milliseconds before
  50.         xor     ah,ah           ;   sending a packet
  51.         or      al,al           ; zero?
  52.         jz      spk1            ; z = yes
  53.         call    pcwait          ;   to let other side get ready
  54. spk1:   mov     dh,trans.spad   ; Get the number of padding chars.
  55. spk2:   dec     dh
  56.         cmp     dh,0
  57.         jl      spk5            ; If none left proceed.
  58.         mov     ah,trans.spadch ; Get the padding char.
  59.         push    dx              ; save loop counter
  60.         call    outchr          ; Output it.
  61.          jmp    spk3            ; failed
  62.          nop                    ; must be three bytes
  63.         pop     dx              ; get loop counter
  64.         jmp     spk2            ; do remaining padding chars
  65. spk3:   pop     dx
  66.         pop     ax
  67.         ret                     ; failed
  68.  
  69. spk5:   pop     ax              ; recover ah
  70.         mov     prvtyp,ah       ; Remember packet type
  71.         mov     bx,portval      ; Get current port structure [umd]
  72.         mov     parmsk,0ffh     ; Set parity mask for 8 bits [umd]
  73.         cmp     [bx].parflg,parnon      ; Using parity? [umd]
  74.         je      spacka          ; e = no. use mask as is. [umd]
  75.         mov     parmsk,7fh      ; else set mask for 7 data bits. [umd]
  76. spacka: call    snddeb          ; do debug display (while it's still our turn)
  77.         mov     pktptr,offset prolog
  78.         mov     word ptr prolog,0
  79.         mov     word ptr prolog+2,0
  80.         mov     word ptr prolog+4,0
  81.         mov     word ptr prolog+6,0
  82.         mov     al,trans.ssoh   ; Get the start of header char.
  83.         mov     prolog,al       ; Put SOH in the packet.
  84.         mov     ax,pack.seqnum  ; SEQ
  85.         add     al,20h          ; ascii bias
  86.         mov     prolog+2,al     ; store SEQ in packet
  87.         mov     ah,0
  88.         mov     chksum,ax       ; start checksum
  89.         mov     al,prvtyp       ; TYPE
  90.         mov     prolog+3,al     ; store TYPE
  91.         add     chksum,ax       ; add to checksum
  92. ;
  93. ; packet length type is directly governed here by length of header plus data
  94. ; field, pack.datlen, plus chksum: regular <= 94, long <= 9024, else X long.
  95. ;
  96.         mov     ax,pack.datlen  ; DATA length
  97.         add     ax,2            ; add SEQ, TYPE lengths
  98.         add     al,trans.chklen ; add checksum length at the end
  99.         adc     ah,0            ; propagate carry, yields overall new length
  100.         cmp     ax,maxpack      ; too big?
  101.         jle     spdlp0          ; le = ok
  102.         ret                     ; return bad
  103. spdlp0:
  104.         mov     pack.lentyp,3   ; assume regular packet
  105.         cmp     ax,94           ; longer than a regular?
  106.         ja      spdlp1          ; a = use long
  107.         add     al,20h          ; convert length to ascii
  108.         mov     prolog+1,al     ; store LEN
  109.         mov     ah,0
  110.         add     chksum,ax       ; add LEN to checksum
  111.         jmp     spklp5          ; do regular
  112. spdlp1: push    ax              ; Use Long packets (type 3)
  113.         push    bx
  114.         push    cx
  115.         push    dx
  116.         sub     ax,2            ; deduct SEQ and TYPE from above = data+chksum
  117.         mov     pack.lentyp,0   ; assume type 0 packet
  118.         cmp     ax,(95*95-1)    ; longest type 0 packet (9024)
  119.         jbe     spdlp3          ; be = type 0
  120.         mov     pack.lentyp,1   ; type 1 packet
  121. spdlp3: mov     bl,pack.lentyp  ; add new LEN field to checksum
  122.         add     bl,20h          ; ascii bias, tochar()
  123.         mov     bh,0
  124.         add     chksum,bx       ; add to running checksum
  125.         mov     prolog+1,bl     ; put LEN into packet
  126.         mov     bx,offset prolog+4      ; address of extended length field
  127.         mov     cx,1            ; a counter
  128.         xor     dx,dx           ; high order numerator of length
  129. spdlp7: div     ninefive        ; divide ax by 95. quo = ax, rem = dx
  130.         push    dx              ; push remainder
  131.         inc     cx              ; count push depth
  132.         cmp     ax,95           ; quotient >= 95?
  133.         jae     spdlp7          ; ae = yes, recurse
  134.         push    ax              ; push for pop below
  135. spdlp8: pop     ax              ; get a digit
  136.         add     al,20h          ; apply tochar()
  137.         mov     [bx],al         ; store in data field
  138.         add     chksum,ax       ; accumulate checksum for header
  139.         inc     bx              ; point to next data field byte
  140.         mov     byte ptr[bx],0  ; insert terminator
  141.         loop    spdlp8          ; get the rest
  142.                                 ;
  143.         mov     ax,chksum       ; current checksum
  144.         shl     ax,1            ; put two highest bits of al into ah
  145.         shl     ax,1
  146.         and     ah,3            ; want just those two bits
  147.         shr     al,1            ; put al back in place
  148.         shr     al,1
  149.         add     al,ah           ; add two high bits to earlier checksum
  150.         and     al,03fh         ; chop to lower 6 bits (mod 64)
  151.         add     al,20h          ; apply tochar()
  152.         mov     [bx],al         ; store that in length's header checksum
  153.         mov     ah,0
  154.         add     chksum,ax       ; add that byte to running checksum
  155.         pop     dx
  156.         pop     cx
  157.         pop     bx
  158.         pop     ax
  159.  
  160. spklp5: push    si      ; assume soh, len, seq, type, extra len are in prolog
  161.         push    di
  162.         push    cx
  163.         push    ds
  164.         pop     es              ; set es to data segment for implied es:di
  165.         mov     si,offset prolog        ; source
  166.         mov     di,offset data-1        ; end point of destination
  167.         mov     pktptr,offset data      ; start of packet ptr for debug
  168.         cmp     pack.lentyp,0   ; long packets?
  169.         jne     spklp6          ; ne = no
  170.         add     si,6            ; long packets
  171.         mov     cx,7            ; seven bytes soh,len,seq,type, xl1,xl2,xlchk
  172.         jmp     spklp8
  173. spklp6: cmp     pack.lentyp,1   ; extra long packets?
  174.         jne     spklp7          ; ne = no
  175.         mov     cx,8            ; extra long packets
  176.         add     si,7
  177.         jmp     spklp8
  178. spklp7: add     si,3            ; regular packets, slide up by four bytes
  179.         mov     cx,4            ; number of bytes to move
  180. spklp8: jcxz    spklp9          ; no movement needed
  181.         sub     pktptr,cx       ; pktprt=new offset of prolog section
  182.         std
  183.         rep     movsb           ; move the protocol header, cx times
  184.         cld
  185. spklp9: pop     cx
  186.         pop     di
  187.         pop     si
  188.         mov     bx,pktptr       ; place where protocol section starts
  189. spklp10:mov     ah,[bx]         ; protocol part
  190.         inc     bx
  191.         call    spkout          ; send byte to serial port
  192.         jnc     spklp11         ; nc = good send
  193.         jmp     spackq          ; bad send
  194. spklp11:cmp     bx,offset data  ; done all protocol parts yet?
  195.         jb      spklp10         ; b = not yet
  196.         mov     bx,offset data  ; select from given data buffer
  197.         mov     dx,pack.datlen  ; Get the number of data bytes in packet.
  198. spack2: dec     dx              ; Decrement the char count.
  199.         js      spack3          ;  sign = no, finish up.
  200.         mov     al,byte ptr[bx] ; get a data char
  201.         inc     bx              ; point to next char [umd]
  202.         test    al,80h          ; eighth bit set?
  203.         jz      spackb          ; z = no
  204.         and     al,parmsk       ; apply parity mask, may clear 8th bit [umd]
  205.         cmp     hierr,0         ; printed high bit error yet? [umd]
  206.         jne     spackb          ; ne = yes [umd]
  207.         push    ax
  208.         push    bx
  209.         push    cx
  210.         push    dx
  211.         call    biterr
  212.         pop     dx
  213.         pop     cx
  214.         pop     bx
  215.         pop     ax
  216.         mov     hierr,0FFH      ; set err flag.
  217. spackb: mov     ah,0
  218.         add     chksum,ax       ; add the char to the checksum [umd]
  219.         and     chksum,0fffh    ; keep only low order 12 bits
  220.         mov     ah,al           ; put char in ah where spkout wants it
  221.         call    spkout          ; send it
  222.         jnc     spack2          ; Go get more data chars
  223.         jmp     spackq          ; bad send
  224.  
  225. spack3: mov     cx,chksum
  226.         cmp     trans.chklen,2  ; What kind of checksum are we using?
  227.         je      spackx          ; e = 2 characters.
  228.         jg      spacky          ; g = 3 characters.
  229.         mov     ah,cl           ; 1 char: get the character total.
  230.         mov     ch,cl           ; Save here too (need 'cl' for shift).
  231.         and     ah,0C0H         ; Turn off all but the two high order bits.
  232.         mov     cl,6
  233.         shr     ah,cl           ; Shift them into the low order position.
  234.         mov     cl,ch
  235.         add     ah,cl           ; Add it to the old bits.
  236.         and     ah,3FH          ; Turn off the two high order bits.  (MOD 64)
  237.         add     ah,' '          ; Add a space so the number is printable.
  238.         mov     [bx],ah         ; Put in the packet.
  239.         inc     bx              ; Point to next char.
  240.         call    spkout          ; send it
  241.         jnc     spackz          ; Add EOL char.
  242.         jmp     spackq          ; bad send
  243. spacky: mov     byte ptr[bx],0  ; null, to determine end of buffer.
  244.         push    bx              ; Don't lose our place.
  245.         mov     bx,pktptr       ; First checksummed character.
  246.         inc     bx              ; skip SOH
  247.         call    crcclc          ; Calculate the CRC.
  248.         pop     bx
  249.         push    cx              ; save the crc
  250.         mov     ax,cx           ; Manipulate it here.
  251.         and     ax,0F000H       ; Get 4 highest bits.
  252.         mov     cl,4
  253.         shr     ah,cl           ; Shift them over 4 bits.
  254.         add     ah,' '          ; Make printable.
  255.         mov     [bx],ah         ; Add to buffer.
  256.         inc     bx
  257.         pop     cx              ; Get back checksum value.
  258.         call    spkout          ; send it
  259.         jnc     spackx
  260.         jmp     spackq          ; bad send
  261. spackx: push    cx              ; Save it for now.
  262.         and     cx,0FC0H        ; Get bits 6-11.
  263.         mov     ax,cx
  264.         mov     cl,6
  265.         shr     ax,cl           ; Shift them bits over.
  266.         add     al,' '          ; Make printable.
  267.         mov     [bx],al         ; Add to buffer.
  268.         inc     bx
  269.         mov     ah,al
  270.         call    spkout          ; send it
  271.         pop     cx              ; Get back the original.
  272.         jc      spackq          ; c = bad send
  273.         and     cx,003FH        ; Get bits 0-5.
  274.         add     cl,' '          ; Make printable.
  275.         mov     [bx],cl         ; Add to buffer.
  276.         inc     bx
  277.         mov     ah,cl
  278.         call    spkout          ; send it
  279.         jnc     spackz
  280. spackq: RET                     ; bad send, do ret to caller of spack
  281. spackz: mov     ah,trans.seol   ; Get the EOL the other host wants.
  282.         mov     [bx],ah         ; Put eol
  283.         inc     bx
  284.         call    deblin          ; do debug display (while it's still our turn)
  285.         cmp     flags.debug,0   ; In debug mode?
  286.         jne     spackz0         ; ne = yes
  287.         test    flags.capflg,logpkt ; log packets?
  288.         jz      spackz1         ; z = no
  289. spackz0:cmp     linecnt,0       ; anything on current line?
  290.         je      spackz1         ; e = no
  291.         mov     dx,offset crlf  ; finish line with cr/lf
  292.         call    captdol         ;  to log file
  293. spackz1:mov     ah,trans.seol   ; recover EOL
  294.         call    spkout          ; send it
  295.         jnc     spackz2
  296.         jmp     spackq          ; bad send
  297. spackz2:
  298.         mov     ax,spkcnt       ; number of bytes sent in this packet
  299.         add     fsta.psbyte,ax  ; total bytes sent
  300.         adc     fsta.psbyte+2,0 ; propagate carry to high word
  301.         call    chkcon          ; check console for user interrupts
  302.          nop                    ;  no action on plain rets
  303.          nop
  304.          nop
  305.         jmp     rskp            ; return successfully
  306. SPKT    ENDP
  307.  
  308. spkout: push    ax              ; send char in ah out the serial port
  309.         push    bx              ; return carry clear if success
  310.         push    cx
  311.         push    dx
  312.         mov     tmp,1           ; retry counter
  313. spkour: call    outchr          ; serial port transmitter procedure
  314.          jmp    short spkoux    ; bad send, retry
  315.          nop
  316.         inc     spkcnt          ; count number of bytes sent in this packet
  317.         pop     dx
  318.         pop     cx
  319.         pop     bx
  320.         pop     ax
  321.         clc                     ; carry clear for good send
  322.         ret
  323. spkoux: cmp     tmp,5           ; done 5 attempts on this char?
  324.         jge     spkoux1         ; ge = yes, fail the sending
  325.         inc     tmp
  326.         push    ax
  327.         mov     ax,10           ; wait 10 milliseconds
  328.         call    pcwait
  329.         pop     ax
  330.         jmp     short spkour    ; retry
  331. spkoux1:pop     dx              ; failed to send char
  332.         pop     cx
  333.         pop     bx
  334.         pop     ax
  335.         stc                     ; set carry for bad send
  336.         ret
  337.  
  338. ; Calculate the CRC of the null-terminated string whose address is in BX.
  339. ; Returns the CRC in CX.  Destroys BX and AX.
  340. ; The CRC is based on the SDLC polynomial: x**16 + x**12 + x**5 + 1.
  341. ; By Edgar Butt  28 Oct 1987 [ebb].
  342. crcclc: push    dx
  343.         mov     dx,0                ; Initial CRC value is 0
  344.         mov     cl,4                ; Load shift count
  345. crc0:   mov     ah,[bx]             ; Get the next char of the string
  346.         cmp     ah,0                ; If null, then we're done
  347.         je      crc1
  348.         inc     bx
  349.         xor     dl,ah               ; XOR input with lo order byte of CRC
  350.         mov     ah,dl               ; Copy it
  351.         shl     ah,cl               ; Shift copy
  352.         xor     ah,dl               ; XOR to get quotient byte in ah
  353.         mov     dl,dh               ; High byte of CRC becomes low byte
  354.         mov     dh,ah               ; Initialize high byte with quotient
  355.         mov     al,0
  356.         shr     ax,cl               ; Shift quotient byte
  357.         xor     dl,ah               ; XOR (part of) it with CRC
  358.         shr     ax,1                ; Shift it again
  359.         xor     dx,ax               ; XOR it again to finish up
  360.         jmp     short crc0
  361. crc1:   mov     cx,dx               ; Return it in CX
  362.         pop     dx
  363.         ret
  364.  
  365. ; Receive_Packet
  366. ; This routine waits for a packet arrive from the host.  It reads
  367. ; chars until it finds a SOH.
  368. ; Returns
  369. ;       PACK.SEQNUM - Packet sequence number
  370. ;       PACK.DATLEN - Number of data characters
  371. ;       DATA array  - data in packet
  372. ;       AH -  packet type (letter code)
  373. ; Packet construction areas:
  374. ;       Prolog (8 bytes+2 nulls)        null    Data    null  Data     null
  375. ;+----------------------------------------+---------------+---------------+
  376. ;| SOH,LEN,SEQ,TYPE,Xlen(2-3),Xlen chksum | packet's data | chksum,EOL,HS |
  377. ;+----------------------------------------+---------------+---------------+
  378. ; where Xlen is 2 byte (Long) or 3 byte (Extra Long) count of bytes to follow.
  379.  
  380. RPACK   PROC    NEAR
  381.         call    rcvdeb                  ; setup debug banner, if needed.
  382.         mov     fairflg,0               ; set fairness flag
  383.         mov     pktptr,offset prolog   ; where to place packet prolog material
  384.         mov     bx,pktptr               ; bx = debug buffer pointer for new data
  385.         mov     rpkcnt,0             ; number of bytes received in this packet
  386.         mov     ax,0                  ; most recently read char, initialize it
  387.         push    bx
  388.         mov     bl,flags.cxzflg         ; Remember original value
  389.         mov     tmpflg,bl               ; Store it here
  390.         mov     parmsk,0ffh             ; parity mask, assume 8 bit data
  391.         mov     bx,portval
  392.         cmp     [bx].parflg,parnon      ; parity is none?
  393.         pop     bx
  394.         je      rpack0                  ; e = none
  395.         mov     parmsk,07fh             ; else strip parity (8th) bit
  396. rpack0: call    deblin                  ; debug, show chars received thus far
  397.         mov     word ptr prolog,0       ; clear prolog and data fields
  398.         mov     word ptr prolog+2,0
  399.         mov     word ptr prolog+4,0
  400.         mov     word ptr prolog+6,0
  401.         mov     word ptr data,0
  402.         mov     pktptr,offset prolog  ; where to place packet prolog material
  403.         mov     bx,pktptr             ; bx = debug buffer pointer for new data
  404.         mov     status,stat_suc         ; assume success
  405.         call    inchr                   ; Get a character. SOH
  406.          jmp    rpack0a         ; failure (eol, timeout, user intervention)
  407.          nop
  408. rpack0b:mov     byte ptr[bx],al ; store char in buffer
  409.         inc     bx
  410.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  411.         jne     rpack0          ; ne = no, go until it is.
  412.         jmp     rpack1          ; got the SOH char from the port
  413. rpack0a:jc      rpack0b         ; c = hit eol from prev packet, restart
  414.         jmp     rpack6          ; timeout or user intervention
  415. rpack1: mov     pktptr,offset prolog    ; if we got here from below
  416.         mov     bx,pktptr               ; debug pointer
  417.         mov     byte ptr[bx],al ; store SOH in buffer
  418.         inc     bx
  419.         mov     status,stat_suc ; say success, in case rescanning for pkt.
  420.         call    inchr           ; Get a character. LEN
  421.          jmp    rpack4          ; failure
  422.          nop
  423.         mov     byte ptr[bx],al ; store LEN in buffer
  424.         inc     bx
  425.         mov     ah,0
  426.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  427.         jne     rpack1e         ; ne = no
  428.         jmp     rpack7          ; yes, start over
  429. rpack1e:mov     chksum,ax       ; start the checksum
  430.         sub     al,20h          ; unchar() to binary
  431.         mov     pack.datlen,ax  ; Save the data count (byte)
  432.         call    inchr           ; Get a character. SEQ
  433.          jmp    rpack4          ; failure
  434.          nop
  435.         mov     byte ptr[bx],al ; store SEQ in buffer
  436.         inc     bx
  437.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  438.         jz      rpack1          ; nz = yes, then go start over.
  439.         mov     ah,0
  440.         add     chksum,ax
  441.         sub     al,' '          ; Get the real packet number.
  442.         mov     ah,0
  443.         mov     pack.seqnum,ax  ; Save the packet number. SEQ
  444.         call    inchr           ; Get a character. TYPE
  445.          jmp    rpack4          ; failure
  446.         mov     byte ptr[bx],al ; store TYPE in buffer
  447.         inc     bx
  448.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  449.         jz      rpack1          ; nz = yes, then go start over.
  450.         mov     pktype,al       ; Save the message type
  451.         mov     ah,0
  452.         add     chksum,ax       ; Add it to the checksum.
  453.         push    bx
  454.         mov     bx,portval      ; Point to current port structure
  455.         cmp     [bx].ecoflg,0   ; Is the host echoing?
  456.         pop     bx
  457.         jne     rpak11          ; No, packets not echoed
  458.         cmp     al,prvtyp       ; Packet type same as last sent?
  459.         jne     rpak11          ; ne = no
  460.         mov     prvtyp,0        ; clear to respond to next packet
  461.         jmp     rpack0          ; Yes, chuck echoed packet
  462. rpak11: call    getlen          ; get complicated data length (reg, lp, elp)
  463.                                 ; into  pack.datlen and kind into pack.lentyp
  464.                                 ; carry set if error
  465.         jnc     rpack1d         ; nc = long packet checksum is ok
  466.         or      status,stat_chk ; say bad checksum
  467.         jmp     rpack4          ; checksum failure
  468. rpack1d:
  469. ; Start of change.
  470. ; Now determine block check type for this packet.  Here we violate the layered
  471. ; nature of the protocol by inspecting the packet type in order to detect when
  472. ; the two sides get out of sync.  Two heuristics allow us to resync here:
  473. ;   a. I and S packets always has a type 1 checksum.
  474. ;   b. A NAK never contains data, so its block check type is seqnum1.
  475.         cmp     prolog+3,'S'    ; Is this an "S" packet?
  476.         jne     rpk0            ; ne = no.
  477.         mov     trans.chklen,1  ; S packets use one byte checksums
  478.         jmp     rpk3
  479. rpk0:   cmp     prolog+3,'I'    ; I packets are like S packets
  480.         jne     rpk1
  481.         mov     trans.chklen,1  ; I packets use one byte checksums
  482.         jmp     rpk3
  483. rpk1:   cmp     prolog+3,'N'    ; Is this a NAK?
  484.         jne     rpk3            ; ne = no.
  485.         cmp     pack.datlen,1   ; NAK, get length of data + chklen
  486.         jb      rpk1a           ; b = impossible length
  487.         cmp     pack.datlen,3   ; longest NAK (3 char checksum)
  488.         jbe     rpk2            ; be = possible
  489. rpk1a:  or      status,stat_ptl ; status = bad length
  490.         jmp     rpack4          ;  ret on impossible length
  491. rpk2:   mov     ax,pack.datlen
  492.         mov     trans.chklen,al ; remainder must be checksum type for NAK.
  493. rpk3:   mov     ax,pack.datlen  ; get length of data + chksum
  494.         sub     al,trans.chklen ; minus checksum length, for all packets
  495.         sbb     ah,0            ; propagate borrow
  496.         mov     pack.datlen,ax  ; store apparent length of data field
  497. ; End of change.
  498. ; now, for long packets we start the real data (after the extended byte
  499. ; count 3 or 4 bytes) at offset data and thus the checksumming starts
  500. ; such packets a few bytes earlier. [jrd]
  501.         push    si
  502.         push    di
  503.         push    cx
  504.         mov     di,offset data-1
  505.         mov     si,offset prolog
  506.         mov     pktptr,offset data
  507.         cmp     pack.lentyp,0   ; long packets?
  508.         jne     rpk5            ; ne = no
  509.         mov     cx,7            ; seven bytes mark...type, xl,xl,xlchk
  510.         add     si,6
  511.         jmp     rpk7
  512. rpk5:   cmp     pack.lentyp,1   ; extra long packets?
  513.         jne     rpk6            ; ne = no
  514.         mov     cx,8            ; extra long packets, no movement
  515.         add     si,7
  516.         jmp     rpk7
  517. rpk6:   add     si,3            ; regular packets, slide by four bytes
  518.         mov     cx,4            ; number of bytes to move
  519. rpk7:   jcxz    rpk8            ; no movement needed
  520.         sub     pktptr,cx       ; pktptr=new offset of prolog section
  521.         push    es              ; save es
  522.         push    ds
  523.         pop     es              ; set es to datas segment
  524.         std                     ; move backward
  525.         rep     movsb           ; move the protocol header, cx times
  526.         pop     es
  527.         cld                     ; reset direction flag to normal
  528. rpk8:   pop     cx
  529.         pop     di
  530.         pop     si
  531.         mov     dx,pack.datlen  ; length of data field, excl LP header
  532.         mov     chrcnt,dx
  533.         mov     dx,trans.rlongp ; longest packet we can receive
  534.         sub     dl,trans.chklen ; minus checksum length
  535.         sbb     dh,0            ; propagate borrow
  536.         cmp     pack.lentyp,3   ; Regular Packet?
  537.         jne     rpk8a           ; ne = no
  538.         sub     dx,2            ; minus SEQ, TYPE for regular packets
  539. rpk8a:  cmp     dx,pack.datlen  ; is data field too long?
  540.         jae     rpk8b           ; ae = not too big
  541.         or      status,stat_ptl ; failure status, packet too long
  542.         jmp     rpack4          ; too big, quit now
  543. rpk8b:  mov     bx,offset data  ; Point to the data buffer.
  544.  
  545.                                 ; Get DATA field characters
  546. rpack2: dec     chrcnt          ; # data chars
  547.         js      rpack3          ; s = exhausted data, go get the checksum.
  548.         call    inchr           ; Get a character into al. DATA
  549.          jmp    rpack4          ; control-c, timeout (out of data), eol
  550.          nop
  551.         mov     byte ptr[bx],al ; Put the char into the packet.
  552.         inc     bx              ; Point to the next character.
  553.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  554.         jnz     rpak2b          ; nz = no
  555.         jmp     rpack7          ; yes, then go start over.
  556. rpak2b: mov     ah,0
  557.         add     chksum,ax
  558.         and     chksum,0fffh    ; keep only lower 12 bits
  559.         jmp     rpack2          ; Go get another.
  560.  
  561. rpack3: call    inchr           ; Get a character. Start Checksum bytes
  562.          jmp    rpack4          ; failed
  563.          nop
  564.         mov     byte ptr[bx],al ; place to store checksum, EOL, HS for debug
  565.         inc     bx              ; point at next slot
  566.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  567.         jne     rpk3x           ; ne = no
  568.         jmp     rpack7          ; yes, then go start over.
  569. rpk3x:  sub     al,' '          ; Turn the char back into a number.
  570.         mov     cx,chksum       ; current checksum
  571.         cmp     trans.chklen,2  ; What checksum length is in use.
  572.         je      rpackx          ; e = Two character checksum.
  573.         jg      rpacky          ; g = Three character CRC.
  574.         shl     cx,1            ; put two highest digits of al into ah
  575.         shl     cx,1
  576.         and     ch,3            ; want just those two bits
  577.         shr     cl,1            ; put al back in place
  578.         shr     cl,1
  579.         add     cl,ch           ; add two high bits to earlier checksum
  580.         and     cl,03fh         ; chop to lower 6 bits (mod 64)
  581.         cmp     cl,al           ; computed vs received checksum byte (binary)
  582.         je      rpk3xa          ; e = equal, so finish up.
  583.         or      status,stat_chk ; say checksum failure
  584. rpk3xa: jmp     rpack4
  585.  
  586. rpack7: call    deblin          ; dump debugging information so far
  587.         jmp     rpack1          ; For the jump out of range.
  588.  
  589. rpacky: mov     tmp,al          ; Save value from packet here.
  590.         push    bx              ; Three character CRC.
  591.         mov     cx,[bx-1]       ; save checksum char and next
  592.         mov     temp,cx
  593.         mov     word ptr[bx-1],0 ; put null at end of Data field for crc
  594.         mov     bx,pktptr       ; Where data for CRC is.
  595.         inc     bx              ; skip SOH
  596.         call    crcclc          ; Calculate the CRC and put into CX.
  597.         pop     bx
  598.         mov     ax,temp
  599.         mov     [bx-1],ax       ; restore char pair from above
  600.         mov     ah,ch           ; cx = 16 bit binary CRC of rcv'd data
  601.         and     ah,0f0h         ; Manipulate it here.
  602.         shr     ah,1
  603.         shr     ah,1            ; Get 4 highest bits.
  604.         shr     ah,1
  605.         shr     ah,1            ; Shift them over 4 bits.
  606.         cmp     ah,tmp          ; Is what we got == what we calculated?
  607.         je      rpky1           ; e = yes
  608.         or      status,stat_chk ; checksum failure
  609. rpky1:  call    inchr           ; Get next character of checksum.
  610.          jmp    rpack4          ; Failed.
  611.          nop
  612.         mov     byte ptr[bx],al ; put into buffer for debug
  613.         inc     bx
  614.         cmp     al,trans.rsoh   ; Restarting?
  615.         je      rpack7          ; e = yes
  616.         sub     al,' '          ; Get back real value.
  617. rpackx: mov     tmp,al          ; Save here for now.
  618.         push    cx              ; Two character checksum.
  619.         and     cx,0FC0H        ; Get bits 6-11.
  620.         mov     ax,cx
  621.         mov     cl,6
  622.         shr     ax,cl           ; Shift them bits over.
  623.         pop     cx              ; Get back the original.
  624.         cmp     al,tmp          ; Are they equal?
  625.         je      rpkx1           ; yes
  626.         or      status,stat_chk ; checksum failure
  627. rpkx1:  call    inchr           ; Get last character of checksum.
  628.          jmp    rpack4          ; Failed.
  629.          nop
  630.         mov     byte ptr[bx],al ; put into buffer for debug
  631.         inc     bx
  632.         cmp     al,trans.rsoh   ; Restarting?
  633.         je      rpack7          ; e = yes
  634.         sub     al,' '          ; Get back real value.
  635.         and     cx,003FH        ; Get bits 0-5.
  636.         cmp     al,cl           ; Do the last chars match?
  637.         je      rpack4          ; e = yes
  638.         or      status,stat_chk ; say checksum failure
  639.  
  640. rpack4: test    status,stat_tmo ; timeout?
  641.         jnz     rpack6          ; nz = yes
  642.         test    status,stat_eol ; premature eol?
  643.         jnz     rpack4c         ; nz = yes, try handshake
  644.         call    inchr           ; get eol char (ok = ret with carry set)
  645.          jnc    rpack6          ; nc = timeout or user intervention
  646.          nop
  647.         cmp     bx,offset data+maxpack+7        ; filled debug buffer yet?
  648.         ja      rpack4e         ; a = yes
  649.         mov     byte ptr[bx],al ; put into buffer for debug
  650.         inc     bx
  651. rpack4e:cmp     al,trans.rsoh   ; soh already?
  652.         jne     rpack4a         ; ne = no
  653.         jmp     rpack7          ; yes
  654. rpack4a:and     status,not stat_eol ; desired eol is not an error
  655. rpack4c:push    bx              ; test for line turn char, if handshaking
  656.         mov     bx,portval
  657.         mov     ah,[bx].hands   ; get desired handshake char
  658.         cmp     [bx].hndflg,0   ; doing half duplex handshaking?
  659.         pop     bx
  660.         je      rpack6          ; e = no
  661.         mov     tmp,ah          ; keep it here
  662.         call    inchr           ; get handshake char
  663.          jnc    rpack5          ; nc = timeout or user intervention
  664.          nop
  665.         and     status,not stat_eol     ; ignore unexpected eol status here.
  666.         cmp     bx,offset data+maxpack+7        ; filled debug buffer yet?
  667.         ja      rpack4f         ; a = yes
  668.         mov     byte ptr[bx],al ; put into buffer for debug
  669.         inc     bx
  670. rpack4f:cmp     al,trans.rsoh   ; soh already?
  671.         jne     rpack4d         ; ne = no
  672.         jmp     rpack7          ; yes, do debug display and start over
  673. rpack4d:cmp     al,tmp          ; compare received char with handshake
  674.         jne     rpack4c         ; ne = not handshake, try again til timeout
  675. rpack5: and     status,not stat_tmo     ; ignore timeouts on handshake char
  676.  
  677. rpack6: call    deblin          ; do debug display
  678.         cmp     flags.debug,0   ; In debug mode?
  679.         jne     rpack6a         ; ne = yes
  680.         test    flags.capflg,logpkt ; log packets?
  681.         jz      rpack6b         ; z = no
  682. rpack6a:cmp     linecnt,0       ; anything on current line?
  683.         je      rpack6b         ; e = no
  684.         mov     dx,offset crlf  ; finish line with cr/lf
  685.         call    captdol         ;  to log file
  686.  
  687. rpack6b:call    chkcon          ; check console for user interrupt
  688.          nop
  689.          nop
  690.          nop
  691.         test    status,stat_tmo ; did a timeout get us here?
  692.         jz      rpack6c         ; z = no
  693.         mov     pktype,'T'      ; yes, say 'T' type packet (timeout)
  694. rpack6c:mov     bl,tmpflg       ; flags before rpack began
  695.         cmp     bl,flags.cxzflg ; did flags change?
  696.         je      rpack6e         ; e = no
  697.         cmp     flags.cxzflg,'C'; did user type contol-C?
  698.         je      rpack6d         ; e = yes
  699.         cmp     flags.cxzflg,'E'; protocol exit request?
  700.         jne     rpack6e         ; ne = no
  701. ;        mov     bx,offset cemsg ; user intervention message for error packet
  702.         mcmsgb  cemsg, ccemsg
  703.         call    errpack         ; send error message
  704. rpack6d:mov     pack.state,'A'  ; and move to abort state
  705.         call    intmsg          ; show interrupt msg for control-C-E
  706.  
  707. rpack6e:mov     ax,rpkcnt       ; number of bytes received in this packet
  708.         add     fsta.prbyte,ax  ; total received bytes
  709.         adc     fsta.prbyte+2,0 ; propagate carry to high word
  710.         add     fsta.prpkt,1    ; count received packet
  711.         adc     fsta.prpkt+2,0  ;  ripple carry
  712.         mov     ah,pktype       ; return packet type in ah
  713.         cmp     status,stat_suc ; successful so far?
  714.         jne     rpack6x         ; ne = no
  715.         jmp     rskp            ; success exit
  716. rpack6x:ret                     ; failure exit
  717.  
  718. RPACK   ENDP
  719.  
  720. ; Check Console (keyboard). Ret if "action" chars: cr for forced timeout,
  721. ; Control-E for force out Error packet, Control-C for quit work now.
  722. ; Return rskp on Control-X and Control-Z as these are acted upon by higher
  723. ; layers. Consume and ignore anything else.
  724. chkcon: call    isdev           ; is stdin a device and not a disk file?
  725.         jnc     chkco5          ; nc = no, a disk file so do not read here
  726.         mov     dl,0ffh
  727.         mov     ah,dconio       ; read console
  728.         int     dos
  729.         jz      chkco5          ; z = nothing there
  730.         cmp     al,cr           ; carriage return?
  731.         je      chkco3          ; e = yes, simulate timeout
  732.         cmp     al,'C'-40h      ; Control-C?
  733.         je      chkco1          ; e = yes
  734.         cmp     al,'E'-40h      ; Control-E?
  735.         je      chkco1          ; e = yes
  736.         cmp     al,'X'-40h      ; Control-X?
  737.         je      chkco4          ; e = yes
  738.         cmp     al,'Z'-40h      ; Control-Z?
  739.         je      chkco4          ; record it, take no immmediate action here
  740.         cmp     al,0            ; scan code being returned?
  741.         jne     chkcon          ; ne = no
  742.         mov     ah,dconio       ; read and discard second byte
  743.         mov     dl,0ffh
  744.         int     dos
  745.         jmp     chkcon          ; else unknown, read any more
  746. chkco1: add     al,40h          ; Make Control-C-E printable.
  747.         mov     flags.cxzflg,al ; Remember what we saw.
  748. chkco2: or      status,stat_int ; interrupted
  749.         ret                     ; act   now
  750. chkco3: or      status,stat_tmo ; cr simulates timeout
  751.         ret                     ; act   now
  752. chkco4: add     al,40h          ; make control-X-Z printable
  753.         mov     flags.cxzflg,al ; put into flags
  754.         jmp     rskp            ; do not act on them here
  755. chkco5: cmp     flags.cxzflg,'C'; control-C intercepted elsewhere?
  756.         je      chkco2          ; e = yes
  757.         jmp     rskp            ; else say no immediate action needed
  758.  
  759.  
  760. getlen  proc    near            ; compute packet length for short & long types
  761.                                 ; returns length in pack.datlen and length
  762.                                 ; type (0, 1, 3) in pack.lentyp
  763.                                 ; returns length of  data + checksum
  764.         mov     ax,pack.datlen  ; LEN from packet's second byte
  765.         xor     ah,ah           ; clear unused high byte
  766.         cmp     al,3            ; regular packet has 3 or larger here
  767.         jb      getln0          ; b = long packet
  768.         sub     pack.datlen,2   ; minus SEQ and TYPE = DATA + CHKSUM
  769.         mov     pack.lentyp,3   ; store assumed length type (3 = regular)
  770.         clc                     ; clear carry for success
  771.         ret
  772.  
  773. getln0: push    cx              ; counter for number of length bytes
  774.         mov     pack.lentyp,0   ; store assumed length type 0 (long)
  775.         mov     cx,2            ; two base-95 digits
  776.         cmp     al,0            ; is this a type 0 (long packet)?
  777.         je      getln5          ; e = yes, go find & check length data
  778. getln1: mov     pack.lentyp,1   ; store length type (1 = extra long)
  779.         mov     cx,3            ; three base 95 digits
  780.         cmp     al,1            ; is this a type 1 (extra long packet)?
  781.         je      getln5          ; e = yes, go find & check length data
  782.         pop     cx
  783.         stc                     ; set carry bit to say error (unkn len code)
  784.         ret
  785. getln5:                         ; chk header chksum and recover binary length
  786.         push    dx              ; save working reg
  787.         xor     ax,ax           ; clear length accumulator, low part
  788.         mov     pack.datlen,ax  ; clear final length too
  789. getln7: xor     dx,dx           ; ditto, high part
  790.         mov     ax,pack.datlen  ; length to date
  791.         mul     ninefive        ; multiply accumulation (in ax) by 95
  792.         mov     pack.datlen,ax  ; save results
  793.         push    cx
  794.         call    inchr           ; read another serial port char into al
  795.          nop                    ; should do something here about failures
  796.          nop
  797.          nop
  798.         pop     cx
  799.         mov     ah,0
  800.         mov     byte ptr[bx],al ; store in buffer
  801.         inc     bx
  802.         add     chksum,ax
  803.         sub     al,20h          ; subtract space, apply unchar()
  804.         add     pack.datlen,ax  ; add to overall length count
  805.         loop    getln7          ; cx preset earlier for type 0 or type 1
  806.         mov     dx,chksum       ; get running checksum
  807.         shl     dx,1            ; get two high order bits into dh
  808.         shl     dx,1
  809.         and     dh,3            ; want just these two bits
  810.         shr     dl,1            ; put low order part back
  811.         shr     dl,1
  812.         add     dl,dh           ; add low order byte to two high order bits
  813.         and     dl,03fh         ; chop to lower 6 bits (mod 64)
  814.         add     dl,20h          ; apply tochar()
  815.         push    dx
  816.         call    inchr           ; read another serial port char
  817.          nop
  818.          nop
  819.          nop
  820.         pop     dx
  821.         mov     ah,0
  822.         mov     byte ptr[bx],al ; store in buf for debug
  823.         inc     bx
  824.         add     chksum,ax
  825.         cmp     dl,al           ; our vs their checksum, same?
  826.         pop     dx              ; unsave regs (preserves flags)
  827.         pop     cx
  828.         je      getln9          ; e = checksums match, success
  829.         or      status,stat_chk ; checksum failure
  830.         stc                     ; else return carry set for error
  831.         ret
  832. getln9: clc                     ; clear carry (say success)
  833.         ret
  834. getlen  endp
  835.  
  836. ; Get char from serial port into al, with timeout and console check.
  837. ; Ret carry clear if timeout or console char, Ret carry set if EOL seen,
  838. ; Rskp on other port chars. Fairflg allows occassional reads from console
  839. ; before looking at serial port, to avoid latchups.
  840. inchr:  mov     timeit,0        ; reset timeout flag (do each char separately)
  841.         push    bx              ; save a reg
  842.         cmp     fairflg,maxpack ; look at console first every now and then
  843.         jbe     inchr1          ; be = not console's turn yet
  844.         call    chkcon          ; check console
  845.          jmp    inchr5          ; got cr or control-c/e input
  846.          nop
  847.         mov     fairflg,0       ; reset fairness flag for next time
  848. inchr1: call    prtchr          ; Is there a serial port character to read?
  849.          jmp    inchr6          ; Got one (in al); else does rskp.
  850.          nop
  851.         call    chkcon          ; check console
  852.          jmp    inchr5          ; got cr or control-c/e input
  853.          nop
  854. inchr2: cmp     flags.timflg,0  ; Are timeouts turned off?
  855.         je      inchr1          ; e = yes, just check for more input.
  856.         cmp     trans.stime,0   ; Doing time outs?
  857.         je      inchr1          ; e = no, just go check for more input.
  858.         push    cx              ; save regs
  859.         push    dx              ; Stolen from Script code.
  860.         cmp     timeit,0        ; have we gotten time of day for first fail?
  861.         jne     inchr4          ; ne = yes, just compare times
  862.         mov     ah,gettim       ; get DOS time of day
  863.         int     dos             ; ch = hh, cl = mm, dh = ss, dl = 0.01 sec
  864.         xchg    ch,cl           ; get ordering of low byte = hours, etc
  865.         mov     word ptr rptim,cx ; hours and minutes
  866.         xchg    dh,dl
  867.         mov     word ptr rptim+2,dx ; seconds and fraction
  868.         mov     bl,trans.stime  ; our desired timeout interval (seconds)
  869.         mov     bh,0            ; one byte's worth
  870.         mov     temp,bx         ; work area
  871.         mov     bx,2            ; start with seconds field
  872. inchr3: mov     ax,temp         ; desired timeout interval, working copy
  873.         add     al,rptim[bx]    ; add current tod digit interval
  874.         adc     ah,0
  875.         xor     dx,dx           ; clear high order part thereof
  876.         div     sixzero         ; compute number of minutes or hours
  877.         mov     temp,ax         ; quotient, for next time around
  878.         mov     rptim[bx],dl    ; put normalized remainder in timeout tod
  879.         dec     bx              ; look at next higher order time field
  880.         cmp     bx,0            ; done all time fields?
  881.         jge     inchr3          ; ge = no
  882.         cmp     rptim[0],24     ; normalize hours
  883.         jl      inchr3a         ; l = not 24 hours or greater
  884.         sub     rptim[0],24     ; discard part over 24 hours
  885. inchr3a:mov     timeit,1        ; say have tod of timeout
  886.  
  887. inchr4: mov     ah,gettim       ; compare present tod versus timeout tod
  888.         int     dos             ; get the time of day
  889.         sub     ch,rptim        ; hours difference, ch = (now - timeout)
  890.         je      inchr4b         ; e = same, check mmss.s
  891.         jl      inchr4d         ; l = we are early
  892.         cmp     ch,12           ; hours difference, large or small?
  893.         jge     inchr4d         ; ge = we are early
  894.         jl      inchr4c         ; l = we are late, say timeout
  895. inchr4b:cmp     cl,rptim+1      ; minutes, hours match
  896.         jb      inchr4d         ; b = we are early
  897.         ja      inchr4c         ; a = we are late
  898.         cmp     dh,rptim+2      ; seconds, hours and minutes match
  899.         jb      inchr4d         ; b = we are early
  900.         ja      inchr4c         ; a = we are late
  901.         cmp     dl,rptim+3      ; hundredths of seconds, hhmmss match
  902.         jb      inchr4d         ; b = we are early
  903. inchr4c:or      status,stat_tmo ; say timeout
  904.         pop     dx
  905.         pop     cx
  906.         jmp     inchr5          ; timeout exit
  907. inchr4d:pop     dx
  908.         pop     cx
  909.         jmp     inchr1          ; not timed out yet
  910.  
  911. inchr5: pop     bx              ; here with console char or timeout
  912.         clc                     ; clear carry bit
  913.         ret                     ; failure
  914.  
  915. inchr6: pop     bx              ; here with char in al from port
  916.         and     al,parmsk       ; apply 7/8 bit parity mask
  917.         or      al,al           ; null char?
  918.         jnz     inchr6b         ; nz = no
  919. inchr6a:jmp     inchr           ; ignore the null, read another char
  920. inchr6b:cmp     al,del          ; ascii del byte?
  921.         je      inchr6a         ; e = yes, ignore it too
  922.         inc     rpkcnt          ; count received byte
  923.         cmp     al,trans.reol   ; eol char we want?
  924.         je      inchr7          ; e = yes, ret with carry set
  925.         jmp     rskp            ; char is in al
  926. inchr7: or      status,stat_eol ; set status appropriately
  927.         stc                     ; set carry to say eol seen
  928.         ret                     ; and return qualified failure
  929.  
  930. ; sleep for the # of seconds in al
  931. ; Preserve all regs. Added console input forced timeout 21 March 1987 [jrd]
  932. sleep   proc    near
  933.         push    ax
  934.         push    cx
  935.         push    dx
  936.         push    ax              ; save argument
  937.         mov     ah,gettim       ; DOS tod (ch=hh, cl=mm, dh=ss, dl=.s)
  938.         int     dos             ; get current time
  939.         pop     ax              ; restore desired # of seconds
  940.         add     dh,al           ; add # of seconds
  941. sleep1: cmp     dh,60           ; too big for seconds?
  942.         jb      sleep2          ; no, keep going
  943.         sub     dh,60           ; yes, subtract a minute's overflow
  944.         inc     cl              ; and add one to minutes field
  945.         cmp     cl,60           ; did minutes overflow?
  946.         jb      sleep1          ; no, check seconds again
  947.         sub     cl,60           ; else take away an hour's overflow
  948.         inc     ch              ; add it back in hours field
  949.         jmp     sleep1          ; and keep checking
  950. sleep2: mov     time,cx         ; store desired ending time,  hh,mm
  951.         mov     time+2,dx       ; ss, .s
  952. sleep3: call    chkcon          ; check console for user timeout override
  953.          jmp    short sleep5    ; have override
  954.          nop                    ;  three bytes for rskp
  955.         mov     ah,gettim       ; get time
  956.         int     dos             ; from dos
  957.         sub     ch,byte ptr time+1 ; hours difference, ch = (now - timeout)
  958.         je      sleep4          ; e = hours match, check mmss.s
  959.         jl      sleep3          ; l = we are early
  960.         cmp     ch,12           ; hours difference, large or small?
  961.         jge     sleep3          ; ge = we are early
  962.         jl      sleep5          ; l = we are late, exit now
  963. sleep4: cmp     cl,byte ptr time ; check minutes, hours match
  964.         jb      sleep3          ; b = we are early
  965.         ja      sleep5          ; a = over limit, time to exit
  966.         cmp     dx,time+2       ; check seconds and fraction, hhmm match
  967.         jb      sleep3          ; b = we are early
  968. sleep5: pop     dx
  969.         pop     cx
  970.         pop     ax
  971.         ret
  972. sleep   endp
  973.                                 ; Packet Debug display routines
  974. rcvdeb: cmp     flags.debug,0   ; In debug mode?
  975.         jne     rcvde1          ; ne = yes
  976.         test    flags.capflg,logpkt ; log packets?
  977.         jnz     rcvde1          ; e = yes
  978.         ret                     ; no
  979. rcvde1: mov     debflg,'R'      ; say receiving
  980.         jmp     deb1
  981.  
  982. snddeb: cmp     flags.debug,0   ; In debug mode?
  983.         jne     sndde1          ; ne = yes
  984.         test    flags.capflg,logpkt ; log packets?
  985.         jnz     sndde1          ; yes
  986.         ret                     ; no
  987. sndde1: mov     debflg,'S'      ; say sending
  988.  
  989. deb1:   push    ax              ; Debug. Packet display.
  990.         push    bx
  991.         push    cx              ; save some regs.
  992.         push    dx
  993.         push    di
  994.         test    flags.debug,logpkt      ; is debug active (vs just logging)?
  995.         jz      deb1d           ; z = no, just logging
  996.         cmp     fmtdsp,0        ; non-formatted display?
  997.         je      deb1d           ; e = yes, skip extra line clearing
  998.         cmp     debflg,'R'      ; receiving?
  999.         je      deb1a           ; e = yes
  1000.         call    sppos           ; spack: cursor position
  1001.         jmp     deb1b
  1002. deb1a:  call    rppos           ; rpack: cursor position
  1003. deb1b:  call    clearl          ; clear the line
  1004.         mov     dx,offset crlf
  1005.         mov     ah,prstr        ; display
  1006.         int     dos
  1007.         call    clearl          ; clear debug line and line beneath
  1008. deb1e:  cmp     debflg,'R'      ; receiving?
  1009.         je      deb1c           ; e = yes
  1010.         call    sppos           ; reposition cursor for spack:
  1011.         jmp     deb1d
  1012. deb1c:  call    rppos           ; reposition cursor for rpack:
  1013. deb1d:  mov     dx,offset spmes ; spack: message
  1014.         cmp     debflg,'R'
  1015.         jne     deb2            ; ne = sending
  1016.         mov     dx,offset rpmes ; rpack: message
  1017. deb2:   call    captdol         ; record dollar terminated string in Log file
  1018.         mov     linecnt,7       ; number of columns used so far
  1019.         pop     di
  1020.         pop     dx
  1021.         pop     cx
  1022.         pop     bx
  1023.         pop     ax
  1024.         ret                     ; done
  1025.  
  1026. ; Display/log packet chars processed so far.
  1027. ; Displays chars from pktptr to bx, both are pointers.
  1028. ; Enter with bx = offset of next new char. All registers preserved
  1029. deblin: cmp     flags.debug,0   ; In debug mode?
  1030.         jne     debln0          ; ne = yes
  1031.         test    flags.capflg,logpkt ; log packets?
  1032.         jnz     debln0          ; nz = yes
  1033.         ret                     ; else  nothing to do
  1034. debln0: push    cx
  1035.         push    dx
  1036.         push    di
  1037.         mov     di,pktptr       ; starting place for debug analysis
  1038.         mov     cx,bx           ; place for next new char
  1039.         sub     cx,di           ; minus where we start = number chars to do
  1040.         cmp     cx,0
  1041.         jle     debln5          ; le = nothing to do
  1042. debln2: cmp     di,offset data+maxpack+10 ; end of buffer data?
  1043.         ja      debln5          ; a = all done
  1044.         push    cx              ; save loop counter
  1045.         cmp     linecnt,70
  1046.         jb      debln3          ; b = not yet, get next data char
  1047.         mov     dx,offset crlf  ; break line with cr/lf
  1048.         call    captdol         ; and in log file
  1049.         mov     linecnt,0       ; setup for next line
  1050. debln3: mov     dl,byte ptr [di]; get char
  1051.         test    dl,80h          ; high bit set?
  1052.         jz      debln3b         ; z = no
  1053.         push    dx              ; save char in dl
  1054.         mov     dl,7eh          ; show tilde char for high bit set
  1055.         call    captchr         ; record in Log file
  1056.         inc     linecnt         ; count displayed column
  1057.         cmp     linecnt,70      ; exhausted line count yet?
  1058.         jb      debln3a         ; b = not yet
  1059.         mov     dx,offset crlf  ; break line with cr/lf
  1060.         call    captdol         ; and in log file
  1061.         mov     linecnt,0       ; setup for next line
  1062. debln3a:pop     dx
  1063.         and     dl,7fh          ; get lower seven bits here
  1064. debln3b:cmp     dl,' '          ; control char?
  1065.         jae     debln4          ; ae = no
  1066.         add     dl,40h          ; uncontrollify the char
  1067.         push    dx              ; save char in dl
  1068.         mov     dl,5eh          ; show caret before control code
  1069.         call    captchr         ; record in Log file
  1070.         inc     linecnt         ; count displayed column
  1071.         cmp     linecnt,70      ; exhausted line count yet?
  1072.         jb      debln3c         ; b = not yet
  1073.         mov     dx,offset crlf  ; break line with cr/lf
  1074.         call    captdol         ; and in log file
  1075.         mov     linecnt,0       ; setup for next line
  1076. debln3c:pop     dx              ; recover char in dl
  1077.  
  1078. debln4: call    captchr         ; record char in dl in the log file
  1079.         inc     di              ; done with this char, point to next
  1080.         inc     linecnt         ; one more column used on screen
  1081.         pop     cx              ; recover loop counter
  1082.         loop    debln2          ; get next data char
  1083. debln5: pop     di
  1084.         pop     dx
  1085.         pop     cx
  1086.         ret
  1087.  
  1088. captdol proc    near            ; write dollar sign terminated string in dx
  1089.                                 ; to the capture file (Log file). [jrd]
  1090.         push    ax              ; save regs
  1091.         push    si
  1092.         mov     si,dx           ; point to start of string
  1093. captdo1:lodsb                   ; get   a byte into al
  1094.         cmp     al,'$'          ; at the end yet?
  1095.         je      captdo2         ; e = yes
  1096.         mov     dl,al
  1097.         call    captchr         ; Log the char
  1098.         jmp     short captdo1   ; repeat until dollar sign is encountered
  1099. captdo2:pop     si
  1100.         pop     ax
  1101.         ret
  1102. captdol endp
  1103.  
  1104. captcx  proc    near            ; record counted string, starts in di, count
  1105.                                 ;  is in cx. [jrd]
  1106.         jcxz    captc2          ; if count = zero, exit now
  1107.         push    ax              ; save regs
  1108.         push    cx
  1109.         push    si
  1110.         mov     si,di           ; get start address
  1111. captc1: lodsb                   ; get a char into al
  1112.         call    pktcpt          ; record it, cptchr is in msster.asm
  1113.         loop    captc1          ; do this cx times
  1114.         pop     si
  1115.         pop     cx
  1116.         pop     ax
  1117. captc2: ret
  1118. captcx  endp
  1119.  
  1120. captchr proc    near            ; record char in dl into the Log file
  1121.         push    ax
  1122.         cmp     flags.debug,0   ; debug display active?
  1123.         jz      captch1         ; z = no.
  1124.         mov     ah,conout
  1125.         int     dos             ; display char in dl
  1126. captch1:test    flags.capflg,logpkt ; logging active?
  1127.         jz      captch2         ; z = no
  1128.         mov     al,dl           ; where pktcpt wants it
  1129.         call    pktcpt          ; record the char, pktcpt is in msster.asm
  1130. captch2:pop     ax
  1131.         ret
  1132. captchr endp
  1133.  
  1134. ; Jumping to this location is like retskp.  It assumes the instruction
  1135. ;   after the call is a jmp addr.
  1136.  
  1137. RSKP    PROC    NEAR
  1138.         pop     bp
  1139.         add     bp,3
  1140.         push    bp
  1141.         ret
  1142. RSKP    ENDP
  1143.  
  1144. ; Jumping here is the same as a ret.
  1145.  
  1146. R       PROC    NEAR
  1147.         ret
  1148. R       ENDP
  1149.  
  1150. code    ends
  1151.         end
  1152.