<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://fileformats.archiveteam.org/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://fileformats.archiveteam.org/index.php?action=history&amp;feed=atom&amp;title=CrLZH%2FLZHREL.DOC</id>
		<title>CrLZH/LZHREL.DOC - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://fileformats.archiveteam.org/index.php?action=history&amp;feed=atom&amp;title=CrLZH%2FLZHREL.DOC"/>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/index.php?title=CrLZH/LZHREL.DOC&amp;action=history"/>
		<updated>2026-05-08T05:07:02Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.19.2</generator>

	<entry>
		<id>http://fileformats.archiveteam.org/index.php?title=CrLZH/LZHREL.DOC&amp;diff=7408&amp;oldid=prev</id>
		<title>JTN: LZHREL.DOC extracted from CRLZH20.LBR, provided as some sort of reference to the CrLZH format</title>
		<link rel="alternate" type="text/html" href="http://fileformats.archiveteam.org/index.php?title=CrLZH/LZHREL.DOC&amp;diff=7408&amp;oldid=prev"/>
				<updated>2012-12-06T01:54:12Z</updated>
		
		<summary type="html">&lt;p&gt;LZHREL.DOC extracted from CRLZH20.LBR, provided as some sort of reference to the &lt;a href=&quot;/wiki/CrLZH&quot; title=&quot;CrLZH&quot;&gt;CrLZH&lt;/a&gt; format&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;A document LZHREL.DOC including some information on the [[CrLZH]] format (buried in information about interfacing with a library file -- scroll down), extracted as LZHREL.DYC from [http://www.classiccmp.org/cpmarchives/cpm/mirrors/oak.oakland.edu/pub/cpm/squsq/crlzh20.lbr CRLZH20.LBR] (itself compressed with CrLZH):&lt;br /&gt;
&lt;br /&gt;
                      UNLZH.REL and CRLZH.REL Documentation&lt;br /&gt;
               for Version 2.0 (with RUNTIME buffer allocation)&lt;br /&gt;
                                   July  1991&lt;br /&gt;
 &lt;br /&gt;
                                    Abstract&lt;br /&gt;
                                   ----------&lt;br /&gt;
 &lt;br /&gt;
   UNLZH.REL and CRLZH.REL contain assembly language routines for the decoding &lt;br /&gt;
   and generation of LZH-encoded files, respectively.  The routines need only &lt;br /&gt;
   be supplied with a pointer to a large scracth area and linkages to character &lt;br /&gt;
   input and character output routines to be used.  There are a few easily met &lt;br /&gt;
   functional requirements for the calling routine and I/O routine.&lt;br /&gt;
 &lt;br /&gt;
   No Z80 opcodes are used, so these routines may be used on 8080/8085/V20/Z80 &lt;br /&gt;
   based machines.&lt;br /&gt;
 &lt;br /&gt;
   The coding contained within UNLZH.REL and CRLZH.REL are Copyright (c) 1989, &lt;br /&gt;
   1991 by Roger Warren and may not be used or reproduced on a for-profit &lt;br /&gt;
   basis.  Non-profit use is freely permitted.  The author will not be &lt;br /&gt;
   responsible for any damage, loss, etc.  caused by the use of these programs.&lt;br /&gt;
 &lt;br /&gt;
                        Version History and Compatibility&lt;br /&gt;
                        ---------------------------------&lt;br /&gt;
 &lt;br /&gt;
   Version 1.1 was released in Sept. '89 and was the first public offering of &lt;br /&gt;
   LZH encoding for CP/M.&lt;br /&gt;
 &lt;br /&gt;
   Version 2.0 (July '91) introduces several improvements/changes:&lt;br /&gt;
       More efficient encoding&lt;br /&gt;
       Greater speed&lt;br /&gt;
       More compact object code&lt;br /&gt;
 &lt;br /&gt;
   There are NO interface changes from the 1.x version.&lt;br /&gt;
 &lt;br /&gt;
   Of greatest importance is the encoding improvement.  This change, while &lt;br /&gt;
   generating even smaller output files, means that files compressed with &lt;br /&gt;
   version 2.x programs cannot be decoded by old 1.x programs.&lt;br /&gt;
 &lt;br /&gt;
   However, the version 2.x UNLZH module DYNAMICALLY ADJUSTS for 1.x encoded &lt;br /&gt;
   input files.  Thus, version 2.x of UNLZH can be used on all LZH-encoded &lt;br /&gt;
   files regardless of which algorithm version was used to encode the files.&lt;br /&gt;
 &lt;br /&gt;
   By extensive rewriting for size and speed, a 20% improvement in performance &lt;br /&gt;
   was achieved.  Since the LZH algorithm is intrinsically slow, this will be &lt;br /&gt;
   of great interest to many.  The recoding project allowed the incorporation &lt;br /&gt;
   of version 2.x extensions to the original algorithm while not appreciably &lt;br /&gt;
   affecting the code module size.&lt;br /&gt;
 &lt;br /&gt;
                                Care and Feeding&lt;br /&gt;
                               ------------------&lt;br /&gt;
 &lt;br /&gt;
   The infomation that follows documents both CRLZH.REL and UNLZH.REL.  One or &lt;br /&gt;
   both may be in the library this file is in, depending upon the nature of &lt;br /&gt;
   the program(s) it's bundled with...so ignore the superfluous information &lt;br /&gt;
   (if any).&lt;br /&gt;
 &lt;br /&gt;
   UNLZH.REL performs LZH decoding.  It's progamming interface is similar to &lt;br /&gt;
   the UNCR.REL it was made to mimic.  The programmer must provide the program &lt;br /&gt;
   with 8k of buffer space.  If RUNTIME buffer allocation is selected (it IS &lt;br /&gt;
   selected in the version supplied with LT, FCRLZH, CRLZH, and UCRLZH), a &lt;br /&gt;
   pointer to the buffer must be supplied in the H/L register pair when the &lt;br /&gt;
   routine is invoked.  If RUNTIME buffer allocation is not selected, the user &lt;br /&gt;
   must supply a PUBLIC symbol, UTABLE, which is the base of the provided &lt;br /&gt;
   buffer area.&lt;br /&gt;
 &lt;br /&gt;
   Once invoked, the routine allocates its own stack and 'stays in control' &lt;br /&gt;
   until the de-compression is completed (or an error is encountered).  The &lt;br /&gt;
   programmer must supply two routines GLZHUN and PLZHUN, via which UNLZH &lt;br /&gt;
   'GETS' bytes from the input stream and 'PUTS' bytes to the output stream, &lt;br /&gt;
   respectively.&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
   UNLZH *DOES NOT* compute/process checksums, etc. on the  input file.  Any &lt;br /&gt;
   support of such features must be handled externally.&lt;br /&gt;
 &lt;br /&gt;
   GLZHUN and PLZHUN should save all registers except the A register and &lt;br /&gt;
   flags. GLZHUN must return the next character from the input stream in the A &lt;br /&gt;
   register.  GLZHUN should return with the CARRY flag RESET for a valid &lt;br /&gt;
   character, or with the CARRY flag SET when the end of the input stream is &lt;br /&gt;
   encountered (the content of the A reg should be zero in that case).&lt;br /&gt;
 &lt;br /&gt;
   Upon exit (return to the caller), UNLZH returns the following information:&lt;br /&gt;
 &lt;br /&gt;
              Carry reset (or A reg = 0) - Success&lt;br /&gt;
              Carry set,  A reg = 1      - Newer version required&lt;br /&gt;
              Carry set,  A reg = 2      - File not LZH endocoded&lt;br /&gt;
              Carry set,  A reg = 3      - Bad or corrupt file&lt;br /&gt;
              Carry set,  A reg = 4      - Insufficient memory&lt;br /&gt;
 &lt;br /&gt;
   UNLZH has 2 entry points, to be used as the programmer needs:&lt;br /&gt;
 &lt;br /&gt;
     UNLZH is the 'normal' entry point which expects the file to be completely &lt;br /&gt;
     REWOUND.  At this entry point, the entire file is processed - the &lt;br /&gt;
     standard header is examined, but not reported or acted upon.  By &lt;br /&gt;
     examining the return code, the programmer can discern if the file was, &lt;br /&gt;
     indeed, an LZH-encoded file and act accordingly.&lt;br /&gt;
 &lt;br /&gt;
     UNL is a secondary entry point which can be used when the programmer &lt;br /&gt;
     needs to process the standard header information (file name and stamp) &lt;br /&gt;
     and cannot (or doesn't want to) rewind the file.  When this entry point &lt;br /&gt;
     is invoked, the header (down to and including the stamps/comment &lt;br /&gt;
     terminating zero) must have been processed (so the next byte in the input &lt;br /&gt;
     stream will be the revision level).&lt;br /&gt;
      &lt;br /&gt;
   The revision level of UNLZH.REL performs is at the byte at UNLZH-1.  A hex &lt;br /&gt;
   value of 11 indicates version 1.1, etc.&lt;br /&gt;
 &lt;br /&gt;
   CRLZH.REL performs LZH encoding.  It's progamming interface is similar to &lt;br /&gt;
   the CRUNCH.REL it was made to mimic.	The programmer must provide the &lt;br /&gt;
   program with 20k of buffer space.  If RUNTIME buffer allocation is selected &lt;br /&gt;
   (it IS selected in the version supplied with LT, FCRLZH, CRLZH, and &lt;br /&gt;
   UCRLZH),a pointer to the buffer must be supplied in the H/L register pair &lt;br /&gt;
   when the routine is invoked.  If RUNTIME buffer allocation is not selected, &lt;br /&gt;
   the user must supply a PUBLIC symbol, CTABLE, which is the base of the &lt;br /&gt;
   provided buffer area.&lt;br /&gt;
 &lt;br /&gt;
   In addition, at invocation time the A register must contain a value for &lt;br /&gt;
   CRLZH to install in the 'CHECKSUM FLAG' portion of the file header (see &lt;br /&gt;
   below).  This byte, to be semi-compatible with C.B. Falconer's version of &lt;br /&gt;
   CRN for the 8080, is a subset of CRN's strategy byte:&lt;br /&gt;
 &lt;br /&gt;
                      value (hex)   meaning&lt;br /&gt;
                      ----------------------------------------------------&lt;br /&gt;
                           00       Standard modulo 65536 checksum is used&lt;br /&gt;
                           10       CRC16 is used&lt;br /&gt;
                           20,30    Unassigned&lt;br /&gt;
 &lt;br /&gt;
   SUPPORT FOR CHECK INFORMATION MUST BE EXTERNALLY PROVIDED IN THE &lt;br /&gt;
   USER-SUPPLIED I/O ROUTINES (see below).  THIS IS ALSO TRUE OF CRN...BUT WAS &lt;br /&gt;
   NOT EMPHASIZED!  CRLZH merely provides the support for posting the value in &lt;br /&gt;
   the output stream since it happens to 'follow' some of the information &lt;br /&gt;
   posted by CRLZH (see the header description, below).&lt;br /&gt;
 &lt;br /&gt;
   CRLZH supports no other features of the CRN's strategy byte, all other bits &lt;br /&gt;
   are ignored.&lt;br /&gt;
 &lt;br /&gt;
   Once invoked, the routine allocates its own stack and 'stays in control' &lt;br /&gt;
   until the de-compression is completed (or an error is encountered).  The &lt;br /&gt;
   programmer must supply two routines GLZHEN and PLZHEN, via which CRLZH &lt;br /&gt;
   'GETS' bytes from the input stream and 'PUTS' bytes to the output stream, &lt;br /&gt;
   respectively.&lt;br /&gt;
 &lt;br /&gt;
   CRLZH *DOES NOT* compute/process checksums, etc. on the  input file.  Any &lt;br /&gt;
   support of such features must be handled externally.  Specifically, the &lt;br /&gt;
   GLZHEN routine must provide for the accumulation of check information and &lt;br /&gt;
   the caller must write that check information to the output stream when &lt;br /&gt;
   CRLZH returns to the caller.&lt;br /&gt;
 &lt;br /&gt;
   GLZHEN and PLZHEN should save all registers except the A register and &lt;br /&gt;
   flags. GLZHEN must return the next character from the input stream in the A &lt;br /&gt;
   register.  GLZHEN should return with the CARRY flag RESET for a valid &lt;br /&gt;
   character, or with the CARRY flag SET when the end of the input stream is &lt;br /&gt;
   encountered (the content of the A reg should be zero in that case).  As a &lt;br /&gt;
   service to the user's output processor, every 256th call to PLZHEN is made &lt;br /&gt;
   with the Z flag set (for monitoring).  All other times the Z flag is reset.&lt;br /&gt;
 &lt;br /&gt;
   Upon exit (return to the caller), CRLZH returns the following information:&lt;br /&gt;
 &lt;br /&gt;
              Carry reset (or A reg = 0) - Success&lt;br /&gt;
              Carry set,  A reg = 1      - File already LZH-Encoded,CRUNCHed or&lt;br /&gt;
                                           SQueezed&lt;br /&gt;
              Carry set,  A reg = 2      - File empty&lt;br /&gt;
              Carry set,  A reg = 3      - Insufficient memory&lt;br /&gt;
 &lt;br /&gt;
   CRLZH has a single entry point at the label CRLZH.  The user must have &lt;br /&gt;
   placed the standard header information in the output stream and must have &lt;br /&gt;
   the input stream REWOUND prior to invoking CRLZH.&lt;br /&gt;
 &lt;br /&gt;
   The revision level of CRLZH.REL performs is at the byte at CRLZH-1.  A hex &lt;br /&gt;
   value of 11 indicates version 1.1, etc.&lt;br /&gt;
 &lt;br /&gt;
   Since CRLZH and UNLZH allocate their own stacks, the user is reminded not &lt;br /&gt;
   to make too large a use of that stack in the user-supplied I/O routines.  &lt;br /&gt;
   In addition, if the user-supplied I/O routines decide to abort the CRLZH or &lt;br /&gt;
   UNLZH operation (due to operator keystrokes, for example), the user must &lt;br /&gt;
   take steps to restore his own stack.  Upon a normal (or error) return from &lt;br /&gt;
   CRLZH or UNLZH the user's stack is properly restored.&lt;br /&gt;
 &lt;br /&gt;
                           STANDARD HEADER information&lt;br /&gt;
                          -----------------------------&lt;br /&gt;
 &lt;br /&gt;
   LZH encoding follows Steve Greenberg's CRUNCH file format.  The header &lt;br /&gt;
   contains information identifying compression format, original file name, &lt;br /&gt;
   etc:&lt;br /&gt;
     field  size     value    Purpose&lt;br /&gt;
   -----------------------------------------------------------------------  &lt;br /&gt;
       1   1 byte    076h     Signifies compressed form&lt;br /&gt;
       2   1 byte    0FDh     Signifies LZH encoding (0ff is for squeezed and&lt;br /&gt;
                              0feh is for CRUNCHED)&lt;br /&gt;
       3   variable  User     Original file name in the form name.ext Trailing&lt;br /&gt;
                   supplied   blanks on the name portion should be suppressed,&lt;br /&gt;
                              but a full 3 characters following the '.' should&lt;br /&gt;
                              be used for the extension (i.e. no blank&lt;br /&gt;
                              suppression).&lt;br /&gt;
       4   variable  User     OPTIONAL.  Used for file comment/stamp.  If used&lt;br /&gt;
                              the convention is that the comment is placed in&lt;br /&gt;
                              square brackets [Like this].  Other information&lt;br /&gt;
                              may be placed here (e.g., date stamp).  The&lt;br /&gt;
                              logical restriction is that a binary zero must&lt;br /&gt;
                              not be part of the comment and/or other informa-&lt;br /&gt;
                              tion.&lt;br /&gt;
       5   1 byte     00h     Signifies end of STANDARD HEADER&lt;br /&gt;
   &lt;br /&gt;
   For use of CRLZH, the user must supply all of the information above.&lt;br /&gt;
 &lt;br /&gt;
   For UNLZH, use of the UNLZH entry point causes UNLZH to expect to process &lt;br /&gt;
   the above information.  It will discard the file name and optional &lt;br /&gt;
   comment/stamp, but will examine the general form (first 2 fields for a &lt;br /&gt;
   match and general form of the rest of the header).  If the user chooses to &lt;br /&gt;
   use the UNL entry point, UNL will expect to process the first byte &lt;br /&gt;
   following the end of the standard header.&lt;br /&gt;
 &lt;br /&gt;
   What follows is the following:&lt;br /&gt;
 &lt;br /&gt;
     field  size     value    Purpose&lt;br /&gt;
   -----------------------------------------------------------------------  &lt;br /&gt;
       6   1 byte  variable   Identifies generating program revision level.&lt;br /&gt;
                              (11H signifies program generated by version 1.1&lt;br /&gt;
       7   1 byte  variable   Significant revision level.  Indicates major&lt;br /&gt;
                              revision level of algorithm for decoding program&lt;br /&gt;
                              compatability. (10h indicates significant&lt;br /&gt;
                              revision 1.0)&lt;br /&gt;
       8   1 byte  variable   Check type.  0=checksum, 1=CRC16, others&lt;br /&gt;
                              currently undefined.&lt;br /&gt;
       9   1 byte     05h     Currently a SPARE, set to 05H by convention.&lt;br /&gt;
 &lt;br /&gt;
   Following this is the compressed file, itself.&lt;br /&gt;
 &lt;br /&gt;
                 What LZH compression does and how it compares&lt;br /&gt;
                -----------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
   FIRST - It's SLOW.  Much slower than CRUNCH.  About even with the old &lt;br /&gt;
   SQueeze.  It's the nature of the algorithm, but the current implementation &lt;br /&gt;
   contributes somewhat (more on that later).&lt;br /&gt;
 &lt;br /&gt;
   The most impressive aspect of the algorithm is that it compresses further &lt;br /&gt;
   than CRUNCH.  The nature of material being compressed is important - prose &lt;br /&gt;
   and high level language code will compress further.  Since the algorithm &lt;br /&gt;
   depends, in part, on patterns within the file being compressed, I was &lt;br /&gt;
   somewhat surprised to discover that it does a better job (in general) on &lt;br /&gt;
   .COM files than CRUNCH.  Personally, I was surprised to discover that LZH &lt;br /&gt;
   compression of CRUNCHed files is possible (but I've disabled that ability &lt;br /&gt;
   in this release)!&lt;br /&gt;
 &lt;br /&gt;
   Examples:&lt;br /&gt;
    CRUNCH of SLR180.COM   106% ratio   (actually made a larger file)&lt;br /&gt;
    CRLZH  of SLR180.COM    84% ratio&lt;br /&gt;
    CRUNCH of TYPELZ22.Z80  45% ratio&lt;br /&gt;
    CRLZH  of TYPELZ22.Z80  40% ratio&lt;br /&gt;
    CRUNCH of 'C' source    45% ratio   (typical 'C' src selected at random)&lt;br /&gt;
    CRLZH  of 'C' source    33% ratio   (same file as above)&lt;br /&gt;
 &lt;br /&gt;
                                A small history&lt;br /&gt;
                               -----------------&lt;br /&gt;
 &lt;br /&gt;
   I am NOT the originator of the LZH encoding.  The program that started my &lt;br /&gt;
   whole involvement in the introduction of this method of compression to the &lt;br /&gt;
   8-bit world bears the following opening comments:&lt;br /&gt;
      /*&lt;br /&gt;
      * LZHUF.C English version 1.0&lt;br /&gt;
      * Based on Japanese version 29-NOV-1988&lt;br /&gt;
      * LZSS coded by Haruhiko OKUMURA&lt;br /&gt;
      * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI&lt;br /&gt;
      * Edited and translated to English by Kenji RIKITAKE&lt;br /&gt;
      */&lt;br /&gt;
 &lt;br /&gt;
   This 'C' program implemented the compression algorithm of the LHARC program &lt;br /&gt;
   which arrived on the US scene in the spring of '89.&lt;br /&gt;
 &lt;br /&gt;
   Being of a curious nature, I figured I'd play with the algorithm just to &lt;br /&gt;
   understand it (the internal comments were, indeed, sparse - leaving MUCH to &lt;br /&gt;
   the reader's contemplation/reverse engineering) while 'better minds' than I &lt;br /&gt;
   tackled it in earnest.&lt;br /&gt;
 &lt;br /&gt;
   Months passed.  I found that I was 'mastering' the algorithm (read that as &lt;br /&gt;
   demonstrating to myself that I understood it) by converting it piece-wise &lt;br /&gt;
   to assembly language.  After a while, I was left with a 'C' language main &lt;br /&gt;
   program, run time library, and I/O with the business end of the compression &lt;br /&gt;
   and decompression implemented entirely in assembly language.  Since the &lt;br /&gt;
   expected event of one of the 'heavies' in the PD and/or compression world &lt;br /&gt;
   releasing a CP/M version of the compression algorithm hadn't come to pass, &lt;br /&gt;
   I set about making a version myself.&lt;br /&gt;
 &lt;br /&gt;
   The natural choice was to prepare an analog to the CRUNCH.REL and UNCR.REL &lt;br /&gt;
   of Mr. Steven Greenberg and Mr. C.B. Falconer and append to/substitute in &lt;br /&gt;
   the existing, widely known programs for handling SQueezed and/or CRUNCHed &lt;br /&gt;
   files.&lt;br /&gt;
 &lt;br /&gt;
   I saw no reason to tamper with the format CRUNCH uses on the output file.  &lt;br /&gt;
   Therefore, with the exception of taking the 'next' file type in sequence &lt;br /&gt;
   (SQueezed files begin with a 76h,FFh sequence; Crunched files with 76h,FEh; &lt;br /&gt;
   so LZH encoded files begin with 076h,FDh) and setting the revision levels &lt;br /&gt;
   in the header to appropriate values , there's no difference in the output &lt;br /&gt;
   file format.  So, you can probably coax your time/date stamping into &lt;br /&gt;
   operating on LZH encoded files.&lt;br /&gt;
 &lt;br /&gt;
 R. Warren&lt;br /&gt;
 Sysop, The Elephant's Graveyard (Z-Node#9)&lt;br /&gt;
 619-270-3148 (PCP area CASDI)&lt;/div&gt;</summary>
		<author><name>JTN</name></author>	</entry>

	</feed>