LHA

From Just Solve the File Format Problem
(Difference between revisions)
Jump to: navigation, search
(Software)
(Compression schemes: Added table of "other" identifiers)
(29 intermediate revisions by 3 users not shown)
Line 4: Line 4:
 
|mimetypes={{mimetype|application/x-lzh-compressed}}
 
|mimetypes={{mimetype|application/x-lzh-compressed}}
 
|pronom={{PRONOM|fmt/626}}
 
|pronom={{PRONOM|fmt/626}}
 +
|wikidata={{wikidata|Q368782}}
 
|kaitai struct=lzh
 
|kaitai struct=lzh
 
|released=1988
 
|released=1988
 
}}
 
}}
'''LHA''' is an archiving program and file format created by Haruyasu Yoshizaki in 1988. It was originally called LHarc, then was briefly LH before settling on LHA. In the 1990s, it was the most popular archiving format on the Amiga platform. It also got some use on the PC platform including in the installers for id Software games such as Doom and Quake, because [[ZIP]] compression was inferior until the release of PKZIP 2.0, which brought the formats to parity. At present, it is mostly used in Japan.
+
'''LHA''' is an archiving program and file format created by Haruyasu Yoshizaki (a.k.a. Yoshi) in 1988. It was originally called LHarc, then was briefly LH before settling on LHA. In the 1990s, it was the most popular archiving format on the Amiga platform. It also got some use on the PC platform including in the installers for id Software games such as Doom and Quake, because [[ZIP]] compression was inferior until the release of PKZIP 2.0, which brought the formats to parity.
  
The file format is also known as '''LZH''' (not to be confused with [[CrLZH]], which is also sometimes called this).
+
It was particularly popular in Japan. Most of the best information about it is in Japanese.
 +
 
 +
It supports a number of different compression schemes, most of which use [[LZ77 with Huffman coding|LZ77 combined with Huffman coding]].
 +
 
 +
The file format is also known as '''LZH'''. See the [[LZH|LZH disambiguation page]] for other "LZH" formats.
 +
 
 +
This article covers the format used by LHarc/LHA, as well as "generalized" LHA format: the same file format, but with other compression schemes. The generalized format was possibly designed by Kazuhiko Miki in 1988 for the LArc software, but confirmation of this is needed. If so, it was soon borrowed by LHarc, with new compression schemes.
  
 
== Format details ==
 
== Format details ==
An LHA file consists of a sequence of elements, each representing a member file or directory. There is no global archive-level header.
+
=== File structure ===
 +
An LHA file consists mainly of a sequence of elements, each representing a member file or directory. The sequence is usually terminated by an end-of-archive marker consisting of a single 0x00 byte (but take care, as level 2 headers could start with 0x00). There is no global archive-level header.
  
There are at least four different formats that an element can have. (Note that this is independent of compression schemes.) In LHA jargon, the formats are known as "header levels", and are usually called "header level 0", "... 1", "... 2", and "... 3".
+
=== Member format ===
 +
There are at least four different formats that an element can have. (Note that this is independent of compression schemes.) In LHA jargon, the formats are known as "header levels", and are usually called "header level 0", "... 1", "... 2", and "... 3". The header level is determined by the byte at offset 20 from the beginning of that element.
  
The format of an element is determined by the byte at offset 20 from the beginning of that element. It is possible for different formats to be used in the same LHA file.
+
The header levels are similar, but irritatingly different. They don't even follow the same principles with respect to how they must be parsed.
  
The formats are similar, but irritatingly different. They don't even follow the same principles with respect to how they must be parsed.
+
=== LZH compression overview ===
 +
From a decompression perspective, the LZ77+Huffman schemes work roughly as follows. (This is oversimplified.) There is a ''codes'' Huffman tree, and a separate ''offsets'' tree. A symbol is read using the codes tree which, depending on its value, represents either a literal byte value, or a ''length''. If it is a length, then an additional symbol is read using the offsets tree. Based on the offset and length, a run of recently-decompressed bytes is repeated.
  
 
=== Compression schemes ===
 
