home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol197 / unsq80.lib < prev    next >
Encoding:
Text File  |  1984-10-17  |  10.0 KB  |  378 lines

  1.  
  2. ;    -------------------------------------------------------------
  3. ;    UNSQ.LIB is a library file to be used with Digital Research's
  4. ;    ED.COM to insert the set of subroutines which it contains
  5. ;    into another program. The purpose of these subroutines is to
  6. ;    read text from a file which has been squeezed by a program
  7. ;    such as SQ.COM (SIG/M 58.26).
  8. ;
  9. ;    UNSQ.LIB is divided into several sections, which can be left
  10. ;    as they are, or integrated into the host program, according
  11. ;    to your sense of orderliness. There are two subroutines that
  12. ;    will be most likely to be called upon - unii and onsq. The
  13. ;    first should be called for initialization, because it reads
  14. ;    in the code directory and sets it up. It also separates out
  15. ;    the file's checksum and the unsqueezed file name. The second
  16. ;    is to be called each time that a character is to be taken out
  17. ;    of the squeezed file.
  18. ;
  19. ;    UNSQ.LIB assumes that the host program contains the following
  20. ;    three subroutines:
  21. ;
  22. ;        ibyt - which will deliver one character from an
  23. ;               external input stream each time it is called.
  24. ;               the external stream can be taken from memory,
  25. ;               from a buffer that is periodically replenished
  26. ;               from disk, or whatever.
  27. ;
  28. ;        ufil - which will dispose of the characters forming
  29. ;               the unsqueezed file name one by one. It might
  30. ;               ignore them, store them in some file control
  31. ;               block, or make some other use of them.
  32. ;
  33. ;        ferm - which will type a fatal error message on the
  34. ;               console and then return to CP/M - or take any
  35. ;               other action which is desired.
  36. ;
  37. ;             UNSQ.LIB  Copyright (C) 1984
  38. ;            Universidad Autonoma de Puebla
  39. ;                July 14, 1984
  40. ;
  41. ;    [Harold V. McIntosh, 14 July 1984]
  42. ;    -------------------------------------------------------------
  43.  
  44. ;    -------------------------------------------------------------
  45. ;    Section 1.  Equivalences defining constants.
  46. ;
  47. ;            CR, LF are used in the messages, and are
  48. ;            traditionally defined in each program. 
  49. ;
  50. ;            csiz is the expected maximum number of
  51. ;            characters which have been coded; 256
  52. ;            is appropriate if all possible bytes may
  53. ;            have been encoded.
  54. ;
  55. ;            <idhi,idlo> = <FF76> but some other pair
  56. ;            might sometimes be used to mark a squeezed
  57. ;            file
  58.  
  59. CR    equ    0DH
  60. LF    equ    0AH
  61.  
  62. csiz    equ    256
  63. idhi    equ    0FFH
  64. idlo    equ    076H
  65.  
  66. ;    -----------------------------------------------------------
  67. ;    Section 2.  Initialization.
  68. ;
  69. ;        <call unii> will initialize two necessary variables
  70. ;        (rcnt, roco), then start reading the squeezed file.
  71. ;        This file must previously have been opened, and its
  72. ;        suitability checked - eg that it has extension ?Q?.
  73. ;        It may even have already been loaded into memory.
  74. ;        All interaction with it is through <call ibyt>, and
  75. ;        the only requirement is that ibyt start reading the
  76. ;        file from the beginning.
  77. ;
  78. ;        unii goes through the following sequence:
  79. ;
  80. ;            check squeezed marker <FF76>
  81. ;            read and store checksum
  82. ;            read, make available name for original file
  83. ;            check the length of the code dictionary
  84. ;            load and store the code dictionary
  85. ;
  86. ;        unii will offer a fatal error message if
  87. ;
  88. ;            the marker <idhi,idlo> is not present
  89. ;            space will not accomodate the code table
  90. ;
  91. ;        unii requires two host subroutines:
  92. ;
  93. ;            ibyt returns the next byte from the source
  94. ;            ufil disposes of the original file name
  95. ;
  96. ;        No assumptions should be made concerning conservation
  97. ;        of the 8080 registers by unii.
  98. ;
  99. ;        unii will alter the following memory registers:
  100. ;
  101. ;            rcnt - repeated character - set to 0
  102. ;            roco - count bits/byte - set to 1
  103. ;            cksm - checksum - set to file's checksum
  104. ;            dode - code table - loaded with dictionary
  105.  
  106. ;    Initializations.
  107.  
  108. unii:    mvi    a,0
  109.     sta    rcnt        ;repetition count
  110.     mvi    a,1
  111.     sta    roco        ;bit rotation counter
  112.  
  113. ;    Set up code table. Squeezed files seem to begin with the
  114. ;    hexadecimal word (FF76) stored in Intel byte order, which
  115. ;    would not be likely to start an unsqueezed file.
  116.  
  117. cota:    call    ibyt        ;fetch one byte from input stream
  118.     cpi    idlo
  119.     jnz    cote        ;mssg: 'not squeezed file'
  120.     call    ibyt        ;fetch one byte from input stream
  121.     cpi    idhi
  122.     jz    rchk        ;read checksum
  123. cote:    lxi    d,nsqz        ;'not a squeezed file'
  124.     jmp    ferm        ;fatal error message
  125.  
  126. ;    The "squeezed" marker is followed by a two-byte checksum,
  127. ;    which is the simple sum of all the one-byte characters in
  128. ;    the source file, carried as a two byte sum modulo 2**16.
  129.  
  130. rchk:    call    iwor        ;fetch two bytes from input stream
  131.     shld    cksm        ;checksum
  132.  
  133. ;    Unsqueezed file name. It is an ASCII sequence, may be lower
  134. ;    case if SQ.COM received it in response to a prompt, ending
  135. ;    with a zero byte. Some trash may be present if SQ.COM wasn't
  136. ;    used correctly. If the file name is to be used for something,
  137. ;    such as defining an output file or checking the file type,
  138. ;    this is the place to insert the appropriate code.
  139.  
  140. luup:    call    ibyt        ;fetch one byte from input stream
  141.     push    psw
  142.     call    ufil        ;process unsqueezed filename
  143.     pop    psw
  144.     ora    a
  145.     jnz    luup
  146.  
  147. ;    Load code dictionary. It is preceded by its two-byte length,
  148. ;    and consists of a series of pairs of two-byte addresses. For
  149. ;    each bit in the code, select the first element (0) or the
  150. ;    second (1) element of the pair. If the pair is positive, it
  151. ;    is the table entry (code + 4*index) at which to continue with
  152. ;    the next bit. If the pair is negative, it is the complement
  153. ;    of the coded ASCII character (low order byte except for [end]).
  154.  
  155. ldic:    call    iwor        ;fetch two bytes from input stream
  156.     dad    h
  157.     dad    h
  158.     mov    c,l
  159.     mov    b,h
  160.     lxi    h,csiz
  161.     mov    a,l
  162.     sub    c
  163.     mov    a,h
  164.     sbb    b
  165.     jnc    ldii
  166.     lxi    d,ntab        ;'insufficient dictionary'
  167.     jmp    ferm        ;fatal error message
  168.  
  169. ldii:    lxi    h,code        ;decoding table
  170. ldij:    push    b
  171.     push    h
  172.     call    ibyt        ;fetch one byte from input stream
  173.     pop    h
  174.     pop    b
  175.     mov    m,a
  176.     inx    h
  177.     dcx    b
  178.     mov    a,c
  179.     ora    b
  180.     jnz    ldij
  181.     ret
  182.  
  183. ;    ----------------------------------------------------------
  184. ;    Section 3.  Read next unsqueezed byte.
  185. ;
  186. ;            <call onby> will withdraw a sufficient
  187. ;            number of bits from the source file to
  188. ;            generate one byte, returning it in the
  189. ;            accumulator. The end of the source file
  190. ;            will be signified by c = 1; otherwise
  191. ;            c = 0 will prevail. Reading of the source
  192. ;            file may terminate before this condition
  193. ;            is reached, for example if the source
  194. ;            was an ASCII file terminating with ^Z,
  195. ;            or a HEX file terminated by a final line.
  196. ;
  197. ;            The preservation of registers cannot be
  198. ;            guaranteed; surround <call onby> with
  199. ;            pushes and pops is such continuity is
  200. ;            required.
  201. ;
  202. ;            onby will solicit the fatal error message
  203. ;            subroutine if the [eof] marker signified
  204. ;            by c = 1 has been reached without the
  205. ;            checksum having balanced. This protection
  206. ;            can be secured for files that were not
  207. ;            read in their entirity by reading out the
  208. ;            remaining bytes in a dummy loop.
  209. ;
  210. ;            onby alters the following memory registers:
  211. ;
  212. ;                lach - last character deposited
  213. ;                rcnt - repetition count
  214. ;                roco - rotating bit counter
  215. ;                roby - rotating byte
  216. ;                cksm - checksum
  217.  
  218. ;    Type unsqueezed code. Beware of the [end] marker,
  219. ;    and also the repeat marker 90H which occurs in the
  220. ;    combination <char><90H><count>. When count is zero,
  221. ;    90H itself is intended; otherwise <char> is to be
  222. ;    repeated <count> times, including the occurrence just
  223. ;    before 90H was seen.
  224.  
  225. onsq:    lda    rcnt        ;repetition count
  226.     ora    a
  227.     jnz    onsr
  228.     call    dnch        ;decode next character
  229.     jc    vchk        ;verify the checksum
  230.     cpi    090H        ;repeat last character
  231.     jnz    onsu        ;normal character
  232.     call    dnch        ;decode next character
  233.     ora    a
  234.     jz    onss
  235.     dcr    a
  236. onsr:    dcr    a
  237.     sta    rcnt        ;repetition count
  238.     lda    lach
  239.     jmp    achk
  240.  
  241. onss:    mvi    a,090H
  242.     jmp    achk
  243.  
  244. onsu:    sta    lach        ;last character typed
  245.     jmp    achk
  246.  
  247. ;    Decode next character.
  248.  
  249. dnch:    lxi    h,code        ;decoding table
  250. dncr:    call    ibit        ;read next bit
  251.     jnc    dncs        ;skip for 1, stay for 0
  252.     inx    h
  253.     inx    h
  254. dncs:    mov    e,m        ;get next offset
  255.     inx    h
  256.     mov    d,m
  257.     mov    a,d
  258.     cpi    0FEH        ;FEFF means [end]
  259.     jz    dnct
  260.     ora    a
  261.     jp    dncu        ;p means new offset
  262.     mov    a,e        ;m means complemented char
  263.     cma
  264.     stc
  265.     cmc
  266.     ret
  267.  
  268. dnct:    stc            ;flag [end] with carry bit
  269.     ret
  270.  
  271. ;    Calculate <code>+4*<offset>.
  272.  
  273. dncu:    lxi    h,code        ;decoding table
  274.     dad    d
  275.     dad    d
  276.     dad    d
  277.     dad    d
  278.     jmp    dncr
  279.  
  280. ;    Read one bit at a time.
  281.  
  282. ibit:    push    h
  283.     lxi    h,roco        ;bit rotation counter
  284.     dcr    m
  285.     jnz    ibiu
  286.     mvi    m,8
  287.     call    ibyt        ;fetch one byte from input stream
  288.     sta    roby        ;rotating byte
  289. ibiu:    lda    roby        ;rotating byte
  290.     rar
  291.     sta    roby        ;rotating byte
  292.     pop    h
  293.     ret
  294.  
  295. ;    Read one word.
  296.  
  297. iwor:    call    ibyt        ;fetch one byte from input stream
  298.     mov    l,a
  299.     push    h
  300.     call    ibyt        ;fetch one byte from input stream
  301.     pop    h
  302.     mov    h,a
  303.     ret
  304.  
  305. ;    Accumulate checksum.
  306.  
  307. achk:    lxi    h,cksm
  308.     mov    b,a
  309.     mov    a,m
  310.     sub    b
  311.     mov    m,a
  312.     inx    h
  313.     mov    a,m
  314.     sbi    0
  315.     mov    m,a
  316.     mov    a,b
  317.     stc
  318.     cmc
  319.     ret
  320.  
  321. ;    Verify the checksum.
  322.  
  323. vchk:    lhld    cksm        ;checksum
  324.     mov    a,l
  325.     ora    h
  326.     stc
  327.     rz            ;return to CP/M
  328.     lxi    d,chno        ;'Checksum failure.'
  329.     jmp    ferm        ;fatal error message
  330.  
  331. ;    -----------------------------------------------------------
  332. ;    Section 4.  Host subroutines.
  333. ;
  334. ;            The following subroutines must be provided
  335. ;            by the host program:
  336. ;
  337. ;                ibyt - deliver the next byte from
  338. ;                the source program, in register A,
  339. ;                on each call. Need not preserve any
  340. ;                8080 registers.
  341. ;
  342. ;                ufil - must absorb one byte from
  343. ;                register A on each call. These bytes
  344. ;                will be the information that is
  345. ;                nominally the name of the source
  346. ;                file, SOURCE.EXT, including the dot.
  347. ;                ufil should be prepared for possible
  348. ;                variants, however. ufil will be given
  349. ;                final zero byte to signal the end of
  350. ;                the bytestream it will receive. Of
  351. ;                course, ufil could be imbedded in
  352. ;                place of a call to it.
  353. ;
  354. ;                ferm - send a fatal error message to
  355. ;                the console. Normally control would
  356. ;                return to CP/M, but some other action
  357. ;                may be taken.
  358.  
  359. ibyt:    ret            ;fetch byte from the input stream
  360. ufil:    ret            ;process unsqueezed filename
  361. ferm:    ret            ;fatal error message
  362.  
  363. ;    -------------------------------------------------------------
  364. ;    Section 5.  Messages and memory locations used by the program.
  365.  
  366. ntab:    db    CR,LF,'Insufficient dictionary space.$'
  367. nsqz:    db    CR,LF,'Not a squeezed file.$'
  368. chno:    db    CR,LF,'Checksum failure.$'
  369.  
  370. lach:    ds    1        ;last character typed
  371. rcnt:    ds    1        ;repetition count
  372. roco:    ds    1        ;rotating bit counter
  373. roby:    ds    1        ;rotating byte
  374. cksm:    ds    2        ;checksum
  375. code:    ds    4*csiz        ;decoding table
  376.  
  377.     end
  378.