home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / mssfil.asm < prev    next >
Assembly Source File  |  2020-01-01  |  118KB  |  2,998 lines

  1.     NAME    mssfil
  2. ; File MSSFIL.ASM
  3.     include mssdef.h
  4. ;    Copyright (C) 1982, 1997, Trustees of Columbia University in the 
  5. ;    City of New York.  The MS-DOS Kermit software may not be, in whole 
  6. ;    or in part, licensed or sold for profit as a software product itself,
  7. ;    nor may it be included in or distributed with commercial products
  8. ;    or otherwise distributed by commercial concerns to their clients 
  9. ;    or customers without written permission of the Office of Kermit 
  10. ;    Development and Distribution, Columbia University.  This copyright 
  11. ;    notice must not be removed, altered, or obscured.
  12. ;
  13. ; Edit history
  14. ; 12 Jan 1995 version 3.14
  15. ; Last edit
  16. ; 12 Jan 1995
  17. ; 27 August 1992 version 3.13
  18. ; 6 Sept 1991 version 3.11
  19. ; 2 March 1991 version 3.10
  20.  
  21.     public    buff, gofil, ptchr, gtchr, getfil, gtnfil, doenc, dodec
  22.     public    encbuf, decbuf, diskio, auxfile, fparse, prtasz, prtscr
  23.     public    strlen, strcat, strcpy, tfilsz, templp, latin1, charids
  24.     public    L1cp437, L1cp850, L1cp860, L1cp863, L1cp865, unique
  25.     public    cplatin, goopen, latininv, protlist, jpnxtof, templf
  26.     public    jpnftox, echrcnt, rcvpathflg, sndpathflg, atfile, atflag
  27.     public    l5cp866, lccp866r, k8cp866r, k7cp866r, cp866koi7, cp866koi8
  28.     public    cp866lci
  29.  
  30. SIchar    equ    0fh
  31. SOchar    equ    0eh
  32. DLE    equ    10h
  33.  
  34. data    segment
  35.     extrn    flags:byte, trans:byte, dtrans:byte, denyflg:word,dosnum:word
  36.     extrn    oldkbt:word, oldper:word, filtst:byte, rdbuf:byte, fsta:byte
  37.     extrn    curdsk:byte, fdate:byte, ftime:byte, wrpmsg:byte
  38.  
  39. ermes4  db    'Unable to make unique name',0
  40. ermes9    db    'Printer not ready',0
  41. erms12    db    'Unable to create file ',0
  42. erms13    db    'Error writing output file',0
  43. infms5  db    'Renaming file to $'
  44. infms6    db    cr,lf,'?Unable to open file$'
  45. asmsg    db    ' as $'
  46. crlf    db    cr,lf,'$'
  47. printer    db    'PRN',0
  48. screen    db    'CON',0
  49. vacuum    db    'NUL',0
  50. loadhlp    db    'filename$'
  51.                 ; DOS special chars allowed in filenames
  52. spchar2    db    '$', 26h, 23h, 40h, 21h, 25h, 27H, '(', ')', '-', 7bh, 7dh
  53.     db    5fh, 5eh, 7eh, 60h
  54. spc2len    equ    $-spchar2
  55.  
  56. textctl    db    cr,lf,tab,bell,ff,ctlz    ; controls allowed in text files
  57. textctlen equ    $-textctl
  58.     even
  59. filflg    db    0        ; input buffer has data, if non-zero
  60. rptct    db    1        ; number of times it's repeated
  61. dblbyte    db    0        ; first of two bytes in a pair
  62. dblbyteflg db    0        ; non-zero if processing second byte of pair
  63. DLEseen    db    0
  64. shiftstate db    0        ; locking shift (0 = unshifted, 80h = shifted)
  65. decoutp    dw    0        ; ptr to proc to dump decode output buffer
  66. encinp    dw    0        ; ptr to proc to refill encode input buffer
  67. dchrcnt dw    0        ; number of chars in the decode file buffer
  68. echrcnt dw    0        ; number of chars in the encode file buffer
  69. dbufpnt dw    0        ; position in file buffer, decoder
  70. ebufpnt dw    0        ; position in file buffer, encoder
  71.  
  72.     db    0        ; this MUST directly preceed decbuf, jpnwrite
  73. decbuf    db    decbuflen dup (0) ; decoding source buffer
  74.     db    0        ; safety for possible null terminator
  75. encbuf    db    encbuflen dup (0) ; encoding source buffer
  76.     db    0        ; safety for possible null terminator
  77. protlist db    32 dup (0)     ; list of protected control codes (if = 0)
  78.  
  79. tfilsz    dw    0,0        ; bytes transferred (double word qty)
  80. nmoflg    db    0        ; have override filename, if non-zero
  81. templp    db    65 dup (0)    ; temp for local path part
  82. templf    db    14 dup (0)    ; temp for local filename part
  83. temprp    db    65 dup (0)    ; temp for remote path part
  84. temprf    db    14 dup (0)    ; temp for remote filename part
  85. auxfile    db    65 dup (0)    ; auxillary filename for general use
  86. atfile    db    67 dup (0)    ; at sign sending source file
  87. atflag    db    0        ; non-zero if using at sign file sending
  88. diskio    filest    <>        ; ditto, for ordinary file transfers
  89. buff    db    buffsz dup (?)    ; use as our Disk Transfer Area
  90. havdot    db    0        ; dot-found status in verify
  91. unum    dw    0        ; unique filename generation number
  92. ifdef    no_terminal
  93. rcvpathflg db    0        ; remove(0)/retain(1) remote paths on RECEIVE
  94. else
  95. rcvpathflg db    1        ; remove(0)/retain(1) remote paths on RECEIVE
  96. endif    ; no_terminal          BBS flavor gets no receive pathnames
  97. sndpathflg db    0        ; remove(0)/retain(1) local paths on SEND
  98. temp    dw    0
  99.                 ; charids: table of transfer char-set idents
  100. charids dw    7        ; qty, pointers to char set idents
  101.     dw    chtrans,chlatin1,chlatin2,chhebiso,chcyrill,chjapan,chjapanold
  102. chtrans    db    1,'A'        ; Transparent: char count, ident
  103. chlatin1 db    6,'I6/100'    ; Latin1: char count, ident
  104. chlatin2 db    6,'I6/101'    ; Latin2: char count, ident
  105. chhebiso db    6,'I6/138'    ; Hebrew-ISO: char count, ident
  106. chcyrill db    6,'I6/144'    ; Cyrillic: char count, ident
  107. chjapan    db    9,'I14/87/13'    ; Japanese-EUC: char count, ident (new)
  108. chjapanold db    7,'I14/87E'    ; Japanese-EUC: char count, ident (obsolete)
  109.                 ; end of charids info
  110. ;loadtab    db    1        ; LOAD command table
  111. ;    mkeyw    'Transfer-character-set',0
  112. ;
  113. ;filtab    macro
  114. ;    cnt = 128
  115. ;    rept    128            ; 128 idenity entries
  116. ;    db    cnt            ; initialize table to 128 .. 255
  117. ;    cnt = cnt + 1
  118. ;    endm
  119. ;endm
  120. ;
  121. ;userin    equ    this byte        ; LOAD command
  122. ;    filtab                ; init table to idenity
  123. ;namein    db    20 dup (0)        ; name of the character set
  124. ;userout    equ    this byte
  125. ;    filtab                ; init table to idenity
  126. ;nameout db    20 dup (0)        ; name of the character set
  127. ;tblptr    dw    0            ; LOAD command
  128. ;xlines    dw    0            ; LOAD command
  129. ;linecnt dw    0            ; LOAD command
  130. ;badvalue db    cr,lf,'?Bad value on line $'
  131.  
  132. data    ends
  133.  
  134. data1    segment
  135. ; Translation tables for byte codes 0a0h..0ffh to map ISO 8859-1 to Code Pages
  136. ; Codes 00h-1fh are 7-bit controls (C0), codes 20h..7eh are ASCII, 7fh DEL is
  137. ; considered to be a control code, 80h..9fh are 8-bit controls (C1).
  138. ; Each table is 96 translatable bytes followed by the table size (96), the
  139. ; ISO announcer ident ('A' and a null here); LATIN5/Cyrillic uses 'L'.
  140. ; The decimal tables are from Frank da Cruz working with the formal IBM docs.
  141.                     ; from ISO 8859-1 Latin-1 to Code Page
  142.                         ; to CP437 United States
  143. L1cp437    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  144.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  145.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  146.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  147.     db    20h,0adh,9bh,9ch,  0fh,9dh,7ch,15h    ; column 10
  148.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  149.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  150.     db    2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  151.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  152.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  153.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  154.     db    4fh,55h,55h,55h,   9ah,59h,3fh,0e1h
  155.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  156.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  157.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  158.     db    6fh,97h,0a3h,96h,  81h,79h,3fh,98h
  159.     db    96,'A',0            ; 96 byte set, letter ident
  160.  
  161.                         ; to CP850 Multilingual
  162. L1cp850    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  163.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  164.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  165.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  166.     db    20h,0adh,0bdh,9ch,  0cfh,0beh,0ddh,0f5h    ; column 10
  167.     db    0f9h,0b8h,0a6h,0aeh, 0aah,0f0h,0a9h,0eeh
  168.     db    0f8h,0f1h,0fdh,0fch, 0efh,0e6h,0f4h,0fah ; column 11
  169.     db    0f7h,0fbh,0a7h,0afh, 0ach,0abh,0f3h,0a8h
  170.     db    0b7h,0b5h,0b6h,0c7h, 8eh,8fh,92h,80h    ; column 12
  171.     db    0d4h,90h,0d2h,0d3h, 0deh,0d6h,0d7h,0d8h
  172.     db    0d1h,0a5h,0e3h,0e0h, 0e2h,0e5h,99h,9eh    ; column 13
  173.     db    9dh,0ebh,0e9h,0eah, 9ah,0edh,0e8h,0e1h
  174.     db    85h,0a0h,83h,0c6h,  84h,86h,91h,87h    ; column 14
  175.     db    8ah,82h,88h,89h,    8dh,0a1h,8ch,8bh
  176.     db    0d0h,0a4h,95h,0a2h, 93h,0e4h,94h,0f6h    ; column 15
  177.     db    9bh,97h,0a3h,96h,   81h,0ech,0e7h,98h
  178.     db    96,'A',0            ; 96 byte set, letter ident
  179.  
  180.                         ; to CP860 Portugal
  181. L1cp860    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  182.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  183.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  184.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  185.     db    20h,0adh,9bh,9ch,  0fh,59h,7ch,15h    ; column 10
  186.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,2dh
  187.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  188.     db    2ch,31h,0a7h,0afh, 0ach,0abh,3fh,0a8h
  189.     db    91h,86h,8fh,8eh,   41h,41h,41h,80h    ; column 12
  190.     db    92h,90h,89h,45h,   8bh,98h,49h,49h
  191.     db    44h,0a5h,0a9h,9fh, 8ch,99h,4fh,58h    ; column 13
  192.     db    4fh,9dh,96h,55h,   9ah,59h,3fh,0e1h
  193.     db    85h,0a0h,83h,84h,  61h,61h,61h,87h    ; column 14
  194.     db    8ah,82h,88h,65h,   8dh,0a1h,69h,69h
  195.     db    3fh,0a4h,95h,0a2h, 93h,94h,6fh,0f6h    ; column 15
  196.     db    6fh,97h,0a3h,75h,  81h,79h,3fh,79h
  197.     db    96,'A',0            ; 96 byte set, letter ident
  198.  
  199.                         ; to CP861 Iceland
  200. L1cp861    db    80h,0fch,82h,83h,  84h,85h,86h,87h    ; column 8
  201.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  202.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  203.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  204.     db    20h,0adh,43h,9ch,  0fh,59h,7ch,15h    ; column 10
  205.     db    22h,3fh,0a6h,0aeh,  0aah,16h,3fh,2dh
  206.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  207.     db    2ch,31h,3fh,0afh,  0ach,0abh,3fh,0a8h
  208.     db    41h,0a4h,41h,41h,  8eh,8fh,92h,80h    ; column 12
  209.     db    45h,90h,45h,45h,   49h,0a5h,49h,49h
  210.     db    8bh,4eh,4fh,0a6h,  4fh,4fh,99h,58h    ; column 13
  211.     db    9dh,55h,0a7h,55h,  9ah,97h,8dh,0e1h
  212.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  213.     db    8ah,82h,88h,89h,   69h,0a1h,69h,69h
  214.     db    8ch,6eh,6fh,0a2h,  93h,6fh,94h,0f6h    ; column 15
  215.     db    9bh,75h,0a3h,96h,  81h,98h,95h,79h
  216.     db    96,'A',0            ; 96 byte set, letter ident
  217.  
  218.                         ; to CP863 Canada-French
  219. L1cp863    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  220.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  221.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  222.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  223.     db    20h,3fh,9bh,9ch,   98h,59h,0a0h,8fh    ; column 10
  224.     db    0a4h,40h,61h,0aeh, 0aah,0c4h,3fh,0a7h
  225.     db    0f8h,0f1h,0fdh,0a6h, 0a1h,0e6h,86h,0fah    ; column 11
  226.     db    0a5h,31h,6fh,0afh, 0ach,0abh,0adh,3fh
  227.     db    8eh,41h,84h,41h,   41h,41h,41h,80h    ; column 12
  228.     db    91h,90h,92h,94h,   49h,49h,0a8h,95h
  229.     db    44h,4eh,4fh,4fh,   99h,4fh,4fh,58h    ; column 13
  230.     db    4fh,9dh,55h,9eh,   9ah,59h,3fh,0e1h
  231.     db    85h,61h,83h,61h,   61h,61h,61h,87h    ; column 14
  232.     db    8ah,82h,88h,89h,   69h,69h,8ch,8bh
  233.     db    3fh,6eh,6fh,0a2h,  93h,6fh,6fh,0f6h    ; column 15
  234.     db    6fh,97h,0a3h,96h,  81h,79h,3fh,79h
  235.     db    96,'A',0            ; 96 byte set, letter ident
  236.                         ; to CP865 Norway
  237. L1cp865    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  238.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  239.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  240.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  241.     db    20h,0adh,3fh,9ch,  0afh,59h,7ch,15h    ; column 10
  242.     db    22h,40h,0a6h,0aeh, 0aah,0c4h,3fh,0c4h
  243.     db    0f8h,0f1h,0fdh,33h, 27h,0e6h,14h,0fah    ; column 11
  244.     db    2ch,31h,0a7h,03fh, 0ach,0abh,3fh,0a8h
  245.     db    41h,41h,41h,41h,   8eh,8fh,92h,80h    ; column 12
  246.     db    45h,90h,45h,45h,   49h,49h,49h,49h
  247.     db    44h,0a5h,4fh,4fh,  4fh,4fh,99h,58h    ; column 13
  248.     db    9dh,55h,55h,55h,  9ah,59h,3fh,0e1h
  249.     db    85h,0a0h,83h,61h,  84h,86h,91h,87h    ; column 14
  250.     db    8ah,82h,88h,89h,   8dh,0a1h,8ch,8bh
  251.     db    3fh,0a4h,95h,0a2h, 93h,6fh,94h,0f6h    ; column 15
  252.     db    9bh,97h,0a3h,96h,  81h,79h,3fh,98h
  253.     db    96,'A',0            ; 96 byte set, letter ident
  254.                             ; Latin2 to CP852
  255. L2cp852    db 174,175,176,177,178,179,180,185,186,187,188,191,192,193,194,195
  256.     db 196,197,200,201,202,203,204,205,206,217,218,219,220,223,240,254
  257.     db 255,164,244,157,207,149,151,245,249,230,184,155,141,170,166,189
  258.     db 248,165,242,136,239,150,152,243,247,231,173,156,171,241,167,190
  259.     db 232,181,182,198,142,145,143,128,172,144,168,211,183,214,215,210
  260.     db 209,227,213,224,226,138,153,158,252,222,233,235,154,237,221,225
  261.     db 234,160,131,199,132,146,134,135,159,130,169,137,216,161,140,212
  262.     db 208,228,229,162,147,139,148,246,253,133,163,251,129,236,238,250
  263.     db    96,'B',0            ; 96 byte set, letter ident
  264.  
  265.                 ; Hebrew-ISO to Code Page 862, GLeft
  266. HIcp862    db 158,159,160,161,162,163,164,165,166,167,168,169,173,176,177,178
  267.     db 179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194
  268.     db 255,195,155,156,196,157,197,198,199,200,201,174,170,202,203,204
  269.     db 248,241,253,206,207,230,208,249,209,210,246,175,172,171,211,212
  270.     db 213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228
  271.     db 229,231,232,233,234,235,236,237,238,239,240,242,243,244,245,205
  272.     db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  273.     db 144,145,146,147,148,149,150,151,152,153,154,247,250,251,252,254
  274.     db    96,'H',0
  275.  
  276.                             ; Latin5 to CP866
  277. L5cp866    db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 8
  278.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  279.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 9
  280.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  281.     db    0ffh,0f0h,3fh,3fh,  0f2h,53h,49h,4fh    ; column 10
  282.     db    4ah,3fh,3fh,48h,   4bh,2dh,0f6h,3fh
  283.     db    80h,81h,82h,83h,   84h,85h,86h,87h    ; column 11
  284.     db    88h,89h,8ah,8bh,   8ch,8dh,8eh,8fh
  285.     db    90h,91h,92h,93h,   94h,95h,96h,97h    ; column 12
  286.     db    98h,99h,9ah,9bh,   9ch,9dh,9eh,9fh
  287.     db    0a0h,0a1h,0a2h,0a3h,0a4h,0a5h,0a6h,0a7h ; column 13
  288.     db    0a8h,0a9h,0aah,0abh,0ach,0adh,0aeh,0afh
  289.     db    0e0h,0e1h,0e2h,0e3h,0e4h,0e5h,0e6h,0e7h ; column 14
  290.     db    0e8h,0e9h,0eah,0ebh,0ech,0edh,0eeh,0efh
  291.     db    0fch,0f1h,3fh,3fh, 0f3h,73h,69h,0f5h    ; column 15
  292.     db    6ah,3fh,3fh,68h,   6bh,15h,0f7h,3fh
  293.     db    96,'L',0            ; 96 byte set, Latin5/Cyrillic
  294.  
  295. ;yl143[]   /* Latin-1 to IBM Code Page 437 */
  296. ; Although the IBM CDRA does not include an official translation between CP437
  297. ; and ISO Latin Alphabet 1,it does include an official,invertible
  298. ; translation between CP437 and CP850 (page 196),and another from CP850 to
  299. ; Latin-1 (CP819) (page 153).  This translation was obtained with a two-step
  300. ; process based on those tables.
  301.  
  302. iL1cp437 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  303.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  304.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  305.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  306.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  307.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  308.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  309.     db 173,177,143,190,20,21,247,184,176,168,183,185,179,178,142,160
  310.     db 96,'A',0                ; 96 byte set,letter ident
  311.  
  312. ;yl185[]   /* Latin-1 to IBM Code Page 850 */
  313. ; This is IBM's official invertible translation.  Reference: IBM Character
  314. ; Data Representation Architecture (CDRA),Level 1, Registry, SC09-1291-00
  315. ; (1990), p.152.  (Note: Latin-1 is IBM Code Page 00819.)
  316. iL1cp850 db 186,205,201,187,200,188,204,185,203,202,206,223,220,219,254,242
  317.     db 179,196,218,191,192,217,195,180,194,193,197,176,177,178,213,159
  318.     db 255,173,189,156,207,190,221,245,249,184,166,174,170,240,169,238
  319.     db 248,241,253,252,239,230,244,250,247,251,167,175,172,171,243,168
  320.     db 183,181,182,199,142,143,146,128,212,144,210,211,222,214,215,216
  321.     db 209,165,227,224,226,229,153,158,157,235,233,234,154,237,232,225
  322.     db 133,160,131,198,132,134,145,135,138,130,136,137,141,161,140,139
  323.     db 208,164,149,162,147,228,148,246,155,151,163,150,129,236,231,152
  324.     db 96,'A',0                ; 96 byte set, letter ident
  325.  
  326. ; invertable Latin-1 to CP861 
  327. iL1cp861 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  328.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  329.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  330.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  331.     db 148,164,152,150,145,154,227,195,132,130,137,136,134,165,138,164
  332.     db 139,208,202,166,200,158,205,206,157,149,167,141,140,151,141,139
  333.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  334.     db 140,177,143,190, 20, 21,247,184,155,168,183,185,179,152,149,160
  335.     db 96,'A',0                ; 96 byte set, letter ident
  336.  
  337.  
  338. ; 128 byte translation tables from Code Pages to ISO 8859-1 Latin1 or Latin5
  339. ; For GRight only (high bit set).
  340.                             ; from Code Page 437
  341. cp437L1    db    0c7h,0fch,0e9h,0e2h,0e4h,0e0h,0e5h,0e7h ; column 8
  342.     db    0eah,0ebh,0e8h,0efh,0eeh,0ech,0c4h,0c5h
  343.     db    0c9h,0e6h,0c6h,0f4h,0f6h,0f2h,0fbh,0f9h ; column 9
  344.     db    0ffh,0d6h,0dch,0a2h,0a3h,0a5h,3fh,3fh
  345.     db    0e1h,0edh,0f3h,0fah,0f1h,0d1h,0aah,0bah ; column 10
  346.     db    0bfh,3fh,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  347.     db    16 dup (3fh)                 ; column 11
  348.     db    16 dup (3fh)                 ; column 12
  349.     db    16 dup (3fh)                 ; column 13
  350.     db    3fh,0dfh,4 dup (3fh),        0b5h,3fh ; column 14
  351.     db    5 dup(3fh),            0f8h,3fh,3fh
  352.     db    3fh,0b1h,4 dup (3fh),        0f7h,3fh ; column 15
  353.     db    0b0h,0b7h,0b7h,3fh,3fh,        0b2h,3fh,3fh
  354.                              ; from Code Page 850
  355. cp850L1    db    0c7h,0fch,0e9h,0e2h,0e4h,0e0h,0e5h,0e7h ; column 8
  356.     db    0eah,0ebh,0e8h,0efh,0eeh,0ech,0c4h,0c5h
  357.     db    0c9h,0e6h,0c6h,0f4h,0f6h,0f2h,0fbh,0f9h ; column 9
  358.     db    0ffh,0d6h,0dch,0f8h,0a3h,0d8h,0d7h,3fh
  359.     db    0e1h,0edh,0f3h,0fah,0f1h,0d1h,0aah,0bah ; column 10
  360.     db    0bfh,0aeh,0ach,0bdh,0bch,0a1h,0abh,0bbh
  361.     db    5 dup (3fh),             0c1h,0c2h,0c0h ; column 11
  362.     db    0a9h,4 dup (3fh),      0a2h,0a5h,3fh
  363.     db    6 dup (3fh),0e3h,0c3h,7 dup (3fh),0a4h     ; column 12
  364.     db    0f0h,0d0h,0cah,0cbh,0c8h,0b9h,0cdh,0ceh ; column 13
  365.     db    0cfh, 4 dup (3fh),       0a6h,0cch,3fh
  366.     db    0d3h,0dfh,0d4h,0d2h, 0f5h,0d5h,0b5h,0feh ; column 14
  367.     db    0deh,0dah,0dbh,0d9h, 0fdh,0ddh,0afh,0b4h
  368.     db    0adh,0b1h,3dh,0beh,  0b6h,0a7h,0f7h,0b8h ; column 15
  369.     db    0b0h,0a8h,0b7h,0b9h, 0b3h,0b2h,3fh,20h
  370.  
  371.                              ; from Code Page 860
  372. cp860L1    db    0c7h,0fch,0e9h,0e2h, 0e3h,0e0h,0c1h,0e7h ; column 8
  373.     db    0eah,0cah,0e8h,0cch, 0d4h,0ech,0c3h,0c2h
  374.     db    0c9h,0c0h,0c8h,0f4h, 0f5h,0f2h,0dah,0f9h ; column 9
  375.     db    0cdh,0d5h,0dch,0a2h, 0a3h,0d9h,3fh,0d3h
  376.     db    0e1h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  377.     db    0bfh,0d2h,0ach,0bdh, 0bch,0a1h,0abh,0bbh
  378.     db    16 dup (3fh)                 ; column 11
  379.     db    16 dup (3fh)                 ; column 12
  380.     db    16 dup (3fh)                 ; column 13
  381.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  382.     db    5 dup(3fh),            0f8h,3fh,3fh
  383.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  384.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  385.  
  386.                             ; from Code Page 861
  387. cp861L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  388.     db    0eah,0ebh,0e8h,0d0h, 0f0h,0deh,0c4h,0c5h
  389.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0feh,0fbh,0ddh ; column 9
  390.     db    0fdh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  391.     db    0e1h,0edh,0f3h,0fah, 0c1h,0cdh,0d3h,0dah ; column 10
  392.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0bbh
  393.     db    16 dup (3fh)                 ; column 11
  394.     db    16 dup (3fh)                 ; column 12
  395.     db    16 dup (3fh)                 ; column 13
  396.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  397.     db    5 dup(3fh),            0f8h,3fh,3fh
  398.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  399.     db    0b0h,0b7h,0b7h,3fh,3fh,        0b2h,3fh,3fh
  400.  
  401.                              ; from Code Page 863
  402. cp863L1    db    0c7h,0fch,0e9h,0e2h, 0c2h,0e0h,0b6h,0e7h ; column 8
  403.     db    0eah,0ebh,0e8h,0efh, 0eeh,3dh,0c0h,0a7h
  404.     db    0c9h,0c8h,0cah,0f4h, 0cbh,0cfh,0fbh,0f9h ; column 9
  405.     db    0a4h,0d4h,0dch,0a2h, 0a3h,0d9h,0dbh,3fh
  406.     db    0a6h,0b4h,0f3h,0fah, 0a8h,0b8h,0b3h,0afh ; column 10
  407.     db    0ceh,3fh,0ach,0bdh,  0bch,0beh,0abh,0bbh
  408.     db    16 dup (3fh)                 ; column 11
  409.     db    16 dup (3fh)                 ; column 12
  410.     db    16 dup (3fh)                 ; column 13
  411.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  412.     db    5 dup(3fh),            0f8h,3fh,3fh
  413.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  414.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  415.                                   ; from Code Page 865
  416. cp865L1    db    0c7h,0fch,0e9h,0e2h, 0e4h,0e0h,0e5h,0e7h ; column 8
  417.     db    0eah,0ebh,0e8h,0efh, 0eeh,0ech,0c4h,0c5h
  418.     db    0c9h,0e6h,0c6h,0f4h, 0f6h,0f2h,0fbh,0f9h ; column 9
  419.     db    0ffh,0d6h,0dch,0f8h, 0a3h,0d8h,3fh,3fh
  420.     db    0e2h,0edh,0f3h,0fah, 0f1h,0d1h,0aah,0bah ; column 10
  421.     db    0bfh,3fh,0ach,0bdh,  0bch,0a1h,0abh,0a4h
  422.     db    16 dup (3fh)                 ; column 11
  423.     db    16 dup (3fh)                 ; column 12
  424.     db    16 dup (3fh)                 ; column 13
  425.     db    3fh,0dfh, 4 dup (3fh),        0b5h,3fh ; column 14
  426.     db    5 dup(3fh),            0f8h,3fh,3fh
  427.     db    3fh,0b1h, 4 dup (3fh),        0f7h,3fh ; column 15
  428.     db    0b0h,0b7h,0b7h,3fh,  3fh,0b2h,3fh,3fh
  429.  
  430.                     ; from Code Page 852 to LATIN2
  431. cp852L2    db 199,252,233,226,228,249,230,231,179,235,213,245,238,172,196,198
  432.     db 201,197,229,244,246,165,181,166,182,214,220,171,187,163,215,232
  433.     db 225,237,243,250,161,177,174,190,202,234,173,188,200,186,128,129
  434.     db 130,131,132,133,134,193,194,204,170,135,136,137,138,175,191,139
  435.     db 140,141,142,143,144,145,195,227,146,147,148,149,150,151,152,164
  436.     db 240,208,207,203,239,210,205,206,236,153,154,155,156,222,217,157
  437.     db 211,223,212,209,241,242,169,185,192,218,224,219,253,221,254,180
  438.     db 158,189,178,183,162,167,247,184,176,168,255,251,216,248,159,160
  439.  
  440.                     ; Code Page 862 to Hebrew-ISO
  441. cp862HI db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  442.     db 240,241,242,243,244,245,246,247,248,249,250,162,163,165,128,129
  443.     db 130,131,132,133,134,135,136,137,138,139,172,189,188,140,171,187
  444.     db 141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156
  445.     db 157,158,159,161,164,166,167,168,169,170,173,174,175,223,179,180
  446.     db 182,184,185,190,191,192,193,194,195,196,197,198,199,200,201,202
  447.     db 203,204,205,206,207,208,181,209,210,211,212,213,214,215,216,217
  448.     db 218,177,219,220,221,222,186,251,176,183,252,253,254,178,255,160
  449.  
  450.                      ; from Code Page 866 to LATIN5
  451. cp866L5    db    0b0h,0b1h,0b2h,0b3h, 0b4h,0b5h,0b6h,0b7h ; column 8
  452.     db    0b8h,0b9h,0bah,0bbh, 0bch,0bdh,0beh,0bfh
  453.     db    0c0h,0c1h,0c2h,0c3h, 0c4h,0c5h,0c6h,0c7h ; column 9
  454.     db    0c8h,0c9h,0cah,0cbh, 0cch,0cdh,0ceh,0cfh
  455.     db    0d0h,0d1h,0d2h,0d3h, 0d4h,0d5h,0d6h,0d7h ; column 10
  456.     db    0d8h,0d9h,0dah,0dbh, 0dch,0ddh,0deh,0dfh
  457.     db    16 dup (3fh)                 ; column 11
  458.     db    16 dup (3fh)                 ; column 12
  459.     db    16 dup (3fh)                 ; column 13
  460.     db    0e0h,0e1h,0e2h,0e3h, 0e4h,0e5h,0e6h,0e7h ; column 14
  461.     db    0e8h,0e9h,0eah,0ebh, 0ech,0edh,0eeh,0efh
  462.     db    0a1h,0f1h,0a4h,0f4h, 0a7h,0f7h,0aeh,0feh ; column 15
  463.     db    4 dup (3fh),         0f0h,3fh,3fh,0a0h
  464.  
  465. ;y43l1[]   /* IBM Code Page 437 to Latin-1 */
  466. ;  This table is the inverse of yl143[].
  467. icp437L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  468.     db 201,230,198,244,246,242,251,249,255,214,220,162,163,165,215,159
  469.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  470.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  471.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  472.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  473.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  474.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  475.  
  476. ;y85l1[]   /* IBM Code Page 850 to Latin-1 */
  477. ;  This is from IBM CDRA page 153.  It is the inverse of yl185[].
  478. icp850L1 db 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
  479.     db 201,230,198,244,246,242,251,249,255,214,220,248,163,216,215,159
  480.     db 225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187
  481.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,162,165,147
  482.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  483.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  484.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  485.     db 173,177,143,190,182,167,247,184,176,168,183,185,179,178,142,160
  486.  
  487. ;y86l1[]   /* IBM Code Page 861 to Latin-1 */
  488. ;  This table is the inverse of yl186[].
  489. icp861L1 db 199,252,233,226,228,224,229,231,234,235,232,208,240,222,196,197
  490.     db 201,230,198,244,246,254,251,221,253,214,220,248,163,216,215,159
  491.     db 225,237,243,250,193,205,211,218,191,174,172,189,188,161,171,187
  492.     db 155,156,157,144,151,193,194,192,169,135,128,131,133,248,216,147
  493.     db 148,153,152,150,145,154,227,195,132,130,137,136,134,129,138,164
  494.     db 240,208,202,203,200,158,205,206,207,149,146,141,140,166,204,139
  495.     db 211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180
  496.     db 173,177,143,190, 20, 21,247,184,176,168,183,185,179,178,142,160
  497.  
  498. UNK    equ    '?'
  499.  
  500. ;Latin/Cyrillic -> CP866 Readable:
  501. lccp866r db 196,179,192,217,191,218,195,193,180,194,197,176,177,178,211,216
  502.     db 205,186,200,188,187,201,204,202,185,203,206,223,220,219,254,253
  503.     db 255,240,132,131,242, 83, 73,244, 74,139,141,151,138, 45,246,135
  504.     db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  505.     db 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
  506.     db 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175
  507.     db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  508.     db 252,241,164,163,243,115,105,245,106,171,173,231,170,181,247,167
  509.  
  510. ;Latin/Cyrillic -> CP866 Invertible:
  511. lccp866i db 196,179,192,217,191,218,195,193,180,194,197,176,177,178,211,216
  512.     db 205,186,200,188,187,201,204,202,185,203,206,223,220,219,254,253
  513.     db 255,240,208,207,242,189,183,244,184,212,213,214,210,182,246,209
  514.     db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  515.     db 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
  516.     db 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175
  517.     db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  518.     db 252,241,221,215,243,199,190,245,198,249,250,251,248,181,247,222
  519.  
  520. ;KOI8 to CP866 Readable:
  521. k8cp866r db  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
  522.     db  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
  523.     db  UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  524.     db  UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  525.     db  238,160,161,230,164,165,228,163,229,168,169,170,171,172,173,174
  526.     db  175,239,224,225,226,227,166,162,236,235,167,232,237,233,231,234
  527.     db  158,128,129,150,132,133,148,131,149,136,137,138,139,140,141,142
  528.     db  143,159,144,145,146,147,134,130,156,155,135,152,157,153,151,UNK
  529.  
  530. ;KOI7 to CP866 Readable:
  531. k7cp866r db   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15
  532.      db  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
  533.      db  32, 33, 34, 35,253, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
  534.      db  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,UNK
  535.      db  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79
  536.      db  80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
  537.      db 158,128,129,150,132,133,148,131,149,136,137,138,139,140,141,142
  538.      db 143,159,144,145,146,147,134,130,156,155,135,152,157,153,151,UNK
  539.  
  540. ;CP866 Invertible -> Latin/Cyrillic:
  541. cp866lci db 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191
  542.     db 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
  543.     db 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
  544.     db 139,140,141,129,136,253,173,166,168,152,145,148,147,165,246,132
  545.     db 130,135,137,134,128,138,248,245,146,149,151,153,150,144,154,163
  546.     db 162,175,172,142,169,170,171,243,143,131,133,157,156,242,255,155
  547.     db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  548.     db 161,241,164,244,167,247,174,254,252,249,250,251,240,159,158,160
  549.  
  550. ; CP866 to KOI7:
  551. cp866koi7 db  97, 98,119,103,100,101,118,122,105,106,107,108,109,110,111,112
  552.     db 114,115,116,117,102,104, 99,126,123,125, 39,121,120,124, 96,113
  553.     db  97, 98,119,103,100,101,118,122,105,106,107,108,109,110,111,112
  554.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  555.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  556.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  557.     db 114,115,116,117,102,104, 99,126,123,125, 39,121,120,124, 96,113
  558.     db 101,101,UNK,UNK, 73, 73,117,117,UNK,UNK,UNK,UNK,UNK, 36,UNK, 32
  559.  
  560. ; CP866 to KOI8:
  561. cp866koi8 db 225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240
  562.     db 242,243,244,245,230,232,227,254,251,253,223,249,248,252,224,241
  563.     db 193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208
  564.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  565.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  566.     db UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK,UNK
  567.     db 210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209
  568.     db 229,197,UNK,UNK, 73,105,245,213,UNK,UNK,UNK,UNK,UNK, 36,UNK, 32
  569. data1    ends
  570.  
  571. ;  L/C = ISO Latin/Cyrillic
  572. ;  CP866R = Readable      <-- use this for terminal emulation
  573. ;  CP866I = Invertible    <-- use this for file transfer
  574. ;  KOI8   = "Old" KOI-8   <-- use this for terminal emulation
  575. ;  KOI7   = Short KOI     <-- use this for terminal emulation
  576. ;
  577. ;KOI8 and KOI7 are used only as terminal character sets, so they only
  578. ;need to be readable.  So since we aren't worried about keyboarding, we
  579. ;only need five tables:
  580. ;
  581. ; CP866I -> L/C    (for file transfer) 
  582. ; L/C    -> CP866I (for file transfer) 
  583. ; L/C    -> CP866R (terminal emulation)
  584. ; KOI8   -> CP866R (terminal emulation)
  585. ; KOI7   -> CP866R (terminal emulation)
  586. ;
  587. ; L/C   CP866R  CP866I   KOI8   KOI7    UNICODE 
  588. ;  0       0       0       0      0      0x0000 
  589. ;  1       1       1       1      1      0x0001 
  590. ;  2       2       2       2      2      0x0002 
  591. ;  3       3       3       3      3      0x0003 
  592. ;  4       4       4       4      4      0x0004 
  593. ;  5       5       5       5      5      0x0005 
  594. ;  6       6       6       6      6      0x0006 
  595. ;  7       7       7       7      7      0x0007 
  596. ;  8       8       8       8      8      0x0008 
  597. ;  9       9       9       9      9      0x0009 
  598. ; 10      10      10      10     10      0x000A 
  599. ; 11      11      11      11     11      0x000B 
  600. ; 12      12      12      12     12      0x000C 
  601. ; 13      13      13      13     13      0x000D 
  602. ; 14      14      14      14     14      0x000E 
  603. ; 15      15      15      15     15      0x000F 
  604. ; 16      16      16      16     16      0x0010 
  605. ; 17      17      17      17     17      0x0011 
  606. ; 18      18      18      18     18      0x0012 
  607. ; 19      19      19      19     19      0x0013 
  608. ; 20      20      20      20     20      0x0014 
  609. ; 21      21      21      21     21      0x0015 
  610. ; 22      22      22      22     22      0x0016 
  611. ; 23      23      23      23     23      0x0017 
  612. ; 24      24      24      24     24      0x0018 
  613. ; 25      25      25      25     25      0x0019 
  614. ; 26      26      26      26     26      0x001A 
  615. ; 27      27      27      27     27      0x001B 
  616. ; 28      28      28      28     28      0x001C 
  617. ; 29      29      29      29     29      0x001D 
  618. ; 30      30      30      30     30      0x001E 
  619. ; 31      31      31      31     31      0x001F 
  620. ; 32      32      32      32     32      0x0020    SPACE 
  621. ; 33      33      33      33     33      0x0021    EXCLAMATION MARK 
  622. ; 34      34      34      34     34      0x0022    QUOTATION MARK 
  623. ; 35      35      35      35     35      0x0023    NUMBER SIGN 
  624. ; 36      36      36      36     36      0x0024    DOLLAR SIGN 
  625. ; 37      37      37      37     37      0x0025    PERCENT SIGN 
  626. ; 38      38      38      38     38      0x0026    AMPERSAND 
  627. ; 39      39      39      39     39      0x0027    APOSTROPHE 
  628. ; 40      40      40      40     40      0x0028    LEFT PARENTHESIS 
  629. ; 41      41      41      41     41      0x0029    RIGHT PARENTHESIS 
  630. ; 42      42      42      42     42      0x002A    ASTERISK 
  631. ; 43      43      43      43     43      0x002B    PLUS SIGN 
  632. ; 44      44      44      44     44      0x002C    COMMA 
  633. ; 45      45      45      45     45      0x002D    HYPHEN, MINUS SIGN 
  634. ; 46      46      46      46     46      0x002E    PERIOD, FULL STOP 
  635. ; 47      47      47      47     47      0x002F    SOLIDUS, SLASH 
  636. ; 48      48      48      48     48      0x0030    DIGIT ZERO 
  637. ; 49      49      49      49     49      0x0031    DIGIT ONE 
  638. ; 50      50      50      50     50      0x0032    DIGIT TWO 
  639. ; 51      51      51      51     51      0x0033    DIGIT THREE 
  640. ; 52      52      52      52     52      0x0034    DIGIT FOUR 
  641. ; 53      53      53      53     53      0x0035    DIGIT FIVE 
  642. ; 54      54      54      54     54      0x0036    DIGIT SIX 
  643. ; 55      55      55      55     55      0x0037    DIGIT SEVEN 
  644. ; 56      56      56      56     56      0x0038    DIGIT EIGHT 
  645. ; 57      57      57      57     57      0x0039    DIGIT NINE 
  646. ; 58      58      58      58     58      0x003A    COLON 
  647. ; 59      59      59      59     59      0x003B    SEMICOLON 
  648. ; 60      60      60      60     60      0x003C    LEFT ANGLE BRACKET 
  649. ; 61      61      61      61     61      0x003D    EQUALS SIGN 
  650. ; 62      62      62      62     62      0x003E    RIGHT ANGLE BRACKET 
  651. ; 63      63      63      63     63      0x003F    QUESTION MARK 
  652. ; 64      64      64      64     64      0x0040    COMMERCIAL AT SIGN 
  653. ; 65      65      65      65     65      0x0041    CAPITAL LETTER A 
  654. ; 66      66      66      66     66      0x0042    CAPITAL LETTER B 
  655. ; 67      67      67      67     67      0x0043    CAPITAL LETTER C 
  656. ; 68      68      68      68     68      0x0044    CAPITAL LETTER D 
  657. ; 69      69      69      69     69      0x0045    CAPITAL LETTER E 
  658. ; 70      70      70      70     70      0x0046    CAPITAL LETTER F 
  659. ; 71      71      71      71     71      0x0047    CAPITAL LETTER G 
  660. ; 72      72      72      72     72      0x0048    CAPITAL LETTER H 
  661. ; 73      73      73      73     73      0x0049    CAPITAL LETTER I 
  662. ; 74      74      74      74     74      0x004A    CAPITAL LETTER J 
  663. ; 75      75      75      75     75      0x004B    CAPITAL LETTER K 
  664. ; 76      76      76      76     76      0x004C    CAPITAL LETTER L 
  665. ; 77      77      77      77     77      0x004D    CAPITAL LETTER M 
  666. ; 78      78      78      78     78      0x004E    CAPITAL LETTER N 
  667. ; 79      79      79      79     79      0x004F    CAPITAL LETTER O 
  668. ; 80      80      80      80     80      0x0050    CAPITAL LETTER P 
  669. ; 81      81      81      81     81      0x0051    CAPITAL LETTER Q 
  670. ; 82      82      82      82     82      0x0052    CAPITAL LETTER R 
  671. ; 83      83      83      83     83      0x0053    CAPITAL LETTER S 
  672. ; 84      84      84      84     84      0x0054    CAPITAL LETTER T 
  673. ; 85      85      85      85     85      0x0055    CAPITAL LETTER U 
  674. ; 86      86      86      86     86      0x0056    CAPITAL LETTER V 
  675. ; 87      87      87      87     87      0x0057    CAPITAL LETTER W 
  676. ; 88      88      88      88     88      0x0058    CAPITAL LETTER X 
  677. ; 89      89      89      89     89      0x0059    CAPITAL LETTER Y 
  678. ; 90      90      90      90     90      0x005A    CAPITAL LETTER Z 
  679. ; 91      91      91      91     91      0x005B    LEFT SQUARE BRACKET 
  680. ; 92      92      92      92     92      0x005C    REVERSE SOLIDUS, BACKSLASH 
  681. ; 93      93      93      93     93      0x005D    RIGHT SQUARE BRACKET 
  682. ; 94      94      94      94     94      0x005E    CIRCUMFLEX ACCENT 
  683. ; 95      95      95      95     95      0x005F    LOW LINE, UNDERLINE 
  684. ; 96      96      96      96     64      0x0060    GRAVE ACCENT 
  685. ; 97      97      97      97     65      0x0061    SMALL LETTER a 
  686. ; 98      98      98      98     66      0x0062    SMALL LETTER b 
  687. ; 99      99      99      99     67      0x0063    SMALL LETTER c 
  688. ;100     100     100     100     68      0x0064    SMALL LETTER d 
  689. ;101     101     101     101     69      0x0065    SMALL LETTER e 
  690. ;102     102     102     102     70      0x0066    SMALL LETTER f 
  691. ;103     103     103     103     71      0x0067    SMALL LETTER g 
  692. ;104     104     104     104     72      0x0068    SMALL LETTER h 
  693. ;105     105     105     105     73      0x0069    SMALL LETTER i 
  694. ;106     106     106     106     74      0x006A    SMALL LETTER j 
  695. ;107     107     107     107     75      0x006B    SMALL LETTER k 
  696. ;108     108     108     108     76      0x006C    SMALL LETTER l 
  697. ;109     109     109     109     77      0x006D    SMALL LETTER m 
  698. ;110     110     110     110     78      0x006E    SMALL LETTER n 
  699. ;111     111     111     111     79      0x006F    SMALL LETTER o 
  700. ;112     112     112     112     80      0x0070    SMALL LETTER p 
  701. ;113     113     113     113     81      0x0071    SMALL LETTER q 
  702. ;114     114     114     114     82      0x0072    SMALL LETTER r 
  703. ;115     115     115     115     83      0x0073    SMALL LETTER s 
  704. ;116     116     116     116     84      0x0074    SMALL LETTER t 
  705. ;117     117     117     117     85      0x0075    SMALL LETTER u 
  706. ;118     118     118     118     86      0x0076    SMALL LETTER v 
  707. ;119     119     119     119     87      0x0077    SMALL LETTER w 
  708. ;120     120     120     120     88      0x0078    SMALL LETTER x 
  709. ;121     121     121     121     89      0x0079    SMALL LETTER y 
  710. ;122     122     122     122     90      0x007A    SMALL LETTER z 
  711. ;123     123     123     123     91      0x007B    LEFT BRACE 
  712. ;124     124     124     124     92      0x007C    VERTICAL BAR 
  713. ;125     125     125     125     93      0x007D    RIGHT BRACE 
  714. ;126     126     126     126     94      0x007E    TILDE 
  715. ;127     127     127     127    127      0x00A0    RUBOUT, DELETE 
  716. ;128     196     196     128      0 
  717. ;129     179     179     129      1 
  718. ;130     192     192     130      2 
  719. ;131     217     217     131      3 
  720. ;132     191     191     132      4 
  721. ;133     218     218     133      5 
  722. ;134     195     195     134      6 
  723. ;135     193     193     135      7 
  724. ;136     180     180     136      8 
  725. ;137     194     194     137      9 
  726. ;138     197     197     138     10 
  727. ;139     176     176     139     11 
  728. ;140     177     177     140     12 
  729. ;141     178     178     141     13 
  730. ;142     211     211     142     14 
  731. ;143     216     216     143     15 
  732. ;144     205     205     144     16 
  733. ;145     186     186     145     17 
  734. ;146     200     200     146     18 
  735. ;147     188     188     147     19 
  736. ;148     187     187     148     20 
  737. ;149     201     201     149     21 
  738. ;150     204     204     150     22 
  739. ;151     202     202     151     23 
  740. ;152     185     185     152     24 
  741. ;153     203     203     153     25 
  742. ;154     206     206     154     26 
  743. ;155     223     223     155     27 
  744. ;156     220     220     156     28 
  745. ;157     219     219     157     29 
  746. ;158     254     254     158     30 
  747. ;159     253     253     159     31             
  748. ;160     255     255     UNK     32      0x0401    No-break space 
  749. ;161     240     240     229    101      0x0402    Cyrillic Io 
  750. ;162     132     208     UNK    UNK      0x0403    Serbocroation Dje 
  751. ;163     131     207     UNK    UNK      0x0404    Macedonian Gje 
  752. ;164     242     242     UNK    UNK      0x0405    Ukranian Ie 
  753. ;165      83     189     83      83      0x0406    Macedonian Dze 
  754. ;166      73     183      73     73      0x0407    Cyrillic I 
  755. ;167     244     244     73      73      0x0408    Ukranian Yi 
  756. ;168      74     184      74     74      0x0409    Cyrillic Je 
  757. ;169     139     212     UNK    UNK      0x040A    Cyrillic Lje 
  758. ;170     141     213     UNK    UNK      0x040B    Cyrillic Nje 
  759. ;171     151     214     UNK    UNK      0x040C    Serbocroation Chje 
  760. ;172     138     210     235    107      0x00AD    Macedonian Kje 
  761. ;173      45     182     UNK     45      0x040E    Soft hyphen 
  762. ;174     246     246     245    117      0x040F    Bielorussian Short U 
  763. ;175     135     209     UNK    UNK      0x0410    Cyrillic Dze 
  764. ;176     128     128     225     97      0x0411    Cyrillic A 
  765. ;177     129     129     226     98      0x0412    Cyrillic Be 
  766. ;178     130     130     247    119      0x0413    Cyrillic Ve 
  767. ;179     131     131     231    103      0x0414    Cyrillic Ghe 
  768. ;180     132     132     228    100      0x0415    Cyrillic De 
  769. ;181     133     133     229    101      0x0416    Cyrillic Ie 
  770. ;182     134     134     246    118      0x0417    Cyrillic Zhe 
  771. ;183     135     135     250    122      0x0418    Cyrillic Ze 
  772. ;184     136     136     233    105      0x0419    Cyrillic I 
  773. ;185     137     137     234    106      0x041A    Cyrillic Short I 
  774. ;186     138     138     235    107      0x041B    Cyrillic Ka 
  775. ;187     139     139     236    108      0x041C    Cyrillic El 
  776. ;188     140     140     237    109      0x041D    Cyrillic Em 
  777. ;189     141     141     238    110      0x041E    Cyrillic En 
  778. ;190     142     142     239    111      0x041F    Cyrillic O 
  779. ;191     143     143     240    112      0x0420    Cyrillic Pe 
  780. ;192     144     144     242    114      0x0421    Cyrillic Er 
  781. ;193     145     145     243    115      0x0422    Cyrillic Es 
  782. ;194     146     146     244    116      0x0423    Cyrillic Te 
  783. ;195     147     147     245    117      0x0424    Cyrillic U 
  784. ;196     148     148     230    102      0x0425    Cyrillic Ef 
  785. ;197     149     149     232    104      0x0426    Cyrillic Ha 
  786. ;198     150     150     227     99      0x0427    Cyrillic Tse 
  787. ;199     151     151     254    126      0x0428    Cyrillic Che 
  788. ;200     152     152     251    123      0x0429    Cyrillic Sha 
  789. ;201     153     153     253    125      0x042A    Cyrillic Shcha 
  790. ;202     154     154     255     39      0x042B    Cyrillic Hard Sign 
  791. ;203     155     155     249    121      0x042C    Cyrillic Yeri 
  792. ;204     156     156     248    120      0x042D    Cyrillic Soft Sign 
  793. ;205     157     157     252    124      0x042E    Cyrillic E 
  794. ;206     158     158     224     96      0x042F    Cyrillic Yu 
  795. ;207     159     159     241    113      0x0430    Cyrillic Ya 
  796. ;208     160     160     193     97      0x0431    Cyrillic a 
  797. ;209     161     161     194     98      0x0432    Cyrillic be 
  798. ;210     162     162     215    119      0x0433    Cyrillic ve 
  799. ;211     163     163     199    103      0x0434    Cyrillic ghe 
  800. ;212     164     164     196    100      0x0435    Cyrillic de 
  801. ;213     165     165     197    101      0x0436    Cyrillic ie 
  802. ;214     166     166     214    118      0x0437    Cyrillic zhe 
  803. ;215     167     167     218    122      0x0438    Cyrillic ze 
  804. ;216     168     168     201    105      0x0439    Cyrillic i 
  805. ;217     169     169     202    106      0x043A    Cyrillic Short i 
  806. ;218     170     170     203    107      0x043B    Cyrillic ka 
  807. ;219     171     171     204    108      0x043C    Cyrillic el 
  808. ;220     172     172     205    109      0x043D    Cyrillic em 
  809. ;221     173     173     206    110      0x043E    Cyrillic en 
  810. ;222     174     174     207    111      0x043F    Cyrillic o 
  811. ;223     175     175     208    112      0x0440    Cyrillic pe 
  812. ;224     224     224     210    114      0x0441    Cyrillic er 
  813. ;225     225     225     211    115      0x0442    Cyrillic es 
  814. ;226     226     226     212    116      0x0443    Cyrillic te 
  815. ;227     227     227     213    117      0x0444    Cyrillic u 
  816. ;228     228     228     198    102      0x0445    Cyrillic ef 
  817. ;229     229     229     200    104      0x0446    Cyrillic ha 
  818. ;230     230     230     195     99      0x0447    Cyrillic tse 
  819. ;231     231     231     222    126      0x0448    Cyrillic che 
  820. ;232     232     232     219    123      0x0449    Cyrillic sha 
  821. ;233     233     233     221    125      0x044A    Cyrillic shcha 
  822. ;234     234     234     223     39      0x044B    Cyrillic hard sign 
  823. ;235     235     235     217    121      0x044C    Cyrillic yeri 
  824. ;236     236     236     216    120      0x044D    Cyrillic soft sign 
  825. ;237     237     237     220    124      0x044E    Cyrillic e 
  826. ;238     238     238     192     96      0x044F    Cyrillic yu 
  827. ;239     239     239     209    113      0x2116    Cyrillic ya 
  828. ;240     252     252     UNK    UNK      0x0451    Number Acronym 
  829. ;241     241     241     197     10      0x0452    Cyrillic io 
  830. ;242     164     221     UNK    UNK      0x0453    Serbocroation dje 
  831. ;243     163     215     UNK    UNK      0x0454    Macedonian gje 
  832. ;244     243     243     UNK    UNK      0x0455    Ukranian ie 
  833. ;245     115     199     115     83      0x0456    Macedonian dze 
  834. ;246     105     190     105     73      0x0457    Cyrillic i 
  835. ;247     245     245     105     73      0x0458    Ukranian yi 
  836. ;248     106     198     106     74      0x0459    Cyrillic je 
  837. ;249     171     249     UNK    UNK      0x045A    Cyrillic lje 
  838. ;250     173     250     UNK    UNK      0x045B    Cyrillic nje 
  839. ;251     231     251     UNK    UNK      0x045C    Serbocroatian chje 
  840. ;252     170     248     203    107      0x00A7    Macedonian kje 
  841. ;253     181     181     UNK    UNK      0x045E    Paragraph sign 
  842. ;254     247     247     213    117      0x045F    Bielorussian short u 
  843. ;255     167     222     UNK    UNK                Cyrillic dze 
  844.  
  845. code1    segment
  846.     extrn    isfile:far,decout:far
  847.     assume    cs:code1
  848. code1    ends
  849.  
  850. code    segment
  851.     extrn    newfn:near,comnd:near
  852.     extrn    ermsg:near,clrfln:far,frpos:near,kbpr:near,perpr:near
  853.  
  854.     assume  cs:code,ds:data,es:nothing
  855.  
  856. ; Set DS:BX to the ISO Latin-1 table appropriate to the
  857. ; currently active Code Page. Defaults to CP437 if no CP found.
  858. LATIN1    proc    near
  859.     push    ax
  860.     mov    ax,seg flags
  861.     mov    DS,ax
  862.     mov    ax,flags.chrset        ; in segment data
  863.     mov    bx,seg L1cp437
  864.     mov    DS,bx            ; set returned DS to table
  865.     mov    bx,offset L1cp437    ; assume CP437
  866.     cmp    ax,437            ; current Code Page is 437?
  867.     je    latin1x            ; e = yes
  868.     mov    bx,offset L1cp850    ; assume CP850
  869.     cmp    ax,850            ; current Code Page is 850?
  870.     je    latin1x            ; e = yes
  871.     mov    bx,offset L1cp860    ; assume CP860
  872.     cmp    ax,860            ; current Code Page is 860?
  873.     je    latin1x            ; e = yes
  874.     mov    bx,offset L1cp861    ; assume CP861
  875.     cmp    ax,861            ; current Code Page is 861?
  876.     je    latin1x            ; e = yes
  877.     mov    bx,offset L2cp852    ; assume CP852
  878.     cmp    ax,852            ; current Code Page is 852?
  879.     je    latin1x            ; e = yes
  880.     mov    bx,offset HIcp862    ; assume CP862
  881.     cmp    ax,862            ; current Code Page is 862?
  882.     je    latin1x            ; e = yes
  883.     mov    bx,offset L1cp863    ; assume CP863
  884.     cmp    ax,863            ; current Code Page is 863?
  885.     je    latin1x            ; e = yes
  886.     mov    bx,offset L1cp865    ; assume CP865
  887.     cmp    ax,865            ; current Code Page is 865?
  888.     je    latin1x            ; e = yes
  889.     mov    bx,offset L5cp866    ; assume CP866
  890.     cmp    ax,866            ; current Code Page is 866?
  891.     je    latin1x            ; e = yes
  892.     mov    bx,offset L1cp437    ; default to CP437
  893. latin1x:pop    ax
  894.     ret
  895. LATIN1    endp
  896.  
  897. ; Call after LATIN1. Revise DS:BX to point to invertible tables rather than
  898. ; readable translation tables. Does not change DS.
  899. latininv proc    near
  900.     push    ax
  901.     push    ds
  902.     mov    ax,seg trans
  903.     mov    ds,ax
  904.     cmp    trans.xchri,0        ; readable (vs invertible)?
  905.     pop    ds
  906.     pop    ax
  907.     je    latinvx            ; e = yes, do nothing
  908.     cmp    bx,offset L1cp437    ; this table in use?
  909.     jne    latinv1            ; ne = no
  910.     mov    bx,offset iL1cp437    ; use invertible instead
  911.     jmp    short latinvx
  912. latinv1:cmp    bx,offset L1cp850    ; this table in use?
  913.     jne    latinv2            ; ne = no
  914.     mov    bx,offset iL1cp850    ; use invertible instead
  915.     jmp    short latinvx
  916. latinv2:cmp    bx,offset L1cp861    ; this table?
  917.     jne    latinvx            ; ne = no
  918.     mov    bx,offset iL1cp861    ; use invertible instead
  919. latinvx:ret
  920. latininv endp
  921.  
  922. ; Set DS:BX to the table for Code Page to ISO 8859-1 Latin1/Latin5
  923. cplatin proc    near
  924.     push    ax
  925.     mov    ax,seg flags
  926.     mov    DS,ax
  927.     mov    ax,flags.chrset
  928.     mov    bx,seg cp437L1
  929.     mov    DS,bx            ; set returned DS to table
  930.     mov    bx,offset cp437L1    ; assume CP437
  931.     cmp    ax,437            ; current Code Page is 437?
  932.     je    cplatx            ; e = yes
  933.     mov    bx,offset cp850L1    ; assume CP850
  934.     cmp    ax,850            ; current Code Page is 850?
  935.     je    cplatx            ; e = yes
  936.     mov    bx,offset cp860L1    ; assume CP860
  937.     cmp    ax,860            ; current Code Page is 860?
  938.     je    cplatx            ; e = yes
  939.     mov    bx,offset cp861L1    ; assume CP861
  940.     cmp    ax,861            ; current Code Page is 861?
  941.     je    cplatx            ; e = yes
  942.     mov    bx,offset cp852L2    ; assume CP852
  943.     cmp    ax,852            ; current Code Page is 852?
  944.     je    cplatx            ; e = yes
  945.     mov    bx,offset cp862HI    ; assume CP862
  946.     cmp    ax,862            ; current Code Page is 862?
  947.     je    cplatx            ; e = yes
  948.     mov    bx,offset cp863L1    ; assume CP863
  949.     cmp    ax,863            ; current Code Page is 863?
  950.     je    cplatx            ; e = yes
  951.     mov    bx,offset cp865L1    ; assume CP865
  952.     cmp    ax,865            ; current Code Page is 865?
  953.     je    cplatx            ; e = yes
  954.     mov    bx,offset cp866L5    ; assume CP866 for LATIN5
  955.     cmp    ax,866            ; corrent Code Page is 866?
  956.     je    cplatx            ; e = yes
  957.     mov    bx,offset cp437L1    ; default to CP437
  958. cplatx:    pop    ax
  959.     ret
  960. cplatin endp
  961.  
  962. ; Call after CPLATIN. Revise DS:BX to point to invertible tables rather than
  963. ; readable translation tables.
  964. cpinvert proc    near
  965.     push    ds
  966.     push    ax
  967.     mov    ax,seg trans
  968.     mov    ds,ax
  969.     cmp    trans.xchri,0        ; readable (vs invertible)?
  970.     pop    ax
  971.     pop    ds
  972.     je    cpinverx        ; e = yes, do nothing
  973.     cmp    bx,offset cp437L1    ; this table in use?
  974.     jne    cpinver1        ; ne = no
  975.     mov    bx,offset icp437L1    ; use invertible instead
  976.     ret
  977. cpinver1:cmp    bx,offset cp850L1    ; this table in use?
  978.     jne    cpinver2        ; ne = no
  979.     mov    bx,offset icp850L1    ; use invertible instead
  980.     ret
  981. cpinver2:cmp    bx,offset cp861L1    ; this table in use?
  982.     jne    cpinverx        ; ne = no
  983.     mov    bx,offset icp861L1    ; use invertible instead
  984. cpinverx:ret
  985. cpinvert endp
  986.  
  987. ; Output the chars in a packet, called only by receiver code.
  988. ; Enter with SI equal to pktinfo structure pointer.
  989. PTCHR:    mov    decoutp,offset outbuf  ; routine to call when buffer gets full
  990.     jmp    short decode
  991.  
  992.  
  993. ; Dodecoding.
  994. ; Decode packet to buffer decbuf. Overflow of decbuf yields error ???
  995. ; Modifies regs BX, CX.
  996. ; Enter with SI equal to pktinfo structure pointer.
  997. dodec    proc    near
  998.     push    ax            ; save reg
  999.     mov    ah,dblbyteflg        ; preserve state
  1000.     mov    al,dblbyte
  1001.     push    ax
  1002.     mov    al,shiftstate
  1003.     mov    ah,DLEseen
  1004.     push    ax
  1005.     mov    dblbyteflg,0        ; init decode as doubles
  1006.     mov    shiftstate,0        ; init shift states
  1007.     mov    DLEseen,0        ; init escape
  1008.     mov    decoutp,offset dnulr    ; routine to dump buffer (null)
  1009.     call    decode
  1010.     pop    ax
  1011.     mov    shiftstate,al        ; restore decoder state
  1012.     mov    DLEseen,ah
  1013.     pop    ax
  1014.     mov    dblbyteflg,ah
  1015.     mov    dblbyte,al
  1016.     push    bx
  1017.     mov    bx,dbufpnt        ; next char position
  1018.     mov    byte ptr [bx],0        ; null terminator
  1019.     pop    bx
  1020.      pop    ax
  1021.     ret
  1022. dodec    endp
  1023.  
  1024. dnulr:    mov    dbufpnt,di         ; point off end of buffer
  1025.     stc                ; fail if needs this
  1026.     ret                ; dummy buffer emptier
  1027.  
  1028. ; Enter with [si].datlen = length of data, [si].datadr = dw address of data,
  1029. ; DECOUTP = pointer to routine which writes output buffer
  1030. ; Returns DBUFPNT = pointer to output buffer address (offset part).
  1031. ; Trans.lshift is non-zero if locking shift encoding is active.
  1032. ; DLEseen is non-zero if a DLE char (Control-P) is decoded while locking shift
  1033. ; is active; under these circumstances DLE escapes DLE, SI, and SO to be
  1034. ; data characters. Under locking shift rules SO (Control-N) shifts high bit
  1035. ; data to non-high bit data (and we thus reverse this); SI (Control-O)
  1036. ; cancels SO.
  1037. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while
  1038. ; performing Japanese translation; dblbyte is the first byte of the pair.
  1039. ; All packets are decoded except I, S, and A types.
  1040. ; Flushes output buffer before returning.
  1041. ; Returns carry clear if success, otherwise carry set
  1042. decode    proc    near
  1043.     push    si
  1044.     push    di
  1045.     push    es
  1046.     push    dx
  1047.     push    ds
  1048.     pop    es
  1049.     cld                ; forward direction
  1050.     mov    dchrcnt,decbuflen    ; size of output buffer
  1051.     mov    dbufpnt,offset decbuf ; decoded data placed here pending output
  1052.     mov    decbuf,0        ; nothing written yet
  1053.     mov    cx,[si].datlen        ; length of source buffer data
  1054.     les    si,[si].datadr        ; source buffer address to es:[si]
  1055.     mov    di,dbufpnt        ; destination of data
  1056.     mov    bl,trans.squote        ; regular quote char
  1057.     xor    dh,dh            ; assume no quote char
  1058.     cmp    trans.ebquot,'N'    ; any 8-bit quoting?
  1059.     je    decod1            ; e = no quoting
  1060.     cmp    trans.ebquot,'Y'    ; or not doing it?
  1061.     je    decod1            ; e = no need to quote
  1062.     mov    dh,trans.ebquot        ; otherwise use 8-bit quote char
  1063.  
  1064. decod1:    mov    rptct,1            ; reset repeat count
  1065.     or    cx,cx            ; any more chars in source?
  1066.     jg    decod2            ; g = yes
  1067.     jmp    decod6            ; else, we're through
  1068. decod2:    mov    al,es:[si]        ; pick up a char
  1069.     inc    si
  1070.     dec    cx            ; count number left
  1071.     cmp    al,trans.rptq        ; repeat quote char?
  1072.     jne    dcod2a            ; ne = no, continue processing it
  1073.     mov    al,es:[si]        ; get the size
  1074.     inc    si
  1075.     dec    cx            ; modify buffer count
  1076.     sub    al,20H            ; make count numeric
  1077.     mov    rptct,al        ; remember how many repetitions
  1078.     mov    al,es:[si]        ; get the char to repeat
  1079.     inc    si
  1080.     dec    cx            ; modify buffer count
  1081.  
  1082. dcod2a:    xor    ah,ah            ; assume no 8-bit quote char
  1083.     cmp    al,dh            ; is this the 8-bit quot char?
  1084.     jne    decod3            ; ne = no
  1085.     mov    al,es:[si]        ; yes, get the real character
  1086.     inc    si
  1087.     dec    cx            ; decrement # chars in packet
  1088.     mov    ah,80H            ; turn on high bit
  1089. decod3:    cmp    al,bl            ; quote char?
  1090.     jne    decod4            ; ne = no, proceed
  1091.     mov    al,es:[si]        ; get the quoted character
  1092.     inc    si
  1093.     dec    cx            ; decrement # of chars in packet
  1094.     or    ah,al            ; save parity (combine with prefix)
  1095.     and    ax,807fh        ; only parity in ah, remove it in al
  1096.     cmp    al,bl            ; quote char?
  1097.     je    decod4            ; e = yes, just go write it out
  1098.     cmp    al,dh            ; 8-bit quote char?
  1099.     je    decod4            ; e = yes, just go write it out
  1100.     cmp    trans.rptq,0        ; disabled repeat quoting?
  1101.     je    decod3a            ; e = yes, disabled
  1102.     cmp    al,trans.rptq        ; repeat quote character?
  1103.     je    decod4            ; e = yes, just write it out
  1104. decod3a:cmp    al,3fh            ; char less than '?' ?
  1105.     jb    decod4            ; b = yes; leave it intact
  1106.     cmp    al,5fh            ; char greater than '_' ?
  1107.     ja    decod4            ; a = yes; leave it alone
  1108.     add    al,40H            ; make it a control char again
  1109.     and    al,7FH            ; modulo 128 (includes DEL)
  1110. decod4:    xor    ah,shiftstate        ; modify high bit by shiftstate
  1111.         or    al,ah            ; or in parity
  1112.  
  1113.     cmp    trans.lshift,lock_disable ; locking shift disabled?
  1114.     je    decod5            ; e = yes
  1115.     mov    ah,al
  1116.     xor    ah,shiftstate        ; adjust high bit by shift state
  1117.     cmp    ah,DLE            ; DLE?
  1118.     jne    dcod4c            ; ne = no
  1119.     cmp    DLEseen,0        ; has DLE been escaped (by DLE)?
  1120.     je    dcod4b            ; e = no, make this the escape
  1121.     mov    DLEseen,0        ; unescape now
  1122.     jmp    short decod5        ; process the literal DLE
  1123.                     ; handle repeat counted DLE's
  1124. dcod4b:    shr    rptct,1            ; divide by two, carry has lsb
  1125.     rcl    DLEseen,1        ; pickup carry bit if odd number
  1126.     jmp    short decod5        ; write the DLE's
  1127.  
  1128. dcod4c:    cmp    DLEseen,0        ; DLE prefix seen?
  1129.     mov    DLEseen,0        ; clear it now too
  1130.     jne    decod5            ; ne = yes, prefixed, do literal
  1131.     cmp    ah,SIchar        ; SI?
  1132.     jne    dcod4d            ; ne = no
  1133.     mov    shiftstate,0        ; say exiting shifted state
  1134.     jmp    decod1            ; nothing to write
  1135. dcod4d:    cmp    ah,SOchar        ; SO?
  1136.     jne    decod5            ; ne = no
  1137.     mov    shiftstate,80h        ; say entering shifted state
  1138.     jmp    decod1            ; nothing to write
  1139.  
  1140. decod5:    push    cx
  1141.     mov    cl,rptct        ; repeat count
  1142.     xor    ch,ch
  1143.     or    cl,cl
  1144.     jle    decod5c            ; le = nothing to do (94 max)
  1145.     cmp    cx,dchrcnt        ; needed vs space available
  1146.     jbe    decod5a            ; be = enough space for rptct chars
  1147.     mov    cx,dchrcnt        ; insufficient space, do dchrcnt
  1148. decod5a:sub    rptct,cl        ; reduce number left to be written
  1149.     sub    dchrcnt,cx        ; reduce output free space
  1150.     pushf                ; save sub status flags
  1151.     shr    cx,1
  1152.     jnc    decod5b            ; nc = an even number
  1153.     mov    [di],al            ; store the odd byte
  1154.     inc    di
  1155.     jcxz    decod5d            ; z = nothing else to write
  1156. decod5b:mov    ah,al            ; make a copy for word writes
  1157.     push    bx            ; source is es:[si], dest is ds:[di]
  1158.     push    es            ; save and swap ds and es
  1159.     push    ds
  1160.     mov    bx,es
  1161.     pop    es            ; old ds to es
  1162.     push    ds            ; restore
  1163.     mov    ds,bx            ; old es to ds
  1164.     rep    stosw            ; store cx words
  1165.     pop    ds
  1166.     pop    es
  1167.     pop    bx
  1168. decod5d:popf                ; recover flags from sub dchrcnt,cx
  1169.     jg    decod5c            ; g = space remaining in output buffer
  1170.     push    dx            ; flush output buffer
  1171.     push    bx
  1172.     push    ax            ; save the char
  1173.     push    es
  1174.     call    decoutp            ; output the buffer
  1175.     pop    es
  1176.     pop    ax            ; recover repeated char
  1177.     pop    bx
  1178.     pop    dx
  1179.     jc    decod7            ; c = error if disk is full
  1180.     mov    di,dbufpnt
  1181.     pop    cx
  1182.     jmp    short decod5        ; see if more chars need be written
  1183. decod5c:pop    cx            ; recover main loop counter
  1184.     jmp    decod1            ; get next source character
  1185.     
  1186. decod6:    mov    dbufpnt,di            ; flush buffer before exiting decode
  1187.     push    cx
  1188.     push    es
  1189.     call    decoutp            ; flush output buffer before final ret
  1190.     pop    es
  1191. decod7:    pop    cx
  1192.  
  1193.     pop    dx
  1194.     pop    es
  1195.     pop    di
  1196.     pop    si
  1197.     ret                ; return successfully if carry clear
  1198. decode    endp
  1199.  
  1200. outbuf    proc    near            ; output decbuf, reset bufpnt & chrcnt
  1201.     mov    cx,decbuflen        ; get full size of buffer
  1202.     sub    cx,dchrcnt        ; minus space remaining = # to write
  1203.     jg    outbu2            ; g = something to do
  1204.     jmp    outbf1
  1205. outbu2:    mov    dx,offset decbuf    ; address of buffer
  1206.     cmp    trans.xtype,1        ; File Type Binary?
  1207.     je    outbu5            ; e = yes, no translation
  1208.     cmp    flags.destflg,dest_disk    ; disk destination?
  1209.     je    outbu5            ; e = yes, DOS will do it
  1210.     cmp    flags.eofcz,0        ; end on Control-Z?
  1211.     je    outbu5            ; e = no
  1212.     push    cx            ; else map Control-Z to space
  1213.     push    di
  1214.     mov    di,seg decbuf
  1215.     mov    es,di            ; data to es
  1216.     mov    di,dx            ; scan buffer es:di, cx chars worth
  1217.     mov    al,ctlz            ; look for Control-Z
  1218.     cld
  1219. outbu3:    repne    scasb
  1220.     jne    outbu4            ; ne = found no Control-Z's
  1221.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  1222.     jcxz    outbu4            ; z = examined all chars
  1223.     jmp    short outbu3        ; until examined everything
  1224. outbu4:    pop    di
  1225.     pop    cx
  1226.                     ; Character set translation section
  1227. outbu5:    cmp    trans.xtype,1        ; File Type Binary?
  1228.     je    outbu7            ; e = yes, no translation
  1229.     cmp    trans.xchset,xfr_xparent ; Transfer Transparent?
  1230.     je    outbu7            ; e = yes, no translation
  1231.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1232.     jne    outbu5a            ; ne = no
  1233.     call    jpnwrite        ; do special decoding
  1234.     jmp    outbu7
  1235. outbu5a:push    cx
  1236.     push    di
  1237.     push    es
  1238.     PUSH    DS
  1239.     call    latin1            ; set DS:BX to xfr char set to CP table
  1240.     call    latininv        ; select invertable or readable set
  1241.     mov    di,seg decbuf
  1242.     mov    es,di
  1243.     mov    di,offset decbuf    ; scan this buffer
  1244.     cld
  1245. outbu6:    mov    al,es:[di]        ; get a char, keep pointer fixed
  1246.     test    al,80h            ; GRight?
  1247.     jnz    outbu6a            ; nz = yes
  1248.     cmp    bx,offset iL1cp437    ; using invertable Latin1 to CP437?
  1249.     jne    outbu6c            ; ne = no
  1250.     cmp    ah,127            ; 127 goes to 28?
  1251.     jne    outbu6e            ; ne = no
  1252.     mov    al,28            ; 127 to 28
  1253.     jmp    short outbu6b
  1254. outbu6e:cmp    al,21            ; special case?
  1255.     ja    outbu6b            ; a = no
  1256.     cmp    al,20            ; special case?
  1257.     jb    outbu6b            ; b = no
  1258.     mov    ah,al
  1259.     mov    al,244            ; 20 to 244
  1260.     cmp    ah,21            ; special case?
  1261.     jne    outbu6b            ; ne = no
  1262.     mov    al,245            ; preset one answer
  1263.     je    outbu6b            ; e = yes, 21 to 245
  1264.     mov    al,244            ; 22 to 244
  1265.     jmp    short outbu6b
  1266. outbu6c:cmp    bx,offset iL1cp850    ; using invertible Latin1 to CP850?
  1267.     jne    outbu6b            ; ne = no
  1268.     cmp    al,26            ; special case?
  1269.     jne    outbu6d            ; ne = no
  1270.     mov    al,127            ; 26 to 127
  1271.     jmp    outbu6b
  1272. outbu6d:cmp    al,127            ; special case?
  1273.     jne    outbu6b            ; ne = no
  1274.     mov    al,28            ; 127 to 28
  1275.     jmp    short outbu6b
  1276. outbu6a:and    al,not 80h        ; strip high bit
  1277.     xlatb                ; translate via bx table
  1278. outbu6b:stosb                ; store char
  1279.     loop    outbu6            ; do all concerned
  1280.     POP    DS
  1281.     pop    es
  1282.     pop    di
  1283.     pop    cx
  1284.  
  1285. outbu7:    push    bx
  1286.     mov    bx,diskio.handle    ; file handle
  1287.     or    bx,bx
  1288.     jle    outbf0            ; le = illegal handle, fail
  1289.     mov    ah,write2        ; write cx bytes
  1290.     int    dos
  1291.     pop    bx
  1292.     jc    outbf0            ; c set means writing error
  1293.     cmp    ax,cx            ; did we write all the bytes?
  1294.     je    outbf1            ; e = yes
  1295.     push    bx
  1296.     mov    bx,offset decbuf
  1297.     add    bx,ax            ; look at break character
  1298.     cmp    byte ptr [bx],ctlz    ; ended on Control-Z?
  1299.     pop    bx
  1300.     je    outbf1            ; e = yes, say no error
  1301.  
  1302. outbf0: mov    dx,offset erms13    ; Error writing device
  1303.     cmp    flags.xflg,0        ; writing to screen?
  1304.     jne    outbf0a            ; ne = yes
  1305.     cmp    flags.destflg,dest_printer ; writing to printer?
  1306.     jne    outbf0a            ; ne = no
  1307.     mov    dx,offset ermes9    ; Printer not ready message
  1308. outbf0a:call    ermsg
  1309.     stc                ; return failure
  1310.     ret
  1311.  
  1312. outbf1:    add    tfilsz,cx        ; count received chars
  1313.     adc    tfilsz+2,0
  1314.     add    fsta.frbyte,cx
  1315.     adc    fsta.frbyte+2,0
  1316.     test    flags.remflg,dserial    ; serial mode display?
  1317.     jnz    outb11            ; nz = yes, skip kbyte and % displays
  1318.     cmp    flags.xflg,0        ; receiving to screen?
  1319.     jne    outb11            ; ne = yes
  1320.     call    kbpr            ; display kilobytes done
  1321.     call    perpr            ; display percentage done
  1322. outb11:    mov    dbufpnt,offset decbuf    ; address for beginning
  1323.     mov    dchrcnt,decbuflen    ; size of empty buffer
  1324.     clc                ; return success
  1325.     ret
  1326. outbuf    endp
  1327.  
  1328. ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp)
  1329. ; Reread buffer decbuf to convert from transfer character set
  1330. ; Japanese-EUC into Shift-JIS (Code Page 932). Double char translation state
  1331. ; is maintained across file buffers. Init dblbyte to 0 before each new file.
  1332. ; Returns registers
  1333. ;    cx      number of bytes written in the buffer
  1334. ;    dx      address of the output buffer
  1335. ;            this points decbuf or decbuf-1, depending on dblbyteflg
  1336. ; Output is otherwise written over the input. [rewritten by jrd]
  1337. jpnwrite proc    near            ; [HF] write Japanese to file
  1338.     push    si            ; decbuf is read/written
  1339.     push    di            ; cx has incoming/outgoing byte count
  1340.     push    bx            ; dblbyte has earlier first byte
  1341.     push    es            ; dblbyteflg is state from prev call
  1342.     mov    dx,ds
  1343.     mov    es,dx
  1344.     cld                ; restore state from previous call
  1345.     mov    dl,dblbyteflg        ; state, non-zero if doing second byte
  1346.     mov    ah,dblbyte        ;  and first byte from previous read
  1347.     mov    si,offset decbuf    ; read/write this buffer
  1348.     mov    di,si            ; set the address for write
  1349.     mov    bx,si            ; save for computing output buf length
  1350.     or    dl,dl            ; carry-in of a double byte char?
  1351.     jz    jpnwri1            ; z = no
  1352.     dec    di            ; start output one byte before decbuf
  1353.     dec    bx            ; adjust the start address
  1354. jpnwri1:lodsb                ; get a byte
  1355.     or    dl,dl            ; processing 2nd byte of a pair?
  1356.     jnz    jpnwri3            ; nz = yes, do second byte processor
  1357.                     ; first byte processor
  1358.     cmp    al,80h            ; 8th bit on?
  1359.     jb    jpnwri5            ; b = no, this is a single char
  1360.     cmp    al,8eh            ; JIS X 0201 Katakana prefix?
  1361.     je    jpnwri2            ; e = yes, is first of two chars
  1362.     cmp    al,0a1h            ; JIS X 0208 Kanji ?
  1363.     jb    jpnwri5            ; b = no, is single char
  1364.     cmp    al,0feh
  1365.     ja    jpnwri5            ; a = no, is single char
  1366. jpnwri2:mov    ah,al            ; save first of two chars
  1367.     mov    dl,1            ; say need second char of pair
  1368.     jmp    short jpnwri6        ; read second byte
  1369.                     ; process second char of two byte pair
  1370. jpnwri3:cmp    ah,8eh            ; was first char JIS X 0201 Katakana?
  1371.     jne    jpnwri4            ; ne = no
  1372.     or    al,80h            ; make sure 8th bit is on
  1373.     jmp    short jpnwri5        ; write one char
  1374. jpnwri4:call    jpnxtof            ; xfer -> file char code conversion
  1375.     xchg    ah,al
  1376.     stosb                ; write first byte
  1377.     xchg    ah,al            ; and second byte
  1378. jpnwri5:stosb                ; write a char
  1379.     xor    dl,dl            ; clear multi-byte counter
  1380. jpnwri6:loop    jpnwri1
  1381.     mov    dblbyteflg,dl        ; save state info
  1382.     mov    dblbyte,ah        ; and the first byte of a pair
  1383.     sub    di,bx            ; find number of chars written
  1384.     mov    cx,di            ; return new count in CX
  1385.     mov    dx,bx            ; return new buffer address for write
  1386.     pop    es            ; can be decbuf - 1 if carry-in of dbl
  1387.     pop    bx
  1388.     pop    di
  1389.     pop    si
  1390.     clc
  1391.     ret
  1392. jpnwrite endp
  1393.  
  1394. ; Transfer character code (EUC) to file character code (Shift-JIS) converter.
  1395. ; input      AH: 1st byte of EUC code
  1396. ;            AL: 2nd byte of EUC code
  1397. ; output     AH: 1st byte of Shift-JIS code
  1398. ;            AL: 2nd byte of Shift-JIS code
  1399. ; From EUC to Shift-JIS
  1400. ;   code1 = (EUC_code1 & 0x7f);
  1401. ;   code2 = (EUC_code2 & 0x7f);
  1402. ;   if( code1 & 1)
  1403. ;     code2 += 0x1f;
  1404. ;   else
  1405. ;     code2 += 0x7d;
  1406. ;   if( code2 >= 0x7f ) code2++;
  1407. ;   code1 = ((code1 - 0x21) >> 1) + 0x81;
  1408. ;   if( code1 > 0x9f ) code1 += 0x40;
  1409. ;   [ fputc( code1, file ); fputc( code2, file ); ]
  1410. ;
  1411. jpnxtof    proc    near
  1412.     and    ax,7f7fh        ; mask both 8-th bits
  1413.     test    ah,1
  1414.     jz    jpnxtof1
  1415.     add    al,1fh
  1416.     jmp    short jpnxtof2
  1417. jpnxtof1:add    al,7dh
  1418. jpnxtof2:cmp    al,7fh
  1419.     jb    jpnxtof3
  1420.     inc    al
  1421. jpnxtof3:sub    ah,21h
  1422.     shr    ah,1
  1423.     add    ah,81h
  1424.     cmp    ah,9fh
  1425.     jbe    jpnxtof4
  1426.     add    ah,40h
  1427. jpnxtof4:ret
  1428. jpnxtof    endp
  1429.  
  1430. ; Get chars from file, encode them to pktinfo structure pointed to by si
  1431.  
  1432. gtchr:    mov    [si].datlen,0        ; say no output data yet
  1433.     cmp    filflg,0        ; is there anything in the buffer?
  1434.     jne    gtchr0            ; ne = yes, use that material first
  1435.     call    inbuf            ; do initial read from source
  1436.     jc    gtchr1            ; c = no more chars, go return EOF
  1437. gtchr0:    mov    encinp,offset inbuf    ; buffer refiller routine
  1438.     jmp    short encode
  1439.  
  1440. gtchr1:    mov    [si].datlen,0        ; report EOF
  1441.     mov    flags.eoflag,1        ; say eof
  1442.     stc                ; return failure
  1443.     ret
  1444.  
  1445. ; Kermit encoding rules:
  1446. ; Prefix codes per se are sent as <control prefix, #><data byte>
  1447. ; C0 and C1 control codes are prefixed by <control prefix, #><data byte>
  1448. ; 8th bit set prefixing is <8th bit prefix, &><composite byte>
  1449. ;  where composite byte is <control prefix><data byte>
  1450. ; Run length encoding is <rle prefix, ~><count><composite byte>
  1451. ;  where composite byte is <8th bit prefix><control prefix><data byte>
  1452. ; So far the maximum transmitted size of any raw byte is three bytes, 
  1453. ; and a run of them is six bytes.
  1454. ;
  1455. ; Locking shifts, applies only if locking shifts have been negotiated.
  1456. ; Data whose lower seven bits are DLE, SI, SO data are sent as other C0/C1
  1457. ; codes, but they are preceeded by DLE. Such pairs of control codes are
  1458. ; subject to control code prefixing (#) and 8th bit prefixing (&); runs
  1459. ; of them are preceeded by the <rle prefix><count> byte pair.
  1460. ; Control SO locks on implication of 8th bit set on all following data,
  1461. ; and that data is sent without the 8th bit set.
  1462. ; Control SI unlocks SO shift.
  1463. ; DLE, SI, and SO shift controls are sent as bare control codes, unencoded.
  1464. ; A single shift operation is used when appropriate to change the state
  1465. ;  of implied 8th bit value (set or reset). The 8th bit prefix character
  1466. ;  is used as a prefix to denote: change the 8th bit from the current state
  1467. ;  to the opposite value for the following data byte only.
  1468. ;
  1469. ;The Control Prefix
  1470. ;   For transparency on serial communication links that are sensitive to
  1471. ;   control characters, the file sender precedes each C0 and C1 control with
  1472. ;   the control prefix, normally "#" (ASCII 35), and then encodes the control
  1473. ;   character itself by "exclusive-ORing" it with 64 decimal (i.e. inverting
  1474. ;   bit 6) to produce a character in the printable ASCII range.  For example,
  1475. ;   Control-C (ASCII 3) becomes "#C" (3 XOR 64 = 67, which is the ASCII code
  1476. ;   for the letter C).  Similarly, NUL becomes "#@", Control-A becomes "#A",
  1477. ;   Control-Z becomes "#Z", Escape becomes "#[", and DEL becomes "#?".  The
  1478. ;   receiver decodes by discarding the prefix and XORing the character with
  1479. ;   64 again.  For example, in "#C", C = ASCII 67, and 67 XOR 64 = 3 =
  1480. ;   Control-C.  Control prefixing is mandatory.  The control prefix is also
  1481. ;   used for quoting prefix characters that occur in the data itself; see
  1482. ;   "The Prefix Quote" below.
  1483. ;
  1484. ;The 8th-bit Prefix
  1485. ;   When one or both of the two Kermit programs knows that the connection
  1486. ;   between them is not transparent to the 8th bit (e.g. because the Kermit
  1487. ;   PARITY variable is not NONE, or because the program always operates that
  1488. ;   way), a feature called "8th-bit prefixing" is used if the two Kermit
  1489. ;   programs negotiate an agreement to do so.  The 8th-bit prefix is Kermit's
  1490. ;   single shift, normally the ampersand character "&" (ASCII 38).  When the
  1491. ;   file sender encounters an 8-bit character, it inserts the "&" prefix in
  1492. ;   front of it, and then inserts the data character itself with its 8th bit
  1493. ;   set to 0.  If the data character is a control character, it is inserted
  1494. ;   after the 8th-bit prefix in control-prefixed form.  Examples: an "A" with
  1495. ;   its 8th bit set to 1 ("<1>A") becomes "&A"; a Control-A with its 8th bit
  1496. ;   set to 1 ("<1><SOH>") becomes "&#A".
  1497. ;
  1498. ;The Repeat-Count Prefix
  1499. ;   The repeat-count prefix provides a simple form of data compression.  It
  1500. ;   is used only when both Kermit programs support this feature and agree to
  1501. ;   use it.  This prefix, normally tilde "~" (ASCII 126), precedes a repeat
  1502. ;   count, which can range from 0 to 94.  The repeat count is encoded as a
  1503. ;   printable ASCII character in the range SP (32) - tilde (126) by adding
  1504. ;   32.  For example, a series of 36 G's would be encoded as "~DG" (D = ASCII
  1505. ;   68 - 32 = 36).  The repeat-count prefix applies to the following prefixed
  1506. ;   sequence, which may be a single character ("~DG"), an 8th-bit prefixed
  1507. ;   character ("~D&G" = 36 Control-G characters with their 8th bits set to
  1508. ;   1), a control-prefixed character ("~D#M" = 36 Control-M's), or an
  1509. ;   8th-bit-and-control-prefixed character ("~~&#Z" = 94 Control-Z's with
  1510. ;   their 8th bits set to 1).
  1511. ;
  1512. ;The Prefix Quote
  1513. ;   The control prefix, normally "#", is also used to quote the control
  1514. ;   prefix itself if it occurs in the data: "##", meaning that the "#"
  1515. ;   character should be taken literally.  If 8th-bit prefixing is in effect,
  1516. ;   the control prefix also quotes the 8th-bit prefix: "#&", so "#&D" stands
  1517. ;   for "&D" rather than "<1>D".  If repeat count prefixing is in effect, the
  1518. ;   control prefix is also used to quote the repeat count prefix: "#~", so
  1519. ;   "#~CG" stands for "~CG" rather than 35 "G" characters.  So the complete
  1520. ;   meaning of the "#" prefix is: if the value of the following character is
  1521. ;   77, 64-95, 192-223 or 205, the prefixed character is to be XORed with 64,
  1522. ;   otherwise it is to be taken literally.  The prefix quote can also be used
  1523. ;   harmlessly to quote 8th-bit or repeat-count prefixing characters even
  1524. ;   when these types of prefixing are not in effect.
  1525. ;
  1526. ;  Examples, using notation of <high bit><lower 7 bits>:
  1527. ;
  1528. ;  Original data stream
  1529. ;  <0>A<0>B<0>C<1>D<1>E<1>F<1>G<1>H<1>I<0>J<0>K<0>L<0>M  (13 characters)
  1530. ;  would be transmitted like this with single shifts:
  1531. ;  &A&B&C&D&E&F&G&H&I&J&K&L&M                            (26 characters)
  1532. ; and like this with locking shifts:
  1533. ;   ABC<SO>DEFGHI<SI>JKLM                                 (15 characters)
  1534. ; On an 8-bit connection, of course, this string of characters can be
  1535. ; transmitted as-is, with no overhead at all.
  1536. ;
  1537. ; Now suppose we have the following character sequence:
  1538. ;  <1>A<1>B<1>C<0>D<1>E<1>F<1>G<0>H<1>I<1>J<1>K<0>L<1>M  (13 characters)
  1539. ; Several isolated 7-bit characters are found in the middle of a long run
  1540. ; of 8-bit characters. Using locking shifts alone, this would be encoded as:
  1541. ; <SO>ABC<SI>D<SO>EFG<SI>H<SO>IJK<SI>L<SO>M              (20 characters)
  1542. ; But using a combination of locking and single shifts, it can be encoded more
  1543. ; compactly, as in this example, in which "&" is the single-shift character:
  1544. ; <SO>ABC&DEFG&HIJK&LM                                   (17 characters)
  1545. ;
  1546. ;
  1547.  
  1548. ; Do encoding.
  1549. ; Enter with CX = data size, source of data is encbuf, si is pktinfo ptr.
  1550. ; Writes output to area pointed to by [si].datadr.
  1551. ; Returns char count in cx and [si].datlen with carry clear if success,
  1552. ; else carry set if overflow.
  1553. ; SI is preserved
  1554. doenc:    clc
  1555.     jcxz    doen0            ; cx = 0 means nothing to encode
  1556.     mov    ah,dblbyteflg        ; preserve state
  1557.     mov    al,dblbyte
  1558.     push    ax
  1559.     mov    al,shiftstate        ; locking shift state
  1560.     mov    ah,DLEseen        ; DLE state
  1561.     push    ax            ; save
  1562.     mov    dblbyteflg,0        ; init encode as doubles
  1563.     mov    shiftstate,0        ; init shift states
  1564.     mov    DLEseen,0
  1565.     mov    echrcnt,cx        ; number of bytes of source data
  1566.     mov    ebufpnt,offset encbuf    ; source of data
  1567.     mov    encinp,offset nulref    ; null routine for refilling buffer
  1568.     call    encode            ; make a packet with size in AX
  1569.     mov    cx,ax
  1570.     pop    ax            ; restore state
  1571.     mov    shiftstate,al
  1572.     mov    DLEseen,ah
  1573.     pop    ax
  1574.     mov    dblbyteflg,ah
  1575.     mov    dblbyte,al
  1576. doen0:    ret
  1577.  
  1578. nulref:    mov    echrcnt,0        ; no data to return
  1579.     stc
  1580.     ret
  1581.  
  1582. ; encode - writes data portion of kermit packet into [[si].datadr].
  1583. ; expects encinp to contain the address of a routine to refill the buffer,
  1584. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  1585. ; the maximum size of the data packet, ebufpnt to contain a pointer to
  1586. ; the source of the characters, and [si].datadr to be output address.
  1587. ; Trans.lshift is non-zero if locking shift encoding is active.
  1588. ; While locking shift is active DLE escapes DLE, SI, and SO to be
  1589. ; data characters. Under locking shift rules SO (Control-N) shifts high bit
  1590. ; data to non-high bit data; SI (Control-O) cancels SO. Shiftstate is
  1591. ; 0 for non-shifted state, 80h for shifted state.
  1592. ; Dblbyteflg is non-zero if the first of a byte pair has been obtained while
  1593. ; performing Japanese translation; dblbyte is the first byte of the pair.
  1594. ; Returns: AX = the number of characters actually written to the buffer
  1595. ; All packets except I, S, and A types are encoded.
  1596. ; Packet space is precomputed allowing for prefixes other than locking shifts.
  1597. ; Returns carry clear for success, carry set otherwise.
  1598.  
  1599. encode    proc    near
  1600.     push    es
  1601.     push    si            ; save caller's si
  1602.     mov    cx,trans.maxdat        ; maximum packet size
  1603.     cmp    cx,[si].datsize        ; buffer capacity of this slot
  1604.     jbe    encod1            ; be = not overflowing slot
  1605.     mov    cx,[si].datsize        ; use smaller pkt buffer
  1606. encod1:    les    di,[si].datadr        ; address of output buffer to es:[di]
  1607.     mov    temp,di            ; remember output buffer start address
  1608.     mov    si,ebufpnt        ; pointer into source buffer
  1609.     mov    dl,trans.rquote        ; send quote char
  1610.     xor    dh,dh            ; assume no 8-bit quoting
  1611.     mov    al,trans.ebquot        ; 8-bit quote
  1612.     cmp    al,'N'            ; refusing 8-bit quoting?
  1613.     je    encod10            ; e = yes
  1614.     cmp    al,'Y'            ; or can but won't?
  1615.     je    encod10            ; e = yes, else specific char
  1616.     mov    dh,0ffh            ; remember we have to do 8-bit quotes
  1617.                     ; top of read loop
  1618. encod10:or    cx,cx            ; any space left in output buffer?
  1619.     jg    encod11            ; g = yes
  1620.     mov    ax,di            ; current output location
  1621.     sub    ax,temp            ; minus start of buffer, ret cnt in AX
  1622.     mov    ebufpnt,si        ; update pointer into source buffer
  1623.     pop    si            ; restore caller's si
  1624.     pop    es
  1625.     mov    [si].datlen,ax
  1626.     clc                ; success
  1627.     ret
  1628.  
  1629. encod11:cmp    echrcnt,0        ; any data in buffer?
  1630.     jg    encod20            ; g = yes, skip over buffer refill
  1631.     push    es
  1632.     call    encinp            ; get another buffer full
  1633.     pop    es
  1634.     jnc    encod14            ; nc = success
  1635.  
  1636. encod12:pop    si            ; restore user's si
  1637.     sub    di,temp            ; minus start of buffer
  1638.     or    di,di            ; buffer empty?
  1639.     jz    encod13            ; z = yes
  1640.     mov    ax,di            ; report size encoded
  1641.     mov    [si].datlen,ax
  1642.     pop    es
  1643.     clc                ; success
  1644.     ret                ; return success
  1645. encod13:xor    ax,ax            ; empty buffer
  1646.         mov    flags.eoflag,1        ; set eof flag
  1647.     mov    filflg,al        ; nothing in input buffer
  1648.     mov    [si].datlen,ax
  1649.     pop    es
  1650.     stc                ; failure
  1651.     ret                ; return failure
  1652.  
  1653. encod14:mov    si,ebufpnt        ; update position in source buffer
  1654.     cmp    echrcnt,0         ; any characters returned?
  1655.     je    encod12            ; e = none, assume eof
  1656.  
  1657. encod20:cld                ; forward direction
  1658.     lodsb
  1659.     dec    echrcnt            ; decrement input count
  1660.     mov    ah,al
  1661.     and    ah,80h            ; keep high bit in ah
  1662.     mov    rptct,1            ; say have one copy of this char
  1663.     cmp    al,'Z'-40H        ; is this a control-Z?
  1664.     jne    encd30            ; ne = no, skip eof-processing
  1665.     cmp    flags.eofcz,0           ; is a Control-Z an end of file?
  1666.     je    encd30            ; e = no
  1667.     cmp    trans.xtype,1        ; file type binary?
  1668.     je    encd30            ; e = yes, send as is
  1669.     mov    flags.eoflag,1        ; yes, set eof flag
  1670.     mov    filflg,0        ; say no more source data in buffer
  1671.     mov    echrcnt,0        ; ditto
  1672.     jmp    short encod12        ; set character count and return
  1673.  
  1674.                     ; analyze current char (al)
  1675. encd30:    cmp    echrcnt,0        ; doing the last character?
  1676.     jle    encod40            ; le = yes, there is no next character
  1677.     or    cx,cx            ; space for repeat group in output?
  1678.     jle    encod40a        ; le = no, not enough for rpt prefix
  1679.     cmp    al,[si]            ; this is char the same as the next?
  1680.     jne    encod40            ; no, do this char independently
  1681.     cmp    trans.rptq,0        ; repeat prefixing disabled?
  1682.     je    encod40            ; e = yes
  1683.     push    cx            ; scan for repeats in input buffer
  1684.     push    bx
  1685.     mov    cx,echrcnt        ; count of bytes left in input buf
  1686.     inc    cx            ; will reread current byte
  1687.     cmp    cx,94            ; max prefix of 94
  1688.     jbe    encod31            ; be = ok, else limit scan to 94
  1689.     mov    cx,94
  1690. encod31:xor    bx,bx            ; count of copies of this char in buf
  1691. encod32:inc    bx
  1692.     cmp    [si+bx-1],al        ; new [si+bx-1] same as current (al)?
  1693.     loope    encod32            ; e = yes, do all of interest
  1694.     cmp    bx,3            ; enough repeats to use prefix?
  1695.     jae    encod33            ; ae = yes
  1696.     mov    bx,1            ; say do one char
  1697. encod33:mov    rptct,bl        ; bl is qty repeated overall
  1698.     dec    bx            ; bx = number of extra chars (>1)
  1699.     add    si,bx            ; move forward by repeat group
  1700.     sub    echrcnt,bx        ; adjust input buffer counter too
  1701.     pop    bx
  1702.     pop    cx
  1703.  
  1704.                     ; test for locking shift applicability
  1705. encod40:cmp    cx,2            ; space left for prefixed lock?
  1706.     jb    encod50            ; b = no, not enough for prefix
  1707.     cmp    trans.lshift,lock_disable ; locking shifts disabled?
  1708.     je    encod50            ; e = yes, skip this material
  1709.     cmp    ah,shiftstate        ; change of high bit status?
  1710.     jne    encod41            ; ne = yes
  1711. encod40a:jmp    encod50            ; no, stay in same lock state
  1712.                     ; change of high bit
  1713. encod41:mov    bx,echrcnt        ; count chars remaining to be read
  1714.     add    bl,rptct        ; add repeat count
  1715.     adc    bh,0
  1716.     cmp    bx,4            ; at least 4 more chars to examine?
  1717.     jb    encod50            ; b = no, not worth a lock change
  1718.     cmp    rptct,4            ; enough repeats to take short cut?
  1719.     jae    encod43            ; ae = plenty of repeats
  1720.     push    ax            ; look for change of shift state
  1721.     push    cx
  1722.     push    si
  1723.     mov    cl,rptct        ; repeat count
  1724.     xor    ch,ch
  1725.     dec    cx            ; count is one for no repeats
  1726.     sub    si,cx            ; back up over repeated chars
  1727.     mov    cx,4            ; look ahead 4 chars
  1728. encod42:lodsb                ; read ahead
  1729.     and    al,80h            ; pick out high bit
  1730.     cmp    al,ah            ; high bit the same?
  1731.     loope    encod42            ; loop while same
  1732.     pop    si
  1733.     pop    cx
  1734.     pop    ax
  1735.     jne    encod50            ; ne = differ, don't change lock
  1736.                     ; change locking shift state
  1737. encod43:mov    es:[di],dl        ; insert quote char (#)
  1738.     inc    di            ; adjust output buffer pointer
  1739.     dec    cx
  1740.     push    ax
  1741.     mov    ah,shiftstate        ; get current shift state
  1742.     xor    ah,80h            ; toggle shift state
  1743.     mov    shiftstate,ah        ; remember it
  1744.     mov    al,SIchar+40h        ; assume going into unshifted state
  1745.     or    ah,ah            ; to unshifted state now?
  1746.     jz    encod44            ; z = yes, go to unshifted state
  1747.     mov    al,SOchar+40h        ; say go to shifted state
  1748. encod44:stosb                ; put lock char into packet
  1749.     dec    cx
  1750.     pop    ax            ; recover current character
  1751.                     ; end of locking shift tests
  1752.  
  1753. encod50:or    dh,dh            ; doing 8-bit quoting?
  1754.     jz    encod60            ; z = no, forget this
  1755.     cmp    trans.lshift,lock_disable ; locking shift disabled?
  1756.     je    encod57            ; e = yes
  1757.     cmp    ah,shiftstate        ; different than current shift state?
  1758.     jne    encod58            ; ne = yes, specials will be prefixed
  1759.     push    ax            ; save char (stripped of high bit)
  1760.     and    al,7fh            ; consider high bit controls too
  1761.     cmp    al,SIchar        ; SI (Control-O)?
  1762.     je    encod53            ; e = yes
  1763.     cmp    al,SOchar        ; SO (Control-N)?
  1764.     je    encod53            ; e = yes
  1765.     cmp    al,DLE            ; DLE (Control-P)?
  1766.     jne    encod54            ; ne = no
  1767. encod53:mov    al,dl            ; stuff a quote (#)
  1768.     stosb
  1769.     dec    cx
  1770.     mov    al,DLE + 40h        ; then a DLE prefix (P)
  1771.     stosb
  1772.     dec    cx            ; account for it in buffer size
  1773. encod54:pop    ax            ; exit with original char in AL
  1774.     jmp    short encod60        ; no 8-bit prefixing needed here
  1775.  
  1776. encod57:cmp    ah,shiftstate        ; different than current shift state?
  1777.     je    encod60            ; e = no, don't send quoted form
  1778. encod58:cmp    rptct,1            ; doing repeats?
  1779.     jbe    encod59            ; be = no
  1780.     cmp    trans.rptq,0        ; disabled?
  1781.     je    encod59            ; e = yes
  1782.     push    ax            ; do repeat prefixing - save data
  1783.     mov    al,trans.rptq        ; insert repeat prefix char
  1784.     stosb
  1785.     dec    cx            ; account for it in buffer size
  1786.     mov    al,rptct        ; get the repeat count
  1787.     add    al,20h            ; make it printable
  1788.     stosb                ; insert into buffer
  1789.     dec    cx
  1790.     pop    ax            ; get back the actual character
  1791. encod59:mov    bl,trans.ebquot        ; get 8-bit quote char
  1792.     mov    es:[di],bl        ; put in packet
  1793.     inc    di
  1794.     dec    cx            ; decrement # of chars left
  1795.     jmp    short encod60b
  1796.                     ; common prefix testing section
  1797. encod60:cmp    rptct,1            ; doing repeats?
  1798.     jbe    encod60b        ; be = no
  1799.     cmp    trans.rptq,0        ; repeat quoting disabled?
  1800.     je    encod60b        ; e = yes, disabled
  1801.     push    ax            ; do repeat prefixing - save data
  1802.     mov    al,trans.rptq        ; insert repeat prefix char
  1803.     stosb
  1804.     dec    cx            ; account for it in buffer size
  1805.     mov    al,rptct        ; get the repeat count
  1806.     add    al,20h            ; make it printable
  1807.     stosb                ; insert into buffer
  1808.     dec    cx
  1809.     pop    ax            ; get back the actual character
  1810.  
  1811. encod60b:and    al,7fh            ; turn off 8th bit in character
  1812.     cmp    al,' '            ; compare to a space
  1813.     jae    encod61            ; ae = not a control code
  1814.     push    bx            ; check for unprefixed selections
  1815.     mov    bl,al            ; as 1=7-bit, 80h=8-bit, 81h=both
  1816.     xor    bh,bh
  1817.     mov    bl,protlist[bx]        ; get 8 and 7 bit encoding rules
  1818.     or    bl,bl            ; anything being excepted from prefix?
  1819.     jz    encod60a        ; z = no
  1820.     test    bl,ah            ; 8-bit unprefixed?
  1821.     jnz    encod60a        ; nz = yes
  1822.     cmp    ah,80h            ; is it a 7-bit char in reality?
  1823.     je    encod60a        ; e = no (prefix it)
  1824.     and    bl,1            ; text 7 bit unprefixed
  1825. encod60a:pop    bx
  1826.     jz    encod64            ; z = char needs quoting
  1827.     jmp    short encod67        ; store char as-is
  1828. encod61:
  1829.     cmp    al,del            ; delete?
  1830.     je    encod64            ; e = yes, go quote it
  1831.     cmp    al,dl            ; quote char?
  1832.     je    encod65            ; e = yes, go add it
  1833.     or    dh,dh            ; doing 8-bit quoting?
  1834.     jz    encod62            ; z = no, don't translate it
  1835.     cmp    al,trans.ebquot        ; 8-bit quote char?
  1836.     je    encod65            ; e = yes, just output with quote
  1837. encod62:cmp    trans.rptq,0        ; repeat prefixing disabled?
  1838.     je    encod67            ; e = yes, don't check for quote char
  1839.     cmp    al,trans.rptq        ; repeat quote character?
  1840.     je    encod65            ; e = yes, then quote it
  1841.     jmp    short encod67        ; else don't quote it
  1842.                     ; control code section
  1843. encod64:xor    al,40h            ; control char, uncontrollify
  1844. encod65:mov    es:[di],dl        ; insert control quote char
  1845.     inc    di
  1846.     dec    cx
  1847. encod67:or    al,ah            ; restore high bit, if stripped
  1848.     or    dh,dh            ; doing eight bit quoting?
  1849.     jz    encod68            ; z = no, retain high bit
  1850.     and    al,not 80h        ; strip high bit
  1851. encod68:stosb
  1852.     dec    cx            ; decrement output buffer counter
  1853.     jmp    encod10            ; get fresh input
  1854. encode    endp 
  1855.  
  1856. ; Fill encode source buffer, report KB and percentage done.
  1857. ; Return carry clear for success
  1858. ; modifies ax
  1859. inbuf    proc    near
  1860.     cmp    flags.eoflag,0        ; reached the end?
  1861.     je    inbuf0            ; e = no
  1862.     stc                ; return failure
  1863.     ret
  1864. inbuf0:    push    dx
  1865.     push    bx
  1866.     push    cx
  1867.     mov    bx,diskio.handle    ; get file handle
  1868.     mov    cx,buffsz        ; record size
  1869.     mov    dx,offset buff        ; buffer
  1870.     mov    ebufpnt,dx        ; buffer pointer
  1871.     cmp    trans.xtype,1        ; [HF3] File type binary?
  1872.     je    inbuf0a            ; [HF3] e = yes, no translation
  1873.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1874.     jne    inbuf0a            ; ne = no
  1875.     shr    cx,1            ; allow for double char encoding
  1876.     mov    dx,offset rdbuf        ; use this as source buffer
  1877. inbuf0a:mov    ah,readf2        ; read a record
  1878.     int    dos
  1879.     jnc    inbuf7            ; nc = no error
  1880.     mov    flags.cxzflg,'X'    ; error, set ^X flag
  1881.      jmp    short inbuf1        ; and truncate the file here
  1882. inbuf7:    or    ax,ax            ; any bytes read?
  1883.     jnz    inbuf2            ; nz = yes (the number read)
  1884. inbuf1:    mov    flags.eoflag,1        ; set End-of-File
  1885.     mov    filflg,0        ; buffer empty
  1886.     mov    echrcnt,0        ; zero bytes left in buffer
  1887.     pop    cx
  1888.     pop    bx
  1889.     pop    dx
  1890.     stc                ; failure
  1891.     ret
  1892.  
  1893. inbuf2:    cmp    trans.xtype,1        ;[HF]941012 type binary ?
  1894.     je    inbuf2a            ;[HF]941012 e = yes
  1895.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1896.     jne    inbuf2a            ; ne = no
  1897.     call    jpnread            ; revise buffer for Japanese
  1898. inbuf2a:add    tfilsz,ax        ; total the # bytes transferred so far
  1899.     adc    tfilsz+2,0        ; it's a double word
  1900.     mov    echrcnt,ax        ; number of chars read from file
  1901.     add    fsta.fsbyte,ax
  1902.     adc    fsta.fsbyte+2,0
  1903.     mov    filflg,1        ; buffer not empty
  1904.     test    flags.remflg,dserial    ; serial display mode?
  1905.     jnz    inbuf3            ; nz = yes, skip kbyte and % display
  1906.     push    si
  1907.     push     ax
  1908.     call    kbpr            ; show kilobytes sent
  1909.     call    perpr            ; show percent sent
  1910.     pop    ax
  1911.     pop    si
  1912.                     ; Character set translation section
  1913. inbuf3:    cmp    trans.xchset,xfr_xparent ; Transparent transfer char set?
  1914.     je    inbuf6            ; e = yes, no translation
  1915.     cmp    trans.xtype,1        ; File Type Binary?
  1916.     je    inbuf6            ; e = yes, no translation
  1917.     cmp    trans.xchset,xfr_japanese ; Japanese-EUC?
  1918.     je    inbuf6            ; e = yes, processed already
  1919.     push    ax            ; save buffer count
  1920.     mov    cx,ax            ; loop counter
  1921.     push    di
  1922.     push    es
  1923.     PUSH    DS
  1924.     call    cplatin            ; set DS:BX to CP to Xfr chr table
  1925.     call    cpinvert        ; check readable vs invertible set
  1926.     mov    di,seg buff
  1927.     mov    es,di
  1928.     mov    di,offset buff        ; scan this buffer
  1929.     cld
  1930. inbuf4:    mov    al,es:[di]        ; get a char, keep pointer fixed
  1931.     cmp    bx,offset icp437L1    ; invertible CP 437 to Latin1?
  1932.     jne    inbuf4b            ; ne = no
  1933.     mov    ah,al
  1934.     cmp    ah,127            ; special case?
  1935.     jne    inbuf4d            ; ne = no
  1936.     mov    al,26            ; 127 to 26
  1937.     jmp    short inbuf5
  1938. inbuf4d:cmp    al,20            ; range for special cases?
  1939.     jb    inbuf5            ; b = no
  1940.     cmp    al,21
  1941.     ja    inbuf5            ; a = no
  1942.     mov    al,167
  1943.     je    inbuf5            ; 21 to 167
  1944.     mov    al,182
  1945.     jmp    short inbuf5        ; 20 to 182
  1946. inbuf4b:cmp    bx,offset icp850L1    ; invertible CP 850 to Latin1?
  1947.     jne    inbuf4a            ; ne = no
  1948.     cmp    al,28            ; special case?
  1949.     jne    inbuf4c            ; ne = no
  1950.     mov    al,127            ; 28 to 127
  1951.     jmp    short inbuf5
  1952. inbuf4c:cmp    al,127            ; special case?
  1953.     jne    inbuf4a
  1954.     mov    al,26            ; 127 to 26
  1955. inbuf4a:test    al,80h            ; GRight?
  1956.     jz    inbuf5            ; z = no
  1957.     and    al,not 80h        ; strip high bit
  1958.     xlatb                ; translate via bx table
  1959. inbuf5:    stosb                ; store char
  1960.     loop    inbuf4            ; do all concerned
  1961.     POP    DS
  1962.     pop    es
  1963.     pop    di
  1964.     pop    ax
  1965. inbuf6:    pop    cx
  1966.     pop    bx
  1967.     pop    dx
  1968.     clc                ; success
  1969.     ret
  1970. inbuf    endp
  1971.  
  1972. ; Japanese file transfer section (Hirofumi Fujii, keibun@kek.ac.jp)
  1973. ; Read buffer rdbuf to convert from file character set Shift-JIS (Code Page 
  1974. ; 932) to transfer character set Japanese-EUC. Double char translation state
  1975. ; is maintained across file buffers. Init dblbyte to 0 before each new file.
  1976. ; Output is written to buff, with byte count in register AX. The output
  1977. ; could be twice the size of the input. [rewritten by jrd]
  1978. jpnread    proc    near            ; [HF] read Japanese from file
  1979.     push    si
  1980.     push    di
  1981.     push    es
  1982.     mov    cx,ax            ; number of chars in source buffer
  1983.     mov    ax,ds
  1984.     mov    es,ax
  1985.     mov    dl,dblbyteflg        ; get state info from previous call
  1986.     mov    ah,dblbyte        ;  first byte too
  1987.     mov    si,offset rdbuf        ; read from here
  1988.     mov    di,offset buff        ; write to here (avoids overwrites)
  1989.     cld
  1990. jpnrea1:lodsb                ; get a byte
  1991.     or    dl,dl            ; doing first byte?
  1992.     jnz    jpnread3        ; nz = no, second of a pair
  1993.     cmp    al,81h            ; is it Kanji?
  1994.     jb    jpnrea5            ; b = no
  1995.     cmp    al,0fch
  1996.     ja    jpnrea5            ; a = no
  1997.     cmp    al,9fh
  1998.     jbe    jpnrea2            ; be = yes
  1999.     cmp    al,0e0h
  2000.     jb    jpnrea5            ; b = no
  2001. jpnrea2:mov    ah,al            ; AL is first byte of Kanji, save it
  2002.     mov    dl,1            ; say ready to do second byte next
  2003.     jmp    short jpnrea8        ; continue loop
  2004.  
  2005. jpnread3:cmp    al,40h            ; is second byte Kanji?
  2006.     jb    jpnrea6            ; b = no
  2007.     cmp    al,0fch
  2008.     ja    jpnrea6            ; a = no
  2009.     cmp    al,7eh
  2010.     jbe    jpnrea4            ; be = yes
  2011.     cmp    al,80h
  2012.     jb    jpnrea6            ; b = no
  2013. jpnrea4:call    jpnftox            ; convert to xfer char code
  2014.     jmp    short jpnrea6        ; write the pair
  2015.  
  2016. jpnrea5:cmp    al,0a1h            ; Katakana?
  2017.     jb    jpnrea7            ; b = no
  2018.     cmp    al,0dfh
  2019.     ja    jpnrea7            ; a = no
  2020.     mov    ah,8eh            ; set Katakana prefix
  2021. jpnrea6:xchg    ah,al            ; write two bytes
  2022.     stosb                ; store first byte
  2023.     xchg    ah,al            ; get second byte into AL again
  2024. jpnrea7:stosb                ; store a byte
  2025.     xor    dl,dl            ; say all bytes have been written
  2026. jpnrea8:loop    jpnrea1
  2027.     mov    dblbyteflg,dl        ; save state info
  2028.     mov    dblbyte,ah        ; and first char of a pair
  2029.     sub    di,offset buff        ; compute number of bytes written
  2030.     mov    ax,di            ; report new count in AX
  2031.     pop    es
  2032.     pop    di
  2033.     pop    si
  2034.     ret
  2035. jpnread    endp
  2036.  
  2037. ; File character code (Shift-JIS) to xfer character code (EUC) converter.
  2038. ; From Shift-JIS to EUC
  2039. ;   if( code1 <= 0x9f )
  2040. ;     code1 -= 0x71;
  2041. ;   else
  2042. ;     code1 -= 0xb1;
  2043. ;   code1 = code1 * 2 + 1;
  2044. ;   if( code2 > 0x7f ) code2 -= 1;
  2045. ;   if( code2 >= 0x9e ){
  2046. ;     code2 -= 0x7d;
  2047. ;     code1 += 1;
  2048. ;   } else
  2049. ;     code2 -= 0x1f;
  2050. ;   EUC_code1 = (code1 | 0x80);
  2051. ;   EUC_code2 = (code2 | 0x80);
  2052. ;   [ fputc( EUC_code1, packet ); fputc( EUC_code2, packet ); ]
  2053. ;
  2054. jpnftox    proc    near
  2055.     cmp    ah,9fh
  2056.     ja    jpnftox1
  2057.     sub    ah,71h
  2058.     jmp    short jpnftox2
  2059. jpnftox1:sub    ah,0b1h
  2060. jpnftox2:shl    ah,1
  2061.     inc    ah
  2062.     cmp    al,7fh
  2063.     jbe    jpnftox3
  2064.     dec    al
  2065. jpnftox3:cmp    al,9eh
  2066.     jb    jpnftox4
  2067.     sub    al,7dh
  2068.     inc    ah
  2069.     jmp    jpnftox5
  2070. jpnftox4:sub    al,1fh
  2071. jpnftox5:or    ax,8080h
  2072.     ret
  2073. jpnftox    endp
  2074.  
  2075. ; GETFIL, called only by send code
  2076. ; Enter with raw filename pattern in diskio.string
  2077. ; Returns carry clear if success, else carry set
  2078. getfil    proc    near
  2079.     mov    dblbyteflg,0        ; clear encoder state variable
  2080.     mov    shiftstate,0        ; locking shift state
  2081.     mov    DLEseen,0        ; escape state
  2082.     mov    filflg,0        ; say nothing is in the buffer
  2083.     mov    flags.eoflag,0        ; not the end of file
  2084.     cmp    atflag,0        ; at sign file list?
  2085.     je    getfil2            ; e = no
  2086.             ; get a filename to diskio.string from file atfile+2
  2087.     call    readatfile
  2088.     jnc    getfil2            ; nc = success
  2089.     ret                ; else return carry set for failure
  2090. getfil2:mov    dx,offset diskio.dta    ; data transfer address
  2091.     mov    ah,setdma        ; set disk transfer address
  2092.     int    dos
  2093.     xor    cx,cx            ; attributes: find only normal files
  2094.     mov    dx,offset diskio.string ; filename string (may have wild cards)
  2095.     mov    ah,first2        ; DOS 2.0 search for first
  2096.     int    dos            ; get file's characteristics
  2097.     pushf                ; save c flag
  2098.     mov    ah,setdma        ; reset dta address
  2099.     mov    dx,offset buff        ; restore dta
  2100.     int    dos
  2101.     popf                ; restore status of search for first
  2102.     jnc    getfi1            ; nc = ok so far
  2103.     ret                ; else take error exit
  2104. getfi1:    jmp    getfcom            ; do common code
  2105. getfil    endp
  2106.  
  2107.  
  2108. ; GTNFIL called by send code to get next file.
  2109. ; Returns carry clear for success, carry set for failure.
  2110. gtnfil    proc    near
  2111.     xor    al,al
  2112.     mov    dblbyteflg,al        ; clear encoder state variable
  2113.     mov    shiftstate,al        ; locking shift state
  2114.     mov    DLEseen,al        ; escape state
  2115.     mov    auxfile,al        ; clear override name
  2116.     cmp    flags.cxzflg,'Z'    ; Did we have a ^Z?
  2117.     jne    gtnfi1            ; ne = no, else done sending files
  2118.     stc                ; carry set for failure
  2119.     ret                ; take failure exit
  2120.  
  2121. gtnfi1:    mov    filflg,al        ; nothing in the DMA
  2122.     mov    flags.eoflag,al        ; not the end of file
  2123.     mov    dx,offset diskio.dta    ; point at dta
  2124.     mov    ah,setdma        ; set the dta address
  2125.     int    dos
  2126.     mov    ah,next2        ; DOS 2.0 search for next
  2127.     int    dos
  2128.     pushf                ; save carry flag
  2129.     mov    ah,setdma        ; restore dta
  2130.     mov    dx,offset buff
  2131.     int    dos
  2132.     popf                ; recover carry flag
  2133.     jnc    getfcom            ; nc = success, do common code
  2134.     cmp    atflag,0        ; at sign file list?
  2135.     jne    getfil            ; ne = yes
  2136.     stc
  2137.     ret                ; carry    set means no more files found
  2138. gtnfil    endp
  2139.                     ; worker for getfil, gtnfil
  2140. getfcom    proc    near
  2141.     push    si
  2142.     push    di
  2143.     mov    dx,offset diskio.string    ; original file spec (may be wild)
  2144.     mov    di,offset templp    ; place for path part
  2145.     mov    si,offset templf    ; place for filename part
  2146.     call    fparse            ; split them
  2147.     mov    si,offset diskio.fname    ; current filename from DOS
  2148.     call    strcat            ; (di)= local path + diskio.fname
  2149.     cmp    sndpathflg,0        ; include SEND PATH?
  2150.     je    getfco4            ; e = no
  2151.     cmp    auxfile,0        ; already have an override name?
  2152.     jne    getfco4            ; ne = yes
  2153.     mov    si,di            ; source is local path +diskio.fname
  2154.     cmp    byte ptr [si+1],':'    ; disk drive included?
  2155.     jne    getfco4            ; ne = no
  2156.     add    si,2            ; yes, skip drive: part
  2157. getfco4:mov    di,offset encbuf    ; name to send to host (no path)
  2158.     call    strcpy              ; new string = old path + DOS's filename
  2159.     push    bx
  2160.     push    cx
  2161.     test    flags.remflg,dquiet    ; quiet display?
  2162.     jnz    getfco1            ; e = yes, do not display filename
  2163.     call    clrfln            ; position cursor & blank out the line
  2164.     mov    dx,offset encbuf    ; name host sees
  2165.     call    prtasz
  2166. getfco1:call    newfn            ; update encbuf with "send as" name
  2167.     pop    cx
  2168.     pop    bx
  2169.     mov    ah,open2        ; file open
  2170.     xor    al,al            ; 0 = open readonly
  2171.     cmp    dosnum,300h        ; at or above DOS 3?
  2172.     jb    getfco2            ; b = no, so no shared access
  2173.     or    al,40h            ; open readonly, deny none
  2174. getfco2:mov    dx,offset templp    ; filename string with path
  2175.     int    dos
  2176.     jc    getfco3            ; c = failed to open the file
  2177.     mov    diskio.handle,ax    ; save file handle
  2178.     xor    ax,ax
  2179.     mov    tfilsz,ax        ; set bytes sent to zero
  2180.     mov    tfilsz+2,ax
  2181.     mov    ax,-1            ; get a minus one
  2182.     mov    oldkbt,ax
  2183.     mov    oldper,ax
  2184.     clc                ; carry clear for success
  2185. getfco3:pop    si
  2186.     pop    di
  2187.     ret
  2188. getfcom    endp
  2189.  
  2190. ; Read line from file in atfile+2, return unpadded ASCIIZ string to
  2191. ; diskio.string.
  2192. ; Return carry clear if success, else carry set.
  2193. readatfile proc    near
  2194.     cmp    word ptr atfile,0    ; file handle, open?
  2195.     jne    reada3            ; ne = is open, do a read line
  2196.     mov    dx,offset atfile+3    ; get filename, skip handle and @
  2197.     mov    di,dx
  2198.     mov    cx,64            ; max length of a filename.
  2199. reada1:    cmp    byte ptr [di],' '    ; whitespace or control code?
  2200.     jbe    reada2            ; be = yes, found termination
  2201.     inc    di            ; else look at next char
  2202.     loop    reada1            ; limit search
  2203. reada2:    mov    byte ptr [di],0        ; make asciiz
  2204.     mov    ah,open2        ; DOS 2 open file
  2205.     xor    al,al            ; open for reading
  2206.     int    dos
  2207.     mov    word ptr atfile,ax    ; store file handle
  2208.     jnc    reada3            ; nc = open ok, read from file
  2209.     mov    word ptr atfile,0    ; say file is closed
  2210.     ret                ; carry set for fail
  2211.  
  2212. reada3:    mov    bx,word ptr atfile    ; file handle
  2213.     mov    cx,63            ; # of bytes to read
  2214.     mov    di,offset diskio.string    ; destination
  2215.     mov    ah,ioctl        ; ioctl, is this the console device?
  2216.     xor    al,al            ; get device info
  2217.     int    dos
  2218.     and    dl,81h            ; ISDEV and ISCIN bits needed together
  2219.     cmp    dl,81h            ; Console input device?
  2220.     jne    reada5            ; ne = no, use regular file i/o
  2221. reada4:    mov    ah,coninq        ; read console, no echo
  2222.     int    dos
  2223.     cmp    al,CR            ; end of the line yet?
  2224.     je    reada4b            ; e = yes
  2225.     cmp    al,' '            ; whitespace?
  2226.     je    reada4            ; e = yes
  2227.     cmp    al,TAB
  2228.     je    reada4
  2229.     cmp    al,'C'-40h        ; Control-C?
  2230.     jne    reada4a            ; ne = no
  2231.     stc
  2232.     ret                ; return failure
  2233. reada4a:mov    [di],al
  2234.     inc    di
  2235.     loop    reada4            ; keep reading
  2236. reada4b:mov    byte ptr [di],0        ; insert terminator
  2237.     jmp    short reada6        ; finish up
  2238.  
  2239. reada5:    mov    dx,di            ; destination ptr
  2240.     push    cx
  2241.     push    es
  2242.     mov    cx,seg diskio
  2243.     mov    es,cx
  2244.     mov    cx,1            ; one byte
  2245.     mov    byte ptr [di],0        ; insert null terminator, clears line
  2246.     mov    ah,readf2        ; DOS 2 read from file
  2247.     int    dos
  2248.     pop    es
  2249.     pop    cx
  2250.     or    ax,ax            ; bytes read, zero?
  2251.     je    reada6            ; e = yes, exit reading
  2252.     mov    al,[di]            ; byte just read
  2253.     cmp    al,' '            ; white space?
  2254.     je    reada5            ; e = yes, skip
  2255.     cmp    al,TAB            ; white space?
  2256.     je    reada5            ; e = yes, skip
  2257.     cmp    al,','            ; comma separator?
  2258.     je    reada5a            ; e = yes
  2259.     cmp    al,CR            ; first part of line terminator?
  2260.     je    reada5            ; e = yes, skip
  2261.     cmp    al,LF            ; end of the line yet?
  2262.     je    reada5a            ; e = yes
  2263.     inc    di            ; where to write next time
  2264.     loop    reada5            ; keep reading
  2265. reada5a:mov    byte ptr [di],0        ; insert terminator
  2266.     cmp    diskio.string,0        ; empty field?
  2267.     jne    reada6            ; ne = no
  2268.     jmp    readatfile        ; start over
  2269.  
  2270. reada6:    cmp    diskio.string,0        ; anything present?
  2271.     jne    reada7            ; ne = yes
  2272.     mov    bx,word ptr atfile    ; file handle
  2273.     mov    ah,close2        ; close file (wanted just one line)
  2274.     int    dos
  2275.     mov    word ptr atfile,0    ; clear handle
  2276.     mov    atflag,0
  2277.     stc                ; say EOF
  2278.     ret
  2279. reada7:    clc                ; say success
  2280.     ret
  2281. readatfile endp
  2282.  
  2283. ; Get the file name from the data portion of the F packet or from locally
  2284. ; specified override filename (in auxfile), displays the filename, does any
  2285. ; manipulation of the filename necessary, including changing the name to
  2286. ; prevent collisions. Returns carry clear for success. Failures return
  2287. ; carry set with dx pointing at error message text.
  2288. ; Called by file receive module in mssrcv.asm.
  2289.  
  2290. gofil    proc    near
  2291.     mov    si,offset decbuf    ; filename in packet
  2292.     mov    di,offset diskio.string    ; place where prtfn finds name
  2293.     call    strcpy            ; copy pkt filename to diskio.string
  2294.     mov    di,offset fsta.xname    ; statistics external filespec area
  2295.     call    strcpy            ; record external name
  2296.     cmp    rcvpathflg,0        ; RECEIVE PATHNAMES enabled?
  2297.     jne    gofil0c            ; ne = ues
  2298.     cmp    auxfile,0        ; in use already?
  2299.     jne    gofil0c            ; ne = yes
  2300.     mov    auxfile,'.'        ; dot+nul forces use of current dir
  2301.     mov    auxfile+1,0
  2302.     jmp    short gofil0d
  2303.  
  2304. gofil0c:cmp    auxfile,0        ; have override name?
  2305.     jne    gofil1            ; ne = yes
  2306. gofil0d:cmp    flags.xflg,0        ; receiving to screen?
  2307.     jne    gofil0a            ; ne = yes, filename becomes CON
  2308.     cmp    flags.destflg,dest_disk    ; destination is disk?
  2309.     je    gofil1            ; e = yes
  2310.     mov    di,offset printer    ; assume PRN is local file name
  2311.     jb    gofil0b            ; b = yes
  2312. gofil0a:mov    di,offset screen    ; use CON (screen) as local file name
  2313.     mov    flags.xflg,1        ; say receiving to screen
  2314. gofil0b:xchg    di,si            ; di --> decbuf, si --> file name
  2315.     call    strcpy            ; put local name (si) into decbuf
  2316.     mov    nmoflg,1        ; say that we have a replacement name
  2317.     jmp    gofil9            ; final filename is now in 'decbuf'
  2318.  
  2319. gofil1:    xor    ax,ax
  2320.     mov    nmoflg,al        ; assume no override name
  2321.     cmp    auxfile,al        ; overriding name from other side?
  2322.     jne    gofi1e            ; ne = yes
  2323.     jmp    gofil4            ; e = no, get the other end's filename
  2324. gofi1e:    mov    nmoflg,1        ; say using an override name
  2325.     mov    ax,offset auxfile    ; get local override filename
  2326.     cmp    word ptr auxfile+1,003ah; colon+null?(primative drive spec A:)
  2327.     je    gofil3        ; e = yes, skip screwy DOS response (No Path)
  2328.     cmp    word ptr auxfile,'..'    ; parent directory?
  2329.     jne    gofi1g            ; ne = no
  2330.     cmp    word ptr auxfile+1,002eh ; dot dot + null?
  2331.     je    gofi1b            ; e = yes, process as directory
  2332. gofi1g:    cmp    word ptr auxfile,002eh    ; dot + null (current dir)?
  2333.     je    gofi1b            ; e = yes, process as directory
  2334.     call    isfile            ; does it exist?
  2335.     jnc    gofi1f            ; nc = file exists
  2336.     test    filtst.fstat,80h    ; serious error?
  2337.     jz    gofil3            ; z = no, just no such file
  2338.     jmp    gofi18a            ; else quit here
  2339. gofi1f:    test    byte ptr filtst.dta+21,10H ; subdirectory name?
  2340.     jnz    gofi1b            ; nz = yes
  2341.     cmp    filtst.fname,2eh    ; directory name?
  2342.     je    gofi1b            ; e = yes, process as directory
  2343.     cmp    auxfile+2,5ch        ; a root directory like b:\?
  2344.     jne    gofi1d            ; ne = no. (DOS is not helpful with roots)
  2345.     cmp    auxfile+3,0        ; and is it terminated in a null?
  2346.     je    gofi1b            ; e = yes, so it is a root spec
  2347. gofi1d:    test    byte ptr filtst.dta+21,0fh   ; r/o, hidden, system, vol label?
  2348.     jz    gofil3            ; z = no
  2349.      jmp    gofi18a               ; yes. Complain and don't transfer file
  2350. gofi1b:    mov    dx,offset auxfile    ; auxfile is a (sub)directory name
  2351.     call    strlen            ; get its length w/o terminator
  2352.     jcxz    gofil2            ; zero length
  2353.     dec    cx            ; examine last char
  2354.     push    bx            ; save bx
  2355.     mov    bx,cx
  2356.     add    bx,dx
  2357.     cmp    byte ptr [bx],5ch    ; ends in backslash?
  2358.     je    gofil2            ; e = yes
  2359.     cmp    byte ptr [bx],2fh    ; maybe forward slash?
  2360.     je    gofil2            ; e = yes
  2361.     mov    byte ptr [bx + 1],5ch    ; no slash yet. use backslash
  2362.     mov    byte ptr [bx + 2],0    ; plant new terminator
  2363. gofil2:    pop    bx
  2364.  
  2365. gofil3:    mov    di,offset templp    ; local path
  2366.     mov    si,offset templf    ; local filename
  2367.     mov    dx,offset auxfile    ; local string
  2368.     call    fparse            ; split local string
  2369.     mov    di,offset temprp    ; remote path
  2370.     mov    si,offset temprf    ; remote file
  2371.     mov    dx,offset decbuf    ; remote string
  2372.     mov    decbuf+64,0        ; force filename to be <= 64 chars
  2373.     call    fparse            ; split remote string
  2374.     test    flags.remflg,dserver    ; running in Server mode?
  2375.     jz    gofi3c            ; z = no
  2376.     test    denyflg,sndflg        ; is Deny Send mode in operation?
  2377.     jz    gofi3c            ; z = no
  2378.     mov    temprp,0        ; DENY, means remove remote path
  2379. gofi3c:    mov    si,offset templp    ; copy local path to
  2380.     mov    di,offset decbuf    ;  final filename
  2381.     call    strcpy            ; do the copy
  2382.     mov    si,offset templf    ; assume using local file name
  2383.     cmp    byte ptr templf,0    ; local file name given?
  2384.     jne    gofi3b            ; ne = yes
  2385.     mov    si,offset temprf    ; else use remote file name
  2386. gofi3b:    call    strcat            ; append path and filename again
  2387.                     ; offset decbuf holds the new filename
  2388.                     ;
  2389.                 ; recheck legality of filename in 'decbuf'
  2390. gofil4:    mov    decbuf+64,0        ; guard against long filenames
  2391.     mov    di,offset temprp    ; remote path
  2392.     mov    si,offset temprf    ; remote file
  2393.     mov    dx,offset decbuf    ; remote string
  2394.     call    strlen            ; get original size
  2395.     push    cx            ; remember it
  2396.     call    fparse            ; further massage filename
  2397.     push    si            ; put pieces back together
  2398.     call    verfil            ; verify each char in temprf string
  2399.     mov    si,di            ; get path part first
  2400.     mov    di,dx            ; set destination
  2401.     call    strcpy            ; copy in path part
  2402.     pop    si            ; recover (new) filename
  2403.     cmp    byte ptr [si],'.'    ; does filename part start with a dot?
  2404.     jne    gofil5            ; ne = no
  2405.     push    di            ; save regs
  2406.     push    si
  2407.     mov    di,offset rdbuf        ; a work area
  2408.     mov    byte ptr [di],'X'    ; start name with letter X
  2409.     inc    di
  2410.     call    strcpy            ; copy rest of filename
  2411.     mov    di,si
  2412.     mov    si,offset rdbuf      ; copy new name back to original location
  2413.     call    strcpy
  2414.     pop    si            ; restore regs
  2415.     pop    di    
  2416. gofil5:    call    strcat            ; append it
  2417.     call    strlen            ; see if we chopped out something
  2418.     pop    si            ; get original length (from push cx above)
  2419.     cmp    cx,si            ; same size?
  2420.     je    gofil9            ; e = yes
  2421.     mov    nmoflg,1        ; say that we have a replacement name
  2422.                 ; filename is now in 'decbuf', all converted
  2423. gofil9:    test    flags.remflg,dquiet    ; quiet display mode?
  2424.     jnz    gofi10            ; nz = yes, don't print it
  2425.     test    flags.remflg,dserial    ; serial display mode?
  2426.     jz    gofi9a            ; z = no
  2427.     mov    ah,prstr
  2428.     mov    dx,offset crlf        ; display cr/lf
  2429.     int    dos
  2430. gofi9a:    call    prtfn            ; show packet filename
  2431.     cmp    nmoflg,0        ; using local override name?
  2432.     je    gofil9b            ; e = no
  2433.     cmp    flags.xflg,0        ; receiving to screen? (X versus F)
  2434.     jne    gofil9b            ; ne = yes
  2435.     mov    ah,prstr
  2436.     mov    dx,offset asmsg        ; print " as "
  2437.     int    dos
  2438.     mov    dx,offset decbuf    ; plus the local filename
  2439.     call    prtasz            ; print asciiz string
  2440. gofil9b:mov    ah,flags.remflg        ; display a following cr/lf?
  2441.     and    ah,dserial        ; for serial display mode
  2442.     or    ah,flags.xflg        ; receiving to screen
  2443.     jz    gofi10            ; z = neither, no cr/lf
  2444.     mov    ah,prstr        ; finish the line with cr/lf
  2445.     mov    dx,offset crlf
  2446.     int    dos
  2447. gofi10:    mov    filtst.fstat2,0        ; 0 = assume is a disk file
  2448.     mov    dx,offset decbuf    ; point to name
  2449.     mov    ah,open2
  2450.     xor    al,al            ; open readonly
  2451.     cmp    dosnum,300h        ; above DOS 2?
  2452.     jb    gofi10a            ; b = no, so no shared access
  2453.     or    al,40h            ; open for reading, deny none
  2454. gofi10a:mov    dx,offset decbuf    ; the filename
  2455.     int    dos
  2456.     jc    gofi16            ; c = cannot open so just proceed
  2457.     mov    bx,ax            ; file handle
  2458.     mov    ah,ioctl
  2459.     xor    al,al            ; 0 = get info
  2460.     int    dos
  2461.     mov    ah,close2        ; close it
  2462.     int    dos
  2463.     mov    ax,offset decbuf    ; point to filename again
  2464.     and    dl,80h            ; ISDEV bit
  2465.     mov    filtst.fstat2,dl    ; 0 = disk file, else device
  2466.     test    dl,80h            ; ISDEV bit set?
  2467.     jz    gofi11            ; z = no, not a device
  2468.     jmp    gofi16            ; device, use name as given
  2469. gofi11:    cmp    flags.flwflg,filecol_discard    ; no-supersede existing file?
  2470.     jne    gofi12            ; ne = no (i.e., do a rename)
  2471.     cmp    flags.flwflg,filecol_update ; updating?
  2472.     je    gofi16            ; e = yes, delay opening
  2473.     cmp    flags.flwflg,filecol_overwrite    ; overwrite existing file?
  2474.     je    gofi16            ; e = yes
  2475.  
  2476. gofi11a:mov    flags.cxzflg,'X'    ; say stop this file
  2477.     mov    word ptr decbuf,'UN'
  2478.     mov    decbuf+2,'L'        ; file name of NUL
  2479.     mov    decbuf+3,0        ; asciiz
  2480.     jmp    short gofi13
  2481. gofi12:    cmp    flags.flwflg,filecol_rename ; rename existing file?
  2482.     jne    gofi16            ; ne = no
  2483.     mov    ax,offset decbuf    ; point to filename again
  2484.     call    unique            ; generate unique name
  2485.     jc    gofi14            ; could not generate a unique name
  2486.     test    flags.remflg,dquiet    ; quiet display mode?
  2487.     jnz    gofi13            ; nz = yes, skip printing
  2488.     push    ax            ; save unique name again
  2489.     call    frpos            ; position cursor
  2490.     mov    ah,prstr           ; say we are renaming the file
  2491.     mov    dx,offset infms5
  2492.     int    dos
  2493.     pop    ax            ; get name back into ax again
  2494.     push    ax            ; save around these calls
  2495.     mov    dx,ax            ; print current filename
  2496.     call    prtasz            ; display filename
  2497.     pop    ax            ; pointer to name, again
  2498. gofi13:    jmp    short gofi16        ; and go handle file
  2499.  
  2500. gofi14:    mov    dx,offset ermes4
  2501.     call    ermsg
  2502.     stc                ; failure, dx has msg pointer
  2503.     ret
  2504.  
  2505. gofi16:    mov    si,offset decbuf    ; pointer to (maybe new) name
  2506.     mov    di,offset diskio.string    ; filename, used in open
  2507.     call    strcpy             ; copy name to diskio.string
  2508.     xor    ax,ax
  2509.     mov    diskio.sizehi,ax    ; original file size is unknown
  2510.     mov    diskio.sizelo,ax    ; double word
  2511.     mov    tfilsz,ax        ; set bytes received to zero
  2512.     mov    tfilsz+2,ax
  2513.     mov    ax,-1            ; get a minus one
  2514.     mov    oldkbt,ax
  2515.     mov    oldper,ax
  2516.     mov    wrpmsg,al
  2517.     clc                ; finished composing filename
  2518.     ret                ; in diskio.string
  2519.  
  2520. gofi18a:mov    si,ax             ; pointer to local override name
  2521.     mov    di,offset diskio.string    ; filename, used in open
  2522.     call    strcpy             ; copy name to diskio.string
  2523.                     ; fall    through to gofi18
  2524. gofi18:    test    flags.remflg,dquiet    ; quiet display mode?
  2525.     jnz    gofi19            ; nz = yes, don't try printing
  2526.     mov    dx,offset erms12    ; unable to create file
  2527.     call    ermsg
  2528.     push    dx
  2529.     mov    dx,offset diskio.string    ; print offending name
  2530.     call    prtasz            ; display filename
  2531.     pop    dx
  2532. gofi19:    stc                ; failure, dx has msg pointer
  2533.     ret
  2534. gofil    endp
  2535.  
  2536. ; Open file for writing with name in diskio.string
  2537. goopen    proc    near
  2538.     xor    ax,ax
  2539.     mov    dblbyteflg,al        ; clear decoder state variable
  2540.     mov    shiftstate,al        ; locking shift state
  2541.     mov    DLEseen,al        ; escape state
  2542.     mov    tfilsz,ax        ; set bytes received to zero
  2543.     mov    tfilsz+2,ax
  2544.     mov    ax,-1            ; get a minus one
  2545.     mov    oldkbt,ax
  2546.     mov    oldper,ax
  2547.  
  2548.     cmp    diskio.handle,-1    ; is handle unused?
  2549.     je    goopen5            ; e = yes
  2550.     mov    dx,diskio.handle    ; close the file now
  2551.     mov    ah,close2
  2552.     int    dos
  2553.     mov    diskio.handle,-1    ; clear handle of previous usage
  2554. goopen5:mov    ax,offset diskio.string    ; filename, asciiz
  2555.     call    isfile        ; check for read-only/system/vol-label/dir
  2556.     jc    goopen1            ; c = file does not exist
  2557.     test    byte ptr filtst.dta+21,1fh    ; the no-no file attributes
  2558.     jnz    gofi18            ; nz = do not write over one of these
  2559.     jmp    short goopen2        ; open existing
  2560.  
  2561. goopen1:test    filtst.fstat,80h    ; access problem?
  2562.     jnz    gofi18            ; nz = yes, quit here
  2563.     mov    dx,offset diskio.string    ; filename, asciiz
  2564.     mov    ah,creat2        ; create file
  2565.     xor    cx,cx            ; 0 = attributes bits
  2566.     int    dos
  2567.     jc    goopen2            ; c = did not work, try regular open
  2568.     mov    diskio.handle,ax    ; save file handle here
  2569.     xor    dx,dx            ; file size, high word
  2570.     xor    ax,ax            ; low word
  2571.     clc                ; carry clear for success
  2572.     ret
  2573. goopen2:test    byte ptr filtst.dta+21,1bh    ; r/o, hidden, volume label?
  2574.     jnz    gofi18            ; we won't touch these
  2575.     mov    dx,offset diskio.string    ; filename, asciiz
  2576.     mov    ah,open2           ; open existing file (usually a device)
  2577.     mov    al,1+1            ; open for writing
  2578.     int    dos
  2579.     jc    gofi18            ; carry set means can't open
  2580.     mov    diskio.handle,ax    ; file handle
  2581.     cmp    flags.flwflg,filecol_update ; updating?
  2582.     jne    goopen2c        ; ne = no
  2583.     mov    ah,fileattr        ; get file date/time attributes
  2584.     xor    al,al            ; get, not set
  2585.     mov    bx,diskio.handle    ; file handle
  2586.     int    dos            ; dx=date, cx=time
  2587.     cmp    dx,word ptr fdate    ; date is earlier than our file?
  2588.     ja    goopen2a        ; a = yes, skip file
  2589.     jb    goopen2c        ; b = incoming date is later
  2590.     cmp    cx,word ptr ftime    ; same date, how about time
  2591.     jb    goopen2c        ; b = later time, get the file
  2592. goopen2a:mov    dx,diskio.handle    ; file handle
  2593.     mov    ah,close2        ; close it
  2594.     int    dos
  2595.     mov    flags.cxzflg,'X'    ; say stop this file
  2596.     mov    ah,open2
  2597.     mov    al,1            ; open for writing
  2598.     cmp    dosnum,300h        ; above DOS 2?
  2599.     jb    goopen2b        ; b = no, so no shared access
  2600.     or    al,40h            ; open for reading, deny none
  2601. goopen2b:mov    dx,offset vacuum    ; NUL as a filename
  2602.     int    dos
  2603.     mov    diskio.handle,ax    ; file handle
  2604.     stc                ; carry set for failure
  2605.     ret
  2606.  
  2607. goopen2c:cmp    flags.flwflg,filecol_append ; append to existing file?
  2608.     je    goopen3            ; e = yes
  2609.     clc                ; carry clear for success
  2610.     ret
  2611. goopen3:mov    bx,diskio.handle    ; file handle for seeking
  2612.     xor    cx,cx            ; high order displacement
  2613.     xor    dx,dx            ; low order part of displacement
  2614.     mov    ah,lseek        ; seek to EOF (to do appending)
  2615.     mov    al,2            ; says to EOF
  2616.     int    dos
  2617.     ret                ; return DX:AX as new file pointer
  2618. goopen    endp
  2619.  
  2620. ; Given incoming filename in 'decbuf'.  Verify that each char is legal
  2621. ; (if not change it to an "X"), force max of three chars after a period (dot)
  2622. ; Source is at ds:si (si is changed here).
  2623.  
  2624. VERFIL    PROC    NEAR
  2625.     push    es            ; verify each char in 'data'
  2626.     push    cx
  2627.     push    ds
  2628.     pop    es
  2629.     mov    havdot,0        ; say no dot found in name yet
  2630.     cld
  2631. verfi1:    lodsb                ; get a byte of name from si
  2632.     and    al,7fH            ; strip any eighth bit
  2633.     jz    verfi5            ; z = end of name
  2634.     cmp    al,'.'            ; a dot?
  2635.     jne    verfi2            ; ne = no
  2636.     cmp    havdot,0        ; have one dot already?
  2637.     jne    verfi3            ; ne = yes, change to X
  2638.     mov    byte ptr [si+3],0    ; forceably end filename after 3 char ext
  2639.     mov    havdot,1        ; say have a dot now
  2640.     jmp    short verfi4        ; continue
  2641. verfi2:    cmp    al,3ah            ; colon?
  2642.     je    verfi4
  2643.     cmp    al,5ch            ; backslash path separator?
  2644.     je    verfi4
  2645.     cmp    al,2fh            ; or forward slash?
  2646.     je    verfi4
  2647.     cmp    al,'0'
  2648.     jb    verfi3            ; see if it's a legal char < '0'
  2649.     cmp    al,'9'
  2650.     jbe    verfi4            ; it's between 0-9 so it's OK
  2651.     cmp    al,'A'
  2652.     jb    verfi3            ; check for a legal punctuation char
  2653.     cmp    al,'Z'
  2654.     jbe    verfi4            ; it's A-Z so it's OK
  2655.     cmp    al,'a'
  2656.     jb    verfi3            ; check for a legal punctuation char
  2657.     cmp    al,'z'
  2658.     ja    verfi3
  2659.     and    al,5FH            ; it's a-z, capitalize
  2660.     jmp    short verfi4        ; continue with no change
  2661.  
  2662. verfi3:    push    di            ; special char. Is it on the list?
  2663.     mov    di,offset spchar2    ; list of acceptable special chars
  2664.     mov    cx,spc2len
  2665.     cld
  2666.     repne    scasb            ; search string for input char
  2667.     pop    di
  2668.     je    verfi4            ; e = in table, return it
  2669.     mov    al,'X'            ; else illegal, replace with "X"
  2670.     mov    nmoflg,1        ; say we have a replacement filename
  2671. verfi4:    mov    [si-1],al        ; update name
  2672.     jmp    short verfi1        ; loop thru rest of name
  2673. verfi5:    mov    byte ptr[si-1],0    ; make sure it's null terminated
  2674.     pop    cx
  2675.     pop    es
  2676.     ret
  2677. VERFIL    ENDP
  2678.  
  2679. ; find a unique filename.
  2680. ; Enter with a pointer to a (null-terminated) filename in ax
  2681. ; Return with same pointer but with a new name (or old if failure)
  2682. ; Success = carry clear; failure = carry set
  2683. ; The idea is to pad out the main name part (8 chars) with ascii zeros and
  2684. ; then change the last chars successively to a 1, 2, etc. until
  2685. ; a unique name is found. All registers are preserved
  2686. ; Make empty main name fields start with letter X, not digit 0
  2687. unique    proc    near
  2688.     push    bx
  2689.     push    cx
  2690.     push    dx
  2691.     push    si
  2692.     push    di
  2693.     push    es
  2694.     push    ax            ; save address of source string
  2695.     mov    dx,ds            ; make es use ds segment
  2696.     mov    es,dx
  2697.     mov    dx,ax            ; point at original filename string
  2698.     mov    di,offset templp    ; place for path
  2699.     mov    si,offset templf    ; place for filename
  2700.     call    fparse            ; separate path (di) and filename (si)
  2701.     mov    dx,di            ; point at path part
  2702.     call    strlen            ; put length in cx
  2703.     mov    si,ax            ; point to original string
  2704.     add    si,cx            ; point to filename part
  2705.     mov    di,offset templf    ; destination is temporary location
  2706.     xor    cx,cx            ; a counter
  2707.     cld                ; set direction to be forward
  2708. uniq1:    lodsb                ; get a byte
  2709.     cmp    al,'.'            ; have a dot?
  2710.     je    uniq2            ; e = yes
  2711.     or    al,al            ; maybe    null at end?
  2712.     jnz    uniq3            ; nz = no, continue loop
  2713.  
  2714. uniq2:    cmp    cl,8            ; have we copied any chars before dot?
  2715.     jge    uniq3            ; ge = all 8
  2716.     mov    byte ptr [di],'0'    ; avoid clobbers; pad with 0's
  2717.     or    cl,cl            ; first char of filename?
  2718.     jnz    uniq2a            ; nz = no
  2719.     mov    byte ptr [di],'X'    ; start name with letter X, not 0
  2720. uniq2a:    inc    di            ; and count the output chars
  2721.     inc    cl            ; and this counter too
  2722.     jmp    short uniq2        ; continue until filled 8 slots
  2723. uniq3:    inc    cl            ; cl = # char in destination
  2724.     stosb                ; store the char
  2725.     or    al,al            ; null at end?
  2726.     jnz    uniq1            ; nz = no, continue copying
  2727.  
  2728.     mov    templf+7,'1'        ; put '1' in last name char
  2729.     mov    unum,1            ; start with this generation digit
  2730.  
  2731. uniq4:    mov    di,offset rdbuf        ; build a temporary full filename
  2732.     mov    si,offset templp    ; path part
  2733.     call    strcpy            ; copy that much
  2734.     mov    si,offset templf    ; get rebuilt filename part
  2735.     call    strcat            ; paste that to the end
  2736.     mov    ax,offset rdbuf        ; point to full name
  2737.     call    isfile            ; does it exist?
  2738.     jc    uniq6            ; c = no, succeed now
  2739.  
  2740.     inc    unum            ; move to next generation
  2741.     mov    di,offset templf+7    ; point to last name char
  2742.     mov    cx,7            ; max # of digits to play with
  2743.     mov    bx,10            ; divisor (16 bits)
  2744.     mov    ax,unum            ; low order part of generation #
  2745. uniq5:    xor    dx,dx            ; high order part of generation #
  2746.     div    bx            ; compute digit (unum / 10)
  2747.     add    dl,'0'            ; make remainder part printable
  2748.     mov    [di],dl            ; put into right place
  2749.     or    ax,ax            ; any more to do? (quotient nonzero)
  2750.     jz    uniq4            ; z = no, try this name
  2751.     dec    di            ; else decrement char position
  2752.     loop    uniq5            ;   and keep making a number
  2753.     stc                ; failure: set carry, keep old name
  2754.     jmp    short uniq7        ;   and exit
  2755.  
  2756. uniq6:    pop    di            ; address of original filename
  2757.     push    ax            ; save for exit clean up
  2758.     mov    si,offset rdbuf
  2759.     call    strcpy            ; copy new filename over old
  2760.     clc                ; success: clear carry flag
  2761. uniq7:    pop    ax
  2762.     pop    es
  2763.     pop    di
  2764.     pop    si
  2765.     pop    dx
  2766.     pop    cx
  2767.     pop    bx
  2768.     ret
  2769. unique    endp
  2770. code    ends 
  2771.  
  2772. code1    segment
  2773.     assume cs:code1    
  2774.  
  2775. ; strlen -- computes the length, excluding the terminator, of an asciiz
  2776. ;    string. Input: ds:dx = address of the string
  2777. ;        Output: cx = the byte count
  2778. ;    All registers except cx are preserved
  2779. ;
  2780. STRLEN    PROC    FAR
  2781.     push    di
  2782.     push    es
  2783.     push    ax
  2784.     mov    ax,ds            ; use proper segment address
  2785.     mov    es,ax
  2786.     mov    di,dx
  2787.     mov    cx,0ffffh        ; large byte count
  2788.     cld                ; set direction to be forward
  2789.     xor    al,al            ; item sought is a null
  2790.     repne    scasb            ; search for it
  2791.     add    cx,2            ; add for -1 and auto dec in scasb
  2792.     neg    cx              ; convert to count, excluding terminator
  2793.     pop    ax
  2794.     pop    es
  2795.     pop    di
  2796.     ret
  2797. STRLEN    ENDP
  2798.  
  2799. ; strcat -- concatenates asciiz string 2 to the end of asciiz string 1
  2800. ;    offset of string 1 is expected to be in ds:di. input & output
  2801. ;    offset of string 2 is expected to be in ds:si. input only (unchanged)
  2802. ;    Preserves all registers. No error returns, returns normally via ret
  2803. ;
  2804. STRCAT    PROC    FAR
  2805.     push    di            ; save work registers
  2806.     push    si
  2807.     push    es
  2808.     push    dx
  2809.     push    cx
  2810.     push    ax
  2811.     mov    ax,ds            ; get data segment value
  2812.     mov    es,ax            ; set es to ds for implied es:di usage
  2813.     mov    dx,di
  2814.     call    strlen        ; get length (w/o terminator) of dest string
  2815.     add    di,cx            ; address of first terminator
  2816.     mov    dx,si            ; start offset of source string
  2817.     call    strlen            ; find its length too (in cx)
  2818.     inc    cx            ; include its terminator in the count
  2819.     cld
  2820.     rep    movsb        ; copy source string to end of output string
  2821.     pop    ax
  2822.     pop    cx
  2823.     pop    dx
  2824.     pop    es
  2825.     pop    si
  2826.     pop    di
  2827.     ret
  2828. STRCAT    ENDP
  2829.  
  2830. ; strcpy -- copies asciiz string pointed to by ds:si into area pointed to by
  2831. ;    ds:di. Returns via ret. All registers are preserved
  2832. ;
  2833. STRCPY    PROC    FAR
  2834.     cmp    si,di            ; same place?
  2835.     jne    strcpy1            ; ne = no
  2836.     ret                ; having done nothing
  2837. strcpy1:mov    byte ptr [di],0        ; clear destination string
  2838.     call    strcat            ; let strcat do the real work
  2839.     ret
  2840. STRCPY    ENDP
  2841.  
  2842. ; fparse -- separate the drive:path part from the filename.ext part of an
  2843. ;    asciiz string. Characters separating parts are  \ or / or :
  2844. ;    Inputs:    asciiz input full filename string offset in ds:dx
  2845. ;        asciiz path offset in ds:di
  2846. ;        asciiz filename offset in ds:si
  2847. ;    Outputs: the above strings in the indicated spots
  2848. ;    Strategy is simple. Reverse scan input string until one of the
  2849. ;    three separators is encountered and then cleave at that point
  2850. ;    Simple filename construction restrictions added 30 Dec 1985;
  2851. ;    to wit: mainname limited to 8 chars or less,
  2852. ;    extension field limited to 3 chars or less and is found by searching
  2853. ;    for first occurence of a dot in the filename field. Thus the whole
  2854. ;    filename part is restricted to 12 (8+dot+3) chars plus a null
  2855. ;    All registers are preserved. Return is always via ret
  2856. ;    (Microsoft should have written this for DOS 2.x et seq.)
  2857.  
  2858. FPARSE    PROC    FAR
  2859.     push    cx            ; local counter
  2860.     push    ax            ; local work area
  2861.     push    es            ; implied segment register for di
  2862.     push    di            ; offset of path part of output
  2863.     push    si            ; offset of file name part of output
  2864.     mov    ax,ds            ; get data segment value
  2865.     mov    es,ax            ; set es to ds for implied es:di usage
  2866.     mov    byte ptr [si],0        ; clear outputs
  2867.     mov    byte ptr [di],0
  2868.  
  2869.     push    si            ; save original file name address
  2870.     mov    si,dx            ; get original string address
  2871.     call    strcpy            ; copy string to original di
  2872.     call    strlen            ; find length (w/o terminator), in cx
  2873.     mov    si,di            ; address of string start
  2874.     add    si,cx
  2875.     dec    si            ; si = address of last non-null char
  2876.     jcxz    fpars5            ; if null skip the path scan
  2877.                     ; now find last path char, if any
  2878.                     ; start at the end of input string
  2879.     std                 ; set direction to be backward
  2880. fpars4:    lodsb                 ; get a byte (dec's si afterward)
  2881.     cmp    al,5ch            ; is it a backslash ('\')? 
  2882.     je    fpars6          ; e = yes
  2883.     cmp    al,2fh            ; or forward slash ('/')?
  2884.     je    fpars6          ; e = yes
  2885.     cmp    al,3ah            ; or even the drive terminator colon?
  2886.     je    fpars6            ; e = yes
  2887.     loop    fpars4             ; else keep looking until cx == 0
  2888.                       ; si is at beginning of file name
  2889. fpars5:    dec    si            ; dec for inc below
  2890. fpars6:    inc    si
  2891.     inc    si            ; si now points at first filename char
  2892.                     ; cx holds number of path chars
  2893.                     ; get original file name address (si)
  2894.     pop    di            ; and make it place to copy filename
  2895.     cld                ; reset direction to be forward
  2896.     mov    ax,si            ; ax holds filename address for awhile
  2897.     push    dx
  2898.     mov    dx,si            ; strlen wants string pointer in dx
  2899.     call    strlen            ; get length of filename part into cx
  2900.     pop    dx
  2901.     jcxz    fpar7a            ; any chars to look at? z = no
  2902. fpars7:    cmp    byte ptr [si],'.'    ; look for a dot in filename
  2903.     je    fpars8            ; e = found one
  2904.     inc    si            ; look at next filename char
  2905.     loop    fpars7            ; keep looking until cx = zero
  2906. fpar7a:    mov    si,ax            ; no dot. recover starting address
  2907.     mov    byte ptr [si+8],0    ; forcably truncate mainname to 8 char
  2908.     call    strcpy            ; copy this part to filename field
  2909.     jmp    short fparsx        ;  and exit
  2910. fpars8: mov    byte ptr [si+4],0   ; plant terminator after dot + 3 ext chars
  2911.     mov    cx,si
  2912.     sub    cx,ax        ; cx now = number of chars in mainname field
  2913.     cmp    cx,9            ; more than 8?
  2914.     jb    fpars9            ; b = no, we're safe
  2915.     mov    cx,8             ; limit ourselves to 8 chars in mainname
  2916. fpars9: push    si             ; remember address of dot and extension
  2917.     mov    si,ax            ; point to start of input filename
  2918.     rep    movsb            ; copy cx chars from si to di (output)
  2919.     mov    byte ptr [di],0        ; plant terminator where dot goes
  2920.     pop    si            ; source = dot and extension address
  2921.     call    strcat        ; append the dot & ext to the filename field
  2922. fparsx: mov    si,ax        ; recover start of filename in input string
  2923.     mov    byte ptr [si],0        ; terminate path field
  2924.     pop    si
  2925.     pop    di
  2926.     pop    es
  2927.     pop    ax
  2928.     pop    cx
  2929.     ret
  2930. FPARSE    ENDP    
  2931.  
  2932. ; Print filename in offset diskio.string.
  2933. PRTFN    PROC    FAR
  2934.     test    flags.remflg,dquiet    ; quiet display mode?
  2935.     jnz    prtfn1            ; nz = yes, don't display filename
  2936.     push    ax            ; saves for messy clrfln routine
  2937.     push    bx
  2938.     push    dx
  2939.     call    clrfln            ; position cursor & blank out the line
  2940.     mov    dx,offset diskio.string
  2941.     call    prtasz
  2942.     pop    dx
  2943.     pop    bx
  2944.     pop    ax
  2945. prtfn1:    ret
  2946. PRTFN    ENDP
  2947.  
  2948.  
  2949. ; Print string to screen from offset ds:di for # bytes given in cx,
  2950. ; regardless of $'s.  All registers are preserved.
  2951.  
  2952. PRTSCR    PROC    FAR
  2953.     jcxz    prtscr4            ; cx = zero means nothing to show
  2954.     push    ax
  2955.     push    bx
  2956.     push    dx
  2957.     mov    dx,di            ; source ptr for DOS
  2958.     cmp    flags.eofcz,0        ; end on Control-Z?
  2959.     jne    prtscr3            ; ne = yes, let DOS do it
  2960.     push    cx            ; else map Control-Z to space
  2961.     push    di
  2962.     push    es
  2963.     push    ds
  2964.     pop    es            ; data to es
  2965.     mov    al,ctlz            ; look for Control-Z
  2966.     cld                ; scan buffer es:di, cx chars worth
  2967. prtscr1:repne    scasb
  2968.     jne    prtscr2            ; ne = found no Control-Z's
  2969.     mov    byte ptr [di-1],' '    ; replace Control-Z with space
  2970.     jcxz    prtscr2            ; z = examined all chars
  2971.     jmp    short prtscr1        ; until examined everything
  2972. prtscr2:pop    es
  2973.     pop    di
  2974.     pop    cx
  2975. prtscr3:mov    bx,1            ; stdout file handle
  2976.     mov    ah,write2
  2977.     int    dos
  2978.     pop    dx
  2979.     pop    bx
  2980.     pop    ax
  2981. prtscr4:ret
  2982. PRTSCR    ENDP
  2983.  
  2984. ; Print to screen asciiz string given in ds:dx. Everything preserved.
  2985. PRTASZ    PROC    FAR
  2986.     push    cx
  2987.     push    di
  2988.     call    strlen            ; get length of asciiz string
  2989.     mov    di,dx            ; where prtscr looks
  2990.     call    prtscr            ; print counted string
  2991.     pop    di
  2992.     pop    cx
  2993.     ret
  2994. PRTASZ    ENDP
  2995.  
  2996. code1    ends 
  2997.     end
  2998.