=== Compression schemes ===
Wikipedia has a [[Wikipedia:LHA (file format)#Compression methods|list of LHA compression methods]], as identified by the alphanumeric bytes of the ''compression method'' field. It includes the following:
+
Each member file has a 5-byte ''compression method'' field, composed of ASCII characters. The first and last characters are virtually always dashes ("<code>-</code>"), and might be left off when discussing LHA compression schemes. Known schemes:
lh0, lh1, lh2, lh4, lh5, lh6, lh7, lh8, lh9,
+
lha, lhb, lhc, lhd, lhe, lhx,
+
lz2, lz3, lz4, lz5, lz7, lz8, lzs,
+
pc1, pm0, pm1, pm2, pms
+
  
<code>lhd</code> is not actually a compression scheme, but indicates that the element represents a subdirectory.
+
{| class="wikitable"
 +
! ID !! Category !! Description and remarks
 +
|-
 +
|<code>-lh0-</code> || || Uncompressed
 +
|-
 +
|<code>-lh1-</code> || || [[LZ77 with Huffman coding|LZ77+Huffman]], 4k window, [[Adaptive Huffman coding|adaptive Huffman]] for codes, offsets use a pre-defined Huffman tree.
 +
|-
 +
|<code>-lh2-</code> || || LZ77+Huffman, 8k window, adaptive Huffman. Considered obsolete.
 +
|-
 +
|<code>-lh3-</code> || || LZ77+Huffman, 8k window, segmented, static Huffman for codes, offsets can use static Huffman or a pre-defined Huffman tree. Considered obsolete.
 +
|-
 +
|<code>-lh4-</code> || || Like lh5, but 4k window. Rare.
 +
|-
 +
|<code>-lh5-</code> || || [[LZ77 with Huffman coding|LZ77+Huffman]], 8k window, segmented, static Huffman
 +
|-
 +
|<code>-lh6-</code> || || Like lh5, but 32k window
 +
|-
 +
|<code>-lh7-</code> || || Like lh5, but 64k window
 +
|-
 +
|<code>-lh7-</code> || LHARK extension || Refer to [[LHARK]].
 +
|-
 +
|<code>-lh8-</code> ||rowspan="5"| Joe Jared extensions || Like lh5, but 64k window. (Same as lh7.)
 +
|-
 +
|<code>-lh9-</code> || Like lh5, but 128k window. Probably never used.
 +
|-
 +
|<code>-lha-</code> || Like lh5, but 256k window. Probably never used.
 +
|-
 +
|<code>-lhb-</code> || Like lh5, but 512k window. Probably never used.
 +
|-
 +
|<code>-lhc-</code> || Like lh5, but 1M window. Probably never used.
 +
|-
 +
|<code>-lhd-</code> || Special || Not a compression scheme. Indicates that the element represents a subdirectory.
 +
|-
 +
|<code>-lhe-</code> || Joe Jared extensions || Like lh5, but 2M window. Probably never used.
 +
|-
 +
|<code>-lhx-</code> ||rowspan="2"| UNLHA32 extensions ||
 +
|-
 +
|<code>-lx1-</code> ||
 +
|-
 +
|<code>-lz2-</code> ||rowspan="7"| LArc methods ||
 +
|-
 +
|<code>-lz3-</code> ||
 +
|-
 +
|<code>-lz4-</code> || Uncompressed
 +
|-
 +
|<code>-lz5-</code> || LZ77/[[LZSS]], 4k window. Almost identical to "SZDD" used in [[MS-DOS installation compression]].
 +
|-
 +
|<code>-lz7-</code> ||
 +
|-
 +
|<code>-lz8-</code> ||
 +
|-
 +
|<code>-lzs-</code> || LZ77/[[LZSS]], 2k window
 +
|-
 +
|<code>-pc1-</code> ||rowspan="4"| PMarc extensions ||rowspan="4"| Refer to [[PMA]].
 +
|-
 +
|<code>-pm0-</code>
 +
|-
 +
|<code>-pm1-</code>
 +
|-
 +
|<code>-pm2-</code>
 +
|-
 +
|<code>-ah0-</code> ||rowspan="3"| MAR extensions ||rowspan="3"| Refer to [[Micrognosis Compression Archiver]].
 +
|-
 +
|<code>-ari-</code>
 +
|-
 +
|<code>-hf0-</code>
 +
|-
 +
|<code>-lZ0-</code> ||rowspan="3"| PUT/GET variants ||rowspan="3"| Refer to [[PUT]].
 +
|-
 +
|<code>-lZ1-</code>
 +
|-
 +
|<code>-lZ5-</code>
 +
|-
 +
|<code>␠LH0␠</code> ||rowspan="2"| SAR variants ||rowspan="2"| Refer to [[SAR (Streamline Design)]]. The compression IDs begin and end with a space (0x20).
 +
|-
 +
|<code>␠LH5␠</code>
 +
|}
 +
 
 +
The Wikipedia article has [[Wikipedia:LHA (file format)#Compression methods|more information]] about some of the schemes.
 +
 
 +
Other LHA-like identifiers:
 +
 
 +
{| class="wikitable"
 +
! ID !! References and remarks
 +
|-
 +
|<code>-arn-</code> ||rowspan="2"| Possibly used by [[Micrognosis Compression Archiver]].
 +
|-
 +
|<code>-lzw-</code>
 +
|-
 +
|<code>-pms-</code> || Refer to [[PMA]].
 +
|-
 +
|<code>-sqx-</code> || Refer to [[SQX]].
 +
|-
 +
|<code>-sw1-</code> || Refer to [[SWG]].
 +
|-
 +
|<code>-TK1-</code> || Unknown. (Recognized by [[IDArc]].)
 +
|}
  
 
=== Extended headers ===
 
=== Extended headers ===
Line 40: Line 142:
  
 
== Identification ==
 
== Identification ==
Bytes {{magic|'-' 'l' ?? ?? '-'}} appear at offset 2. This is not a global file signature, but represents the compression scheme of the first member file of the archive.
+
LHA can be identified with high accuracy, but doing so can be laborious, due to the lack of a signature, and other complicating factors.
  
If you consider [[PMA]] to be a form of LHA, then the second of these bytes can also be <code>'p'</code>.
+
Identification logic could be based on the header of the first member file. Check that the compression method (offset 2–6) and header level (offset 20) fields have valid values. When suitable and possible, validate the header checksum field -- this depends on the header level.
 +
 
 +
See also the "[[#See also]]" section, for some formats that could masquerade as LHA.
  
 
== See also ==
 
== See also ==
 
* [[PMA]]
 
* [[PMA]]
 +
* [[LHARK]]
 
* [[LHice]]
 
* [[LHice]]
 +
* [[PUT]]
 +
* [[Micrognosis Compression Archiver]]
 +
* [[SAR (Streamline Design)]]
 +
 +
Other LHA-like formats to be aware of:
 +
* [[ARX]]
 +
* [[CAR (MylesHi!)]]
 +
* [[SWG]]
  
 
== Format documentation ==
 
== Format documentation ==
Line 54: Line 167:
 
* [http://apple2.org.za/gswv/a2zine/GS.WorldView/Resources/The.MacShrinkIt.Project/ARCHIVES.TXT Archive format info]
 
* [http://apple2.org.za/gswv/a2zine/GS.WorldView/Resources/The.MacShrinkIt.Project/ARCHIVES.TXT Archive format info]
 
* [http://www.textfiles.com/programming/FORMATS/arc_fmts.txt LZH file header format (among other archive types)]
 
* [http://www.textfiles.com/programming/FORMATS/arc_fmts.txt LZH file header format (among other archive types)]
 +
* [http://www33146ue.sakura.ne.jp/staff/iz/formats/lzh.html LZH format]
 +
* [https://hwiegman.home.xs4all.nl/fileformats/lzh/lzhformat.html LZH format] (Aeco Systems)
 
* [https://github.com/libarchive/libarchive/blob/master/libarchive/archive_read_support_format_lha.c libarchive: archive_read_support_format_lha.c] - Has comments with information about the header formats
 
* [https://github.com/libarchive/libarchive/blob/master/libarchive/archive_read_support_format_lha.c libarchive: archive_read_support_format_lha.c] - Has comments with information about the header formats
  
Line 62: Line 177:
 
* [https://web.archive.org/web/20130906133859/http://homepage1.nifty.com/dangan/en/Content/Program/Java/jLHA/jLHA.html Java library] (from archive.org)
 
* [https://web.archive.org/web/20130906133859/http://homepage1.nifty.com/dangan/en/Content/Program/Java/jLHA/jLHA.html Java library] (from archive.org)
 
* [https://www.libarchive.org libarchive]
 
* [https://www.libarchive.org libarchive]
* LHarc/LHA (DOS software)
+
* [http://lha.osdn.jp/ LHa for Unix] · [https://github.com/jca02266/lha GitHub project]
** {{CdTextfiles|hof91/ARC/LH113C.EXE|LHarc v1.13c}} (1989-05-31) - English
+
** [https://web.archive.org/web/20200301124852/http://www2m.biglobe.ne.jp/~dolphin/lha/lha.htm LHa for Unix (Tsukao Okamoto)] (from archive.org)
** {{CdTextfiles|simtel/simtel20/MSDOS/ARCHIVRS/LHA213.EXE|LHA v2.13}} (1991-07-20) - English
+
* [https://micco.mars.jp/mysoft/unlha32.htm UNLHA32.DLL] and [https://micco.mars.jp/mysoft/lhmelt.htm LHMelt]
** {{CdTextfiles|pdos9606/ARCHIVER/TOOLS/LHA255B.EXE|LHA v2.55b}} (1992-11-24) - Japanese (LHA.EXE) and English (LHA_E.EXE)
+
* LHarc/LHA
* LHarc/LHA source code: {{CdTextfiles|simtel/simtel20/MSDOS/ARCHIVRS/LHARCSRC.ZIP|v1.13b}} · {{CdTextfiles|simtel/simtel20/MSDOS/ARCHIVRS/LHA211SR.ZIP|v2.11}}
+
** For DOS
* [http://www.manmrk.net/tutorials/compress/downloads/larc333.exe LArc v3.33] (May 19, 1989) (DOS software)
+
*** {{CdTextfiles|hof91/ARC/LH113C.EXE|LHarc v1.13c}} (1989-05-31) - English
* {{Deark}} (might be useful for analysis; doesn't decompress the format)
+
*** {{CdTextfiles|simtel/simtel20/MSDOS/ARCHIVRS/LHA213.EXE|LHA v2.13}} (1991-07-20) - English
 
+
*** {{CdTextfiles|simtel/simtel9703/disk2/DISC2/ARCERS/LHA255E.EXE|LHA v2.55 English translation}} (1992-11-15) - (unofficial?)
Note: There is an LHA version "2.55e" ({{CdTextfiles|simtel/simtel9703/disk2/DISC2/ARCERS/LHA255E.EXE|LHA255E.EXE}}), but it is an (unauthorized?) English translation of v2.55, and v2.55 is older than v2.55b.
+
*** {{CdTextfiles|pdos9606/ARCHIVER/TOOLS/LHA255B.EXE|LHA v2.55b}} (1992-11-24) - Japanese (LHA.EXE) and English (LHA_E.EXE)
 +
*** [http://info.elf.stuba.sk/packages/pub/pc/pack/lha266.exe LHA v2.66 test version] (1994-12-30) - Japanese
 +
** For Windows console
 +
*** [http://info.elf.stuba.sk/packages/pub/pc/pack/lha267.exe LHA v2.67 test version] (1995-10-07) - Japanese
 +
** Source code
 +
*** {{CdTextfiles|simtel/simtel20/MSDOS/ARCHIVRS/LHARCSRC.ZIP|v1.13b}}
 +
*** {{CdTextfiles|simtel/simtel20/MSDOS/ARCHIVRS/LHA211SR.ZIP|v2.11}}
 +
* [http://www.manmrk.net/tutorials/compress/downloads/larc333.exe LArc v3.33] (1989-05-19) (DOS software)
 +
* LZHUF.C - Source code related to "lh1" compression
 +
** {{CdTextfiles|powerprogramming/PROGTOOL/COMPRESS/LZHSRC10.ZIP|LZHSRC10.ZIP}} - "LZHUF.C English version 1.0 /  Based on Japanese version 29-NOV-1988 / LZSS coded by Haruhiko OKUMURA / Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI / Edited and translated to English by Kenji RIKITAKE"
 +
** {{CdTextfiles|rbbsv3n1/pac4/okumura.zip|okumura.zip}}... - "lzhuf.c / written by Haruyasu Yoshizaki 11/20/1988 / some minor changes 4/6/1989 / comments translated by Haruhiko Okumura 4/7/1989"
 +
** See [http://www.svgalib.org/rus/lbrate.html lbrate] → lzhuf-post.txt for a discussion of the terms of use.
 +
* {{CdTextfiles|sourcecode/msdos/arc_lbr/ar002.zip|ar version "002" by Haruhiko Okumura}} (1990) (DOS binary + source code) - Implementation of "lh5" compression
 +
* [https://github.com/temisu/ancient Ancient] - Has modern C++ code for decompressing most LHA schemes, but as of this writing there's no easy way to use it.
 +
* {{Deark}} (might be useful for analysis; doesn't necessarily decompress the format)
  
 
== Sample files ==
 
== Sample files ==
 +
* [https://github.com/fragglet/lhasa/tree/master/test/archives lhasa test files]
 
* [https://github.com/libarchive/libarchive/tree/master/libarchive/test libarchive test files] → test_read_format_lha_*.lzh.uu
 
* [https://github.com/libarchive/libarchive/tree/master/libarchive/test libarchive test files] → test_read_format_lha_*.lzh.uu
 
* [http://aminet.net/ aminet]
 
* [http://aminet.net/ aminet]
 +
* {{CdTextfiles|hof91/}} ...
 +
* https://telparia.com/fileFormatSamples/archive/lha/hexify.lha
  
 
== Other links ==
 
== Other links ==
 
* [[Wikipedia:LHA (file format)|Wikipedia article]]
 
* [[Wikipedia:LHA (file format)|Wikipedia article]]

Revision as of 14:53, 13 November 2020

File Format
Name LHA
Ontology
Extension(s) .lha, .lzh, .lzs
MIME Type(s) application/x-lzh-compressed
PRONOM fmt/626
Wikidata ID Q368782
Kaitai Struct Spec lzh.ksy
Released 1988

LHA is an archiving program and file format created by Haruyasu Yoshizaki (a.k.a. Yoshi) in 1988. It was originally called LHarc, then was briefly LH before settling on LHA. In the 1990s, it was the most popular archiving format on the Amiga platform. It also got some use on the PC platform including in the installers for id Software games such as Doom and Quake, because ZIP compression was inferior until the release of PKZIP 2.0, which brought the formats to parity.

It was particularly popular in Japan. Most of the best information about it is in Japanese.

It supports a number of different compression schemes, most of which use LZ77 combined with Huffman coding.

The file format is also known as LZH. See the LZH disambiguation page for other "LZH" formats.

This article covers the format used by LHarc/LHA, as well as "generalized" LHA format: the same file format, but with other compression schemes. The generalized format was possibly designed by Kazuhiko Miki in 1988 for the LArc software, but confirmation of this is needed. If so, it was soon borrowed by LHarc, with new compression schemes.

Contents

Format details

File structure

An LHA file consists mainly of a sequence of elements, each representing a member file or directory. The sequence is usually terminated by an end-of-archive marker consisting of a single 0x00 byte (but take care, as level 2 headers could start with 0x00). There is no global archive-level header.

Member format

There are at least four different formats that an element can have. (Note that this is independent of compression schemes.) In LHA jargon, the formats are known as "header levels", and are usually called "header level 0", "... 1", "... 2", and "... 3". The header level is determined by the byte at offset 20 from the beginning of that element.

The header levels are similar, but irritatingly different. They don't even follow the same principles with respect to how they must be parsed.

LZH compression overview

From a decompression perspective, the LZ77+Huffman schemes work roughly as follows. (This is oversimplified.) There is a codes Huffman tree, and a separate offsets tree. A symbol is read using the codes tree which, depending on its value, represents either a literal byte value, or a length. If it is a length, then an additional symbol is read using the offsets tree. Based on the offset and length, a run of recently-decompressed bytes is repeated.

Compression schemes

Each member file has a 5-byte compression method field, composed of ASCII characters. The first and last characters are virtually always dashes ("-"), and might be left off when discussing LHA compression schemes. Known schemes:

ID Category Description and remarks
-lh0- Uncompressed
-lh1- LZ77+Huffman, 4k window, adaptive Huffman for codes, offsets use a pre-defined Huffman tree.
-lh2- LZ77+Huffman, 8k window, adaptive Huffman. Considered obsolete.
-lh3- LZ77+Huffman, 8k window, segmented, static Huffman for codes, offsets can use static Huffman or a pre-defined Huffman tree. Considered obsolete.
-lh4- Like lh5, but 4k window. Rare.
-lh5- LZ77+Huffman, 8k window, segmented, static Huffman
-lh6- Like lh5, but 32k window
-lh7- Like lh5, but 64k window
-lh7- LHARK extension Refer to LHARK.
-lh8- Joe Jared extensions Like lh5, but 64k window. (Same as lh7.)
-lh9- Like lh5, but 128k window. Probably never used.
-lha- Like lh5, but 256k window. Probably never used.
-lhb- Like lh5, but 512k window. Probably never used.
-lhc- Like lh5, but 1M window. Probably never used.
-lhd- Special Not a compression scheme. Indicates that the element represents a subdirectory.
-lhe- Joe Jared extensions Like lh5, but 2M window. Probably never used.
-lhx- UNLHA32 extensions
-lx1-
-lz2- LArc methods
-lz3-
-lz4- Uncompressed
-lz5- LZ77/LZSS, 4k window. Almost identical to "SZDD" used in MS-DOS installation compression.
-lz7-
-lz8-
-lzs- LZ77/LZSS, 2k window
-pc1- PMarc extensions Refer to PMA.
-pm0-
-pm1-
-pm2-
-ah0- MAR extensions Refer to Micrognosis Compression Archiver.
-ari-
-hf0-
-lZ0- PUT/GET variants Refer to PUT.
-lZ1-
-lZ5-
␠LH0␠ SAR variants Refer to SAR (Streamline Design). The compression IDs begin and end with a space (0x20).
␠LH5␠

The Wikipedia article has more information about some of the schemes.

Other LHA-like identifiers:

ID References and remarks
-arn- Possibly used by Micrognosis Compression Archiver.
-lzw-
-pms- Refer to PMA.
-sqx- Refer to SQX.
-sw1- Refer to SWG.
-TK1- Unknown. (Recognized by IDArc.)

Extended headers

For header levels 1 and higher, each member file has an associated list of "extended headers", similar to ZIP's extensible data fields. Each extended header is tagged with a single byte indicating its type. Extended headers are used to store platform-specific metadata, and to extend the format in other ways.

Header level 0 supports extended data in a more limited way. It allows for just one set of extended header fields (called the "extended area"), the content of which is determined by the initial one-byte "OS type" field.

Identification

LHA can be identified with high accuracy, but doing so can be laborious, due to the lack of a signature, and other complicating factors.

Identification logic could be based on the header of the first member file. Check that the compression method (offset 2–6) and header level (offset 20) fields have valid values. When suitable and possible, validate the header checksum field -- this depends on the header level.

See also the "#See also" section, for some formats that could masquerade as LHA.

See also

Other LHA-like formats to be aware of:

Format documentation

Software

Sample files

Other links

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox