<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://moddingwiki.shikadi.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Levellass</id>
	<title>ModdingWiki - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://moddingwiki.shikadi.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Levellass"/>
	<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/wiki/Special:Contributions/Levellass"/>
	<updated>2026-05-14T07:20:03Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.11</generator>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=User_talk:Levellass&amp;diff=10562</id>
		<title>User talk:Levellass</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=User_talk:Levellass&amp;diff=10562"/>
		<updated>2022-06-20T10:40:42Z</updated>

		<summary type="html">&lt;p&gt;Levellass: /* Odd sprite files in Executioners */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi Levellass - not sure if you&#039;ve seen the question on [[Talk:Softdisk Library Format]] but since you wrote it you&#039;re probably best placed to answer! -- [[User:Malvineous|Malvineous]] 02:26, 6 January 2012 (GMT)&lt;br /&gt;
&lt;br /&gt;
Hi Levellass - I reverted your change to [[IMF Format]] (removing [[:Category:File Formats]]) because I am trying to remove all the pages from that category, instead putting them into more specific ones.  So in this case [[IMF Format]] will appear in [[:Category:All file formats]] as well as [[:Category:All music formats]].  And these categories should apply automatically when an infobox is added to the article page, so hopefully there will be no need to add categories manually!  So if you spot any pages missing categories, please add infoboxes to them instead of just the bare categories.  Thanks! -- [[User:Malvineous|Malvineous]] 09:03, 8 March 2013 (GMT)&lt;br /&gt;
: Nifty, that should certainly simplify things. -[[User:Levellass|Endian? What are you on about?]]&lt;br /&gt;
&lt;br /&gt;
Hey, LL! Your new example/explanation of Huffman helped a lot in writing a decompressor, but I&#039;m having an issue using it on EGAGRAPH. I verified that it is identical to the EGADICT created by KG and that I am reading it correctly. I get a tree full of reversed bit sequences, just like you said. However, the EGAGRAPH does not appear to use reversed bit sequences; it is completely uncompressed. (It does still have the UInt32LE at the front of the appropriate chunks specifying decompressed length.) Keen can read it and KeenGraph can read it, but using the provided dictionary, I can&#039;t. Can you help me? [[User:Fleexy|Fleexy]] ([[User talk:Fleexy|talk]]) 17:32, 3 January 2014 (GMT)&lt;br /&gt;
&lt;br /&gt;
== Titlebuild: black stripe ==&lt;br /&gt;
&lt;br /&gt;
Hey! I used your Keen Dreams title builder, but when I used it in my mod, black stripe appeared at the right corner of the title screen that doesn&#039;t and never wanna disappear at all. Fix it please! [[User:Szemigi|Szemigi]] ([[User talk:Szemigi|talk]]) 00:57, 8 September 2021 (GMT)&lt;br /&gt;
&lt;br /&gt;
== Odd sprite files in Executioners ==&lt;br /&gt;
&lt;br /&gt;
I&#039;ve been digging into the [[Executioners]] stuff you added, and while most sprites decode perfectly fine, I found a few really peculiar entries I can&#039;t figure out. The problem are the two files called &amp;lt;tt&amp;gt;GWORDS.VOL&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RWORDS.VOL&amp;lt;/tt&amp;gt;, from inside the &amp;lt;tt&amp;gt;INTRO.VOL&amp;lt;/tt&amp;gt; archive.&lt;br /&gt;
&lt;br /&gt;
They seem to be just more RLE-masked sprite files, but when decoding, things start looking... weird. According to their headers, the dimensions of the two files are respectively 218&amp;amp;times;72 and 162&amp;amp;times;82 but this gives weird corrupted output. instead, the RLE data, which specifically can&#039;t cross line width boundaries, seem to act as if their widths are, respectively, 55 and 41, as can be seen by full-line skip commands that are chopped off at these as maximum length. But when forcing the files to decode with those widths, the output barely looks any less distorted. In fact, the second halves of both files seem to align to widths that are one pixel less than the top halves, without any visible separation between the two blocks.&lt;br /&gt;
&lt;br /&gt;
Do you have any idea what those files are, and how to decode them? -[[User:Nyerguds|Nyerguds]] ([[User talk:Nyerguds|talk]]) 21:39, 29 April 2022 (GMT)&lt;br /&gt;
: Hey there. Yeah, some images in the archive have an odd format. They are composed of several smaller images arranged in a grid, but the game samples pixels from each image in sequence to build up the final picture. A good example of this is REAPBIO.VOL, consisting of a 4x4 grid of images with the complete image coming out like 0123456789aABCDEF0123...&lt;br /&gt;
: As another note, I have written a utility in BASIC that can extract most of the game&#039;s files, including levels. I&#039;m only having trouble with the cinematics since my Dosbox setup cannot display them so I can&#039;t test by altering their data. I&#039;ve been meaning to add more to the executioner&#039;s page but if you want my notes on stuff I can put them somewhere. -[[User:Levellass|Endian? What are you on about?]] ([[User talk:Levellass|talk]]) 08:34, 19 June 2022 (GMT)&lt;br /&gt;
:: Ah, don&#039;t worry too much about the article&#039;s formatting; a lot of articles started as pretty bare bones infodumps and only got refined later. That&#039;s what the todo tag is for. I&#039;ve often taken incomplete articles in the wiki, researched the formats, added code for them in [[Engie File Converter|my conversion tool]], and in the process, reformatted and rewritten the articles. Any specific info on how exactly these grid-images work would be welcome.&lt;br /&gt;
:: The cinematics seem to play fine for be, btw, but I haven&#039;t dug into what files they use. The first cinematic (the bloody TV room) seems to use these odd grid images, though.&lt;br /&gt;
:: File extraction is no issue for me; I already implemented that in [[Librarian|my own archive handling tool]]. I haven&#039;t encountered anything I can&#039;t extract with that. But since I hit that roadblock, I kind of stopped working on it, and haven&#039;t gotten around to releasing a new version with that update. -[[User:Nyerguds|Nyerguds]] ([[User talk:Nyerguds|talk]]) 09:45, 19 June 2022 (GMT)&lt;br /&gt;
:::Nifty. Well I&#039;ll try and get the other file formats up here, some are quite curious. There&#039;s a difference between animating images and movies proper, which seem to be able to place sounds, sprites and images onscreen. If you&#039;ve looked through the level format you&#039;ll know how convoluted this game&#039;s files can get. I&#039;ll try and look into whether the game has any sort of hard coding for those odd images. It&#039;s nice to know I won&#039;t need to code up an import tool. -[[User:Levellass|Endian? What are you on about?]] ([[User talk:Levellass|talk]]) 10:40, 20 June 2022 (GMT)&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=User_talk:Levellass&amp;diff=10558</id>
		<title>User talk:Levellass</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=User_talk:Levellass&amp;diff=10558"/>
		<updated>2022-06-19T08:34:41Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Wow, should&amp;#039;ve replied to this message. Executioner&amp;#039;s stuff.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi Levellass - not sure if you&#039;ve seen the question on [[Talk:Softdisk Library Format]] but since you wrote it you&#039;re probably best placed to answer! -- [[User:Malvineous|Malvineous]] 02:26, 6 January 2012 (GMT)&lt;br /&gt;
&lt;br /&gt;
Hi Levellass - I reverted your change to [[IMF Format]] (removing [[:Category:File Formats]]) because I am trying to remove all the pages from that category, instead putting them into more specific ones.  So in this case [[IMF Format]] will appear in [[:Category:All file formats]] as well as [[:Category:All music formats]].  And these categories should apply automatically when an infobox is added to the article page, so hopefully there will be no need to add categories manually!  So if you spot any pages missing categories, please add infoboxes to them instead of just the bare categories.  Thanks! -- [[User:Malvineous|Malvineous]] 09:03, 8 March 2013 (GMT)&lt;br /&gt;
: Nifty, that should certainly simplify things. -[[User:Levellass|Endian? What are you on about?]]&lt;br /&gt;
&lt;br /&gt;
Hey, LL! Your new example/explanation of Huffman helped a lot in writing a decompressor, but I&#039;m having an issue using it on EGAGRAPH. I verified that it is identical to the EGADICT created by KG and that I am reading it correctly. I get a tree full of reversed bit sequences, just like you said. However, the EGAGRAPH does not appear to use reversed bit sequences; it is completely uncompressed. (It does still have the UInt32LE at the front of the appropriate chunks specifying decompressed length.) Keen can read it and KeenGraph can read it, but using the provided dictionary, I can&#039;t. Can you help me? [[User:Fleexy|Fleexy]] ([[User talk:Fleexy|talk]]) 17:32, 3 January 2014 (GMT)&lt;br /&gt;
&lt;br /&gt;
== Titlebuild: black stripe ==&lt;br /&gt;
&lt;br /&gt;
Hey! I used your Keen Dreams title builder, but when I used it in my mod, black stripe appeared at the right corner of the title screen that doesn&#039;t and never wanna disappear at all. Fix it please! [[User:Szemigi|Szemigi]] ([[User talk:Szemigi|talk]]) 00:57, 8 September 2021 (GMT)&lt;br /&gt;
&lt;br /&gt;
== Odd sprite files in Executioners ==&lt;br /&gt;
&lt;br /&gt;
I&#039;ve been digging into the [[Executioners]] stuff you added, and while most sprites decode perfectly fine, I found a few really peculiar entries I can&#039;t figure out. The problem are the two files called &amp;lt;tt&amp;gt;GWORDS.VOL&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;RWORDS.VOL&amp;lt;/tt&amp;gt;, from inside the &amp;lt;tt&amp;gt;INTRO.VOL&amp;lt;/tt&amp;gt; archive.&lt;br /&gt;
&lt;br /&gt;
They seem to be just more RLE-masked sprite files, but when decoding, things start looking... weird. According to their headers, the dimensions of the two files are respectively 218&amp;amp;times;72 and 162&amp;amp;times;82 but this gives weird corrupted output. instead, the RLE data, which specifically can&#039;t cross line width boundaries, seem to act as if their widths are, respectively, 55 and 41, as can be seen by full-line skip commands that are chopped off at these as maximum length. But when forcing the files to decode with those widths, the output barely looks any less distorted. In fact, the second halves of both files seem to align to widths that are one pixel less than the top halves, without any visible separation between the two blocks.&lt;br /&gt;
&lt;br /&gt;
Do you have any idea what those files are, and how to decode them? -[[User:Nyerguds|Nyerguds]] ([[User talk:Nyerguds|talk]]) 21:39, 29 April 2022 (GMT)&lt;br /&gt;
: Hey there. Yeah, some images in the archive have an odd format. They are composed of several smaller images arranged in a grid, but the game samples pixels from each image in sequence to build up the final picture. A good example of this is REAPBIO.VOL, consisting of a 4x4 grid of images with the complete image coming out like 0123456789aABCDEF0123...&lt;br /&gt;
: As another note, I have written a utility in BASIC that can extract most of the game&#039;s files, including levels. I&#039;m only having trouble with the cinematics since my Dosbox setup cannot display them so I can&#039;t test by altering their data. I&#039;ve been meaning to add more to the executioner&#039;s page but if you want my notes on stuff I can put them somewhere. -[[User:Levellass|Endian? What are you on about?]] ([[User talk:Levellass|talk]]) 08:34, 19 June 2022 (GMT)&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10325</id>
		<title>Executioners</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10325"/>
		<updated>2022-03-25T23:48:41Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add sprites&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{NeedMoreInfo}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Levels = No&lt;br /&gt;
 | Tiles = No&lt;br /&gt;
 | Sprites = No&lt;br /&gt;
 | Fullscreen = No&lt;br /&gt;
 | Sound = No&lt;br /&gt;
 | Music = No&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Executioners&#039;&#039;&#039; is a DOS game made by Ethan Petty and Icer Addis of Bloodlust Software in 1992. It was their first game, and it sold relatively well at the time. It is notable for its violent content, moderated only by the constraints of the hardware of the time.&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACK*.VOL&amp;lt;br/&amp;gt;E.VOL&amp;lt;br/&amp;gt;FUCKED.VOL&amp;lt;br/&amp;gt;FUCKED2.VOL&amp;lt;br/&amp;gt;GUILLBIO.VOL&amp;lt;br/&amp;gt;PROD*.VOL&amp;lt;br/&amp;gt;REAPBOI.VOL&amp;lt;br/&amp;gt;SKETCH.VOL&amp;lt;br/&amp;gt;SKETCH2.VOL&amp;lt;br/&amp;gt;SKULL.VOL&amp;lt;br/&amp;gt;TITLE.VOL&lt;br /&gt;
 | Format = [[Raw VGA Image]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = 320x200 VGA images, no palette data&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACKPAL.VOL&amp;lt;br/&amp;gt;BIOPAL.VOL&amp;lt;br/&amp;gt;DARKPAL.VOL&amp;lt;br/&amp;gt;LIGHTPAL.VOL&amp;lt;br/&amp;gt;PRODPAL.VOL&amp;lt;br/&amp;gt;RUNPAL.VOL&amp;lt;br/&amp;gt;SDPAL.VOL&amp;lt;br/&amp;gt;SLPAL.VOL&amp;lt;br/&amp;gt;TPAL.VOL&amp;lt;br/&amp;gt;TVPAL.VOL&lt;br /&gt;
 | Format = [[VGA Palette]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game palettes, &#039;Classic&#039; VGA format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BLOOD.VOL&amp;lt;br/&amp;gt;BOOM.VOL&amp;lt;br/&amp;gt;END*.VOL&amp;lt;br/&amp;gt;EXECUTE.VOL&amp;lt;br/&amp;gt;FIRE.VOL&amp;lt;br/&amp;gt;GR.VOL&amp;lt;br/&amp;gt;GUILL*.VOL&amp;lt;br/&amp;gt;NEWS*.VOL&amp;lt;br/&amp;gt;PLAYERS.VOL&amp;lt;br/&amp;gt;RATATATA.VOL&amp;lt;br/&amp;gt;REAP*.VOL&lt;br /&gt;
 | Format = [[Creative Voice File]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game sounds, old VOC format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = EXEC.VOL&amp;lt;br/&amp;gt;RUN.VOL&amp;lt;br/&amp;gt;SOUND.VOL&lt;br /&gt;
 | Format = [[CMF Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = FONT.VOL&lt;br /&gt;
 | Format = [[Executioners Font Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game font&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = EDLAUGH.VOL&amp;lt;br/&amp;gt;FLOOR.VOL&amp;lt;br/&amp;gt;GF*.VOL&amp;lt;br/&amp;gt;GR*.VOL&amp;lt;br/&amp;gt;GS*.VOL&amp;lt;br/&amp;gt;GSHOCK.VOL&amp;lt;br/&amp;gt;GTALK.VOL&amp;lt;br/&amp;gt;GWORDS.VOL&amp;lt;br/&amp;gt;HBLOOD*.VOL&amp;lt;br/&amp;gt;HMOUTH*.VOL&amp;lt;br/&amp;gt;JAW.VOL&amp;lt;br/&amp;gt;P*.VOL&amp;lt;br/&amp;gt;PBALL.VOL&amp;lt;br/&amp;gt;PTR.VOL&amp;lt;br/&amp;gt;PWORD.VOL&amp;lt;br/&amp;gt;RBLINK*.VOL&amp;lt;br/&amp;gt;RF*.VOL&amp;lt;br/&amp;gt;RR*.VOL&amp;lt;br/&amp;gt;RS*.VOL&amp;lt;br/&amp;gt;RTALK.VOL&amp;lt;br/&amp;gt;RSHOCK.VOL&amp;lt;br/&amp;gt;RWORDS.VOL&amp;lt;br/&amp;gt;TVD*.VOL&amp;lt;br/&amp;gt;TVN*.VOL&amp;lt;br/&amp;gt;TVS*.VOL&lt;br /&gt;
 | Format = [[Executioners RLE Compression]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Individual RLE-compressed images&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *CHAR.VOL&amp;lt;br/&amp;gt;BOSS*.VOL&amp;lt;br/&amp;gt;MISC.VOL&amp;lt;br/&amp;gt;OBJECT.VOL&lt;br /&gt;
 | Format = [[Executioners Sprite Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game sprites&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = INTRO.VOL&lt;br /&gt;
 | Format = [[Executioners Archive Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Most, but not all, game files in a simple archive&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
== Related Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://dosgames.com/game/executioners/] Executioners on DOSGames.com&lt;br /&gt;
&lt;br /&gt;
[[Category:Bloodlust Software]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Sprite_Format&amp;diff=10324</id>
		<title>Executioners Sprite Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Sprite_Format&amp;diff=10324"/>
		<updated>2022-03-25T23:43:24Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Sprite format isn&amp;#039;t TOO tricky, the others though. whooo...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{stub}}&lt;br /&gt;
{{Tileset Infobox&lt;br /&gt;
 | Hardware1 = VGA&lt;br /&gt;
 | Palette = External&lt;br /&gt;
 | Names = N&lt;br /&gt;
 | TileMinSize = 0&amp;amp;times;0&lt;br /&gt;
 | TileMaxSize = 255&amp;amp;times;255&lt;br /&gt;
 | NumPlanes = 1&lt;br /&gt;
 | PlaneArrangement = Linear&lt;br /&gt;
 | HasTransparency = Y&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subtilesets = N&lt;br /&gt;
 | Compressed = Y&lt;br /&gt;
 | Hidden = Y&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Sprites for [[Executioners]] are stored in various files, notable in that they are not kept in the [[Executioners Archive Format|game&#039;s main archive.]] Chiefly these are &amp;lt;tt&amp;gt;*CHAR.VOL&amp;lt;/tt&amp;gt; Each file contains a single character in the game.&lt;br /&gt;
&lt;br /&gt;
== Signature ==&lt;br /&gt;
&lt;br /&gt;
Sprite files lack a specific signature. However the sprite files start with a &amp;lt;tt&amp;gt;word&amp;lt;/tt&amp;gt; that gives the size of the sprite header block. This is equivalent to the number of sprite entries multiplied by 13. The first byte after this will be 0x10 and the fourth 0xFF. (This is the header of an [[Executioners RLE Compression|RLE block.]]) This can be used to identify the file with high accuracy.&lt;br /&gt;
&lt;br /&gt;
== Header ==&lt;br /&gt;
&lt;br /&gt;
Each sprite entry has a nul-terminated 13 byte entry in the file header as follows:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Description!!Notes&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT16LE]]||iSize||Size of compressed data block&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT16LE]]||Frame||Sprite frame image belongs to&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT16LE]]||L-H-Position||Position of image horizontally, relative to left facing sprite&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT16LE]]||L-V-Position||Position of image vertically, relative to left facing sprite&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT16LE]]||R-H-Position||Position of image horizontally, relative to right facing sprite&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT16LE]]||R-V-Position||Position of image vertically, relative to right facing sprite&lt;br /&gt;
|-&lt;br /&gt;
|[[char]][1]||END||0x00, terminates entry&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Character sprites are divided into independently animating sections such as an upper and lower half, allowing for the full sprite image to have more states. Each &#039;part&#039; of a sprite occupies its own &#039;frame&#039; in the level and sprite files cannot share any frames of bugs will occur. What each image &#039;is&#039; is also hard-coded into the game based on its frame number, limiting how they may be used.&lt;br /&gt;
&lt;br /&gt;
Images also have a horizontal\vertical offset that positions them relative to the sprite &#039;core&#039; which varies depending on whether the sprite is facing right or left.&lt;br /&gt;
&lt;br /&gt;
== Sprite data ==&lt;br /&gt;
&lt;br /&gt;
Each image is a single [[Executioners RLE Compression|Executioners RLE]] compressed block. The game reads each block sequentially, using the sum of the block sizes given in the header entries to tell where a new block begins.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10323</id>
		<title>Executioners</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10323"/>
		<updated>2022-03-25T22:33:35Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add masked image &amp;#039;format&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{NeedMoreInfo}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Levels = No&lt;br /&gt;
 | Tiles = No&lt;br /&gt;
 | Sprites = No&lt;br /&gt;
 | Fullscreen = No&lt;br /&gt;
 | Sound = No&lt;br /&gt;
 | Music = No&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Executioners&#039;&#039;&#039; is a DOS game made by Ethan Petty and Icer Addis of Bloodlust Software in 1992. It was their first game, and it sold relatively well at the time. It is notable for its violent content, moderated only by the constraints of the hardware of the time.&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACK*.VOL&amp;lt;br/&amp;gt;E.VOL&amp;lt;br/&amp;gt;FUCKED.VOL&amp;lt;br/&amp;gt;FUCKED2.VOL&amp;lt;br/&amp;gt;GUILLBIO.VOL&amp;lt;br/&amp;gt;PROD*.VOL&amp;lt;br/&amp;gt;REAPBOI.VOL&amp;lt;br/&amp;gt;SKETCH.VOL&amp;lt;br/&amp;gt;SKETCH2.VOL&amp;lt;br/&amp;gt;SKULL.VOL&amp;lt;br/&amp;gt;TITLE.VOL&lt;br /&gt;
 | Format = [[Raw VGA Image]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = 320x200 VGA images, no palette data&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACKPAL.VOL&amp;lt;br/&amp;gt;BIOPAL.VOL&amp;lt;br/&amp;gt;DARKPAL.VOL&amp;lt;br/&amp;gt;LIGHTPAL.VOL&amp;lt;br/&amp;gt;PRODPAL.VOL&amp;lt;br/&amp;gt;RUNPAL.VOL&amp;lt;br/&amp;gt;SDPAL.VOL&amp;lt;br/&amp;gt;SLPAL.VOL&amp;lt;br/&amp;gt;TPAL.VOL&amp;lt;br/&amp;gt;TVPAL.VOL&lt;br /&gt;
 | Format = [[VGA Palette]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game palettes, &#039;Classic&#039; VGA format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BLOOD.VOL&amp;lt;br/&amp;gt;BOOM.VOL&amp;lt;br/&amp;gt;END*.VOL&amp;lt;br/&amp;gt;EXECUTE.VOL&amp;lt;br/&amp;gt;FIRE.VOL&amp;lt;br/&amp;gt;GR.VOL&amp;lt;br/&amp;gt;GUILL*.VOL&amp;lt;br/&amp;gt;NEWS*.VOL&amp;lt;br/&amp;gt;PLAYERS.VOL&amp;lt;br/&amp;gt;RATATATA.VOL&amp;lt;br/&amp;gt;REAP*.VOL&lt;br /&gt;
 | Format = [[Creative Voice File]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game sounds, old VOC format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = EXEC.VOL&amp;lt;br/&amp;gt;RUN.VOL&amp;lt;br/&amp;gt;SOUND.VOL&lt;br /&gt;
 | Format = [[CMF Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = FONT.VOL&lt;br /&gt;
 | Format = [[Executioners Font Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game font&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = EDLAUGH.VOL&amp;lt;br/&amp;gt;FLOOR.VOL&amp;lt;br/&amp;gt;GF*.VOL&amp;lt;br/&amp;gt;GR*.VOL&amp;lt;br/&amp;gt;GS*.VOL&amp;lt;br/&amp;gt;GSHOCK.VOL&amp;lt;br/&amp;gt;GTALK.VOL&amp;lt;br/&amp;gt;GWORDS.VOL&amp;lt;br/&amp;gt;HBLOOD*.VOL&amp;lt;br/&amp;gt;HMOUTH*.VOL&amp;lt;br/&amp;gt;JAW.VOL&amp;lt;br/&amp;gt;P*.VOL&amp;lt;br/&amp;gt;PBALL.VOL&amp;lt;br/&amp;gt;PTR.VOL&amp;lt;br/&amp;gt;PWORD.VOL&amp;lt;br/&amp;gt;RBLINK*.VOL&amp;lt;br/&amp;gt;RF*.VOL&amp;lt;br/&amp;gt;RR*.VOL&amp;lt;br/&amp;gt;RS*.VOL&amp;lt;br/&amp;gt;RTALK.VOL&amp;lt;br/&amp;gt;RSHOCK.VOL&amp;lt;br/&amp;gt;RWORDS.VOL&amp;lt;br/&amp;gt;TVD*.VOL&amp;lt;br/&amp;gt;TVN*.VOL&amp;lt;br/&amp;gt;TVS*.VOL&lt;br /&gt;
 | Format = [[Executioners RLE Compression]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Individual RLE-compressed images&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = INTRO.VOL&lt;br /&gt;
 | Format = [[Executioners Archive Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Most, but not all, game files in a simple archive&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
== Related Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://dosgames.com/game/executioners/] Executioners on DOSGames.com&lt;br /&gt;
&lt;br /&gt;
[[Category:Bloodlust Software]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Archive_Format&amp;diff=10322</id>
		<title>Executioners Archive Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Archive_Format&amp;diff=10322"/>
		<updated>2022-03-25T22:33:22Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add note on repeated files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = 4095&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = Yes, 8.3&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = Y&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;Executioners Archive Format&#039;&#039;&#039; is how most, but not all, files in the game [[Executioners]] is stored. The game will check the archive file first and fall back to the game directory if the desired file could not be found in the archives. This means you can simply rename or remove the archive files to force the game to use external files from the game directory. The default volume file also contains duplicates of some files, (such as &amp;lt;tt&amp;gt;GF1.VOL&amp;lt;/tt&amp;gt;) intended to be used at different points in the game. However, since the game scans the file header sequentially, it always stops at the first matching entry, never reading the repeats.&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
There is no known signature for this format.  One method to identify files is to check the first &amp;lt;tt&amp;gt;word&amp;lt;/tt&amp;gt; of the file and compare it to the &amp;lt;tt&amp;gt;word&amp;lt;/tt&amp;gt; at 0x0A. The first value will be a multiple of 16 (the file entries) and the second will be two larger (FAT plus the FAT size &amp;lt;tt&amp;gt;word&amp;lt;/tt&amp;gt;). This should give a minimal chance of incorrectly identifing a file. &lt;br /&gt;
&lt;br /&gt;
=== File entry ===&lt;br /&gt;
&lt;br /&gt;
The first section of the file consists of file entries, with the remainder containing the data.  Each file entry consists of the filename, its offset and its size.  This slightly unusual configuration (storing both the offset and the size) means it is possible (in theory) for two different files to share the same data, and to insert &amp;quot;hidden&amp;quot; data between files.&lt;br /&gt;
&lt;br /&gt;
A file entry is laid out as follows:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|[[char]] cFilename[8]||Filename (8.3 style, but lacking extension), only NULL-terminated if there is enough room&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT32LE]] iOffset||File offset from start of group file&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT32LE]] iSize||File size&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
File entries in the archive do not store the file extension, which is &amp;lt;tt&amp;gt;.VOL&amp;lt;/tt&amp;gt; by default, for all contained files.&lt;br /&gt;
&lt;br /&gt;
=== Implementation Restrictions &amp;amp; Bugs ===&lt;br /&gt;
&lt;br /&gt;
* All file names in the archive must be in upper case&lt;br /&gt;
&lt;br /&gt;
* When searching for a file name, the first match in the FAT is used.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Font_Format&amp;diff=10321</id>
		<title>Executioners Font Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Font_Format&amp;diff=10321"/>
		<updated>2022-03-25T22:15:04Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Simplify format since some stuff belongs on the RLE page.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Font Infobox&lt;br /&gt;
 | MaxGlyphs = 256&lt;br /&gt;
 | GlyphMinSize = 0&amp;amp;times;0&lt;br /&gt;
 | GlyphMaxSize = 255&amp;amp;times;255&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Bitmap = Y&lt;br /&gt;
 | Vector = N&lt;br /&gt;
 | Compressed = Y&lt;br /&gt;
 | Hidden = Y&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
[[Executioners]] uses a simple, [[RLE Compression|RLE-compressed]] format to store its game font. It consists of a 512 byte header followed by blocks of data.&lt;br /&gt;
&lt;br /&gt;
The header of the font file consists of 256 &amp;lt;tt&amp;gt;words&amp;lt;/tt&amp;gt; giving the address of each character of the font in the file. Blank characters have an address of 0, while all &#039;valid&#039; characters should have an address of at least 0x200. This allows the game to display text strings consisting of all 256 ASCII values, assigning one font character to each.&lt;br /&gt;
&lt;br /&gt;
Following this are blocks of data. Each is essentially a amsked VGA image in [[Executioners RLE Compression]] format.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners_RLE_Format&amp;diff=10320</id>
		<title>Executioners RLE Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners_RLE_Format&amp;diff=10320"/>
		<updated>2022-03-25T22:11:39Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Tweak page now I know a bit more&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-byte&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
[[Executioners]] occasionally uses [[RLE Compression]], or Run Length Encoding, which is explained here. The scheme is used by and large to handle the masking of certain images in-game, rather than to compress the image pixels themselves.&lt;br /&gt;
&lt;br /&gt;
Each &#039;block&#039; of RLE data begins with a 4-byte header that gives the height and width of the uncompressed image (and thus the block&#039;s decompressed size) as well as having two flags identifying it as a block of the right format.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Description!!Notes&lt;br /&gt;
|-&lt;br /&gt;
|[[char]][1]||ID||0x10, indicates a valid block&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT8]]||iwidth||Image width&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT8]]||iheight||Image height&lt;br /&gt;
|-&lt;br /&gt;
|[[char]][1]||END||0xFF, ends header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The RLE scheme itself is relatively simple and relies on the data being composed of two kinds of pixels; image pixels which are always read as literals, and unmasked &#039;empty&#039; pixels which are rows of the same type of pixel. This does, however, mean that no compression can be performed on any non-empty pixels. The scheme can be considered as follows:&lt;br /&gt;
&lt;br /&gt;
 1.) While the output data is less than heightXwidth:&lt;br /&gt;
 2.) Get a byte&lt;br /&gt;
 3.) Is the value of this byte larger than 127?&lt;br /&gt;
     -&amp;gt; If no then:&lt;br /&gt;
        -&amp;gt; Get the next [Value] bytes&lt;br /&gt;
        -&amp;gt; Move forward [Value] bytes and go to 1&lt;br /&gt;
     -&amp;gt; If yes, then:&lt;br /&gt;
        -&amp;gt; Use value 0xFF and copy it [Value - 128] times&lt;br /&gt;
        -&amp;gt; Move forward a byte and go to 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that it is possible to have zero length runs of both literals and empty pixels, allowing compressed data to be arbitrarily larger than uncompressed data. Image data also tends to be compressed line-by-line; that is, each row of pixels is considered separately and concatenated. This further reduces compression efficiency.&lt;br /&gt;
&lt;br /&gt;
The exact value of the byte used for &#039;empty pixels&#039; is uncertain, images can contain pixels with value 0xFF and display that color in the palette correctly.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners_RLE_Format&amp;diff=10319</id>
		<title>Executioners RLE Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners_RLE_Format&amp;diff=10319"/>
		<updated>2022-03-25T14:36:18Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Create page! Good thing Executioners doesn&amp;#039;t have much complex coding.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-byte&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
[[Executioners]] occasionally uses [[RLE Compression]], or Run Length Encoding, which is explained here.&lt;br /&gt;
&lt;br /&gt;
The RLE routine works from a given location to output a given length of data. However these are not part of the encoding itself and are hard-coded into the game. For example, game font characters get their starting position from the font file header, whereas scrolling images merely start at the fifth byte of the file.&lt;br /&gt;
&lt;br /&gt;
The RLE scheme is relatively simple and relies on the data being composed of two kinds of pixels; image pixels which are always read as literals, and unmasked &#039;empty&#039; pixels which are rows of the same type of pixel. This does, however, mean that no compression can be performed on any non-empty pixels. The scheme can be considered as follows:&lt;br /&gt;
&lt;br /&gt;
 1.) Get a byte&lt;br /&gt;
 2.) Is the value of this byte larger than 127?&lt;br /&gt;
     -&amp;gt; If no then:&lt;br /&gt;
        -&amp;gt; Get the next [Value] bytes&lt;br /&gt;
        -&amp;gt; Move forward [Value] bytes and go to 1&lt;br /&gt;
     -&amp;gt; If yes, then:&lt;br /&gt;
        -&amp;gt; Use value 0xFF and copy it [Value - 128] times&lt;br /&gt;
        -&amp;gt; Move forward a byte and go to 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that it is possible to have zero length runs of both literals and empty pixels, allowing compressed data to be arbitrarily larger than uncompressed data. A compressed block can also have arbitrary data appended to it that will be loaded into memory as the game gets the size of the compressed block from elsewhere and there is no hard coded end to each block of data.&lt;br /&gt;
&lt;br /&gt;
The exact value of the byte used for &#039;empty pixels&#039; is uncertain, images can contain pixels with value 0xFF and display that color in the palette correctly.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Font_Format&amp;diff=10318</id>
		<title>Executioners Font Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Font_Format&amp;diff=10318"/>
		<updated>2022-03-25T14:15:43Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Font Infobox&lt;br /&gt;
 | MaxGlyphs = 256&lt;br /&gt;
 | GlyphMinSize = 0&amp;amp;times;0&lt;br /&gt;
 | GlyphMaxSize = 255&amp;amp;times;255&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Bitmap = Y&lt;br /&gt;
 | Vector = N&lt;br /&gt;
 | Compressed = Y&lt;br /&gt;
 | Hidden = Y&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
[[Executioners]] uses a simple, [[RLE Compression|RLE-compressed]] format t store its game font and also, in a slightly simpler form, scrolling images. An animating image is stored as a single font character, in its own file, without the header found in the game font.&lt;br /&gt;
&lt;br /&gt;
== Header ==&lt;br /&gt;
&lt;br /&gt;
The header of the font file consists of 256 &amp;lt;tt&amp;gt;words&amp;lt;/tt&amp;gt; giving the address of each character of the font in the file. Blank characters have an address of 0, while all &#039;valid&#039; characters should have an address of at least 0x200. This allows the game to display text strings consisting of all 256 ASCII values.&lt;br /&gt;
&lt;br /&gt;
== Character entries ==&lt;br /&gt;
&lt;br /&gt;
Each character address in the header points to a character entry whose format is as follows:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Description!!Notes&lt;br /&gt;
|-&lt;br /&gt;
|[[char]][1]||ID||0x10, indicates a valid character&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT8]]||iwidth||Image width&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT8]]||iheight||Image height&lt;br /&gt;
|-&lt;br /&gt;
|[[char]][1]||END||0xFF, ends header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Image data is compressed using the [[Executioners RLE Compression]] format. Because of this, arbitrary data can be stored at the end of each character&#039;s compressed data.&lt;br /&gt;
&lt;br /&gt;
== Scrolling images ==&lt;br /&gt;
&lt;br /&gt;
As noted above, scrolling images are formatted as a single character, given its own file. (As such the first character of the file will be 0x10 and the fourth 0xFF). Scrolling images are images that move around the screen in some fashion.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10317</id>
		<title>Executioners</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10317"/>
		<updated>2022-03-25T14:13:44Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add the game font format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{NeedMoreInfo}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Levels = No&lt;br /&gt;
 | Tiles = No&lt;br /&gt;
 | Sprites = No&lt;br /&gt;
 | Fullscreen = No&lt;br /&gt;
 | Sound = No&lt;br /&gt;
 | Music = No&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Executioners&#039;&#039;&#039; is a DOS game made by Ethan Petty and Icer Addis of Bloodlust Software in 1992. It was their first game, and it sold relatively well at the time. It is notable for its violent content, moderated only by the constraints of the hardware of the time.&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACK*.VOL&amp;lt;br/&amp;gt;E.VOL&amp;lt;br/&amp;gt;FUCKED.VOL&amp;lt;br/&amp;gt;FUCKED2.VOL&amp;lt;br/&amp;gt;GUILLBIO.VOL&amp;lt;br/&amp;gt;PROD*.VOL&amp;lt;br/&amp;gt;REAPBOI.VOL&amp;lt;br/&amp;gt;SKETCH.VOL&amp;lt;br/&amp;gt;SKETCH2.VOL&amp;lt;br/&amp;gt;SKULL.VOL&amp;lt;br/&amp;gt;TITLE.VOL&lt;br /&gt;
 | Format = [[Raw VGA Image]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = 320x200 VGA images, no palette data&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACKPAL.VOL&amp;lt;br/&amp;gt;BIOPAL.VOL&amp;lt;br/&amp;gt;DARKPAL.VOL&amp;lt;br/&amp;gt;LIGHTPAL.VOL&amp;lt;br/&amp;gt;PRODPAL.VOL&amp;lt;br/&amp;gt;RUNPAL.VOL&amp;lt;br/&amp;gt;SDPAL.VOL&amp;lt;br/&amp;gt;SLPAL.VOL&amp;lt;br/&amp;gt;TPAL.VOL&amp;lt;br/&amp;gt;TVPAL.VOL&lt;br /&gt;
 | Format = [[VGA Palette]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game palettes, &#039;Classic&#039; VGA format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BLOOD.VOL&amp;lt;br/&amp;gt;BOOM.VOL&amp;lt;br/&amp;gt;END*.VOL&amp;lt;br/&amp;gt;EXECUTE.VOL&amp;lt;br/&amp;gt;FIRE.VOL&amp;lt;br/&amp;gt;GR.VOL&amp;lt;br/&amp;gt;GUILL*.VOL&amp;lt;br/&amp;gt;NEWS*.VOL&amp;lt;br/&amp;gt;PLAYERS.VOL&amp;lt;br/&amp;gt;RATATATA.VOL&amp;lt;br/&amp;gt;REAP*.VOL&lt;br /&gt;
 | Format = [[Creative Voice File]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game sounds, old VOC format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = EXEC.VOL&amp;lt;br/&amp;gt;RUN.VOL&amp;lt;br/&amp;gt;SOUND.VOL&lt;br /&gt;
 | Format = [[CMF Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = FONT.VOL&lt;br /&gt;
 | Format = [[Executioners Font Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game font&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = INTRO.VOL&lt;br /&gt;
 | Format = [[Executioners Archive Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Most, but not all, game files in a simple archive&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
== Related Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://dosgames.com/game/executioners/] Executioners on DOSGames.com&lt;br /&gt;
&lt;br /&gt;
[[Category:Bloodlust Software]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Font_Format&amp;diff=10316</id>
		<title>Executioners Font Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Font_Format&amp;diff=10316"/>
		<updated>2022-03-25T14:13:17Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Create page, I should not be staying up so late&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Font Infobox&lt;br /&gt;
 | MaxGlyphs = 256&lt;br /&gt;
 | GlyphMinSize = 0&amp;amp;times;0&lt;br /&gt;
 | GlyphMaxSize = 255&amp;amp;times;255&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Bitmap = Y&lt;br /&gt;
 | Vector = N&lt;br /&gt;
 | Compressed = Y&lt;br /&gt;
 | Hidden = Y&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
[[Executioners]] uses a simple, RLE-compressed format t store its game font and also, in a slightly simpler form, scrolling images. An animating image is stored as a single font character, in its own file, without the header found in the game font.&lt;br /&gt;
&lt;br /&gt;
== Header ==&lt;br /&gt;
&lt;br /&gt;
The header of the font file consists of 256 &amp;lt;tt&amp;gt;words&amp;lt;/tt&amp;gt; giving the address of each character of the font in the file. Blank characters have an address of 0, while all &#039;valid&#039; characters should have an address of at least 0x200. This allows the game to display text strings consisting of all 256 ASCII values.&lt;br /&gt;
&lt;br /&gt;
== Character entries ==&lt;br /&gt;
&lt;br /&gt;
Each character address in the header points to a character entry whose format is as follows:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Description!!Notes&lt;br /&gt;
|-&lt;br /&gt;
|[[char]][1]||ID||0x10, indicates a valid character&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT8]]||iwidth||Image width&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT8]]||iheight||Image height&lt;br /&gt;
|-&lt;br /&gt;
|[[char]][1]||END||0xFF, ends header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Image data is compressed using the [[Executioners RLE Compression]] format. Because of this, arbitrary data can be stored at the end of each character&#039;s compressed data.&lt;br /&gt;
&lt;br /&gt;
== Scrolling images ==&lt;br /&gt;
&lt;br /&gt;
As noted above, scrolling images are formatted as a single character, given its own file. (As such the first character of the file will be 0x10 and the fourth 0xFF). Scrolling images are images that move around the screen in some fashion.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Jazz_Jackrabbit_Font_Format&amp;diff=10315</id>
		<title>Jazz Jackrabbit Font Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Jazz_Jackrabbit_Font_Format&amp;diff=10315"/>
		<updated>2022-03-25T13:52:49Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Clarification&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Font Infobox&lt;br /&gt;
 | MaxGlyphs = 65,535&lt;br /&gt;
 | GlyphMinSize = 0&amp;amp;times;0&lt;br /&gt;
 | GlyphMaxSize = 16,383&amp;amp;times;65,535&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Bitmap = Y&lt;br /&gt;
 | Vector = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Jazz Jackrabbit}}&lt;br /&gt;
}}&lt;br /&gt;
The font files in Jazz Jackrabbit are stored in two slightly different ways; most fonts are &#039;normal fonts&#039; with one exception, &amp;lt;tt&amp;gt;FONTS.000&amp;lt;/tt&amp;gt;. Some font characters are stored in non-font files. (For example the bonus font is stored in &amp;lt;tt&amp;gt;BONUS.000&amp;lt;/tt&amp;gt; with the bonus sprites.)&lt;br /&gt;
&lt;br /&gt;
== Normal fonts ==&lt;br /&gt;
&lt;br /&gt;
The standard .0FN files (Fontbig, fontiny, fontmn1, fontmn2 and font2) consist of a 23 byte header (&#039;Digital Dimensions + $1A followed by the h and v spacing between font characters when displayed and two blank bytes.) followed by font characters. Font characters can either contain data, or be placeholders. Placeholders are simply a blank word, and tend to end up in blocks in the font file.&lt;br /&gt;
&lt;br /&gt;
Font characters consist of a character size word (Uncompressed character size + 4) followed by a [[Jazz Jackrabbit RLE compression]] compressed block. (RLE block size word followed by compressed data.)&lt;br /&gt;
&lt;br /&gt;
Uncompressed character data consists of two words, the character width and height, followed by the character pixel data stored in the &#039;normal&#039; way. Fonts contain no palette, so the color of the font will depend on the level it is in.&lt;br /&gt;
&lt;br /&gt;
== FONTS.000 ==&lt;br /&gt;
&lt;br /&gt;
This font file is similar to the others, but with some slight differences. Its header contains only a word dictating how many font characters are in the file (Default 37), directly followed by the character data. There is no h or v spacing for this font.&lt;br /&gt;
&lt;br /&gt;
Characters are uncompressed and consist of a header of 8 bytes. (Four words; width of character \ 4; height of character; height * width / 4; and a blank word.) followed by the character pixel data. &lt;br /&gt;
&lt;br /&gt;
Character data is stored as four interlaced images. Each image is one quarter of the columns of pixels making up the character. Image 1 is columns 1,5,9... image 2 is 2,6,10... and so on.&lt;br /&gt;
&lt;br /&gt;
== Bonus.000 ==&lt;br /&gt;
&lt;br /&gt;
This contains the bonus level font and sprites. It is not a font file &amp;lt;i&amp;gt;per se&amp;lt;/i&amp;gt; but a graphics file.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=File:Jazz_Jackrabbit_Font_Format.png&amp;diff=10314</id>
		<title>File:Jazz Jackrabbit Font Format.png</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=File:Jazz_Jackrabbit_Font_Format.png&amp;diff=10314"/>
		<updated>2022-03-25T13:32:21Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Gotta remember how to add categories.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
The extracted FONTBIG.0FN file, via JJ1MOD.&lt;br /&gt;
&lt;br /&gt;
[[Category:Jazz Jackrabbit]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=File:Jazz_Jackrabbit_Font_Format.png&amp;diff=10313</id>
		<title>File:Jazz Jackrabbit Font Format.png</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=File:Jazz_Jackrabbit_Font_Format.png&amp;diff=10313"/>
		<updated>2022-03-25T13:30:54Z</updated>

		<summary type="html">&lt;p&gt;Levellass: The extracted FONTBIG.0FN file, via JJ1MOD.

Category:Jazz Jackrabbit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
The extracted FONTBIG.0FN file, via JJ1MOD.&lt;br /&gt;
&lt;br /&gt;
Category:Jazz Jackrabbit&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10312</id>
		<title>Executioners</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10312"/>
		<updated>2022-03-25T13:14:42Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add first novel format, the archive!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{NeedMoreInfo}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Levels = No&lt;br /&gt;
 | Tiles = No&lt;br /&gt;
 | Sprites = No&lt;br /&gt;
 | Fullscreen = No&lt;br /&gt;
 | Sound = No&lt;br /&gt;
 | Music = No&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Executioners&#039;&#039;&#039; is a DOS game made by Ethan Petty and Icer Addis of Bloodlust Software in 1992. It was their first game, and it sold relatively well at the time. It is notable for its violent content, moderated only by the constraints of the hardware of the time.&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACK*.VOL&amp;lt;br/&amp;gt;E.VOL&amp;lt;br/&amp;gt;FUCKED.VOL&amp;lt;br/&amp;gt;FUCKED2.VOL&amp;lt;br/&amp;gt;GUILLBIO.VOL&amp;lt;br/&amp;gt;PROD*.VOL&amp;lt;br/&amp;gt;REAPBOI.VOL&amp;lt;br/&amp;gt;SKETCH.VOL&amp;lt;br/&amp;gt;SKETCH2.VOL&amp;lt;br/&amp;gt;SKULL.VOL&amp;lt;br/&amp;gt;TITLE.VOL&lt;br /&gt;
 | Format = [[Raw VGA Image]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = 320x200 VGA images, no palette data&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACKPAL.VOL&amp;lt;br/&amp;gt;BIOPAL.VOL&amp;lt;br/&amp;gt;DARKPAL.VOL&amp;lt;br/&amp;gt;LIGHTPAL.VOL&amp;lt;br/&amp;gt;PRODPAL.VOL&amp;lt;br/&amp;gt;RUNPAL.VOL&amp;lt;br/&amp;gt;SDPAL.VOL&amp;lt;br/&amp;gt;SLPAL.VOL&amp;lt;br/&amp;gt;TPAL.VOL&amp;lt;br/&amp;gt;TVPAL.VOL&lt;br /&gt;
 | Format = [[VGA Palette]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game palettes, &#039;Classic&#039; VGA format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BLOOD.VOL&amp;lt;br/&amp;gt;BOOM.VOL&amp;lt;br/&amp;gt;END*.VOL&amp;lt;br/&amp;gt;EXECUTE.VOL&amp;lt;br/&amp;gt;FIRE.VOL&amp;lt;br/&amp;gt;GR.VOL&amp;lt;br/&amp;gt;GUILL*.VOL&amp;lt;br/&amp;gt;NEWS*.VOL&amp;lt;br/&amp;gt;PLAYERS.VOL&amp;lt;br/&amp;gt;RATATATA.VOL&amp;lt;br/&amp;gt;REAP*.VOL&lt;br /&gt;
 | Format = [[Creative Voice File]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game sounds, old VOC format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = EXEC.VOL&amp;lt;br/&amp;gt;RUN.VOL&lt;br /&gt;
 | Format = [[CMF Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = INTRO.VOL&lt;br /&gt;
 | Format = [[Executioners Archive Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Most, but not all, game files in a simple archive&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
== Related Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://dosgames.com/game/executioners/] Executioners on DOSGames.com&lt;br /&gt;
&lt;br /&gt;
[[Category:Bloodlust Software]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Archive_Format&amp;diff=10311</id>
		<title>Executioners Archive Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners_Archive_Format&amp;diff=10311"/>
		<updated>2022-03-25T13:13:30Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Create page! First in a while, many more to come&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = 4095&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = Yes, 8.3&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = Y&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;Executioners Archive Format&#039;&#039;&#039; is how most, but not all, files in the game [[Executioners]] is stored. The game will check the archive file first and fall back to the game directory if the desired file could not be found in the archives. This means you can simply rename or remove the archive files to force the game to use external files from the game directory.&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
There is no known signature for this format.  One method to identify files is to check the first &amp;lt;tt&amp;gt;word&amp;lt;/tt&amp;gt; of the file and compare it to the &amp;lt;tt&amp;gt;word&amp;lt;/tt&amp;gt; at 0x0A. The first value will be a multiple of 16 (the file entries) and the second will be two larger (FAT plus the FAT size &amp;lt;tt&amp;gt;word&amp;lt;/tt&amp;gt;). This should give a minimal chance of incorrectly identifing a file. &lt;br /&gt;
&lt;br /&gt;
=== File entry ===&lt;br /&gt;
&lt;br /&gt;
The first section of the file consists of file entries, with the remainder containing the data.  Each file entry consists of the filename, its offset and its size.  This slightly unusual configuration (storing both the offset and the size) means it is possible (in theory) for two different files to share the same data, and to insert &amp;quot;hidden&amp;quot; data between files.&lt;br /&gt;
&lt;br /&gt;
A file entry is laid out as follows:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|[[char]] cFilename[8]||Filename (8.3 style, but lacking extension), only NULL-terminated if there is enough room&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT32LE]] iOffset||File offset from start of group file&lt;br /&gt;
|-&lt;br /&gt;
|[[UINT32LE]] iSize||File size&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
File entries in the archive do not store the file extension, which is &amp;lt;tt&amp;gt;.VOL&amp;lt;/tt&amp;gt; by default, for all contained files.&lt;br /&gt;
&lt;br /&gt;
=== Implementation Restrictions &amp;amp; Bugs ===&lt;br /&gt;
&lt;br /&gt;
* All file names in the archive must be in upper case&lt;br /&gt;
&lt;br /&gt;
* When searching for a file name, the first match in the FAT is used.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10310</id>
		<title>Executioners</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10310"/>
		<updated>2022-03-25T12:50:08Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Ooop, should&amp;#039;ve noted the classic VGA format, adding the game sound format too since it&amp;#039;s here&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{NeedMoreInfo}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Levels = No&lt;br /&gt;
 | Tiles = No&lt;br /&gt;
 | Sprites = No&lt;br /&gt;
 | Fullscreen = No&lt;br /&gt;
 | Sound = No&lt;br /&gt;
 | Music = No&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Executioners&#039;&#039;&#039; is a DOS game made by Ethan Petty and Icer Addis of Bloodlust Software in 1992. It was their first game, and it sold relatively well at the time. It is notable for its violent content, moderated only by the constraints of the hardware of the time.&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACK*.VOL&amp;lt;br/&amp;gt;E.VOL&amp;lt;br/&amp;gt;FUCKED.VOL&amp;lt;br/&amp;gt;FUCKED2.VOL&amp;lt;br/&amp;gt;GUILLBIO.VOL&amp;lt;br/&amp;gt;PROD*.VOL&amp;lt;br/&amp;gt;REAPBOI.VOL&amp;lt;br/&amp;gt;SKETCH.VOL&amp;lt;br/&amp;gt;SKETCH2.VOL&amp;lt;br/&amp;gt;SKULL.VOL&amp;lt;br/&amp;gt;TITLE.VOL&lt;br /&gt;
 | Format = [[Raw VGA Image]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = 320x200 VGA images, no palette data&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACKPAL.VOL&amp;lt;br/&amp;gt;BIOPAL.VOL&amp;lt;br/&amp;gt;DARKPAL.VOL&amp;lt;br/&amp;gt;LIGHTPAL.VOL&amp;lt;br/&amp;gt;PRODPAL.VOL&amp;lt;br/&amp;gt;RUNPAL.VOL&amp;lt;br/&amp;gt;SDPAL.VOL&amp;lt;br/&amp;gt;SLPAL.VOL&amp;lt;br/&amp;gt;TPAL.VOL&amp;lt;br/&amp;gt;TVPAL.VOL&lt;br /&gt;
 | Format = [[VGA Palette]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game palettes, &#039;Classic&#039; VGA format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BLOOD.VOL&amp;lt;br/&amp;gt;BOOM.VOL&amp;lt;br/&amp;gt;END*.VOL&amp;lt;br/&amp;gt;EXECUTE.VOL&amp;lt;br/&amp;gt;FIRE.VOL&amp;lt;br/&amp;gt;GR.VOL&amp;lt;br/&amp;gt;GUILL*.VOL&amp;lt;br/&amp;gt;NEWS*.VOL&amp;lt;br/&amp;gt;PLAYERS.VOL&amp;lt;br/&amp;gt;RATATATA.VOL&amp;lt;br/&amp;gt;REAP*.VOL&lt;br /&gt;
 | Format = [[Creative Voice File]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game sounds, old VOC format&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = EXEC.VOL&amp;lt;br/&amp;gt;RUN.VOL&lt;br /&gt;
 | Format = [[CMF Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
== Related Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://dosgames.com/game/executioners/] Executioners on DOSGames.com&lt;br /&gt;
&lt;br /&gt;
[[Category:Bloodlust Software]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10309</id>
		<title>Executioners</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=10309"/>
		<updated>2022-03-25T12:36:12Z</updated>

		<summary type="html">&lt;p&gt;Levellass: I&amp;#039;m not dead! Adding familiar file formats in preparation for writing up UNfamiliar ones and coding an editor.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{NeedMoreInfo}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Levels = No&lt;br /&gt;
 | Tiles = No&lt;br /&gt;
 | Sprites = No&lt;br /&gt;
 | Fullscreen = No&lt;br /&gt;
 | Sound = No&lt;br /&gt;
 | Music = No&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Executioners&#039;&#039;&#039; is a DOS game made by Ethan Petty and Icer Addis of Bloodlust Software in 1992. It was their first game, and it sold relatively well at the time. It is notable for its violent content, moderated only by the constraints of the hardware of the time.&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACK*.VOL&amp;lt;br/&amp;gt;E.VOL&amp;lt;br/&amp;gt;FUCKED.VOL&amp;lt;br/&amp;gt;FUCKED2.VOL&amp;lt;br/&amp;gt;GUILLBIO.VOL&amp;lt;br/&amp;gt;PROD*.VOL&amp;lt;br/&amp;gt;REAPBOI.VOL&amp;lt;br/&amp;gt;SKETCH.VOL&amp;lt;br/&amp;gt;SKETCH2.VOL&amp;lt;br/&amp;gt;SKULL.VOL&amp;lt;br/&amp;gt;TITLE.VOL&lt;br /&gt;
 | Format = [[Raw VGA Image]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = 320x200 VGA images, no palette data&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = BACKPAL.VOL&amp;lt;br/&amp;gt;BIOPAL.VOL&amp;lt;br/&amp;gt;DARKPAL.VOL&amp;lt;br/&amp;gt;LIGHTPAL.VOL&amp;lt;br/&amp;gt;PRODPAL.VOL&amp;lt;br/&amp;gt;RUNPAL.VOL&amp;lt;br/&amp;gt;SDPAL.VOL&amp;lt;br/&amp;gt;SLPAL.VOL&amp;lt;br/&amp;gt;TPAL.VOL&amp;lt;br/&amp;gt;TVPAL.VOL&lt;br /&gt;
 | Format = [[VGA Palette]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game palettes&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = RUN.VOL&lt;br /&gt;
 | Format = [[CMF Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
== Related Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://dosgames.com/game/executioners/] Executioners on DOSGames.com&lt;br /&gt;
&lt;br /&gt;
[[Category:Bloodlust Software]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Jazz_Jackrabbit&amp;diff=10308</id>
		<title>Jazz Jackrabbit</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Jazz_Jackrabbit&amp;diff=10308"/>
		<updated>2022-03-25T12:27:00Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Can confirm Fonts.000 is a 0FN type file with minor modifications. I wrote the tool that can edit fonts, it notes this on the format&amp;#039;s page.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Levels = Edit&lt;br /&gt;
 | Tiles = Edit&lt;br /&gt;
 | Sprites = Edit&lt;br /&gt;
 | Fullscreen = Edit&lt;br /&gt;
 | Sound = Edit&lt;br /&gt;
 | Music = Edit&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
{{BeginFileFormatTools|Type=game}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://www.jazz2online.com/downloads/6143/j1e-jazz-jackrabbit1-level-editor-version-12/ J1E]&lt;br /&gt;
| Platform = Windows&lt;br /&gt;
| grp = N/A&lt;br /&gt;
| map = Edit&lt;br /&gt;
| gfx = ?&lt;br /&gt;
| mus = ?&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://www.jazz2online.com/downloads/6040/jj1mod/ JJ1MOD]&lt;br /&gt;
| Platform = DOS&lt;br /&gt;
| grp = N/A&lt;br /&gt;
| map = No&lt;br /&gt;
| gfx = Edit&lt;br /&gt;
| mus = No&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://www.jazz2online.com/jcs94/ JCS&#039;94]&lt;br /&gt;
| Platform = Windows&lt;br /&gt;
| grp = N/A&lt;br /&gt;
| map = Edit&lt;br /&gt;
| gfx = ?&lt;br /&gt;
| mus = ?&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{EndFileFormatTools}}&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = bonusmap.*&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Bonusmap Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Bonus levels&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = bonus[xy].000&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Bonus Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Bonus fonts and sprites&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.0sc&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Cutscene Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Cutscenes&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = macro.*&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Demo Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Demo macros&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = font*.0fn&amp;lt;br/&amp;gt;fonts.000&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Font Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Fonts&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = level?.*&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Map Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Normal levels&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = menu.000&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Menu Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Menu graphics&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = panel.000&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Panel Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = In-level game panel&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = planet.*&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Planet Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Planet images&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = save.*&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Saved Game Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Saved games&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = hiscore&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Score Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = High scores&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = sounds.*&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Sound Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Sound effects&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = sprites.*&amp;lt;br/&amp;gt;mainchar.000&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Sprite Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Sprites&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = blockx.*&amp;lt;br/&amp;gt;bonus?.000&lt;br /&gt;
 | Format = [[Jazz Jackrabbit Tile Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Level tiles and bonus tiles, respectively&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.psm&lt;br /&gt;
 | Format = [[ProTracker Studio Module]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
Most files are compressed with [[Jazz Jackrabbit RLE compression]].&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [http://www.alister.eu/jazz/oj/ OpenJazz] might provide insight in the various file formats though it is working with flawed information&lt;br /&gt;
&lt;br /&gt;
[[Category:Epic Megagames]]&lt;br /&gt;
[[Category:Renaissance]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=9658</id>
		<title>Executioners</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Executioners&amp;diff=9658"/>
		<updated>2021-04-24T04:30:13Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Create page, should add more data and formats as I figure them out&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{NeedMoreInfo}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Levels = No&lt;br /&gt;
 | Tiles = No&lt;br /&gt;
 | Sprites = No&lt;br /&gt;
 | Fullscreen = No&lt;br /&gt;
 | Sound = No&lt;br /&gt;
 | Music = No&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Executioners&#039;&#039;&#039; is a DOS game made by Ethan Petty and Icer Addis of Bloodlust Software in 1992. It was their first game, and it sold relatively well at the time. It is notable for its violent content, moderated only by the constraints of the hardware of the time.&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = RUN.VOL&lt;br /&gt;
 | Format = [[CMF Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
== Related Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://dosgames.com/game/executioners/] Executioners on DOSGames.com&lt;br /&gt;
&lt;br /&gt;
[[Category:Bloodlust Software]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=CMF_Format&amp;diff=9657</id>
		<title>CMF Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=CMF_Format&amp;diff=9657"/>
		<updated>2021-04-24T04:19:27Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add Executioners, which uses this format in music. (Hopefully more will be added on that game soon.)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Music Infobox&lt;br /&gt;
 | Type = MIDI&lt;br /&gt;
 | Instruments = OPL&lt;br /&gt;
 | NumChannels = 16&lt;br /&gt;
 | NumTracks = 1&lt;br /&gt;
 | NumPatterns = 1&lt;br /&gt;
 | NumOrders = 0&lt;br /&gt;
 | Tags = Title, Artist, Remarks&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Jill of the Jungle}}&lt;br /&gt;
   {{Game|Kiloblaster}}&lt;br /&gt;
   {{Game|Scud Atak}}&lt;br /&gt;
   {{Game|Solar Winds}}&lt;br /&gt;
   {{Game|Traffic Department 2192}}&lt;br /&gt;
   {{Game|Math Rescue}}&lt;br /&gt;
   {{Game|Word Rescue}}&lt;br /&gt;
   {{Game|Xargon}}&lt;br /&gt;
   {{Game|King Arthur&#039;s K.O.R.T.}}&lt;br /&gt;
   {{Game|Executioners}}&lt;br /&gt;
}}&lt;br /&gt;
The &amp;lt;b&amp;gt;&amp;lt;u&amp;gt;C&amp;lt;/u&amp;gt;reative &amp;lt;u&amp;gt;M&amp;lt;/u&amp;gt;usic &amp;lt;u&amp;gt;F&amp;lt;/u&amp;gt;ormat (CMF)&amp;lt;/b&amp;gt; was created by Creative Labs for use with their SoundBlaster series of sound cards.  It is a cut-down version of the [[MID Format|MIDI format]] (only one track) but unlike MIDI it allows custom instruments to be stored in the file itself (and unlike the Module formats that preceded it, the instruments were not sampled but were synthesised using the Adlib/SoundBlaster OPL chips.)&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
The file begins with a header:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Name!!Description&lt;br /&gt;
|-&lt;br /&gt;
|BYTE[4]||cSignature||&amp;quot;CTMF&amp;quot; (not NULL-terminated)&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iVersionMinor||Minor version number (normally 0x01)&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iVersionMajor||Major version number (normally 0x01)&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iOffsetInstruments||Offset of the instrument block, from the start of the file&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iOffsetMusic||Offset of the music block, from the start of the file&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iTicksPerQuarter||Clock ticks per quarter note (one beat)&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iTicksPerSecond||Clock ticks per second&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iOffsetTitle||Offset of the song title string, zero if no title&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iOffsetComposer||Offset of the composer&#039;s name, zero if not listed&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iOffsetRemarks||Offset of the &amp;quot;remarks&amp;quot; string, zero if no remarks&lt;br /&gt;
|-&lt;br /&gt;
|UINT8[16]||iChannelInUse||Channel in use table (0x00 == channel not used, 0x01 == channel used in song)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The rest of the header depends on the version:&lt;br /&gt;
&lt;br /&gt;
==== Version 1.0 ====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Name!!Description&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iInstrumentCount||Number of instruments used&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Version 1.1 ====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Name!!Description&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iInstrumentCount||Number of instruments used&lt;br /&gt;
|-&lt;br /&gt;
|UINT16LE||iTempo||Basic tempo (BPM?)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The song title, composer and remarks (if present) should follow this header and the instrument block should follow that (although there is no requirement for them to be located here, as long as the offsets in the header point to the correct location.)  These three strings are NULL-terminated ASCII.&lt;br /&gt;
&lt;br /&gt;
It is worth noting that the header stores both a tempo value and a &amp;quot;ticks per quarter note&amp;quot; value, however the only field that seems to be used for timing during playback is the &amp;quot;ticks per second&amp;quot; field.  The tempo field doesn&#039;t even exist in version 1.0 files.  It is assumed &amp;quot;basic tempo&amp;quot; means BPM (beats per minute) as this is the meaning of the &amp;quot;basic tempo&amp;quot; field in the earlier [[AdLib MIDI Format]].&lt;br /&gt;
&lt;br /&gt;
It is also worth noting that between v1.0 and v1.1, the number of possible instruments expanded from a maximum of 256 (UINT8) to 65536 (UINT16.)  However the MIDI data itself is only capable of addressing up to 128 instruments, so any extras cannot be used.  Perhaps there was originally an intention to make these available through instrument banks like MIDI does.&lt;br /&gt;
&lt;br /&gt;
Be aware that the title/composer/remarks fields are supposed to be zero if there is no metadata, but [[Highway Hunter]] sets them to invalid values (past EOF), so you may wish to check that these fields are within range and ignore them otherwise.&lt;br /&gt;
&lt;br /&gt;
=== Instrument block ===&lt;br /&gt;
&lt;br /&gt;
The instrument block contains all the instruments used in the song.  The first instrument is referred to in the song data as instrument zero (MIDI patch #0.)  The following table lists the fields used to define one instrument - it is repeated &#039;&#039;iInstrumentCount&#039;&#039; times.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data type!!Name!!OPL base register!!Description&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iModChar||0x20||Modulator characteristic (Mult, KSR, EG, VIB and AM flags)&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iCarChar||0x23||Carrier characteristic (Mult, KSR, EG, VIB and AM flags)&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iModScale||0x40||Modulator key scaling/output level&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iCarScale||0x43||Carrier key scaling/output level&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iModAttack||0x60||Modulator attack/decay level&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iCarAttack||0x63||Carrier attack/decay level&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iModSustain||0x80||Modulator sustain/release level&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iCarSustain||0x83||Carrier sustain/release level&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iModWaveSel||0xE0||Modulator wave select&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iCarWaveSel||0xE3||Carrier wave select&lt;br /&gt;
|-&lt;br /&gt;
|UINT8||iFeedback||0xC0||Feedback/connection&lt;br /&gt;
|-&lt;br /&gt;
|BYTE[5]&lt;br /&gt;
|colspan=3|Padding to bring instrument definition up to 16 bytes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
There are 16 default instruments, repeated into the 128 available MIDI instruments (so instrument 0, 16, 32, etc. all refer to this first default instrument.  See [[#Default instruments]] below)  The instrument block then overrides these defaults.  [[Word Rescue]] is notable for having CMFs that rely on these default instruments being present and correct.&lt;br /&gt;
&lt;br /&gt;
==== Percussive instruments ====&lt;br /&gt;
Since each CMF instrument contains both OPL modulator and OPL carrier settings, when an instrument is selected in a CMF file, both the modulator and carrier settings are loaded into the OPL chip for that channel.&lt;br /&gt;
&lt;br /&gt;
When the CMF is in percussive mode however (see [[#Controller 0x67: Rhythm mode]] below), most of the percussive instruments only occupy either a modulator or a carrier (i.e. half an instrument.)  This means that loading these instruments must be treated slightly differently, as a whole instrument is supplied but only half of it will be loaded into the OPL chip, and not necessarily the expected half.&lt;br /&gt;
&lt;br /&gt;
When percussive mode is active and an instrument change event (MIDI event 0xC0) is received on a percussive channel (12-16 inclusive), the instruments should be loaded as follows:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!CMF channel!!Instrument!!Instrument source!!OPL cell&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;center&amp;gt;12&amp;lt;/center&amp;gt;||Bass drum||Modulator&amp;lt;br&amp;gt;Carrier||13 - Channel 7 Modulator&amp;lt;br&amp;gt;16 - Channel 7 Carrier&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;center&amp;gt;13&amp;lt;/center&amp;gt;||Snare drum||Modulator||17 - Channel 8 Carrier&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;center&amp;gt;14&amp;lt;/center&amp;gt;||Tom tom||Modulator||15 - Channel 9 Modulator&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;center&amp;gt;15&amp;lt;/center&amp;gt;||Top cymbal||Modulator||18 - Channel 9 Carrier&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;center&amp;gt;16&amp;lt;/center&amp;gt;||Hi-hat||Modulator||14 - Channel 8 Modulator&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Despite some documentation suggesting that certain instruments cannot have their pitch set, the Creative Labs SBFMDRV will play all percussive instruments at the requested pitch.  Note however that as only one pitch can be set per channel, playing both a snare and hi-hat, or both a tom tom and top cymbal, at the same time, will cause a conflict, potentially changing the pitch of an already-playing note.  The Creative Labs SBFMDRV simply writes the pitch as each note is played, changing the pitch of any currently playing note on the shared channel.&lt;br /&gt;
&lt;br /&gt;
Be aware that some songs (e.g. [[Kiloblaster]]&#039;s &amp;lt;tt&amp;gt;song_2&amp;lt;/tt&amp;gt;) play two different percussive instruments simultaneously, when those two instruments share the same OPL channel (e.g. hi-hat and snare drum.)  The notes are actually played at different pitches, which introduces a conflict, as only one note frequency is available for the channel and it must be shared by both instruments.  In this case the order of events is important, as the pitch of the last event at that instant is the one that gets set for the channel.  Normally with MIDI, if notes are played at the same instant in time it does not matter which order they are issued in, however in this case the song is quite different if the order is not maintained.&lt;br /&gt;
&lt;br /&gt;
Essentially SBFMDRV writes the pitch to the OPL channel as the events are encountered, so whichever note is played last is the frequency the channel will be set to.&lt;br /&gt;
&lt;br /&gt;
=== Song data ===&lt;br /&gt;
&lt;br /&gt;
The song data itself is in standard MIDI format - identical to the &#039;&#039;data&#039;&#039; stored in a MIDI MTrk block (but without the &amp;quot;MTrk&amp;quot; header of course.)  For details on this, see the [[MID Format#MIDI data|MIDI data description]].&lt;br /&gt;
&lt;br /&gt;
One difference worth noting is that the official Creative Labs CMF player does not support pitch bends (code 0xE0) and those events are simply ignored.  Simple sysex data appears to be ignored also, however its use in a CMF file can cause problems with other players.&lt;br /&gt;
&lt;br /&gt;
==== MIDI controllers ====&lt;br /&gt;
&lt;br /&gt;
In addition to the standard MIDI controllers (which are actually rarely used in CMF files), the following controllers have special meaning in a CMF file.  Each controller has one data byte (the &amp;quot;controller value&amp;quot;, 0-127), and the meaning of this byte will of course depend on which controller was selected.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Controller!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|0x63||Non-standard extension: AM+VIB depth control (see below)&lt;br /&gt;
|-&lt;br /&gt;
|0x66||Set marker byte (used as a status flag readable by a music player)&lt;br /&gt;
|-&lt;br /&gt;
|0x67||Switch OPL between melody and rhythm mode (see below)&lt;br /&gt;
|-&lt;br /&gt;
|0x68||Transpose up by given number of 1/128 semitones&lt;br /&gt;
|-&lt;br /&gt;
|0x69||Transpose down by given number of 1/128 semitones&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Controller 0x63: Depth control =====&lt;br /&gt;
MIDI controller 0x63 is a nonstandard extension to allow the OPL&#039;s AM+VIB depth control to be adjusted (normal CMF playback has both the AM and VIB depth control fixed in the on state.)  When this controller is set to zero, the depth control is switched off (i.e. amplitude depth is 1 dB, vibrato depth is 7 cents.)  Setting the controller to a value of one increases the vibrato to a depth of 14 cents (OPL port 0xBD has bit 6 set), and setting the control to a value of two increases the amplitude depth to 4.8 dB (OPL port 0xBD has bit 7 set).  Setting the control to a value of three increases both depth controllers, which is the CMF default setting (OPL port 0xBD has bits 6 and 7 set.)&lt;br /&gt;
&lt;br /&gt;
Since this setting is global and affects the entire OPL chip, it does not matter which channel the controller change is issued on.&lt;br /&gt;
&lt;br /&gt;
===== Controller 0x66: Song markers =====&lt;br /&gt;
Controller 0x66 is used to set a marker byte in the song.  This can be used to notify the music player that a certain point in a song has been reached, or to trigger some kind of action in time with the music.&lt;br /&gt;
&lt;br /&gt;
===== Controller 0x67: Rhythm mode =====&lt;br /&gt;
MIDI controller 0x67 is used to switch between &amp;quot;melody mode&amp;quot; and OPL &amp;quot;rhythm mode.&amp;quot;  In melody mode, nine-channel FM music is possible.  In rhythm-mode, six-channel FM music is possible, with an additional five channels used for percussion (allowing 11 sounds to be played simultaneously.)  In this mode, the last five MIDI channels are reserved for the percussive instruments as shown below.&lt;br /&gt;
&lt;br /&gt;
Since this setting is global and affects the entire OPL chip, it does not matter which channel the controller change is issued on.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Hex channel!!MIDI channel!!Use in melody mode!!Use in rhythm mode&lt;br /&gt;
|-&lt;br /&gt;
|0x00||1||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x01||2||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x02||3||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x03||4||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x04||5||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x05||6||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x06||7||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x07||8||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x08||9||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x09||10||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x0A||11||Normal instrument||Normal instrument&lt;br /&gt;
|-&lt;br /&gt;
|0x0B||12||Normal instrument||Bass drum&lt;br /&gt;
|-&lt;br /&gt;
|0x0C||13||Normal instrument||Snare drum&lt;br /&gt;
|-&lt;br /&gt;
|0x0D||14||Normal instrument||Tom-tom&lt;br /&gt;
|-&lt;br /&gt;
|0x0E||15||Normal instrument||Top cymbal&lt;br /&gt;
|-&lt;br /&gt;
|0x0F||16||Normal instrument||Hi-hat cymbal&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
See [[#CMF/MIDI vs Adlib channels]] below for more details.&lt;br /&gt;
&lt;br /&gt;
===== Controller 0x68: Transpose up =====&lt;br /&gt;
This controller transposes all following notes on the channel up by the given number of 1/128 semitones.  Since the controller value must be between 0 and 127, it will allow a song to be transposed up anywhere between zero and almost a full semitone.  The value is absolute, so a controller requesting a transpose up by 127 followed by a transpose up by 64, will initially be transposed up by almost a full semitone (127) but will then be transposed back by a half semitone (to 64).&lt;br /&gt;
&lt;br /&gt;
A value of zero resets back to &amp;quot;not transposed.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===== Controller 0x69: Transpose down =====&lt;br /&gt;
Identical to controller 0x68 (Transpose up) only of course in the opposite direction, and again only affecting the channel the controller is issued on.&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
&lt;br /&gt;
==== Keyon/off handling ====&lt;br /&gt;
Some songs don&#039;t always send keyoffs after a keyon, or they send them out of order (e.g. note 1 on, delay, note 2 on, note 1 off, delay, note 2 off.)  If you don&#039;t check this you&#039;ll end up switching a note off too early (in the above example the &amp;quot;note 1 off&amp;quot; should *not* switch off &amp;quot;note 2&amp;quot; that was switched on just before it.)  &amp;lt;tt&amp;gt;song_9.xr1&amp;lt;/tt&amp;gt; from the first episode of Xargon is an excellent example of this, right at the start of the song.&lt;br /&gt;
&lt;br /&gt;
The best way of handling this when playing through an OPL chip seems to be to remember the last note played on a channel, and upon receiving a keyoff, only process it if the keyoff is for the note currently playing on the channel (otherwise it can be discarded.)  If a keyon is received and a note is already being played on a channel, the old note should be switched off just before playing the new note.&lt;br /&gt;
&lt;br /&gt;
==== Keyon/off timing ====&lt;br /&gt;
Some songs play a note-on, then immediately (with no delay) have a corresponding note-off.  If this is played faithfully, then the note will not be heard, however the Creative Labs player still plays these notes.  The correct solution is {{TODO|currently unknown - wait for one tick or use the emulator callback between events?}}.  A good example of this is the first few notes in &amp;lt;tt&amp;gt;song_32.xr1&amp;lt;/tt&amp;gt;.  ([https://github.com/adplug/adplug/issues/41 Discussion])&lt;br /&gt;
&lt;br /&gt;
==== Default instruments ====&lt;br /&gt;
Although no documentation exists about this, it seems that the Creative Labs player sets the 128 available instruments based on 16 defaults looped/repeated to fill the 128 slots.  They do not appear to be based on any MIDI instrument specification.  Any instruments included in the CMF file then override these defaults.  Some songs (e.g. the [[Word Rescue]] background music) rely on these default instruments and don&#039;t play properly if only their custom instruments are set.&lt;br /&gt;
&lt;br /&gt;
There appear to be a different set of default instruments used for the percussion channels when rhythm mode is active.  More investigation needs to be done to determine what these are and if they are related to the 16 default melody instruments.&lt;br /&gt;
&lt;br /&gt;
{{TODO|Post a set of OPL settings here (perhaps in [[IBK Format]]) that provides these default parameters.}}&lt;br /&gt;
&lt;br /&gt;
{{TODO|Confirm whether it&#039;s possible to set more than 16 custom instruments, without them looping and overwriting the earlier ones.}}&lt;br /&gt;
&lt;br /&gt;
==== CMF/MIDI vs Adlib channels ====&lt;br /&gt;
MIDI (and consequently CMF) supports up to 16 channels.  The OPL2 synth on the Adlib only supports a maximum of nine channels in normal mode, or six channels plus five percussion instruments in rhythm mode.&lt;br /&gt;
&lt;br /&gt;
This means that any CMF player must correctly map up to 16 MIDI channels to only nine OPL channels.  Many songs from games work correctly with a 1:1 mapping (i.e. the game music doesn&#039;t go beyond MIDI channel 9), however there are some songs that use channels beyond this (e.g. [[Word Rescue]] again, which, given the Voyetra credit, has probably been minimally converted from MIDI.)&lt;br /&gt;
&lt;br /&gt;
At the time of writing, there are no known songs that use more than nine MIDI channels simultaneously, however [[Word Rescue]]&#039;s E1L1 song appears to sound more than nine notes simultaneously across a smaller number of channels, so if all these notes should be heard, the extended OPL3 channels probably need to be used.  [[Xargon]] &amp;lt;tt&amp;gt;song9&amp;lt;/tt&amp;gt; also sounds multiple notes simultaneously in a single channel.  Either of these will result in lost notes unless the available channels are cleverly managed.&lt;br /&gt;
&lt;br /&gt;
As an aside, it would be interesting to test this with Creative&#039;s driver to see how it behaves.&lt;br /&gt;
&lt;br /&gt;
==== Note velocity ====&lt;br /&gt;
The velocity values are loaded more or less directly into the OPL chip.  This means unlike MIDI, the velocity is not a linear scale from 0 to 127, but logarithmic.  A value of 1 is almost silent, and rapidly increase in volume so that values 2 and 3 are much louder.  At the other end of the scale, 127 is full volume, but 126 and 125 are barely any quieter.&lt;br /&gt;
&lt;br /&gt;
==== Format violations ====&lt;br /&gt;
&lt;br /&gt;
These format violations may require special consideration in order for a player to correctly handle these files.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;dan.cmf&amp;lt;/tt&amp;gt; from [[Jill of the Jungle]] should end with bytes &amp;lt;tt&amp;gt;FF 2F 00&amp;lt;/tt&amp;gt; (the &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt; indicating no data bytes for the &amp;lt;tt&amp;gt;2F&amp;lt;/tt&amp;gt; &#039;end of song&#039; event) but it instead ends with &amp;lt;tt&amp;gt;FF 2F FE&amp;lt;/tt&amp;gt;, with &amp;lt;tt&amp;gt;FE&amp;lt;/tt&amp;gt; being an invalid (truncated) MIDI number.&lt;br /&gt;
&lt;br /&gt;
* [[Highway Hunter]] CMF files contain invalid offsets for the metadata fields, as they point past the end of the file.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
{{BeginFileFormatTools|Type=audio}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://www.hitsquad.com/smm/programs/cmf2mid/ CMF2MID]&lt;br /&gt;
| Platform = DOS&lt;br /&gt;
| canPlay = No&lt;br /&gt;
| canCreate = No&lt;br /&gt;
| canModify = No&lt;br /&gt;
| canExport = Yes; .mid&lt;br /&gt;
| canImport = Yes; [[CMF Format|.cmf]]&lt;br /&gt;
| editHidden = No&lt;br /&gt;
| editMetadata = No&lt;br /&gt;
| notes = Convert CMF files into MIDI&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://adplug.sourceforge.net AdPlug/AdPlay]&lt;br /&gt;
| Platform = DOS, Linux, Windows&lt;br /&gt;
| canPlay = Yes&lt;br /&gt;
| canCreate = No&lt;br /&gt;
| canModify = No&lt;br /&gt;
| canExport = No&lt;br /&gt;
| canImport = No&lt;br /&gt;
| editHidden = No&lt;br /&gt;
| editMetadata = No&lt;br /&gt;
| notes = Plugins for various audio players (plus a command line player) that mostly supports CMF files&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://www.shikadi.net/utils/xmms.html Malvineous&#039; Adlib plugin]&lt;br /&gt;
| Platform = Linux&lt;br /&gt;
| canPlay = Yes&lt;br /&gt;
| canCreate = No&lt;br /&gt;
| canModify = No&lt;br /&gt;
| canExport = No&lt;br /&gt;
| canImport = No&lt;br /&gt;
| editHidden = No&lt;br /&gt;
| editMetadata = No&lt;br /&gt;
| notes = Plugin for XMMS and Audacious that plays most CMF files more accurately than AdPlug&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [[OPL3 Bank Editor]]&lt;br /&gt;
| Platform = Linux, Windows, macOS&lt;br /&gt;
| canPlay = No&lt;br /&gt;
| canCreate = No&lt;br /&gt;
| canModify = No&lt;br /&gt;
| canExport = Yes; many&lt;br /&gt;
| canImport = No&lt;br /&gt;
| editHidden = No&lt;br /&gt;
| editMetadata = No&lt;br /&gt;
| notes = Import instruments from CMF files to use them in banks&lt;br /&gt;
}}&lt;br /&gt;
{{EndFileFormatTools}}&lt;br /&gt;
&lt;br /&gt;
== Similar formats ==&lt;br /&gt;
* The CMF song data is stored in the same format as used by [[MID Format|MIDI files]]&lt;br /&gt;
* The [[SBI Format]] (SoundBlaster Instrument) is the same as used in the CMF instrument block, with a header on the front.&lt;br /&gt;
* The [[IBK Format]] (Instrument Bank) is a group of SBI instruments, similar to the whole CMF instrument block.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_Archive_Format&amp;diff=9090</id>
		<title>All Dogs Archive Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_Archive_Format&amp;diff=9090"/>
		<updated>2020-06-12T13:40:30Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Create this apge, I think that&amp;#039;s all the formats in this game!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Tileset Infobox&lt;br /&gt;
 | Hardware1 = CGA&lt;br /&gt;
 | Hardware2 = EGA&lt;br /&gt;
 | Hardware3 = TGA&lt;br /&gt;
 | Palette = External&lt;br /&gt;
 | Names = N&lt;br /&gt;
 | TileMinSize = 0&amp;amp;times;0&lt;br /&gt;
 | TileMaxSize = 8,191&amp;amp;times;65,535&lt;br /&gt;
 | NumPlanes = 1&lt;br /&gt;
 | HasTransparency = N&lt;br /&gt;
 | Metadata = Yes&lt;br /&gt;
 | Subtilesets = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|All Dogs Go To Heaven}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The Polarware game [[All Dogs Go To Heaven]] stores its graphics in two sets of seven archive files with the names &amp;lt;tt&amp;gt;MRH_DOG?.DB?&amp;lt;/tt&amp;gt;. There are two sets of graphics, one for the [[Raw CGA data|CGA]] version of the game and the other for the [[Raw EGA data|EGA]] and TGA versions. Both sets of archive use the same format to store the graphics (and text) chunks used by the game.&lt;br /&gt;
&lt;br /&gt;
Each file is divided into two sections, a header giving the location, size and decompressed size of graphics chunks, and the chunks themselves. Chunks may or may not be compressed; the game decides this by checking to see if the decompressed data size is the same as that of the actual chunk size. All text chunks are uncompressed but only a few graphics chunks are as well. The chunks that are compressed are done so using [[All Dogs RLE compression]] which is very inefficient.&lt;br /&gt;
&lt;br /&gt;
The graphics data is either CGA or EGA (With the TGA graphics being based on the EGA data) in linear (rather than planar) format. As such the raw data can simply be given a bitmap header to convert it into a 2bpp or 4bpp image.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Format ==&lt;br /&gt;
&lt;br /&gt;
 Number of images:&lt;br /&gt;
 0   2    NumImages   The total number of images in the file. The header&#039;s total size will be this&lt;br /&gt;
                      multiplied by 8 plus 2 bytes long.&lt;br /&gt;
 List:&lt;br /&gt;
 0   2    DeCmpSize   Size of the chunk when decompressed, in bytes.&lt;br /&gt;
 2   2    CmpSize     Size of the chunk in the file.&lt;br /&gt;
 12  4    DataStart   Where in the file the chunk starts&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&lt;br /&gt;
Each graphic chunk contains six bytes giving the graphic width (in data bytes, not pixels), height and total size when decompressed (again in bytes).&lt;br /&gt;
&lt;br /&gt;
Some chunks have a corresponding &#039;mask&#039; chunk used by the game to give the graphic some transparency. This is a black and white image. Other chunks simply set black as the transparent color.&lt;br /&gt;
&lt;br /&gt;
Some (but far from all) of the game&#039;s text is stored as 32-byte chunks. Specifically the strings used in the &#039;hangman&#039; type minigame. These chunks are always uncompressed and nul-padded. They also lack the size size bytes at the start.&lt;br /&gt;
&lt;br /&gt;
The first four bytes of a chunk are not compressed but the next two are, despite bytes 5&amp;amp;6 being metadata (The image size) rather than graphics data.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=File:Raw_CGA_Data.png&amp;diff=9089</id>
		<title>File:Raw CGA Data.png</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=File:Raw_CGA_Data.png&amp;diff=9089"/>
		<updated>2020-06-12T13:17:42Z</updated>

		<summary type="html">&lt;p&gt;Levellass: The CGA titlescreen of All Dogs Go To Heaven showing the four color palette.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The CGA titlescreen of [[All Dogs Go To Heaven]] showing the four color palette.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=File:All_Dogs_Go_To_Heaven.png&amp;diff=9088</id>
		<title>File:All Dogs Go To Heaven.png</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=File:All_Dogs_Go_To_Heaven.png&amp;diff=9088"/>
		<updated>2020-06-12T13:15:37Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Box cover for the Amiga version of All Dogs Go To Heaven.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Box cover for the Amiga version of [[All Dogs Go To Heaven]].&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Category:All_Dogs_Go_To_Heaven&amp;diff=9087</id>
		<title>Category:All Dogs Go To Heaven</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Category:All_Dogs_Go_To_Heaven&amp;diff=9087"/>
		<updated>2020-06-12T13:12:49Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Well this needs blueshifting.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GameCategory}}&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=LPCM_format&amp;diff=9086</id>
		<title>LPCM format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=LPCM_format&amp;diff=9086"/>
		<updated>2020-06-12T13:10:21Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Create page, it&amp;#039;s a basic format but a surprisingly commonly used one, even way back when.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Sound Infobox&lt;br /&gt;
 | Type = PCM&lt;br /&gt;
 | NumChannels = 1&lt;br /&gt;
 | BitsPerSample = 8&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Tags = Name&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|All Dogs Go To Heaven}}&lt;br /&gt;
   {{Game|Jazz Jackrabbit}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Linear pulse-code modulation (LPCM) is a specific type of PCM (pulse-code modulation) where the quantization levels are linearly uniform. This is in contrast to PCM encodings where quantization levels vary as a function of amplitude. Though PCM is a more general term, it is often used to describe data encoded as LPCM. It is the standard form of digital audio in computers, compact discs, digital telephony and other digital audio applications. In a PCM stream, the amplitude of the analog signal is sampled regularly at uniform intervals, and each sample is quantized to the nearest value within a range of digital steps.&lt;br /&gt;
&lt;br /&gt;
A PCM stream has two basic properties that determine the stream&#039;s fidelity to the original analog signal: the sampling rate, which is the number of times per second that samples are taken; and the bit depth, which determines the number of possible digital values that can be used to represent each sample.&lt;br /&gt;
&lt;br /&gt;
In short such data consists of an uncompressed steam of data where a certain number of bytes represents a piece of a soundwave. Playing a specific amplitude for each &#039;tick&#039; of time will reproduce the sound to varying levels of fidelity depending on how often the sound was sampled. It is a highly inefficient way to store audio data as even very poor quality audio must be sampled several thousand times per second.&lt;br /&gt;
&lt;br /&gt;
In most early games using this format the sampling rate is either very low, around a tenth of a standard wave file, ([[All Dogs Go To Heaven]]) or the game &#039;smoothed&#039; or altered the data to improve quality ([[Jazz Jackrabbit]]). The stream is read as mono (rather than stereo) with 16 bits per sample.  This makes the format exceedingly simple, lacking any organization or compression of any kind aside from the raw sound data.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_RLE_Compression&amp;diff=9085</id>
		<title>All Dogs RLE Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_RLE_Compression&amp;diff=9085"/>
		<updated>2020-06-12T13:09:20Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Fix that template!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-bit&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|All Dogs Go To Heaven}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[All Dogs Go To Heaven]] uses [[RLE Compression]] to compress graphics chunks in its [[All Dogs Archive format|graphics archives.]] This is one of many possible ways to create a functional RLE system.&lt;br /&gt;
&lt;br /&gt;
The compressed file consists of an UINT32LE giving the number of bytes (not pixels) in each row of the graphics chunk, an UINT32LE giving the number of rows in the graphic, and the compressed data. The first UINT32LE of the compressed data, which is almost always uncompressed, gives the size of the uncompressed data. As a check the decompressed size value should be equal to the width and height values multiplied.&lt;br /&gt;
&lt;br /&gt;
The data can be either [[Raw CGA Data|CGA]] or [[Raw EGA data|EGA]] data which are four or two pixels of data per byte respectively.&lt;br /&gt;
&lt;br /&gt;
The compressed data is processed in a loop. After each byte is read, its value is used to select an action. If the byte has a value of 27 (val &amp;amp; 0x1B) then the next word gives the number of identical bytes to output and the byte after that is the byte to repeat. All other bytes are passed through unchanged. The next byte is then read and the same procedure followed until there is no more data or the decompressed size has been reached. (This will be obtained elsewhere in the graphics archive even though it is also part of the graphics chunk.)&lt;br /&gt;
&lt;br /&gt;
It should be noted that the repeat length words are big-endian, unlike all others in the game.&lt;br /&gt;
&lt;br /&gt;
As a result of this inefficient scheme it is possible to &#039;compress&#039; data in this format by simply replacing and 0x1B bytes with the sequence 1B 00 01 1B.&lt;br /&gt;
&lt;br /&gt;
An illustration:&lt;br /&gt;
&lt;br /&gt;
 12 34 1B 00 03 56 78 90&lt;br /&gt;
&lt;br /&gt;
This data is interpreted as follows:&lt;br /&gt;
&lt;br /&gt;
 12 34          # Copy 12 and 34 through unchanged&lt;br /&gt;
 1B 00 03 56    # Repeat 56 three times&lt;br /&gt;
 81 78 90       # Copy 78 and 90 through unchanged&lt;br /&gt;
&lt;br /&gt;
Or as pseudocode:&lt;br /&gt;
&lt;br /&gt;
* If [Decompressed data length] &amp;lt; [Final length] then:&lt;br /&gt;
*# Read a byte [Value]&lt;br /&gt;
*# If the byte value = 27, then:&lt;br /&gt;
*#* Move forward a byte&lt;br /&gt;
*#* Read the next two bytes&lt;br /&gt;
*#* Store this big-endian value as [length]&lt;br /&gt;
*#* Move forward two bytes&lt;br /&gt;
*#* Read the next byte&lt;br /&gt;
*#* Repeat the byte [length] thimes&lt;br /&gt;
*#* Move forward a byte and return to step 1.&lt;br /&gt;
*# Else:&lt;br /&gt;
*#* Read the next byte and output it unchanged&lt;br /&gt;
*#* Move forward a byte and return to step 1.&lt;br /&gt;
&lt;br /&gt;
It can be seen that this system is very far from optimal since two, three and even four repeating bytes must be treated as non-repeating.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_Go_To_Heaven&amp;diff=9084</id>
		<title>All Dogs Go To Heaven</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_Go_To_Heaven&amp;diff=9084"/>
		<updated>2020-06-12T12:54:57Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Change format link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Title = All_Dogs_Title.png&lt;br /&gt;
 | Levels = None&lt;br /&gt;
 | Tiles = None&lt;br /&gt;
 | Sprites = Not editable&lt;br /&gt;
 | Fullscreen = Not editable&lt;br /&gt;
 | Sound = None&lt;br /&gt;
 | Music = Not editable&lt;br /&gt;
 | Text = Not editable&lt;br /&gt;
 | Story = Not editable&lt;br /&gt;
 | Interface = Not editable&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;All Dogs Go To Heaven&#039;&#039;&#039; is a 1989 video game for DOS and Amiga. It is based on the 1989 film of the same name and features ten minigames loosely tied together to form a story mode. The MS-DOS version is known for having surprisingly loud &#039;music&#039; that plays at unexpected time.&lt;br /&gt;
&lt;br /&gt;
The MS-DOS version also contains three executables and two sets of graphics files, for CGA, EGA,and TGA display respectively, with the TGA graphics being sourced from the EGA files.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = MRH_DOGC.DB?&lt;br /&gt;
 | Format = [[All Dogs Archive format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = CGA graphics files&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = MRH_DOGC.DB?&lt;br /&gt;
 | Format = [[All Dogs Archive format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = EGA\TGA graphics files&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.MUS&lt;br /&gt;
 | Format = [[LPCM format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Low quality audio clips used for short bits of music and sound&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = ?&lt;br /&gt;
 | Format = [[All Dogs RLE compression]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = This is a modified form of RLE used to compress some graphics data in the game archives&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
* Some game text is contained in the executable, the executable is uncompressed. But some text is also stored, uncompressed, in the graphics archives.&lt;br /&gt;
&lt;br /&gt;
[[Category:Polarware]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_RLE_Compression&amp;diff=9083</id>
		<title>All Dogs RLE Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_RLE_Compression&amp;diff=9083"/>
		<updated>2020-06-12T12:49:51Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Create page for the format, it was surprisingly annoying to figure out&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-bit&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{All Dogs Go To Heaven}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[All Dogs Go To Heaven]] uses [[RLE Compression]] to compress graphics chunks in its [[All Dogs Archive format|graphics archives.]] This is one of many possible ways to create a functional RLE system.&lt;br /&gt;
&lt;br /&gt;
The compressed file consists of an UINT32LE giving the number of bytes (not pixels) in each row of the graphics chunk, an UINT32LE giving the number of rows in the graphic, and the compressed data. The first UINT32LE of the compressed data, which is almost always uncompressed, gives the size of the uncompressed data. As a check the decompressed size value should be equal to the width and height values multiplied.&lt;br /&gt;
&lt;br /&gt;
The data can be either [[Raw CGA Data|CGA]] or [[Raw EGA data|EGA]] data which are four or two pixels of data per byte respectively.&lt;br /&gt;
&lt;br /&gt;
The compressed data is processed in a loop. After each byte is read, its value is used to select an action. If the byte has a value of 27 (val &amp;amp; 0x1B) then the next word gives the number of identical bytes to output and the byte after that is the byte to repeat. All other bytes are passed through unchanged. The next byte is then read and the same procedure followed until there is no more data or the decompressed size has been reached. (This will be obtained elsewhere in the graphics archive even though it is also part of the graphics chunk.)&lt;br /&gt;
&lt;br /&gt;
It should be noted that the repeat length words are big-endian, unlike all others in the game.&lt;br /&gt;
&lt;br /&gt;
As a result of this inefficient scheme it is possible to &#039;compress&#039; data in this format by simply replacing and 0x1B bytes with the sequence 1B 00 01 1B.&lt;br /&gt;
&lt;br /&gt;
An illustration:&lt;br /&gt;
&lt;br /&gt;
 12 34 1B 00 03 56 78 90&lt;br /&gt;
&lt;br /&gt;
This data is interpreted as follows:&lt;br /&gt;
&lt;br /&gt;
 12 34          # Copy 12 and 34 through unchanged&lt;br /&gt;
 1B 00 03 56    # Repeat 56 three times&lt;br /&gt;
 81 78 90       # Copy 78 and 90 through unchanged&lt;br /&gt;
&lt;br /&gt;
Or as pseudocode:&lt;br /&gt;
&lt;br /&gt;
* If [Decompressed data length] &amp;lt; [Final length] then:&lt;br /&gt;
*# Read a byte [Value]&lt;br /&gt;
*# If the byte value = 27, then:&lt;br /&gt;
*#* Move forward a byte&lt;br /&gt;
*#* Read the next two bytes&lt;br /&gt;
*#* Store this big-endian value as [length]&lt;br /&gt;
*#* Move forward two bytes&lt;br /&gt;
*#* Read the next byte&lt;br /&gt;
*#* Repeat the byte [length] thimes&lt;br /&gt;
*#* Move forward a byte and return to step 1.&lt;br /&gt;
*# Else:&lt;br /&gt;
*#* Read the next byte and output it unchanged&lt;br /&gt;
*#* Move forward a byte and return to step 1.&lt;br /&gt;
&lt;br /&gt;
It can be seen that this system is very far from optimal since two, three and even four repeating bytes must be treated as non-repeating.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=File:All_Dogs_Title.png&amp;diff=9082</id>
		<title>File:All Dogs Title.png</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=File:All_Dogs_Title.png&amp;diff=9082"/>
		<updated>2020-06-12T12:25:03Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Titlescreen for All Dogs Go To Heaven.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Titlescreen for [[All Dogs Go To Heaven]].&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_Go_To_Heaven&amp;diff=9081</id>
		<title>All Dogs Go To Heaven</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=All_Dogs_Go_To_Heaven&amp;diff=9081"/>
		<updated>2020-06-12T12:23:00Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Create page. Not much to say here.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
{{Game Infobox&lt;br /&gt;
 | Title = All_Dogs_Title.png&lt;br /&gt;
 | Levels = None&lt;br /&gt;
 | Tiles = None&lt;br /&gt;
 | Sprites = Not editable&lt;br /&gt;
 | Fullscreen = Not editable&lt;br /&gt;
 | Sound = None&lt;br /&gt;
 | Music = Not editable&lt;br /&gt;
 | Text = Not editable&lt;br /&gt;
 | Story = Not editable&lt;br /&gt;
 | Interface = Not editable&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;All Dogs Go To Heaven&#039;&#039;&#039; is a 1989 video game for DOS and Amiga. It is based on the 1989 film of the same name and features ten minigames loosely tied together to form a story mode. The MS-DOS version is known for having surprisingly loud &#039;music&#039; that plays at unexpected time.&lt;br /&gt;
&lt;br /&gt;
The MS-DOS version also contains three executables and two sets of graphics files, for CGA, EGA,and TGA display respectively, with the TGA graphics being sourced from the EGA files.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = MRH_DOGC.DB?&lt;br /&gt;
 | Format = [[All Dogs Archive format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = CGA graphics files&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = MRH_DOGC.DB?&lt;br /&gt;
 | Format = [[All Dogs Archive format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = EGA\TGA graphics files&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.MUS&lt;br /&gt;
 | Format = [[Wave file format|LPCM format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Low quality audio clips used for short bits of music and sound&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = ?&lt;br /&gt;
 | Format = [[All Dogs RLE compression]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = This is a modified form of RLE used to compress some graphics data in the game archives&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
* Some game text is contained in the executable, the executable is uncompressed. But some text is also stored, uncompressed, in the graphics archives.&lt;br /&gt;
&lt;br /&gt;
[[Category:Polarware]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Talk:Jill_of_the_Jungle&amp;diff=8805</id>
		<title>Talk:Jill of the Jungle</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Talk:Jill_of_the_Jungle&amp;diff=8805"/>
		<updated>2019-08-20T04:25:06Z</updated>

		<summary type="html">&lt;p&gt;Levellass: JMod reply&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In my version of Jill of the Jungle, the palettes were found at these locations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Jill:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
VGA to EGA conversion table @ 0x24964.&lt;br /&gt;
&lt;br /&gt;
VGA palette @ 0x24A64.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Jill2:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
VGA to EGA conversion table @ 0x1F5B4.&lt;br /&gt;
&lt;br /&gt;
VGA palette @ 0x1F6B4.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Jill3:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
VGA to EGA conversion table @ 0x1F704.&lt;br /&gt;
&lt;br /&gt;
VGA palette @ 0x1F804.&lt;br /&gt;
&lt;br /&gt;
Some of them differ from the posted. Does anyone else have a different version? --[[User:SaxxonPike|SaxxonPike]] 16:10, 12 July 2010 (GMT)&lt;br /&gt;
:Not sure - is there an easy way to tell which version a given .exe is?  If so we should add a column to the table for the version number, so we can list the offsets for all known versions.  Maybe also a signature code so it&#039;s easy for a program to identify which version a given file is. -- [[User:Malvineous|Malvineous]] 22:49, 12 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
::I&#039;ve seen different versions of a couple of Epic games, like Jill of the Jungle, Jazz Jackrabbit, Epic Pinball, Silverball and Extreme Pinball, and I couldn&#039;t find a version number inside the .exe files or see a version number when running the game. The only way to see which version number a game has, is to read what the included Helpme.doc file says. And even that is not foolproof as I&#039;ve seen different .exe files with the same Helpme.doc file. Apogee surely did the version numbering a lot better than Epic :). [[User:Calvero|Calvero]] 11:17, 13 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
:::The HELPME.DOC files can be quite misleading, actually. I&#039;ve found a bunch of copies of the shareware episodes where the HELPME.DOC claims the game is version 2.0 when the game itself identifies itself by another version number (e.g. Solar Winds, version 2.0 in the .DOC and 1.1 in-game). Regarding Jill of the Jungle, there are &amp;quot;officially&amp;quot; (by officially I mean what they identify themselves as in the documents) only two recognized versions, 1.0 and 1.2. But there are also a number of revisions I&#039;ve found to version 1.2 which I personally call 1.2, 1.2a, 1.2b and 1.2c. I know for a fact all of these revisions except 1.2c also have matching registered versions (I&#039;m not too convinced that 1.2c actually had anything else than a shareware release). I have made a document some time ago to make it easier to identify these versions and it can be found from [http://aoebeta.110mb.com/Private/jill_versions.txt here] (the data is that of the main game EXE). --[[User:Litude|Litude]] 11:24, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
::::Wow, would you mind including that info on the main Jill page?  I&#039;m happy to do it but might be better if you do the first edit so it goes against your name in the edit history.  Add an extra column for those palette offsets so we can add them in when we find them out for a particular version.  My Jill versions match up well with your list, except my Jill 1 v1.0 (216804) is dated 1992-06-01, one day earlier than in your list.  Also not sure if you&#039;re recording dates/versions of jjfile0.exe (the episode loader) because I&#039;m not sure where that came from as I didn&#039;t find it until relatively recently. -- [[User:Malvineous|Malvineous]] 11:38, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
:::::Alright, I&#039;ll try adding the info though I don&#039;t really mind having someone else adding them (I don&#039;t really care that much about getting credited for stuff). Regarding the modify date of version 1.0, you&#039;re absolutely right. It seems my finger slipped when putting together that document. JJFILE0.EXE first appeared in version 1.2a and was also present in version 1.2b, but it was removed in 1.2c (which is why I think its shareware only, can&#039;t see any other reason for its removal). I don&#039;t record the dates of that file as as far as I know there are only two versions of the file, one of which is present in version 1.2a and the other one which is present in 1.2b.--[[User:Litude|Litude]] 12:43, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
::::::The version that is called version 1.1 of Jill 1 on [http://www.classicdosgames.com/game/Jill_of_the_Jungle.html RGB Classic Games] is called version 1.2a here, but when you run the game it says it&#039;s the United kingdom version. It gets this version information from the file INTRO.JN1. So at least one version of the game has in-game version information :).&amp;lt;br&amp;gt;Through my own research I found out that only version 1.0 has the references to Commander Keen, Mario, Duke Nukem and Pac-Man in the map level. Can someone confirm this? It&#039;s possible to copy MAP.JN1 of version 1.0 to later versions to restore these references. [[User:Calvero|Calvero]] 15:42, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
:::::::That installer is mislabeled, check the documents and it&#039;s listed as being version 1.2 (there was no version 1.1 of the game as far as I know). I did check that version but didn&#039;t look through it thoroughly enough to notice that it has a modified INTRO.JN1, just concluded it was 1.2a. But that doesn&#039;t mean 1.2a was exclusively made for the United Kingdom, as you can find version 1.2a without this United Kingdom mention from [http://cd.textfiles.com/swheaven1/GAMES/JILL.ZIP here]. Regarding actual changes between the versions, I haven&#039;t really been looking into this but seeing as MAP.JN1 is identical in 1.2, 1.2a, 1.2b and 1.2c it seems likely. --[[User:Litude|Litude]] 16:01, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
:::::::While I can&#039;t confirm it, it has been discussed on the PCKF that the Commander Keen reference only appeared in early versions of Jill and for some reason it was later removed.  Which, being a Commander Keen forum, was then immediately followed by many &amp;quot;where I can get the original version&amp;quot; requests. -- [[User:Malvineous|Malvineous]] 14:07, 16 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
== Ordering Info same format as ZZT graphics? ==&lt;br /&gt;
&lt;br /&gt;
It looks like the Ordering Info format described under the Episode Selection Screen might match the graphics format used for Super ZZT:&lt;br /&gt;
&lt;br /&gt;
[[Super_ZZT_Graphics_Format]]&lt;br /&gt;
&lt;br /&gt;
Thoughts?&lt;br /&gt;
--[[User:SaxxonPike|SaxxonPike]] ([[User talk:SaxxonPike|talk]]) 05:10, 5 March 2019 (UTC)&lt;br /&gt;
:Yes, that&#039;s exactly the format it uses, I was actually in the middle of trying to pick this apart.Maybe I should resurrect that half-done graphics editor. -[[User:Levellass|Endian? What are you on about?]] ([[User talk:Levellass|talk]]) 13:02, 10 March 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
== New Level Editor ==&lt;br /&gt;
&lt;br /&gt;
A new level editor, jMod, has recently been released for this game (http://k1n9duk3.shikadi.net/jmod.html), should it be added to this page?&lt;br /&gt;
&lt;br /&gt;
::I&#039;d vote yes, as a section or link. This is the MODDING wiki after all and should include all the tools that can be used in some form or other.-[[User:Levellass|Endian? What are you on about?]] ([[User talk:Levellass|talk]]) 04:25, 20 August 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Talk:Jill_of_the_Jungle&amp;diff=8407</id>
		<title>Talk:Jill of the Jungle</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Talk:Jill_of_the_Jungle&amp;diff=8407"/>
		<updated>2019-03-10T13:02:55Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Confirm Super ZZT format for order info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In my version of Jill of the Jungle, the palettes were found at these locations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Jill:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
VGA to EGA conversion table @ 0x24964.&lt;br /&gt;
&lt;br /&gt;
VGA palette @ 0x24A64.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Jill2:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
VGA to EGA conversion table @ 0x1F5B4.&lt;br /&gt;
&lt;br /&gt;
VGA palette @ 0x1F6B4.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Jill3:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
VGA to EGA conversion table @ 0x1F704.&lt;br /&gt;
&lt;br /&gt;
VGA palette @ 0x1F804.&lt;br /&gt;
&lt;br /&gt;
Some of them differ from the posted. Does anyone else have a different version? --[[User:SaxxonPike|SaxxonPike]] 16:10, 12 July 2010 (GMT)&lt;br /&gt;
:Not sure - is there an easy way to tell which version a given .exe is?  If so we should add a column to the table for the version number, so we can list the offsets for all known versions.  Maybe also a signature code so it&#039;s easy for a program to identify which version a given file is. -- [[User:Malvineous|Malvineous]] 22:49, 12 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
::I&#039;ve seen different versions of a couple of Epic games, like Jill of the Jungle, Jazz Jackrabbit, Epic Pinball, Silverball and Extreme Pinball, and I couldn&#039;t find a version number inside the .exe files or see a version number when running the game. The only way to see which version number a game has, is to read what the included Helpme.doc file says. And even that is not foolproof as I&#039;ve seen different .exe files with the same Helpme.doc file. Apogee surely did the version numbering a lot better than Epic :). [[User:Calvero|Calvero]] 11:17, 13 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
:::The HELPME.DOC files can be quite misleading, actually. I&#039;ve found a bunch of copies of the shareware episodes where the HELPME.DOC claims the game is version 2.0 when the game itself identifies itself by another version number (e.g. Solar Winds, version 2.0 in the .DOC and 1.1 in-game). Regarding Jill of the Jungle, there are &amp;quot;officially&amp;quot; (by officially I mean what they identify themselves as in the documents) only two recognized versions, 1.0 and 1.2. But there are also a number of revisions I&#039;ve found to version 1.2 which I personally call 1.2, 1.2a, 1.2b and 1.2c. I know for a fact all of these revisions except 1.2c also have matching registered versions (I&#039;m not too convinced that 1.2c actually had anything else than a shareware release). I have made a document some time ago to make it easier to identify these versions and it can be found from [http://aoebeta.110mb.com/Private/jill_versions.txt here] (the data is that of the main game EXE). --[[User:Litude|Litude]] 11:24, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
::::Wow, would you mind including that info on the main Jill page?  I&#039;m happy to do it but might be better if you do the first edit so it goes against your name in the edit history.  Add an extra column for those palette offsets so we can add them in when we find them out for a particular version.  My Jill versions match up well with your list, except my Jill 1 v1.0 (216804) is dated 1992-06-01, one day earlier than in your list.  Also not sure if you&#039;re recording dates/versions of jjfile0.exe (the episode loader) because I&#039;m not sure where that came from as I didn&#039;t find it until relatively recently. -- [[User:Malvineous|Malvineous]] 11:38, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
:::::Alright, I&#039;ll try adding the info though I don&#039;t really mind having someone else adding them (I don&#039;t really care that much about getting credited for stuff). Regarding the modify date of version 1.0, you&#039;re absolutely right. It seems my finger slipped when putting together that document. JJFILE0.EXE first appeared in version 1.2a and was also present in version 1.2b, but it was removed in 1.2c (which is why I think its shareware only, can&#039;t see any other reason for its removal). I don&#039;t record the dates of that file as as far as I know there are only two versions of the file, one of which is present in version 1.2a and the other one which is present in 1.2b.--[[User:Litude|Litude]] 12:43, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
::::::The version that is called version 1.1 of Jill 1 on [http://www.classicdosgames.com/game/Jill_of_the_Jungle.html RGB Classic Games] is called version 1.2a here, but when you run the game it says it&#039;s the United kingdom version. It gets this version information from the file INTRO.JN1. So at least one version of the game has in-game version information :).&amp;lt;br&amp;gt;Through my own research I found out that only version 1.0 has the references to Commander Keen, Mario, Duke Nukem and Pac-Man in the map level. Can someone confirm this? It&#039;s possible to copy MAP.JN1 of version 1.0 to later versions to restore these references. [[User:Calvero|Calvero]] 15:42, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
:::::::That installer is mislabeled, check the documents and it&#039;s listed as being version 1.2 (there was no version 1.1 of the game as far as I know). I did check that version but didn&#039;t look through it thoroughly enough to notice that it has a modified INTRO.JN1, just concluded it was 1.2a. But that doesn&#039;t mean 1.2a was exclusively made for the United Kingdom, as you can find version 1.2a without this United Kingdom mention from [http://cd.textfiles.com/swheaven1/GAMES/JILL.ZIP here]. Regarding actual changes between the versions, I haven&#039;t really been looking into this but seeing as MAP.JN1 is identical in 1.2, 1.2a, 1.2b and 1.2c it seems likely. --[[User:Litude|Litude]] 16:01, 15 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
:::::::While I can&#039;t confirm it, it has been discussed on the PCKF that the Commander Keen reference only appeared in early versions of Jill and for some reason it was later removed.  Which, being a Commander Keen forum, was then immediately followed by many &amp;quot;where I can get the original version&amp;quot; requests. -- [[User:Malvineous|Malvineous]] 14:07, 16 July 2010 (GMT)&lt;br /&gt;
&lt;br /&gt;
== Ordering Info same format as ZZT graphics? ==&lt;br /&gt;
&lt;br /&gt;
It looks like the Ordering Info format described under the Episode Selection Screen might match the graphics format used for Super ZZT:&lt;br /&gt;
&lt;br /&gt;
[[Super_ZZT_Graphics_Format]]&lt;br /&gt;
&lt;br /&gt;
Thoughts?&lt;br /&gt;
--[[User:SaxxonPike|SaxxonPike]] ([[User talk:SaxxonPike|talk]]) 05:10, 5 March 2019 (UTC)&lt;br /&gt;
:Yes, that&#039;s exactly the format it uses, I was actually in the middle of trying to pick this apart.Maybe I should resurrect that half-done graphics editor. -[[User:Levellass|Endian? What are you on about?]] ([[User talk:Levellass|talk]]) 13:02, 10 March 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Softdisk_Library_Format&amp;diff=8238</id>
		<title>Softdisk Library Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Softdisk_Library_Format&amp;diff=8238"/>
		<updated>2018-11-02T23:31:55Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Reword and fix problems&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = 65,535&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = Yes, 8.3&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = Y&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = Y&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Commander Keen Dreams}}&lt;br /&gt;
   {{Game|Dangerous Dave 3}}&lt;br /&gt;
   {{Game|Dangerous Dave 4}}&lt;br /&gt;
}}&lt;br /&gt;
SLIB, or Softdisk LIBrary, compression is a container file format used by [[Softdisk]] software to compress various files used by their games, most notably the Commander Keen Dreams series of games, (Including Dangerous Dave 3 and Dangerous Dave 4)to store title images used at the beginning of each game. It was created in 1992 by Jim Row.&lt;br /&gt;
&lt;br /&gt;
The data held in the file can be compressed in any one of three ways, uncompressed, LZW and LZH. The compression used is primitive and rather different from later or traditional versions of LZW\LZH. SLIB files were created by the program &amp;lt;tt&amp;gt;SOFTLIB.EXE&amp;lt;/tt&amp;gt; and as such any game that uses this format contains various segments of code in common with &amp;lt;tt&amp;gt;SOFTLIB&amp;lt;/tt&amp;gt; for the decompression of data.&lt;br /&gt;
&lt;br /&gt;
There is a closely related format, the SHL or Softdisk Help Library format. SHL files contain only a single file. Their header is slightly different, it&#039;s file signature is &#039;CMP1&#039; (CoMPression of 1 file) while that of SLIB files is SLIB. The veracity of both files can be confirmed by checking for a word of value 2 at offset 4 in the file. The actual files have been given a number of extensions; &amp;lt;tt&amp;gt;.CMP&amp;lt;/tt&amp;gt; (CoMPressed), &amp;lt;tt&amp;gt;.SHL&amp;lt;/tt&amp;gt; (Softdisk Help Library) or the game extension.&lt;br /&gt;
&lt;br /&gt;
The SLIB file can roughly be broken into a number of parts; the header, which contains data about the various data chunks, and the data chunks themselves, each containing a single file. Each chunk also has a short header.&lt;br /&gt;
&lt;br /&gt;
== Header ==&lt;br /&gt;
&lt;br /&gt;
The file header is found only in SLIB files and is absent in SHL files, which are loaded into memory in their enitrety. The SLIB header allows individual data chunks to be loaded inhto memory seperately.&lt;br /&gt;
&lt;br /&gt;
The SLIB header is a variable length header that contains information about how many chunks there are in a file as well as their location in the file and size. It is used by the game to load chunks into memory and by &amp;lt;tt&amp;gt;SOFLIB&amp;lt;/tt&amp;gt; to extract compressed files.&lt;br /&gt;
&lt;br /&gt;
The first part of the header is a fixed length of 8 bytes and allows the game to identify the file as SLIB and also the total length of the header (Which will be 30 * the value at offset 6 plus 8.) The second part is a series of chunk headers that hold information about what file is held in each chunk. (The last six bytes are repeated at the start of the data chunk.)&lt;br /&gt;
&lt;br /&gt;
 FILE HEADER:&lt;br /&gt;
 0 CHAR[4]	fID		Signature, &#039;SLIB&#039; (Softdisk LIBrary)&lt;br /&gt;
 4 UINT16LE	Version		Version number, always $0002&lt;br /&gt;
 6 UINT16LE	Chunks		Number of data chunks in file&lt;br /&gt;
 8 CHAR[30x]	Chunk headers	Chunk headers&lt;br /&gt;
&lt;br /&gt;
 IMAGE HEADERS:&lt;br /&gt;
 ?   CHAR[16]	Name         Name of compressed image (Max len 12 chars) padded with nuls&lt;br /&gt;
 +16 UINT32LE	Dat st       Start of image data in file (From start of first image chunk)&lt;br /&gt;
 +20 UINT32LE	Dat end      End of image data in file (From start of first image chunk)&lt;br /&gt;
 +24 UINT32LE	iOriginalSize	Decompressed data size&lt;br /&gt;
 +28 UINT16LE	iCompression	Compression used, 0 = none, 1 = LZW, 2 = LZH&lt;br /&gt;
&lt;br /&gt;
== Data Chunks ==&lt;br /&gt;
&lt;br /&gt;
The data chunk has a short header followed by the actual data itself. The format differs slightly between SLIB chunkks and SHL files. Both format must identify themselves to the game, and they do so in different ways.&lt;br /&gt;
&lt;br /&gt;
Notice that in the case of SLIB chunks bytes 4-10 are identical to bytes 24-30 of that chunk&#039;s header.&lt;br /&gt;
&lt;br /&gt;
 SLIB CHUNK FORMAT&lt;br /&gt;
 ?   CHAR[4]	cID		Signature&#039;CUNK&#039; (Chunk UNKompressed size)&lt;br /&gt;
 +4  UINT32LE	iOriginalSize	Decompressed data size&lt;br /&gt;
 +8  UINT16LE	iCompression	Compression method&lt;br /&gt;
 +10 CHAR[?]	Data		Image data&lt;br /&gt;
&lt;br /&gt;
SHL files are slightly more tricky; an uncompressed SHL file is simply raw data, compressed data must identify itself as such and so the header is slightly longer. It can be considered a combination of the chunk header and the SLIB header in the section above.&lt;br /&gt;
&lt;br /&gt;
 SHL FILE FORMAT&lt;br /&gt;
 0  CHAR[4]	cID		Signature&#039;CMP1&#039; (CoMPressed s1ingle file)&lt;br /&gt;
 4  UINT16LE	iCompression	Compression method (as above)&lt;br /&gt;
 6  UINT32LE	iOriginalSize	Decompressed data size&lt;br /&gt;
 10 UINT32LE	iCompressedSize	Compressed data size&lt;br /&gt;
 14 CHAR[?]	Data		Image data&lt;br /&gt;
&lt;br /&gt;
== Compression ==&lt;br /&gt;
&lt;br /&gt;
As noted above there are three forms of compression. The first is simple enough, no compression at all, the data is simply stored in the file. (Actually increasing the size!) The other two are called &#039;LZW&#039; and &#039;LZH&#039; by the programmers but both differ from what are now standard implmentations of those formats.&lt;br /&gt;
&lt;br /&gt;
=== LZW ===&lt;br /&gt;
&lt;br /&gt;
A compression value of 1 means the chunk is [[LZW compression|LZW compressed]]. The format of the compression used is different from the more &#039;usual&#039; implementation of LZW. Most LZW works by building a &#039;dictionary&#039;, but LZW is in essence just referring back to data that has already been read.&lt;br /&gt;
&lt;br /&gt;
The core of the implementation is that if a sequence is encountered that has already been read then it is replaced with a pointer to it. There are three types of data, flag bytes, pointers and literals.&lt;br /&gt;
&lt;br /&gt;
Flag bytes divide the datastream into segments of eight &#039;values&#039; which can be either literals or pointers. Pointers are 2 bytes long, literals 1 byte. (Therefore there will be a flag byte every 8 to 16 bytes of data.) The value of each bit (In little endian) indicates whether a value will be a literal (1) or codeword (0) Thus a value of 199 (11000111 in binary) indicates three pointers, three literals and two pointers in that order. (Total of 13 bytes.)&lt;br /&gt;
&lt;br /&gt;
Literals are sequences that have never been seen in the datastream before, they cannot be compressed and are thus the same in the compressed and decompressed datastreams. (If the data is text they become quite obvious.) Any string less than 3 bytes long that has not been read before or cannot be pointed to (See below) will be stored as literals.&lt;br /&gt;
&lt;br /&gt;
Pointers are reference to data that has already been read. They are two bytes long, with the first 12 bits giving the location to read data from and the last 4 bits giving the length of data to read.&lt;br /&gt;
&lt;br /&gt;
The lower nybble (4 bits) of the second pointer byte holds the length of repeat data to read minus three. (This makes sense, the shortest sequence it makes sense to code is three bytes which can be given the value 0.) It will be immediately apparent that the maximum length of repeated data that can be stored as a pointer is 18 bytes.&lt;br /&gt;
&lt;br /&gt;
The high nybble of the second byte is multiplied by 256 then added to the first byte to give the location of the data to read in the &#039;sliding window&#039; minus 18. In hexadecimal this is as simple as appending the nybble to the first byte. For example flag bytes of &amp;lt;tt&amp;gt;$EA $F6&amp;lt;/tt&amp;gt; point to location &amp;lt;tt&amp;gt;$FEA&amp;lt;/tt&amp;gt; with &#039;6&#039; relating to the data length to read.&lt;br /&gt;
&lt;br /&gt;
The &#039;sliding window&#039; in this case is the region of decompressed data that the compressed data can point to. It will be immediately obvious that the pointers can encode values between +-2048, or about 2KB. If the decompressed data is less than 2KB in size then zero is the start of the data, if it is larger than it is 2048 bytes from the end of the data. (This is the origin of the term &#039;sliding window&#039;; it is a window of data that can be slid along the datastream as it gets bigger.)&lt;br /&gt;
&lt;br /&gt;
It will be noted that it is probable that the compressed datastream will not be perfectly divisible by flag bytes. In this case the unused bits are set to 0. The decompressor stops when the decompressed data size is equal to the value given in the chunk header.&lt;br /&gt;
&lt;br /&gt;
The last thing to keep in mind is that the flagged location obtained requires 18 to be added to it. This is due to how the decompressor is set up in memory; it needs a buffer of 18 bytes (the maximum length of compressed data that can be decompressed) between where it is working and the start of the datastream proper. These bytes are initially filled with blank spaces (&amp;lt;tt&amp;gt;$20&amp;lt;/tt&amp;gt; not &amp;lt;tt&amp;gt;$00&amp;lt;/tt&amp;gt;.) and considered part of the datastream but not part that is output to the final file. (Their locations are negative.)&lt;br /&gt;
&lt;br /&gt;
This has an odd result; it&#039;s entirely possible for a flag byte to point to a negative value and output one or more characters that were never part of the uncompressed data. To illustrate this we will look at the text string &#039;I am Sam. Sam I am!&#039; as compressed by &amp;lt;tt&amp;gt;softlib.exe&amp;lt;/tt&amp;gt;. Note that on line 6 it requests 5 bytes from address -1. This is the string &#039; I am&#039;. The last four bytes are from the start of the sentence but the first, a blank space, comes from the buffer.&lt;br /&gt;
&lt;br /&gt;
 FF				Flag byte, 8 literals follow&lt;br /&gt;
 49 20 61 6D 20 53 61 6D		&#039;I am Sam&#039; as literals&lt;br /&gt;
 09				Flag byte, 1L, 2P, 1L,4Blanks ($09 = 00001001)&lt;br /&gt;
 2E				&#039;.&#039; as literal&lt;br /&gt;
 F2 F1				Pointer, read 1 + 3 = 4 bytes from $FF2, or -14 + 18 = 4 in the data. This is &#039; Sam&#039;&lt;br /&gt;
 ED F2				Pointer, read 2 + 3 = 5 bytes from $FED or -19 + 18 = -1 in the data. This is &#039; I am&#039;&lt;br /&gt;
 21				&#039;!&#039; as literal&lt;br /&gt;
&lt;br /&gt;
=== LZH ===&lt;br /&gt;
&lt;br /&gt;
LZH is a combination of LZW and [[Huffman Compression]]. In its simplest implementation it is two levels of compression, first the data is LZW compressed, then it is Huffman compressed. This is used for example in &amp;lt;tt&amp;gt;GAMEMAPS&amp;lt;/tt&amp;gt; However, the compression used in this case seems to be similar to that used in Keen 1, pure LZW using a dictionary.&lt;br /&gt;
&lt;br /&gt;
The format is far from elucidated, but a table in the executables involved can be used to convert data into the 8 and 9 bit codes used for perfectly incompressible data. (Once compression starts being used this changes, indicative that this table is used to build the initial LZW dictionary.)&lt;br /&gt;
&lt;br /&gt;
It is also notable that it seems to use both 8 and 9 bit codes, which is very difficult to do without some table to indicate the length of the codes. This varaible codeword length may be why the compression is said to be &#039;huffman&#039;&lt;br /&gt;
&lt;br /&gt;
The [http://www.apogeesoftware.com/uncategorized/apogee-releases-blake-stone-source-code Planet Strike source code release] contains C code that handles LZH compression and decompression in &amp;lt;tt&amp;gt;JM_LZH.C&amp;lt;/tt&amp;gt;. The code was written by Jim T. Row, who apparently also wrote the Softlib utility, so chances are it is the same implementation of LZH.&lt;br /&gt;
&lt;br /&gt;
== Softlib ==&lt;br /&gt;
&lt;br /&gt;
Soflib (Softdisk Library Creator) is a DOS program that  can be used to create or extract files from SLIB files. It can work with both forms of compression used in SLIB files. It is notable that for some reason files shorter than 24 bytes often fail to be compressed correctly. (Soflib outputs a library with an empty chunk in it.) Soflib can be downloaded from the tools section of this page.&lt;br /&gt;
&lt;br /&gt;
== Data contained in libraries ==&lt;br /&gt;
&lt;br /&gt;
Keen Dreams uses SLIB to compress its title screen and also comes with a number of LZH compressed .SHL files containing text. The title screen is in [[LBM Format]] It is notable that the game does not read most of the LBM chunks, focusing instead on the FORM, BMHD and BODY chunks. This is because while the compressed files were designed to be viewed and edited in a standalone program, the game did not need things such as the LBM palette.&lt;br /&gt;
&lt;br /&gt;
Dangerous Dave 3 and 4 use an additional SLIB file to store their digital sound effects, which are seperate from their [[AudioT Format|PC\adlib sounds]]&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.shikadi.net/files/games/softdisk/softlib.exe SOFTLIB.EXE] - original DOS program that can create and modify Softdisk Libraries&lt;br /&gt;
* [http://dl.dropbox.com/u/3940020/Titlebuild.zip TITLEBUILD] - Windows program to turn a 320x200 bitmap into &amp;lt;tt&amp;gt;KDREAMS.CMP&amp;lt;/tt&amp;gt; for Keen Dreams&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
This format partially reverse engineered by [[User:Lemm]] and [[User:Levellass]].&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Duke_1_Level_Format&amp;diff=7881</id>
		<title>Duke 1 Level Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Duke_1_Level_Format&amp;diff=7881"/>
		<updated>2018-07-30T15:41:02Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Fix two errors in object table&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Map Infobox&lt;br /&gt;
 | Type = 2D tile-based&lt;br /&gt;
 | Layers = 1&lt;br /&gt;
 | Tile size = 16&amp;amp;times;16&lt;br /&gt;
 | Viewport = 208&amp;amp;times;160&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Duke Nukem}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The levels in [[Duke Nukem]] 1 are stored in the files &amp;lt;tt&amp;gt;WORLDALx.DNy&amp;lt;/tt&amp;gt;, where y is the episode number, and x is the level number, going from 1-9 then A-C. Oddly, level 2 is the intermediate level and level C is the demo level.&lt;br /&gt;
&lt;br /&gt;
Level structure is very simple, each level is 128x90 tiles in size and consists of 11520 UINT16LE words (23040 bytes) of data. Each word controls what appears on one tile in the level. (The level has only one plane, containing background, foreground and enemies. Thus each word is sometimes called a ShapeThing. Because of this limit, the game has some interesting shortcuts to allow things to appear more naturally, such as an enemy tile using the tile before it as its background.) The following values control what appears:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Range (hex) !! Class !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0000-05FF || Flashers || Animated backgrounds or stationary backdrops, Duke can pass through these.&lt;br /&gt;
|-&lt;br /&gt;
| 0600-17FF || Backgrounds || Static background objects that Duke can pass through.&lt;br /&gt;
|-&lt;br /&gt;
| 1800-2FFF || Solids || Static foreground objects that Duke cannot pass through.&lt;br /&gt;
|-&lt;br /&gt;
| 3000-3059 || Active || This is the fun stuff, all the things that move, such as techbots, bonuses, items, Duke&#039;s starting location, hazards (spikes, force fields), doors, keyholes/access slots, conveyor belts and some special effect items (such as mirror floor and transparent windows).&lt;br /&gt;
|-&lt;br /&gt;
| 306A-FFFF || (Hacks) || Static foreground objects that Duke cannot pass through. The first tiles use tile images from BORDER.DN? and most of the later tiles are displayed as random junk.  All of these tiles are clingable.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Tile mapping ==&lt;br /&gt;
&lt;br /&gt;
The Level&#039;s tiles use tile graphics from 8 files: &amp;lt;tt&amp;gt;BACK0.DN?&amp;lt;/tt&amp;gt; through &amp;lt;tt&amp;gt;BACK3.DN?&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SOLID0.DN?&amp;lt;/tt&amp;gt; through &amp;lt;tt&amp;gt;SOLID3.DN?&amp;lt;/tt&amp;gt;. Tiles from &amp;lt;tt&amp;gt;BORDER.DN?&amp;lt;/tt&amp;gt; can also be used, though they are not &amp;quot;officially&amp;quot; supported.&lt;br /&gt;
&lt;br /&gt;
Each file contains 48 tiles (at least the game loads 48 tiles from each file), so there are 384 &amp;quot;actual&amp;quot; tiles. Due to the way the tile graphics are stored in memory, you need to divide the tile value by 32 (EGA plane size of a 16x16 pixel tile) to get a tile index from the data stored in the level file.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Range (hex) !! File&lt;br /&gt;
|-&lt;br /&gt;
| 0000-05FF || BACK0.DN?&lt;br /&gt;
|-&lt;br /&gt;
| 0600-0BFF || BACK1.DN?&lt;br /&gt;
|-&lt;br /&gt;
| 0C00-11FF || BACK2.DN?&lt;br /&gt;
|-&lt;br /&gt;
| 1200-17FF || BACK3.DN?&lt;br /&gt;
|-&lt;br /&gt;
| 1800-1DFF || SOLID0.DN?&lt;br /&gt;
|-&lt;br /&gt;
| 1E00-23FF || SOLID1.DN?&lt;br /&gt;
|-&lt;br /&gt;
| 2400-29FF || SOLID2.DN?&lt;br /&gt;
|-&lt;br /&gt;
| 2A00-2FFF || SOLID3.DN?&lt;br /&gt;
|-&lt;br /&gt;
| 3000-367F || Varies, see below&lt;br /&gt;
|-&lt;br /&gt;
| 4000-? || current backdrop 1 (hack)&lt;br /&gt;
|-&lt;br /&gt;
| 8100-? || current backdrop 2 (hack)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Active ===&lt;br /&gt;
&lt;br /&gt;
The follow tiles appear to be manually mapped.  These tile codes from the map do not need to be divided by 32, unlike the other tilecodes.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Tile code (hex) !! File !! Tile index !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 3000 || OBJECT0.DN1 || 0     || Bonus       || Grey box, empty&lt;br /&gt;
|-&lt;br /&gt;
| 3001 || OBJECT0.DN1 || 5     || Interactive || Elevator&lt;br /&gt;
|-&lt;br /&gt;
| 3002 || {{TODO|?}}  || ?     || Interactive || Left-moving conveyor belt start, must be left of end tile&lt;br /&gt;
|-&lt;br /&gt;
| 3003 || {{TODO|?}}  || ?     || Interactive || Left-moving conveyor belt end, must be on right of start tile&lt;br /&gt;
|-&lt;br /&gt;
| 3004 || {{TODO|?}}  || ?     || Interactive || Right-moving conveyor belt start, must be left of end tile&lt;br /&gt;
|-&lt;br /&gt;
| 3005 || {{TODO|?}}  || ?     || Interactive || Right-moving conveyor belt end, must be on right of start tile&lt;br /&gt;
|-&lt;br /&gt;
| 3006 || OBJECT0.DN1 || 10    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains shoes&lt;br /&gt;
|-&lt;br /&gt;
| 3007 || OBJECT0.DN1 || 11-17 || Interactive || Rocket, tile below is replaced with default tile after rocket takeoff&lt;br /&gt;
|-&lt;br /&gt;
| 3008 || OBJECT0.DN1 || 24-28 || Hazard      || Flamethrower, firing to the right (three tiles wide including placement tile)&lt;br /&gt;
|-&lt;br /&gt;
| 3009 || OBJECT0.DN1 || 18    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains celing-clinger&lt;br /&gt;
|-&lt;br /&gt;
| 300A || OBJECT0.DN1 || 29-33 || Hazard      || Flamethrower, firing to the left (three tiles wide including placement tile)&lt;br /&gt;
|-&lt;br /&gt;
| 300B || ANIM0.DN1   || 0-5   || Enemy       || Floating 1x1 robot with purple antenna&lt;br /&gt;
|-&lt;br /&gt;
| 300C || ANIM0.DN1   || 10-33 || Enemy       || Jumping 2x2 robot&lt;br /&gt;
|-&lt;br /&gt;
| 300D || ANIM0.DN1   || 34-41 || Enemy       || Wheeled 2x1 robot with blue wheels&lt;br /&gt;
|-&lt;br /&gt;
| 300E || ANIM1.DN1   || 0-31  || Enemy       || 2x2 rotating wheel with flames&lt;br /&gt;
|-&lt;br /&gt;
| 300F || OBJECT0.DN1 || 43    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains raygun (ammo)&lt;br /&gt;
|-&lt;br /&gt;
| 3010 || ANIM1.DN1   || 32    || Enemy       || 1x1 robot&lt;br /&gt;
|-&lt;br /&gt;
| 3011 || -           || -     || -           || Exit door (only 1 instance allowed!)&lt;br /&gt;
|-&lt;br /&gt;
| 3012 || ANIM2.DN1   || 17    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains dynamite&lt;br /&gt;
|-&lt;br /&gt;
| 3013 || ANIM2.DN1   || 24-31 || Enemy       || Flying orb monster, each shot removes one orb&lt;br /&gt;
|-&lt;br /&gt;
| 3014 || -           || -     || Decorative  || Shimmering water effect, also affects tile below this one&lt;br /&gt;
|-&lt;br /&gt;
| 3015 || ANIM2.DN1   || 32-35 || Bonus       || Red box (1 @ OBJECT2.DN1), contains soda can&lt;br /&gt;
|-&lt;br /&gt;
| 3016 || ANIM2.DN1   || 40-43 || Enemy       || Green bitey creature walking up and down walls, facing right&lt;br /&gt;
|-&lt;br /&gt;
| 3017 || ANIM2.DN1   || 44-47 || Enemy       || Green bitey creature walking up and down walls, facing left&lt;br /&gt;
|-&lt;br /&gt;
| 3018 || OBJECT0.DN1 || 44    || Bonus       || Red box (1 @ OBJECT2.DN1), contains turkey drumstick&lt;br /&gt;
|-&lt;br /&gt;
| 3019 || ANIM3.DN1   || 0     || -           || Bridge that explodes when stepped on twice (only 1 instance allowed!)&lt;br /&gt;
|-&lt;br /&gt;
| 301A || OBJECT1.DN1 || 0-3   || Hazard      || Blue force field, horizontal&lt;br /&gt;
|-&lt;br /&gt;
| 301B || ANIM3.DN1   || 12-19 || Hazard      || Rotating fan blades, can&#039;t stand on when shot&lt;br /&gt;
|-&lt;br /&gt;
| 301C || ANIM3.DN1   || 12-19 || Hazard      || Rotating fan blades, can stand on when shot&lt;br /&gt;
|-&lt;br /&gt;
| 301D || OBJECT1.DN1 || 8     || Bonus       || Blue box (0 @ OBJECT2.DN1), contains football&lt;br /&gt;
|-&lt;br /&gt;
| 301E || OBJECT1.DN1 || 9     || Bonus       || Blue box (0 @ OBJECT2.DN1), contains joystick&lt;br /&gt;
|-&lt;br /&gt;
| 301F || OBJECT1.DN1 || 10    || Bonus       || Blue box (0 @ OBJECT2.DN1), contains &amp;quot;DN&amp;quot; floppy&lt;br /&gt;
|-&lt;br /&gt;
| 3020 || OBJECT1.DN1 || 13    || Bonus       || Grey box (0 @ OBJECT2.DN1), contains robohand&lt;br /&gt;
|-&lt;br /&gt;
| 3021 || OBJECT1.DN1 || 15-18 || Hazard      || White/blue force field, vertical&lt;br /&gt;
|-&lt;br /&gt;
| 3022 || ANIM3.DN1   || 20-47 || Enemy       || Helicopter&lt;br /&gt;
|-&lt;br /&gt;
| 3023 || OBJECT1.DN1 || 19-23 || Bonus       || Blue box (0 @ OBJECT2.DN1), contains balloon&lt;br /&gt;
|-&lt;br /&gt;
| 3024 || ANIM4.DN1   || 8-10  || Bonus       || Security camera&lt;br /&gt;
|-&lt;br /&gt;
| 3025 || ANIM4.DN1   || 11    || Decorative  || Brown spikes&lt;br /&gt;
|-&lt;br /&gt;
| 3026 || ANIM4.DN1   || 12    || Decorative  || Rock, left half&lt;br /&gt;
|-&lt;br /&gt;
| 3027 || ANIM4.DN1   || 13    || Decorative  || Rock, right half&lt;br /&gt;
|-&lt;br /&gt;
| 3028 || ANIM4.DN1   || 14    || Decorative  || Grey rounded window&lt;br /&gt;
|-&lt;br /&gt;
| 3029 || OBJECT1.DN1 || 24    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains nuclear molecule&lt;br /&gt;
|-&lt;br /&gt;
| 302A || OBJECT1.DN1 || 33    || Hazard      || Loose/falling ACME sign&lt;br /&gt;
|-&lt;br /&gt;
| 302B || OBJECT1.DN1 || 34    || Hazard      || Blue reactor&lt;br /&gt;
|-&lt;br /&gt;
| 302C || OBJECT1.DN1 || 45-46 || Hazard      || Spike, pokes up when walking over&lt;br /&gt;
|-&lt;br /&gt;
| 302D || OBJECT1.DN1 || 47-49 || Bonus       || Blue box (0 @ OBJECT2.DN1), contains magenta flag&lt;br /&gt;
|-&lt;br /&gt;
| 302E || OBJECT2.DN1 || 2-4   || Bonus       || Blue box (0 @ OBJECT2.DN1), contains radio&lt;br /&gt;
|-&lt;br /&gt;
| 302F || ANIM4.DN1   || 20-28 || Interactive || Teleporter, transports to tilecode 3030&lt;br /&gt;
|-&lt;br /&gt;
| 3030 || ANIM4.DN1   || 20-28 || Interactive || Teleporter, transports to tilecode 302F&lt;br /&gt;
|-&lt;br /&gt;
| 3031 || ANIM4.DN1   || 31    || Hazard      || Spiky round red bomb, bouncing&lt;br /&gt;
|-&lt;br /&gt;
| 3032 || -           || -     || Interactive || Player start point&lt;br /&gt;
|-&lt;br /&gt;
| 3033 || OBJECT1.DN1 || 14    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains access card&lt;br /&gt;
|-&lt;br /&gt;
| 3034 || OBJECT2.DN1 || 5-12  || Interactive || Access card activation point&lt;br /&gt;
|-&lt;br /&gt;
| 3035 || OBJECT2.DN1 || 14-15 || Interactive || Robohand activation point&lt;br /&gt;
|-&lt;br /&gt;
| 3036 || {{TODO|?}}  || ?     || ?           || Red girder, creates a bridge when Robohand activation point is used&lt;br /&gt;
|-&lt;br /&gt;
| 3037 || OBJECT2.DN1 || 21    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains &amp;quot;D&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 3038 || OBJECT2.DN1 || 21    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains &amp;quot;U&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 3039 || OBJECT2.DN1 || 21    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains &amp;quot;K&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 303A || OBJECT2.DN1 || 21    || Bonus       || Grey box (0 @ OBJECT0.DN1), contains &amp;quot;E&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 303B || ANIM2.DN1   || 18-23 || Bonus       || Purple rabbit thing, 5000 bonus points&lt;br /&gt;
|-&lt;br /&gt;
| 303C || ANIM5.DN1   || 1     || Enemy       || Fire monster&lt;br /&gt;
|-&lt;br /&gt;
| 303D || ANIM5.DN1   || 12    || Decorative  || Diamond-shaped wire mesh&lt;br /&gt;
|-&lt;br /&gt;
| 303E || ANIM5.DN1   || 13    || Decorative  || Window showing through to backdrop, left half&lt;br /&gt;
|-&lt;br /&gt;
| 303F || ANIM5.DN1   || 14    || Decorative  || Window showing through to backdrop, right half&lt;br /&gt;
|-&lt;br /&gt;
| 3040 || OBJECT2.DN1 || 23    || Interactive || Message, press up to read (blank message for most levels?)&lt;br /&gt;
|-&lt;br /&gt;
| 3041 || - || - || - || Screen display with Dr. Proton&lt;br /&gt;
|-&lt;br /&gt;
| 3042 || ANIM5.DN1   || 30-42 || Enemy       || Dr Proton, E3 boss, killable (&amp;quot;I won it all!&amp;quot;, game ends)&lt;br /&gt;
|-&lt;br /&gt;
| 3043 || ANIM5.DN1   || 30-42 || Enemy       || Dr Proton, E1 boss, not killable (escapes to moon, game ends)&lt;br /&gt;
|-&lt;br /&gt;
| 3044 || OBJECT2.DN1 || 24    || Interactive || Door key, red&lt;br /&gt;
|-&lt;br /&gt;
| 3045 || OBJECT2.DN1 || 25    || Interactive || Door key, green&lt;br /&gt;
|-&lt;br /&gt;
| 3046 || OBJECT2.DN1 || 26    || Interactive || Door key, blue&lt;br /&gt;
|-&lt;br /&gt;
| 3047 || OBJECT2.DN1 || 27    || Interactive || Door key, magenta&lt;br /&gt;
|-&lt;br /&gt;
| 3048 || OBJECT2.DN1 || 37    || Interactive || Door lock, operated by red key&lt;br /&gt;
|-&lt;br /&gt;
| 3049 || OBJECT2.DN1 || 38    || Interactive || Door lock, operated by green key&lt;br /&gt;
|-&lt;br /&gt;
| 304A || OBJECT2.DN1 || 39    || Interactive || Door lock, operated by blue key&lt;br /&gt;
|-&lt;br /&gt;
| 304B || OBJECT2.DN1 || 40    || Interactive || Door lock, operated by magenta key&lt;br /&gt;
|-&lt;br /&gt;
| 304C || OBJECT2.DN1 || 28    || Interactive || Door, opened by red lock&lt;br /&gt;
|-&lt;br /&gt;
| 304D || OBJECT2.DN1 || 28    || Interactive || Door, opened by green lock&lt;br /&gt;
|-&lt;br /&gt;
| 304E || OBJECT2.DN1 || 28    || Interactive || Door, opened by blue lock&lt;br /&gt;
|-&lt;br /&gt;
| 304F || OBJECT2.DN1 || 28    || Interactive || Door, opened by magenta lock&lt;br /&gt;
|-&lt;br /&gt;
| 3050 || OBJECT1.DN1 || 8     || Bonus       || Football&lt;br /&gt;
|-&lt;br /&gt;
| 3051 || OBJECT0.DN1 || 44    || Bonus       || Turkey drumstick&lt;br /&gt;
|-&lt;br /&gt;
| 3052 || ANIM2.DN1   || 32-35 || Bonus       || Soda can&lt;br /&gt;
|-&lt;br /&gt;
| 3053 || OBJECT1.DN1 || 10    || Bonus       || &amp;quot;DN&amp;quot; floppy disk&lt;br /&gt;
|-&lt;br /&gt;
| 3054 || OBJECT1.DN1 || 9     || Bonus       || Joystick&lt;br /&gt;
|-&lt;br /&gt;
| 3055 || OBJECT1.DN1 || 47-49 || Bonus       || Purple flag&lt;br /&gt;
|-&lt;br /&gt;
| 3056 || OBJECT2.DN1 || 2-4   || Bonus       || Radio&lt;br /&gt;
|-&lt;br /&gt;
| 3057 || ANIM4.DN1   || 31    || Hazard      || Spiky round red bomb, stationary, explodes on touch&lt;br /&gt;
|-&lt;br /&gt;
| 3058 || OBJECT2.DN1 || 48    || Hazard      || Spikes, poking up&lt;br /&gt;
|-&lt;br /&gt;
| 3059 || OBJECT2.DN1 || 49    || Hazard      || Spikes, poking down&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
There are numerous level editors available, from the basic original ASCII one, to rather advanced ones capable of rendering animations.&lt;br /&gt;
&lt;br /&gt;
* Maps can be found at [http://vgmaps.com/Atlas/PC/index.htm#DukeNukem vgmaps.com]&lt;br /&gt;
* The original level editor is at [http://archive.shikadi.net/sites/www.geocities.com/dooknookimklassik/ Dook Nookim Klassik]&lt;br /&gt;
* A reasonable level editor can be found at [http://crystalshard.net/?p=8&amp;amp;s=51 crystalshard.net]&lt;br /&gt;
* Possibly the best editor is DN1MOD, which renders levels as the game does, by loading the game&#039;s graphics files [http://archive.shikadi.net/sites/members.iinet.net.au/~markim/admiral_bob/files/]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=File:Duke_1_Level_Format.png&amp;diff=7880</id>
		<title>File:Duke 1 Level Format.png</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=File:Duke_1_Level_Format.png&amp;diff=7880"/>
		<updated>2018-07-30T15:38:18Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Custom level in the Duke 1 Level Format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Custom level in the [[Duke 1 Level Format]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Jill_of_the_Jungle&amp;diff=7859</id>
		<title>Jill of the Jungle</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Jill_of_the_Jungle&amp;diff=7859"/>
		<updated>2018-07-09T07:44:48Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add selection executables data formats&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Game Infobox&lt;br /&gt;
 | Levels = Edit&lt;br /&gt;
 | Tiles = No&lt;br /&gt;
 | Sprites = No&lt;br /&gt;
 | Fullscreen = None&lt;br /&gt;
 | Sound = No&lt;br /&gt;
 | Music = Edit&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = Edit&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Jill of the Jungle]] is the first version of the engine which would go on to power [[Xargon]].  It supports CGA, EGA and VGA graphics by way of &amp;quot;colour maps&amp;quot;, which dictate the CGA and EGA colours to be used to display each of the possible 256-colours of a given image.  This way only a single 256-colour image is supplied, rather than a different image for each display.&lt;br /&gt;
&lt;br /&gt;
Jill is also unique in that it is one of a very small number of games that include a level editor, albeit an undocumented one.  See the [[Using the official Jill of the Jungle level editor|tutorial]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
{{BeginFileFormatTools|Type=game}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [[Using the official Jill of the Jungle level editor|Built-in editor]]&lt;br /&gt;
| Platform = DOS&lt;br /&gt;
| grp = N/A&lt;br /&gt;
| map = Edit&lt;br /&gt;
| gfx = No&lt;br /&gt;
| mus = No&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [[Camoto]]&lt;br /&gt;
| Platform = Linux/Windows&lt;br /&gt;
| grp = N/A&lt;br /&gt;
| map = Edit&lt;br /&gt;
| gfx = Read&lt;br /&gt;
| mus = Edit&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://ftp.funet.fi/pub/msdos/games/editors/jilledit.zip JillEdit] [http://www.stuntsillusion.com/download/jilledit.zip (mirror)]&lt;br /&gt;
| Platform = DOS&lt;br /&gt;
| grp = N/A&lt;br /&gt;
| map = Edit&lt;br /&gt;
| gfx = No&lt;br /&gt;
| mus = No&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{EndFileFormatTools}}&lt;br /&gt;
&lt;br /&gt;
{{BeginGameFileList}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.cfg&lt;br /&gt;
 | Format = [[CFG Format (Jill of the Jungle)]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game configuration&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.ddt&lt;br /&gt;
 | Format = [[CMF Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Background music&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = jill,dma&lt;br /&gt;
 | Format = [[DMA Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Tile information&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.jn[123]&lt;br /&gt;
 | Format = [[Jill of the Jungle Map Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Game levels&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.mac&lt;br /&gt;
 | Format = [[MAC Format (Jill of the Jungle)]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Demo macros&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.sha&lt;br /&gt;
 | Format = [[SHA Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Shapes (images/tiles)&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = *.vcl&lt;br /&gt;
 | Format = [[VCL Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Sound and text assets&lt;br /&gt;
}}&lt;br /&gt;
{{GameFile&lt;br /&gt;
 | Name = jn[123]save.[0-9]&lt;br /&gt;
 | Format = [[Jill of the Jungle Map Format]]&lt;br /&gt;
 | KnownFormat = Yes&lt;br /&gt;
 | Desc = Saved games - just dumps of the entire level in its current state&lt;br /&gt;
}}&lt;br /&gt;
{{EndGameFileList}}&lt;br /&gt;
&lt;br /&gt;
== Palette  ==&lt;br /&gt;
[[Image:Jill of the Jungle palette.png|thumb|right|128px|Jill of the Jungle palette]]&lt;br /&gt;
The VGA palette can be found inside the .EXE file. The palette is the same in all episodes and versions.&lt;br /&gt;
&lt;br /&gt;
==== Episode 1: Jill of the Jungle ====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Version!!CRC32!!Date!!Size!!Palette Offset&lt;br /&gt;
|-&lt;br /&gt;
|1.0||7899CC28||1992-06-01||216 804 bytes||0x1ED84&lt;br /&gt;
|-&lt;br /&gt;
|1.2||9540714E||1992-07-12||204 784 bytes||0x1F884&lt;br /&gt;
|-&lt;br /&gt;
|1.2(a)||51ADAE83||1992-07-30||206 963 bytes||0x1FD54&lt;br /&gt;
|-&lt;br /&gt;
|1.2(b)||171E9EC0||1992-08-21||206 712 bytes||0x1FC34&lt;br /&gt;
|-&lt;br /&gt;
|1.2(c)||C52CA6D9||1993-02-17||206 636 bytes||0x1FC04&lt;br /&gt;
|-&lt;br /&gt;
|1.2(d)||0E7C596F||1993-12-27||219 216 bytes||0x24A64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Episode 2: Jill Goes Underground ====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Version!!CRC32!!Date!!Size!!Palette Offset&lt;br /&gt;
|-&lt;br /&gt;
|1.0||6064EA0A||1992-06-17||65 166* bytes||0x1F0B4&amp;lt;sup&amp;gt;†&amp;lt;/sup&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|1.2(a)||?||1992-07-30||?||?&lt;br /&gt;
|-&lt;br /&gt;
|1.2(b)||17477A49||1992-08-21||204 158 bytes||0x1F6E4&lt;br /&gt;
|-&lt;br /&gt;
|1.2(c)||75176ED7||1993-02-17||204 096 bytes||0x1F6B4&lt;br /&gt;
|-&lt;br /&gt;
|1.2(d)||0FDB489E||1993-12-27||218 338 bytes||0x26A64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Episode 3: Jill Saves the Prince ====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Version!!CRC32!!Date!!Size!!Palette Offset&lt;br /&gt;
|-&lt;br /&gt;
|1.0||3B4D8C3B||1992-07-07||201 616 bytes||0x1F1F4&lt;br /&gt;
|-&lt;br /&gt;
|1.2(a)||B4EA288C||1992-07-30||204 425 bytes||0x1F804&lt;br /&gt;
|-&lt;br /&gt;
|1.2(b)||D5345AFB||1992-08-21||204 174 bytes||0x1F6E4&lt;br /&gt;
|-&lt;br /&gt;
|1.2(c)||3FFF0F6C||1993-02-17||204 112 bytes||0x1F6B4&lt;br /&gt;
|-&lt;br /&gt;
|1.2(d)||E27D4300||1993-12-27||218 370 bytes||0x26A64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;amp;#42;This version has been packed using [[LZEXE|LZEXE91]].&amp;lt;br /&amp;gt;&lt;br /&gt;
†Data taken from version after uncompressing using [[UNLZEXE]].&lt;br /&gt;
&lt;br /&gt;
The palette is in [[VGA Palette|classic VGA format]] (6-bit RGB.)  Note that the [[SHA Format]] can override this palette.&lt;br /&gt;
&lt;br /&gt;
== Episode selection screen ==&lt;br /&gt;
&lt;br /&gt;
Some versions of Jill come bundled with an episode loader executable which displays an interactive screen that allows the player to select from three episodes (if present) and ordering info. The executable contains large amounts (About 90%) of raw data used to display the screen itself and the ordering info if selected. The selection screen uses a single image but various areas of it are faded in in sequence when the executable runs.&lt;br /&gt;
&lt;br /&gt;
The ordering info data seems to be slightly compressed using some form of RLE where certain characters act as flags. Values of 0-16 for example set colors, 24 moves down a line and 25 sets a run of spaces indicated by the next byte.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Data!!Location!!Size&lt;br /&gt;
|-&lt;br /&gt;
|Screen||04E7||64&#039;000 bytes&lt;br /&gt;
|-&lt;br /&gt;
|Screen palette||FEE7||768 bytes&lt;br /&gt;
|-&lt;br /&gt;
|Order info||12AF2||23&#039;630 bytes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
* Since the level files are used for a lot of different things, you can e.g. swap &amp;lt;tt&amp;gt;INTRO.JN1&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;1.JN1&amp;lt;/tt&amp;gt; and then when you load the first level you&#039;ll be playing the intro screen.  The demo and help screens can be accessed in the same way.&lt;br /&gt;
* You can also press Ctrl+P on the main menu to play the intro level, and Ctrl+E to enter the [[Using the official Jill of the Jungle level editor|level editor]].&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
* [http://jillofthejungle.110mb.com/home.html Unofficial Jill of the Jungle page] ([http://members.tripod.com/classic_roach/id14.html Older version], and [http://jill-of-the-jungle.tripod.com/jillsite/index.html alternate version])&lt;br /&gt;
* [http://ftp.funet.fi/pub/msdos/games/editors/jilledit.zip JillEdit] [http://www.stuntsillusion.com/download/jilledit.zip (mirror)] - a level editor for Jill of the Jungle created by Rory L. Fisher.&lt;br /&gt;
* [http://www.vgmaps.com/Atlas/PC/index.htm#JillOfTheJungle vgmaps.com] - all Jill maps as image files&lt;br /&gt;
* [http://www.youtube.com/watch?v=_88gJZoLpyc &amp;quot;Funky&amp;quot; remix] by Nick Stubblefield&lt;br /&gt;
&lt;br /&gt;
[[Category:Epic Megagames]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=EGAGraph_Format&amp;diff=7105</id>
		<title>EGAGraph Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=EGAGraph_Format&amp;diff=7105"/>
		<updated>2017-06-17T06:48:35Z</updated>

		<summary type="html">&lt;p&gt;Levellass: REmove stub status (Seriously?) Continue demo format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Tileset Infobox&lt;br /&gt;
 | Hardware1 = VGA&lt;br /&gt;
 | Palette = External&lt;br /&gt;
 | Names = N&lt;br /&gt;
 | HasTransparency = Y&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subtilesets = N&lt;br /&gt;
 | Compressed = Y&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Catacomb 3-D}}&lt;br /&gt;
   {{Game|Catacomb Abyss}}&lt;br /&gt;
   {{Game|Commander Keen 4-6}}&lt;br /&gt;
   {{Game|Commander Keen Dreams}}&lt;br /&gt;
   {{Game|Dangerous Dave 3}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EGAGraph&#039;&#039;&#039;, short for &#039;EGA graphics library&#039; is the format used to store graphics, demos, fonts, game texts and more in many early [[:Category:Id Software|id Software]] games.&lt;br /&gt;
&lt;br /&gt;
The basic format is that of a number of [[Huffman Compression]] compressed sub-files (Chunks) stored in a similar manner to the [[AudioT Format]]. Like this format it has three main files, &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt;and &amp;lt;tt&amp;gt;EGADICT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is notable that while the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;EGADICT&amp;lt;/tt&amp;gt; are stored in the game executable, they need to be extracted for [[TED5]] to edit levels.&lt;br /&gt;
&lt;br /&gt;
This article may contain errors as some formats have not been worked out completely.&lt;br /&gt;
&lt;br /&gt;
== EGA Head (EGAHEAD.xxx) ==&lt;br /&gt;
&lt;br /&gt;
There are two versions of this format. The first version, used in [[Commander Keen Dreams]], [[Dangerous Dave 3]] and [[Dangerous Dave 4]], is an array of 4-byte little-endian values. The second version, used in all later EGA games, is an array of 3-byte unsigned little-endian values.&lt;br /&gt;
&lt;br /&gt;
This header file may be present as an external file (eg. [[Bio Menace]]), or it may be included in the EXE file (eg. [[Catacomb 3-D]]). The last entry in the header is always the size of the EGAGRAPH.xxx file, and the first entry in the header is always 00 00 00. To find the end, you can search for filesize(EGAGRAPH.xxx) as a 3-byte (little-endian) value in the EXE. Then to find the start, go back 3 bytes at a time until you get to 00 000 00. Or use the fact that entries always get smaller as you go back, unless the entry is $FFFFFF. &lt;br /&gt;
&lt;br /&gt;
In [[Catacomb 3-D]] v1.00 &amp;lt;tt&amp;gt;EGAHEAD.C3D&amp;lt;/tt&amp;gt; is at $1BFD0 from the start of the decompressed ([[unlzexe]]) EXE file, and is 1437 bytes long, or 479 3-byte entries (for 478 chunks). It is then followed by 3 zero bytes (padding to multiple of 16?) 00 00 00, then the &amp;lt;tt&amp;gt;MAPHEAD.C3D&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
In [[Catacomb Abyss]] v1.13 &amp;lt;tt&amp;gt;EGAHEAD.ABS&amp;lt;/tt&amp;gt; is at $1BDB0 from the start of the decompressed ([[unlzexe]]) EXE file, and 1881 bytes long and has 626 chunks.&lt;br /&gt;
&lt;br /&gt;
In [[Catacomb Apocalypse]] v1.00b &amp;lt;tt&amp;gt;EGAHEAD.APC&amp;lt;/tt&amp;gt; is at $1E270 from the start of the decompressed ([[unlzexe]]) EXE file, and 2049 bytes long and has 682 chunks.&lt;br /&gt;
&lt;br /&gt;
This header file stores the offsets (relative to the start of the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file) for each sub file.  The format is trivial, in that the header file is simply an array of 3 or 4 byte variables.  (Each variable is a &amp;quot;slot&amp;quot;, as the game refers to files by index.) Most games use the more compact 3-byte variables, since the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file is never larger than $FFFFFF. However games based on older engines, notably [[Commander Keen Dreams]], [[Dangerous Dave 3]] and [[Dangerous Dave 4]], use 4-byte vales as these are easier to deal with.&lt;br /&gt;
&lt;br /&gt;
It is important to note that not every &#039;slot&#039; will be in use. Tiles especially if blank (All black) will be considered &#039;empty&#039; and not worth adding to the file. (A blank 16x16 tile takes up 12 bytes of space if compressed, and there can be hundreds.) There are two ways of dealing with this; by default the games set all empty slot headers to -1, but many programs compress the graphics anyway and use a normal header value for them.&lt;br /&gt;
&lt;br /&gt;
The last offset in the file will be an offset to the end of the main &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file.  (So this should be ignored when reading the file to prevent a zero-byte file appearing last.) The total size of the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; divided by 3 (Or 4) will also give the number of &#039;slots&#039; the game uses. This varies, but is usually about 10,000.&lt;br /&gt;
&lt;br /&gt;
Unlike [[AudioT Format]] files, &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; is always compressed. However the header and dictionary may be external (E.g [[Bio Menace]])&lt;br /&gt;
&lt;br /&gt;
== Dictionary (EGADICT.xxx) ==&lt;br /&gt;
&lt;br /&gt;
The same [[Huffman Compression]] scheme used elsewhere in the [[Commander Keen]] series is used.  When reading compressed chunks out of the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file, the first four bytes located at the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; offset are a UINT32LE specifying the file&#039;s decompressed size (which is required for the decompression algorithm.)  The compressed data then follows, EXCEPT for 16x16 masked and unmasked tiles. Since these all have a similar decompressed size (128 bytes for unmasked, 256 bytes for masked) it is a waste of space to include these (Since tiles make up the bulk of graphics slots.) The decompressed size is hard coded, as are the start and finish of the unmasked and masked tile slots.&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;EGADICT&amp;lt;/tt&amp;gt; file is not often obvious, usually being embedded in the main exe file. It is possible to locate it by looking for the string &amp;lt;tt&amp;gt;$FD $01 $00 $00 $00 $00&amp;lt;/tt&amp;gt;, which appears at the end of nearly all Huffman dictionaries. They are the last 6 bytes out of 1024 (256*2*2), so add 6 and subtract 1024 to get the start (pointer to the head node).&lt;br /&gt;
&lt;br /&gt;
Executables usually contain two or more dictionaries, but the &amp;lt;tt&amp;gt;EGADICT&amp;lt;/tt&amp;gt; is usually &#039;&#039;&#039;the second one&#039;&#039;&#039;, except in the case of early games like Keen Dreams, where it is the first of THREE. (A simple check of whether it decompresses the data sensibly works.)&lt;br /&gt;
&lt;br /&gt;
In [[Catacomb 3-D]] &amp;lt;tt&amp;gt;EGADICT.C3D&amp;lt;/tt&amp;gt; is at offset $24464 from the start of the decompressed CAT3D.EXE, which is the second Huffman dictionary and comes immediately after the first Huffman Dictionary.&lt;br /&gt;
&lt;br /&gt;
In [[Catacomb Abyss]] v1.13 &amp;lt;tt&amp;gt;EGADICT.ABS&amp;lt;/tt&amp;gt; is at offset $2734C from the start of the decompressed CATABYSS.EXE, which is the second Huffman dictionary.&lt;br /&gt;
&lt;br /&gt;
In [[Catacomb Apocalypse]] v1.00b &amp;lt;tt&amp;gt;EGADICT.APC&amp;lt;/tt&amp;gt; is at offset $26B24 from the start of the decompressed CATAPOC.EXE, which is the second Huffman dictionary.&lt;br /&gt;
&lt;br /&gt;
== Main file (EGAGRAPH.xxx) ==&lt;br /&gt;
&lt;br /&gt;
This file is simply an array of data files.  Each file starts at the offset specified in the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; file, and as there are no filenames each file is referred to by its index/slot number.  Slots containing dummy values in the header are treated as if they don&#039;t exist in the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file. Each file within the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file is individually compressed.  A file can be read by opening the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file, seeking to the offset specified in the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; file, reading a UINT32LE for the decompressed file size, and then decompressing the data from that point onwards using standard Huffman decompression techniques.&lt;br /&gt;
&lt;br /&gt;
Note that in early games such as Keen Dreams, the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file may have another name. (Such as &amp;lt;tt&amp;gt;KDREAM.EGA&amp;lt;/tt&amp;gt; in that case.) in which case it is always the largest non-executable file.&lt;br /&gt;
&lt;br /&gt;
=== Chunks ===&lt;br /&gt;
&lt;br /&gt;
Each sub file or chunk is a separate graphic, ordered in the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file in a specific way, much again like the [[AudioT Format]].  Chunks are labeled starting at 0. The game executable is hard coded for the start and finish of various chunk types. For example, Keen 4 has chunks 124-520 as sprites and will treat any chunk between these two numbers as a sprite. (Note that the game refers to chunk number, not sprite number.) The usual order of chunks is:&lt;br /&gt;
&lt;br /&gt;
 Picture table&lt;br /&gt;
 Masked picture table&lt;br /&gt;
 Sprite table&lt;br /&gt;
 Fonts&lt;br /&gt;
 Pictures (Unmasked bitmaps)&lt;br /&gt;
 Masked pictures&lt;br /&gt;
 8x8 unmasked tiles (Single chunk)&lt;br /&gt;
 8x8 masked tiles (Single chunk)&lt;br /&gt;
 16x16 unmasked tiles&lt;br /&gt;
 16x16 masked tiles&lt;br /&gt;
 32x32 unmasked tiles (Optional)&lt;br /&gt;
 32x32 masked tiles (Optional)&lt;br /&gt;
 Misc graphics (Optional)&lt;br /&gt;
 Game texts&lt;br /&gt;
 Demo files (Optional)&lt;br /&gt;
 Misc data (Optional)&lt;br /&gt;
&lt;br /&gt;
== Chunk formats ==&lt;br /&gt;
&lt;br /&gt;
When compressed each chunk consists of a dword giving the decompressed size followed by the compressed data.&lt;br /&gt;
&lt;br /&gt;
=== Picture table ===&lt;br /&gt;
&lt;br /&gt;
Always present and always the first chunk, the picture table is 4 * numpics bytes long, consisting of two words for each picture (Width\8, Height) used when displaying picture chunks.&lt;br /&gt;
&lt;br /&gt;
Divide the decompressed size by 4 to get numpics.&lt;br /&gt;
&lt;br /&gt;
=== Masked picture table ===&lt;br /&gt;
&lt;br /&gt;
Always present and always the second chunk, the picture table is 4 * numpics bytes long, consisting of two words for each picture (Width\8, Height) used when displaying masked picture chunks. This table is often quite small.&lt;br /&gt;
&lt;br /&gt;
=== Sprite table ===&lt;br /&gt;
&lt;br /&gt;
Always present and always the third chunk, the picture table is 16 * numspr bytes long, consisting of eight words for each sprite image (Width\8, Height, x offset, y offset and clipping rectangle left, top, right and bottom; all in that order.) used when displaying sprite chunks. This is what Modkeen exports as its notoriously hard to use xSPRITES.txt file.&lt;br /&gt;
&lt;br /&gt;
=== Fonts ===&lt;br /&gt;
&lt;br /&gt;
Always present and always starting at the fourth chunk. (Chunk 3!) Each chunk is a single monochrome font, containing all the entries from 0-255 for that font. Each &#039;letter&#039; is stored separately and consecutively. A game will have at least one, and usually 3 fonts. The format is version two of [[EGA Font format]]&lt;br /&gt;
&lt;br /&gt;
Fonts are used in the game for game texts. They can be stretched or colored and are always transparent, meaning they look strange when not over a single-color background.&lt;br /&gt;
&lt;br /&gt;
=== Pictures (Bitmaps) ===&lt;br /&gt;
&lt;br /&gt;
These follow game fonts. You need to know how many fonts there are before it to know how what chunk number the first picture is (3+NumFonts). In [[Catacomb 3-D]] there are 2 fonts.&lt;br /&gt;
&lt;br /&gt;
Bitmaps are stored as standard [[Raw EGA data]], the size of each plane being the decompressed chunk size \ 4. In order to be displayed properly these need information from chunk 0, the picture table. Note that unlike fonts, data does not wrap, so a 4x4 sprite will consist of four planes of four bytes in size, the same as an 8x4 sprite.&lt;br /&gt;
&lt;br /&gt;
Pictures are used for things such as title screens or pictures in game texts. Most of the main menu will consist of pictures. They are also used for the wall textures in EGA FPS games like [[Catacomb 3-D]], in which case the wall textures come near the end of the picture list (starting from chunk 137 in [[Catacomb 3-D]]).&lt;br /&gt;
&lt;br /&gt;
The number of picture chunks is given in chunk 0, the picture table.&lt;br /&gt;
&lt;br /&gt;
=== Masked pictures (Masked bitmaps) ===&lt;br /&gt;
&lt;br /&gt;
These follow Pictures. You need to know how many fonts there are, to know how what chunk number the first Masked picture is (3+NumFonts+numpics).&lt;br /&gt;
&lt;br /&gt;
These are identical to the picture chunks in every respect, except being masked, they consist of five EGA planes, not four. Some games (E.g [[Catacomb 3-D]] make great use of masked pictures, but most games have only one or two. They need information from chunk 1, the masked picture table, to be displayed correctly.&lt;br /&gt;
&lt;br /&gt;
The number of Masked pictures is given in Chunk 1.&lt;br /&gt;
&lt;br /&gt;
=== Sprites ===&lt;br /&gt;
&lt;br /&gt;
The first Sprite chunk is at 3+numfonts+numpics+numMaskedPics.&lt;br /&gt;
&lt;br /&gt;
Sprites are exactly identical to masked pictures in format except the game cannot stretch or warp them. Most games use these for enemy, player or item graphics during gameplay. They need information from chunk 2, the sprite table both to display correctly and to interact correctly, something more complex than masked pictures.&lt;br /&gt;
&lt;br /&gt;
There are usually several hundred sprite chunks, but [[Catacomb 3-D]] only has 3 sprite chunks and they are used for the PaddleWar game (Skulls and Bones). The number of sprite chunks is given in chunk 2.&lt;br /&gt;
&lt;br /&gt;
=== 8x8 tiles ===&lt;br /&gt;
&lt;br /&gt;
8x8 tiles are used by most games in status windows or foe the borders of message windows in-game. (And occasionally by TED5 to display levels.) There are thus not many of them. ALL the masked or unmasked tiles are one single chunk stored as four and five plane [[Raw EGA data]] respectively. The number of 8x8 unmasked and masked tiles is hard-coded into the executable, but can be worked out by dividing the decompressed chunk size by 32 and 40 (The size of one tile&#039;s data) respectively.&lt;br /&gt;
&lt;br /&gt;
=== 16x16 and 32x32 tiles ===&lt;br /&gt;
&lt;br /&gt;
32x32 tiles are optional and rarely used. 16x16 tiles are only occasionally absent and for most games make up the bulk of graphics. There are usually several thousand entries. Both come in masked and unmasked kinds, just like 8x8 tiles.&lt;br /&gt;
&lt;br /&gt;
These chunks have notable differences. Each tile is an individual chunk and stored as four or five plane [[Raw EGA data]] with a plane size of 128 (16x16) or 512 (32x32). These chunks do NOT have a dword specifying their decompressed size as this is hard-coded into the executable as a space saving measure. (As is the start and finish of unmasked and masked tile chunks.) This can cause problems for editing programs.&lt;br /&gt;
&lt;br /&gt;
Tiles make up the bulk of 2D game levels but are seldom seen elsewhere.&lt;br /&gt;
&lt;br /&gt;
=== Misc graphics ===&lt;br /&gt;
&lt;br /&gt;
Sometimes following tile graphics are miscellaneous graphics, that cannot be handled by the other chunk types. For example, Keen 4-6 has two misc graphics files used for the &#039;COMMANDER KEEN terminator text&#039; intro. These graphics usually have unique formats that fit their function and few have been investigated.&lt;br /&gt;
&lt;br /&gt;
==== Keen 4-6 Intro Bitmaps ====&lt;br /&gt;
&lt;br /&gt;
This is the text that displays after the &#039;Ready, press any key&#039; screen at Keen startup. It is composed of a monochrome bitmap that is scrolled across the screen and distorted for special effects. When displayed it is transparent, with a special palette so it is not black-and-white. It consists of a header followed by RLE compressed monochrome data.&lt;br /&gt;
&lt;br /&gt;
 HEADER:&lt;br /&gt;
 0   2    Img height  Height of the image in pixels&lt;br /&gt;
 2   2    Img width   Width of the image in pixels&lt;br /&gt;
 4   2x   Line point  Pointers to line 1,2,3..etc of data. There will be [Img height] of&lt;br /&gt;
                      these, each 2 bytes long. The first pointer will  have the value&lt;br /&gt;
                      (2 * [Img height] + 4)&lt;br /&gt;
 +2  ?    RLE data    RLE-WM compressed data&lt;br /&gt;
&lt;br /&gt;
 DATA:&lt;br /&gt;
 0   2    Black run   Number of black pixels to write&lt;br /&gt;
 2   2    Not-blk run Number of not-black pixels to write&lt;br /&gt;
 4   2    Black run....&lt;br /&gt;
 ...&lt;br /&gt;
 ..&lt;br /&gt;
 .&lt;br /&gt;
 ?  2     End         $FFFF; end of row.&lt;br /&gt;
&lt;br /&gt;
=== Game texts ===&lt;br /&gt;
&lt;br /&gt;
Also known as ANSII chunks, these are used by the game for things like help screens, and have their own format. In the main they are simply text documents, interspersed with various commands to make things happen. Each file is divided up into a number of &#039;pages&#039; which are moved between by pressing the up/down arrows. Pages can also have action sequences (Repeated each time the page is moved to, you cannot leave a page until the sequence finishes.)&lt;br /&gt;
&lt;br /&gt;
 ^P		First command in every file. Defines a page start&lt;br /&gt;
 ^E		Ends the file&lt;br /&gt;
 ^Cx		Change font color to $x until next page or ^C command&lt;br /&gt;
 ^Gx,y,z	Display (unmasked) picture chunk z at location x,y (In pixels)&lt;br /&gt;
 ^Tx,y,z,t	Display picture chunk z at x,y for z clicks of time&lt;br /&gt;
 ^Bx,y,z,t,b	?&lt;br /&gt;
 ^Lx,y		?&lt;br /&gt;
&lt;br /&gt;
=== Demo files ===&lt;br /&gt;
&lt;br /&gt;
These files, which can be recorded in several games using the &#039;demo cheat&#039; consist of a series of commands that are played back when a demo is run ingame. (The game is also &#039;derandomized&#039; during recording so all demo playbacks will be predictable.)&lt;br /&gt;
&lt;br /&gt;
The format is quite simple; consisting of two words and a number of byte pairs. The first two bytes store the number of the level to load for the demo, the next two store the length of data to load\play (After this limit is reached the demo will end, whether or not there is any more data to read.) The remaining byte pairs each encode a time and a keypress. The following values are known:&lt;br /&gt;
&lt;br /&gt;
 01	Left&lt;br /&gt;
 04	Up&lt;br /&gt;
 05	Nothing&lt;br /&gt;
 06	Down&lt;br /&gt;
 09	Right&lt;br /&gt;
 15	Ctrl&lt;br /&gt;
 25	Alt&lt;br /&gt;
&lt;br /&gt;
=== Misc files ===&lt;br /&gt;
&lt;br /&gt;
The last few chunks are demo files and occasionally miscellaneous data. Demo file formats are currently unknown but can be recorded using the demo cheat. They contain the level number and difficulty followed by a series of key commands.&lt;br /&gt;
&lt;br /&gt;
== Utilities ==&lt;br /&gt;
&lt;br /&gt;
* [[KeenWiki:ModKeen|ModKeen]] (DOS) and [[KeenWiki:LModKeen|LModKeen]] (Linux/Windows) can be used to modify graphics and text stored in EGAGRAPH.CKx for the Commander Keen [[KeenWiki:Goodbye Galaxy|Goodbye Galaxy]] trilogy.&lt;br /&gt;
* WDC (Windows) can be used to view or modify the graphics and text stored in EGAGRAPH for [[Catacomb 3-D]] and [[Catacomb Abyss]].&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=File:EGAGraph_Format.png&amp;diff=7104</id>
		<title>File:EGAGraph Format.png</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=File:EGAGraph_Format.png&amp;diff=7104"/>
		<updated>2017-06-17T06:35:07Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Commander Keen 5 masked tileset in EGAGraph format.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Commander Keen]] 5 masked tileset in EGAGraph format.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=EGAGraph_Format&amp;diff=7103</id>
		<title>EGAGraph Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=EGAGraph_Format&amp;diff=7103"/>
		<updated>2017-06-17T06:12:11Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Start demo format edit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
{{Tileset Infobox&lt;br /&gt;
 | Hardware1 = VGA&lt;br /&gt;
 | Palette = External&lt;br /&gt;
 | Names = N&lt;br /&gt;
 | HasTransparency = Y&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subtilesets = N&lt;br /&gt;
 | Compressed = Y&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|Catacomb 3-D}}&lt;br /&gt;
   {{Game|Catacomb Abyss}}&lt;br /&gt;
   {{Game|Commander Keen 4-6}}&lt;br /&gt;
   {{Game|Commander Keen Dreams}}&lt;br /&gt;
   {{Game|Dangerous Dave 3}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;EGAGraph&#039;&#039;&#039;, short for &#039;EGA graphics library&#039; is the format used to store graphics, demos, fonts, game texts and more in many early [[:Category:Id Software|id Software]] games.&lt;br /&gt;
&lt;br /&gt;
The basic format is that of a number of [[Huffman Compression]] compressed sub-files (Chunks) stored in a similar manner to the [[AudioT Format]]. Like this format it has three main files, &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt;and &amp;lt;tt&amp;gt;EGADICT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is notable that while the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;EGADICT&amp;lt;/tt&amp;gt; are stored in the game executable, they need to be extracted for [[TED5]] to edit levels.&lt;br /&gt;
&lt;br /&gt;
This article may contain errors as some formats have not been worked out completely.&lt;br /&gt;
&lt;br /&gt;
== EGA Head (EGAHEAD.xxx) ==&lt;br /&gt;
&lt;br /&gt;
There are two versions of this format. The first version, used in [[Commander Keen Dreams]], [[Dangerous Dave 3]] and [[Dangerous Dave 4]], is an array of 4-byte little-endian values. The second version, used in all later EGA games, is an array of 3-byte unsigned little-endian values.&lt;br /&gt;
&lt;br /&gt;
This header file may be present as an external file (eg. [[Bio Menace]]), or it may be included in the EXE file (eg. [[Catacomb 3-D]]). The last entry in the header is always the size of the EGAGRAPH.xxx file, and the first entry in the header is always 00 00 00. To find the end, you can search for filesize(EGAGRAPH.xxx) as a 3-byte (little-endian) value in the EXE. Then to find the start, go back 3 bytes at a time until you get to 00 000 00. Or use the fact that entries always get smaller as you go back, unless the entry is $FFFFFF. &lt;br /&gt;
&lt;br /&gt;
In [[Catacomb 3-D]] v1.00 &amp;lt;tt&amp;gt;EGAHEAD.C3D&amp;lt;/tt&amp;gt; is at $1BFD0 from the start of the decompressed ([[unlzexe]]) EXE file, and is 1437 bytes long, or 479 3-byte entries (for 478 chunks). It is then followed by 3 zero bytes (padding to multiple of 16?) 00 00 00, then the &amp;lt;tt&amp;gt;MAPHEAD.C3D&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
In [[Catacomb Abyss]] v1.13 &amp;lt;tt&amp;gt;EGAHEAD.ABS&amp;lt;/tt&amp;gt; is at $1BDB0 from the start of the decompressed ([[unlzexe]]) EXE file, and 1881 bytes long and has 626 chunks.&lt;br /&gt;
&lt;br /&gt;
In [[Catacomb Apocalypse]] v1.00b &amp;lt;tt&amp;gt;EGAHEAD.APC&amp;lt;/tt&amp;gt; is at $1E270 from the start of the decompressed ([[unlzexe]]) EXE file, and 2049 bytes long and has 682 chunks.&lt;br /&gt;
&lt;br /&gt;
This header file stores the offsets (relative to the start of the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file) for each sub file.  The format is trivial, in that the header file is simply an array of 3 or 4 byte variables.  (Each variable is a &amp;quot;slot&amp;quot;, as the game refers to files by index.) Most games use the more compact 3-byte variables, since the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file is never larger than $FFFFFF. However games based on older engines, notably [[Commander Keen Dreams]], [[Dangerous Dave 3]] and [[Dangerous Dave 4]], use 4-byte vales as these are easier to deal with.&lt;br /&gt;
&lt;br /&gt;
It is important to note that not every &#039;slot&#039; will be in use. Tiles especially if blank (All black) will be considered &#039;empty&#039; and not worth adding to the file. (A blank 16x16 tile takes up 12 bytes of space if compressed, and there can be hundreds.) There are two ways of dealing with this; by default the games set all empty slot headers to -1, but many programs compress the graphics anyway and use a normal header value for them.&lt;br /&gt;
&lt;br /&gt;
The last offset in the file will be an offset to the end of the main &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file.  (So this should be ignored when reading the file to prevent a zero-byte file appearing last.) The total size of the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; divided by 3 (Or 4) will also give the number of &#039;slots&#039; the game uses. This varies, but is usually about 10,000.&lt;br /&gt;
&lt;br /&gt;
Unlike [[AudioT Format]] files, &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; is always compressed. However the header and dictionary may be external (E.g [[Bio Menace]])&lt;br /&gt;
&lt;br /&gt;
== Dictionary (EGADICT.xxx) ==&lt;br /&gt;
&lt;br /&gt;
The same [[Huffman Compression]] scheme used elsewhere in the [[Commander Keen]] series is used.  When reading compressed chunks out of the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file, the first four bytes located at the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; offset are a UINT32LE specifying the file&#039;s decompressed size (which is required for the decompression algorithm.)  The compressed data then follows, EXCEPT for 16x16 masked and unmasked tiles. Since these all have a similar decompressed size (128 bytes for unmasked, 256 bytes for masked) it is a waste of space to include these (Since tiles make up the bulk of graphics slots.) The decompressed size is hard coded, as are the start and finish of the unmasked and masked tile slots.&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;EGADICT&amp;lt;/tt&amp;gt; file is not often obvious, usually being embedded in the main exe file. It is possible to locate it by looking for the string &amp;lt;tt&amp;gt;$FD $01 $00 $00 $00 $00&amp;lt;/tt&amp;gt;, which appears at the end of nearly all Huffman dictionaries. They are the last 6 bytes out of 1024 (256*2*2), so add 6 and subtract 1024 to get the start (pointer to the head node).&lt;br /&gt;
&lt;br /&gt;
Executables usually contain two or more dictionaries, but the &amp;lt;tt&amp;gt;EGADICT&amp;lt;/tt&amp;gt; is usually &#039;&#039;&#039;the second one&#039;&#039;&#039;, except in the case of early games like Keen Dreams, where it is the first of THREE. (A simple check of whether it decompresses the data sensibly works.)&lt;br /&gt;
&lt;br /&gt;
In [[Catacomb 3-D]] &amp;lt;tt&amp;gt;EGADICT.C3D&amp;lt;/tt&amp;gt; is at offset $24464 from the start of the decompressed CAT3D.EXE, which is the second Huffman dictionary and comes immediately after the first Huffman Dictionary.&lt;br /&gt;
&lt;br /&gt;
In [[Catacomb Abyss]] v1.13 &amp;lt;tt&amp;gt;EGADICT.ABS&amp;lt;/tt&amp;gt; is at offset $2734C from the start of the decompressed CATABYSS.EXE, which is the second Huffman dictionary.&lt;br /&gt;
&lt;br /&gt;
In [[Catacomb Apocalypse]] v1.00b &amp;lt;tt&amp;gt;EGADICT.APC&amp;lt;/tt&amp;gt; is at offset $26B24 from the start of the decompressed CATAPOC.EXE, which is the second Huffman dictionary.&lt;br /&gt;
&lt;br /&gt;
== Main file (EGAGRAPH.xxx) ==&lt;br /&gt;
&lt;br /&gt;
This file is simply an array of data files.  Each file starts at the offset specified in the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; file, and as there are no filenames each file is referred to by its index/slot number.  Slots containing dummy values in the header are treated as if they don&#039;t exist in the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file. Each file within the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file is individually compressed.  A file can be read by opening the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file, seeking to the offset specified in the &amp;lt;tt&amp;gt;EGAHEAD&amp;lt;/tt&amp;gt; file, reading a UINT32LE for the decompressed file size, and then decompressing the data from that point onwards using standard Huffman decompression techniques.&lt;br /&gt;
&lt;br /&gt;
Note that in early games such as Keen Dreams, the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file may have another name. (Such as &amp;lt;tt&amp;gt;KDREAM.EGA&amp;lt;/tt&amp;gt; in that case.) in which case it is always the largest non-executable file.&lt;br /&gt;
&lt;br /&gt;
=== Chunks ===&lt;br /&gt;
&lt;br /&gt;
Each sub file or chunk is a separate graphic, ordered in the &amp;lt;tt&amp;gt;EGAGRAPH&amp;lt;/tt&amp;gt; file in a specific way, much again like the [[AudioT Format]].  Chunks are labeled starting at 0. The game executable is hard coded for the start and finish of various chunk types. For example, Keen 4 has chunks 124-520 as sprites and will treat any chunk between these two numbers as a sprite. (Note that the game refers to chunk number, not sprite number.) The usual order of chunks is:&lt;br /&gt;
&lt;br /&gt;
 Picture table&lt;br /&gt;
 Masked picture table&lt;br /&gt;
 Sprite table&lt;br /&gt;
 Fonts&lt;br /&gt;
 Pictures (Unmasked bitmaps)&lt;br /&gt;
 Masked pictures&lt;br /&gt;
 8x8 unmasked tiles (Single chunk)&lt;br /&gt;
 8x8 masked tiles (Single chunk)&lt;br /&gt;
 16x16 unmasked tiles&lt;br /&gt;
 16x16 masked tiles&lt;br /&gt;
 32x32 unmasked tiles (Optional)&lt;br /&gt;
 32x32 masked tiles (Optional)&lt;br /&gt;
 Misc graphics (Optional)&lt;br /&gt;
 Game texts&lt;br /&gt;
 Demo files (Optional)&lt;br /&gt;
 Misc data (Optional)&lt;br /&gt;
&lt;br /&gt;
== Chunk formats ==&lt;br /&gt;
&lt;br /&gt;
When compressed each chunk consists of a dword giving the decompressed size followed by the compressed data.&lt;br /&gt;
&lt;br /&gt;
=== Picture table ===&lt;br /&gt;
&lt;br /&gt;
Always present and always the first chunk, the picture table is 4 * numpics bytes long, consisting of two words for each picture (Width\8, Height) used when displaying picture chunks.&lt;br /&gt;
&lt;br /&gt;
Divide the decompressed size by 4 to get numpics.&lt;br /&gt;
&lt;br /&gt;
=== Masked picture table ===&lt;br /&gt;
&lt;br /&gt;
Always present and always the second chunk, the picture table is 4 * numpics bytes long, consisting of two words for each picture (Width\8, Height) used when displaying masked picture chunks. This table is often quite small.&lt;br /&gt;
&lt;br /&gt;
=== Sprite table ===&lt;br /&gt;
&lt;br /&gt;
Always present and always the third chunk, the picture table is 16 * numspr bytes long, consisting of eight words for each sprite image (Width\8, Height, x offset, y offset and clipping rectangle left, top, right and bottom; all in that order.) used when displaying sprite chunks. This is what Modkeen exports as its notoriously hard to use xSPRITES.txt file.&lt;br /&gt;
&lt;br /&gt;
=== Fonts ===&lt;br /&gt;
&lt;br /&gt;
Always present and always starting at the fourth chunk. (Chunk 3!) Each chunk is a single monochrome font, containing all the entries from 0-255 for that font. Each &#039;letter&#039; is stored separately and consecutively. A game will have at least one, and usually 3 fonts. The format is version two of [[EGA Font format]]&lt;br /&gt;
&lt;br /&gt;
Fonts are used in the game for game texts. They can be stretched or colored and are always transparent, meaning they look strange when not over a single-color background.&lt;br /&gt;
&lt;br /&gt;
=== Pictures (Bitmaps) ===&lt;br /&gt;
&lt;br /&gt;
These follow game fonts. You need to know how many fonts there are before it to know how what chunk number the first picture is (3+NumFonts). In [[Catacomb 3-D]] there are 2 fonts.&lt;br /&gt;
&lt;br /&gt;
Bitmaps are stored as standard [[Raw EGA data]], the size of each plane being the decompressed chunk size \ 4. In order to be displayed properly these need information from chunk 0, the picture table. Note that unlike fonts, data does not wrap, so a 4x4 sprite will consist of four planes of four bytes in size, the same as an 8x4 sprite.&lt;br /&gt;
&lt;br /&gt;
Pictures are used for things such as title screens or pictures in game texts. Most of the main menu will consist of pictures. They are also used for the wall textures in EGA FPS games like [[Catacomb 3-D]], in which case the wall textures come near the end of the picture list (starting from chunk 137 in [[Catacomb 3-D]]).&lt;br /&gt;
&lt;br /&gt;
The number of picture chunks is given in chunk 0, the picture table.&lt;br /&gt;
&lt;br /&gt;
=== Masked pictures (Masked bitmaps) ===&lt;br /&gt;
&lt;br /&gt;
These follow Pictures. You need to know how many fonts there are, to know how what chunk number the first Masked picture is (3+NumFonts+numpics).&lt;br /&gt;
&lt;br /&gt;
These are identical to the picture chunks in every respect, except being masked, they consist of five EGA planes, not four. Some games (E.g [[Catacomb 3-D]] make great use of masked pictures, but most games have only one or two. They need information from chunk 1, the masked picture table, to be displayed correctly.&lt;br /&gt;
&lt;br /&gt;
The number of Masked pictures is given in Chunk 1.&lt;br /&gt;
&lt;br /&gt;
=== Sprites ===&lt;br /&gt;
&lt;br /&gt;
The first Sprite chunk is at 3+numfonts+numpics+numMaskedPics.&lt;br /&gt;
&lt;br /&gt;
Sprites are exactly identical to masked pictures in format except the game cannot stretch or warp them. Most games use these for enemy, player or item graphics during gameplay. They need information from chunk 2, the sprite table both to display correctly and to interact correctly, something more complex than masked pictures.&lt;br /&gt;
&lt;br /&gt;
There are usually several hundred sprite chunks, but [[Catacomb 3-D]] only has 3 sprite chunks and they are used for the PaddleWar game (Skulls and Bones). The number of sprite chunks is given in chunk 2.&lt;br /&gt;
&lt;br /&gt;
=== 8x8 tiles ===&lt;br /&gt;
&lt;br /&gt;
8x8 tiles are used by most games in status windows or foe the borders of message windows in-game. (And occasionally by TED5 to display levels.) There are thus not many of them. ALL the masked or unmasked tiles are one single chunk stored as four and five plane [[Raw EGA data]] respectively. The number of 8x8 unmasked and masked tiles is hard-coded into the executable, but can be worked out by dividing the decompressed chunk size by 32 and 40 (The size of one tile&#039;s data) respectively.&lt;br /&gt;
&lt;br /&gt;
=== 16x16 and 32x32 tiles ===&lt;br /&gt;
&lt;br /&gt;
32x32 tiles are optional and rarely used. 16x16 tiles are only occasionally absent and for most games make up the bulk of graphics. There are usually several thousand entries. Both come in masked and unmasked kinds, just like 8x8 tiles.&lt;br /&gt;
&lt;br /&gt;
These chunks have notable differences. Each tile is an individual chunk and stored as four or five plane [[Raw EGA data]] with a plane size of 128 (16x16) or 512 (32x32). These chunks do NOT have a dword specifying their decompressed size as this is hard-coded into the executable as a space saving measure. (As is the start and finish of unmasked and masked tile chunks.) This can cause problems for editing programs.&lt;br /&gt;
&lt;br /&gt;
Tiles make up the bulk of 2D game levels but are seldom seen elsewhere.&lt;br /&gt;
&lt;br /&gt;
=== Misc graphics ===&lt;br /&gt;
&lt;br /&gt;
Sometimes following tile graphics are miscellaneous graphics, that cannot be handled by the other chunk types. For example, Keen 4-6 has two misc graphics files used for the &#039;COMMANDER KEEN terminator text&#039; intro. These graphics usually have unique formats that fit their function and few have been investigated.&lt;br /&gt;
&lt;br /&gt;
==== Keen 4-6 Intro Bitmaps ====&lt;br /&gt;
&lt;br /&gt;
This is the text that displays after the &#039;Ready, press any key&#039; screen at Keen startup. It is composed of a monochrome bitmap that is scrolled across the screen and distorted for special effects. When displayed it is transparent, with a special palette so it is not black-and-white. It consists of a header followed by RLE compressed monochrome data.&lt;br /&gt;
&lt;br /&gt;
 HEADER:&lt;br /&gt;
 0   2    Img height  Height of the image in pixels&lt;br /&gt;
 2   2    Img width   Width of the image in pixels&lt;br /&gt;
 4   2x   Line point  Pointers to line 1,2,3..etc of data. There will be [Img height] of&lt;br /&gt;
                      these, each 2 bytes long. The first pointer will  have the value&lt;br /&gt;
                      (2 * [Img height] + 4)&lt;br /&gt;
 +2  ?    RLE data    RLE-WM compressed data&lt;br /&gt;
&lt;br /&gt;
 DATA:&lt;br /&gt;
 0   2    Black run   Number of black pixels to write&lt;br /&gt;
 2   2    Not-blk run Number of not-black pixels to write&lt;br /&gt;
 4   2    Black run....&lt;br /&gt;
 ...&lt;br /&gt;
 ..&lt;br /&gt;
 .&lt;br /&gt;
 ?  2     End         $FFFF; end of row.&lt;br /&gt;
&lt;br /&gt;
=== Game texts ===&lt;br /&gt;
&lt;br /&gt;
Also known as ANSII chunks, these are used by the game for things like help screens, and have their own format. In the main they are simply text documents, interspersed with various commands to make things happen. Each file is divided up into a number of &#039;pages&#039; which are moved between by pressing the up/down arrows. Pages can also have action sequences (Repeated each time the page is moved to, you cannot leave a page until the sequence finishes.)&lt;br /&gt;
&lt;br /&gt;
 ^P		First command in every file. Defines a page start&lt;br /&gt;
 ^E		Ends the file&lt;br /&gt;
 ^Cx		Change font color to $x until next page or ^C command&lt;br /&gt;
 ^Gx,y,z	Display (unmasked) picture chunk z at location x,y (In pixels)&lt;br /&gt;
 ^Tx,y,z,t	Display picture chunk z at x,y for z clicks of time&lt;br /&gt;
 ^Bx,y,z,t,b	?&lt;br /&gt;
 ^Lx,y		?&lt;br /&gt;
&lt;br /&gt;
=== Demo files ===&lt;br /&gt;
&lt;br /&gt;
These files, which can be recorded in several games using the &#039;demo cheat&#039; consist of a series of commands that are played back when a demo is run ingame. (The game is also &#039;derandomized&#039; during recording so all demo playbacks will be predictable.)&lt;br /&gt;
&lt;br /&gt;
The format is quite simple; consisting of two words and a number of byte pairs. The first two bytes store the number of the level to load for the demo, the next two store the length of data to load\play (After this limit is reached the demo will end, whether or not there is any more data to read.) The remaining byte pairs each encode a time and a keypress. The following values are known:&lt;br /&gt;
&lt;br /&gt;
 01	Left&lt;br /&gt;
 04	Up&lt;br /&gt;
 05	Nothing&lt;br /&gt;
 06	Down&lt;br /&gt;
 09	Right&lt;br /&gt;
 15	Ctrl&lt;br /&gt;
&lt;br /&gt;
=== Misc files ===&lt;br /&gt;
&lt;br /&gt;
The last few chunks are demo files and occasionally miscellaneous data. Demo file formats are currently unknown but can be recorded using the demo cheat. They contain the level number and difficulty followed by a series of key commands.&lt;br /&gt;
&lt;br /&gt;
== Utilities ==&lt;br /&gt;
&lt;br /&gt;
* [[KeenWiki:ModKeen|ModKeen]] (DOS) and [[KeenWiki:LModKeen|LModKeen]] (Linux/Windows) can be used to modify graphics and text stored in EGAGRAPH.CKx for the Commander Keen [[KeenWiki:Goodbye Galaxy|Goodbye Galaxy]] trilogy.&lt;br /&gt;
* WDC (Windows) can be used to view or modify the graphics and text stored in EGAGRAPH for [[Catacomb 3-D]] and [[Catacomb Abyss]].&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=File:GameMaps_Format.png&amp;diff=7040</id>
		<title>File:GameMaps Format.png</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=File:GameMaps_Format.png&amp;diff=7040"/>
		<updated>2017-03-11T07:59:34Z</updated>

		<summary type="html">&lt;p&gt;Levellass: A [[Commander Keen] 4 level built using the GAMEMAPS format.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A [[Commander Keen] 4 level built using the GAMEMAPS format.&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6848</id>
		<title>Huffman Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6848"/>
		<updated>2016-05-24T10:09:22Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Rewrite complete&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-byte in, 1-bit out&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|The Blues Brothers}}&lt;br /&gt;
   {{Game|Catacomb 3-D}}&lt;br /&gt;
   {{Game|Commander Keen Dreams}}&lt;br /&gt;
   {{Game|Dangerous Dave 2}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Huffman Compression]] is a compression algorithm used in many classic games. It is about as efficient as LZW or RLE compression, with many games using the three formats simultaneously.&lt;br /&gt;
&lt;br /&gt;
Huffman compression involves changing how various characters are stored. Normally all characters in a given segment of data are equal and take an equal amount of space to store. However by making more common characters take up less space while allowing less commonly used characters to take up more the overall size of a segment of data can be reduced. Any Huffman compressed data will thus be associated with a dictionary file (internal or external) used to decompress it. This page will go through each aspect of Huffman compression in a stepwise manner before presenting some examples of usage and source code.&lt;br /&gt;
&lt;br /&gt;
==Frequency tables==&lt;br /&gt;
&lt;br /&gt;
To illustrate the various aspects of Huffman compression the example text &amp;quot;She sells seashells by the sea shore.&amp;quot; will be Huffman compressed and the processes and outputs shown in various sections on this page.&lt;br /&gt;
&lt;br /&gt;
In order to compress data using Huffman compression the compressor must first build a &#039;frequency table&#039; of all the elements it wishes to compress. In most cases this will be the 256 values a single byte can take, though it need not be limited to this. (Due to the binary nature of the compression method, sets of elements that match powers of 2 are both easiest and most efficient to compress.) The data is scanned and each occurrence of a given value. Taking the letters in our example sentence we can construct the following frequency table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Char   Freq&lt;br /&gt;
 &#039;s&#039;      7&lt;br /&gt;
 &#039;e&#039;      7&lt;br /&gt;
 &#039; &#039;      6&lt;br /&gt;
 &#039;h&#039;      4&lt;br /&gt;
 &#039;l&#039;      4&lt;br /&gt;
 &#039;a&#039;      2&lt;br /&gt;
 &#039;S&#039;      1&lt;br /&gt;
 &#039;b&#039;      1&lt;br /&gt;
 &#039;o&#039;      1&lt;br /&gt;
 &#039;r&#039;      1&lt;br /&gt;
 &#039;t&#039;      1&lt;br /&gt;
 &#039;y&#039;      1&lt;br /&gt;
 &#039;.&#039;      1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Binary Tree==&lt;br /&gt;
&lt;br /&gt;
The binary tree is core to how Huffman compression compresses data. This is done by constructing a &#039;binary tree&#039;, so named because of its branching structure. Each branching point or &#039;node&#039; has two options, &#039;left&#039; and &#039;right&#039; which lead either to another node or a character. The tree is constructed so that every character can be placed upon it and every path ends in a character. &lt;br /&gt;
&lt;br /&gt;
This is done by first building a point of origin, &#039;root node&#039; and the adding further nodes from there. Using our example we can build the following binary tree simply by listing the nodes alphabetically (and using &#039;_&#039; to stand in for the space for clarity):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           [Root]&lt;br /&gt;
         ____|_______&lt;br /&gt;
       /             \&lt;br /&gt;
     __|__            |&lt;br /&gt;
    /      \        /   \&lt;br /&gt;
    |       |       |    .&lt;br /&gt;
  /   \   /   \   /   \&lt;br /&gt;
  |   |   |   |   |   |&lt;br /&gt;
 / \ / \ / \ / \ / \ / \&lt;br /&gt;
 _ S a b e h l o r s t y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On this tree we can use &#039;L&#039; to specify a left path and &#039;R&#039; to specify a right. As such the letter &#039;a&#039; is represented by &#039;LLRL&#039; and &#039;y&#039; by &#039;RLRR&#039;. Note that since the number of different characters is not a power of two (E.g. 16) not all paths from the root to a character are the same length, one is considerably shorter. The &#039;.&#039; character is represented by simply &#039;RR&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that &#039;R&#039; and &#039;L&#039; are &#039;0&#039; and &#039;1&#039; each 8-bit character in the original text can be represented by just 4 bits on average, halving the message length. This is far from optimal however and there is a specific procedure used to construct an optimal tree for the shortest message length. To do this advantage is taken of the fact that paths can be different lengths. If one set of paths is made a bit shorter at the expense of making a smaller set of paths a bit longer then the overall message will be made shorter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Constructing an optimal tree===&lt;br /&gt;
&lt;br /&gt;
The first step in creating an optimal tree again is to create a &#039;root node&#039;. To populate its two options the compressor repeatedly divides the frequency table. This is done by starting with the most common character and seeing if it contains more occurrences than the rest of the table combined. If not then the second most common character is added and so on.&lt;br /&gt;
&lt;br /&gt;
In our example there are a total of 37 characters. Three characters make up more than half of this, &#039;s&#039;, &#039;e&#039; and &#039; &#039;. Because of the binary structure of the tree however &#039;&#039;four&#039;&#039; options are needed here so &#039;h&#039; is also included. All of these characters are placed on the left option of the root node while the remaining characters are placed on the right.&lt;br /&gt;
&lt;br /&gt;
The next step creates a new node with left and right options and repeats the process. The two most common characters of the four, &#039;s&#039; and &#039;e&#039; go to the left branch of this new node. A third node is created and, now that there are only two options, each is given a branch. The tree now looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  [Root]&lt;br /&gt;
    / \&lt;br /&gt;
    |  l, a, etc&lt;br /&gt;
   / \&lt;br /&gt;
   | _, h&lt;br /&gt;
 /  \&lt;br /&gt;
 s  e&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the character &#039;s&#039; can be represented as LLL and &#039;e&#039; as LLR.&lt;br /&gt;
&lt;br /&gt;
The compressor now moves &#039;up&#039; to the previous node which still has a branch with more than one option in it. Another node is created and, since there are only two options, one is assigned to each branch. Te compressor then returns to the root node to deal with the right half of the tree. When it has assigned very character to a node the following optimal tree is produced:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      ___[Root]____&lt;br /&gt;
     /             \&lt;br /&gt;
    _|_         ___|_______&lt;br /&gt;
   /   \       /           \&lt;br /&gt;
   |   |       |            |&lt;br /&gt;
 /  \ / \     / \          / \&lt;br /&gt;
 s  e _ h    l   |        |   |&lt;br /&gt;
                / \      / \ / \&lt;br /&gt;
               a  |      o r t |&lt;br /&gt;
                 / \          / \&lt;br /&gt;
                 S b         y  .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that 4 characters now have paths that are just 3 choices long while 4 have paths 4 choices long and 4 have paths 5 choices long. Overall the average path length is the same as our previous tree. However 24 occurrences are one choice shorter, 5 are identical,  3 are one choice longer and &#039;.&#039; is three choices longer. This gives us a compressed message that is  a total of 18 choices (or bits) shorter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Labeling the tree===&lt;br /&gt;
&lt;br /&gt;
Now that a tree has been constructed it needs to be labelled in some form so that it can be stored as data either in the decompressor or to be sent with the compressed code. There are two major issues, what system to use when assigning numbers to the various nodes, and what bit value, 0 or 1, to assign to left or right options.&lt;br /&gt;
&lt;br /&gt;
The most common (but far from unique) system is to label nodes from the &#039;bottom&#039; of the tree to the top, going left-to-right across each &#039;layer&#039; of the tree. (In our example the node that leads to &#039;S&#039; and &#039;b&#039; would thus be the first numbered node.) Nodes are usually numbered starting with 0 and ending with the root node having the highest number. Our tree would be numbered as follows using this system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      ____[11]_____&lt;br /&gt;
     /             \&lt;br /&gt;
    [9]         __[10]_____&lt;br /&gt;
   /   \       /           \&lt;br /&gt;
  [5] [6]     [7]          [8]&lt;br /&gt;
 /  \ / \     / \          / \&lt;br /&gt;
 s  e _ h    l  [2]      [3] [4]&lt;br /&gt;
                / \      / \ / \&lt;br /&gt;
               a [0]     o r t[1]&lt;br /&gt;
                 / \          / \&lt;br /&gt;
                 S b         y  .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually the left branch is given a bit value of 0 and the right branch a bit value of 1. Using this scheme &#039;s&#039; in our example resides on node 1 and is represented by the bit string &#039;000&#039; The complete compressed message in bit form is now &amp;lt;tt&amp;gt;10110 011 001 010 000 001 100 100 000 010 000 001 1010 000 011 001 100 100 000 010 10111 11110 010 1110 011 001 010 000 001 1010 010 000 011 1100 1101 001 11111&amp;lt;/tt&amp;gt; or in bytes &amp;lt;tt&amp;gt;$B3 $28 $19 $02 $06 $83 $32 $05 $7F $2E $65 $03 $48 $3C $D3 $F0&amp;lt;/tt&amp;gt; (The final byte is padded with nul bits.) This is a total of 16 bytes used for a 37 byte message.&lt;br /&gt;
&lt;br /&gt;
===Standard tree size===&lt;br /&gt;
&lt;br /&gt;
The most common implementation of Huffman compression is &#039;1 byte in, 1 bit out&#039;. This involves compressing one byte of data at a time and converting it into a bitstream. In this case the compressor expects to find 256 different possible values of data. This requires a tree with 255 nodes, including the root, and an average path length of 8 choices.&lt;br /&gt;
&lt;br /&gt;
This is not the only possibility however and Huffman can compress data in words or dwords or in more exotic manners. {{Game|Commander Keen Dreams}} for example combines Huffman with LZW compression, building a binary tree of a fixed size and filling it with the most recently encountered strings of bits.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The dictionary==&lt;br /&gt;
&lt;br /&gt;
Often the binary tree must be stored in some form, usually called a &#039;&#039;dictionary&#039;&#039;. This will either be fixed and known by both the compressor and decompressor. (Which minimizes individual message sizes but can limit compression efficiency overall.) or tailored for each message and sent with said message.&lt;br /&gt;
&lt;br /&gt;
Dictionary format is quite standard. It is merely a numerical list of nodes (however they have been labelled.) starting with node 0 and ending with the root. Each node usually taking up four bytes, two bytes per branch. Each branch will have one byte dedicated to identifying if it leads to another node or a character and the other byte identifying the node or character. Usually &#039;0&#039; identifies the option asleading to a character and &#039;1&#039; to another node, but again this can be reversed.&lt;br /&gt;
&lt;br /&gt;
Using this system, our example tree could be stored as either of the two following:&lt;br /&gt;
&lt;br /&gt;
    0S0b 0y0. 0a10 0o0r 0t11 0s0e 0_0h 0l12 1314 1516 1718 19110&lt;br /&gt;
&lt;br /&gt;
    $00 $53 $00 $62 $00 $79 $00 $2E $00 $6F $00 $72 $00 $74 $01 $01 $00 $73 $00 $65 $00 $20 $00 $68...&lt;br /&gt;
     -   S   -   b   -   y   -   .   -   o   -   r   -   t   |  n1   -   s    -  e   -   _   -   h ...&lt;br /&gt;
         (node 0)         (node 1)       (node 3)        (node 4)        (node 5)      (node 6)    ...&lt;br /&gt;
    &lt;br /&gt;
The dictionary is thus usually 1020 bytes long, containing 255 nodes of 4 bytes each, though again this can vary depending on how readable the dictionary is to humans and whether or not the dictionary itself is compressed.&lt;br /&gt;
&lt;br /&gt;
==Huffman implementation in ID Software games==&lt;br /&gt;
&lt;br /&gt;
Games created by Id Software  have a shared but distinct implementation of Huffman compression.&lt;br /&gt;
&lt;br /&gt;
In older games such as {{Game|Dangerous Dave 2}} the dictionary and data are included together in one file. First is a four-byte header,, &#039;HUFF&#039; followed by four bytes that give the decompressed size of the data (for memory purposes.). Following that is the dictionary, 1020 bytes in length then the compressed data.&lt;br /&gt;
&lt;br /&gt;
In newer games (such as [[Commander Keen 4-6]] or [[Wolfenstein 3-D]]) the data is stored in an external file which consists of a number of concatenated &#039;chunks&#039;, each chunk beginning with a dword giving its decompressed size (again for memory purposes.). These chunks are addressed by an internal or external &#039;header&#039; file consisting of a series of three (or sometimes four) byte offsets to the start of various chunks in the data file. (The end of the header is easily found as the last entry is the length of the data file.) The dictionary is 1024 bytes long and stored in the executable.&lt;br /&gt;
&lt;br /&gt;
The dictionary consists of 255 nodes (in newr games plus four null bytes of padding) and there are two or three dictionaries stored in the executable depending on the game. The end of these dictionaries can be found by looking for node 255 (number 254!) which universally consists of the string &amp;lt;tt&amp;gt;$00 $00 $FD $01&amp;lt;/tt&amp;gt; due to the fact that the byte &amp;lt;tt&amp;gt;$00&amp;lt;/tt&amp;gt; is the single most common character in game data and thus always occupies the left branch of the root node while the other branch must go to the next lowest node, number 253.&lt;br /&gt;
&lt;br /&gt;
An important but subtle difference is how data is read. While bytes are read sequentially (1, 2, 3...) bits within each byte are read in reverse order (8, 7, 6...). (Technically each byte is little endian.)&lt;br /&gt;
&lt;br /&gt;
===Trivial ID dictionary===&lt;br /&gt;
&lt;br /&gt;
The following is a complete &#039;trivial&#039; dictionary. This dictionary is constructed such that data compressed with it is not altered in any way, the output and input are the same. When used to construct a binary tree all paths are of equal length, 8 choices or bits. And the nodes are arranged in a logical order with an easily seen pattern; the first half of the tree consists of terminal nodes, the second half of branch nodes. (Of the second half the first half of &#039;&#039;that&#039;&#039; consists of branch nodes that lead to terminal nodes while the second half consists of branch nodes to two branch nodes and so on.)&lt;br /&gt;
&lt;br /&gt;
 $00 $00 $80 $00 $40 $00 $C0 $00 $20 $00 $A0 $00 $60 $00 $E0 $00&lt;br /&gt;
 $10 $00 $90 $00 $50 $00 $D0 $00 $30 $00 $B0 $00 $70 $00 $F0 $00&lt;br /&gt;
 $08 $00 $88 $00 $48 $00 $C8 $00 $28 $00 $A8 $00 $68 $00 $E8 $00&lt;br /&gt;
 $18 $00 $98 $00 $58 $00 $D8 $00 $38 $00 $B8 $00 $78 $00 $F8 $00&lt;br /&gt;
 $04 $00 $84 $00 $44 $00 $C4 $00 $24 $00 $A4 $00 $64 $00 $E4 $00&lt;br /&gt;
 $14 $00 $94 $00 $54 $00 $D4 $00 $34 $00 $B4 $00 $74 $00 $F4 $00&lt;br /&gt;
 $0C $00 $8C $00 $4C $00 $CC $00 $2C $00 $AC $00 $6C $00 $EC $00&lt;br /&gt;
 $1C $00 $9C $00 $5C $00 $DC $00 $3C $00 $BC $00 $7C $00 $FC $00&lt;br /&gt;
 $02 $00 $82 $00 $42 $00 $C2 $00 $22 $00 $A2 $00 $62 $00 $E2 $00&lt;br /&gt;
 $12 $00 $92 $00 $52 $00 $D2 $00 $32 $00 $B2 $00 $72 $00 $F2 $00&lt;br /&gt;
 $0A $00 $8A $00 $4A $00 $CA $00 $2A $00 $AA $00 $6A $00 $EA $00&lt;br /&gt;
 $1A $00 $9A $00 $5A $00 $DA $00 $3A $00 $BA $00 $7A $00 $FA $00&lt;br /&gt;
 $06 $00 $86 $00 $46 $00 $C6 $00 $26 $00 $A6 $00 $66 $00 $E6 $00&lt;br /&gt;
 $16 $00 $96 $00 $56 $00 $D6 $00 $36 $00 $B6 $00 $76 $00 $F6 $00&lt;br /&gt;
 $0E $00 $8E $00 $4E $00 $CE $00 $2E $00 $AE $00 $6E $00 $EE $00&lt;br /&gt;
 $1E $00 $9E $00 $5E $00 $DE $00 $3E $00 $BE $00 $7E $00 $FE $00&lt;br /&gt;
 $01 $00 $81 $00 $41 $00 $C1 $00 $21 $00 $A1 $00 $61 $00 $E1 $00&lt;br /&gt;
 $11 $00 $91 $00 $51 $00 $D1 $00 $31 $00 $B1 $00 $71 $00 $F1 $00&lt;br /&gt;
 $09 $00 $89 $00 $49 $00 $C9 $00 $29 $00 $A9 $00 $69 $00 $E9 $00&lt;br /&gt;
 $19 $00 $99 $00 $59 $00 $D9 $00 $39 $00 $B9 $00 $79 $00 $F9 $00&lt;br /&gt;
 $05 $00 $85 $00 $45 $00 $C5 $00 $25 $00 $A5 $00 $65 $00 $E5 $00&lt;br /&gt;
 $15 $00 $95 $00 $55 $00 $D5 $00 $35 $00 $B5 $00 $75 $00 $F5 $00&lt;br /&gt;
 $0D $00 $8D $00 $4D $00 $CD $00 $2D $00 $AD $00 $6D $00 $ED $00&lt;br /&gt;
 $1D $00 $9D $00 $5D $00 $DD $00 $3D $00 $BD $00 $7D $00 $FD $00&lt;br /&gt;
 $03 $00 $83 $00 $43 $00 $C3 $00 $23 $00 $A3 $00 $63 $00 $E3 $00&lt;br /&gt;
 $13 $00 $93 $00 $53 $00 $D3 $00 $33 $00 $B3 $00 $73 $00 $F3 $00&lt;br /&gt;
 $0B $00 $8B $00 $4B $00 $CB $00 $2B $00 $AB $00 $6B $00 $EB $00&lt;br /&gt;
 $1B $00 $9B $00 $5B $00 $DB $00 $3B $00 $BB $00 $7B $00 $FB $00&lt;br /&gt;
 $07 $00 $87 $00 $47 $00 $C7 $00 $27 $00 $A7 $00 $67 $00 $E7 $00&lt;br /&gt;
 $17 $00 $97 $00 $57 $00 $D7 $00 $37 $00 $B7 $00 $77 $00 $F7 $00&lt;br /&gt;
 $0F $00 $8F $00 $4F $00 $CF $00 $2F $00 $AF $00 $6F $00 $EF $00&lt;br /&gt;
 $1F $00 $9F $00 $5F $00 $DF $00 $3F $00 $BF $00 $7F $00 $FF $00&lt;br /&gt;
 $00 $01 $01 $01 $02 $01 $03 $01 $04 $01 $05 $01 $06 $01 $07 $01&lt;br /&gt;
 $08 $01 $09 $01 $0A $01 $0B $01 $0C $01 $0D $01 $0E $01 $0F $01&lt;br /&gt;
 $10 $01 $11 $01 $12 $01 $13 $01 $14 $01 $15 $01 $16 $01 $17 $01&lt;br /&gt;
 $18 $01 $19 $01 $1A $01 $1B $01 $1C $01 $1D $01 $1E $01 $1F $01&lt;br /&gt;
 $20 $01 $21 $01 $22 $01 $23 $01 $24 $01 $25 $01 $26 $01 $27 $01&lt;br /&gt;
 $28 $01 $29 $01 $2A $01 $2B $01 $2C $01 $2D $01 $2E $01 $2F $01&lt;br /&gt;
 $30 $01 $31 $01 $32 $01 $33 $01 $34 $01 $35 $01 $36 $01 $37 $01&lt;br /&gt;
 $38 $01 $39 $01 $3A $01 $3B $01 $3C $01 $3D $01 $3E $01 $3F $01&lt;br /&gt;
 $40 $01 $41 $01 $42 $01 $43 $01 $44 $01 $45 $01 $46 $01 $47 $01&lt;br /&gt;
 $48 $01 $49 $01 $4A $01 $4B $01 $4C $01 $4D $01 $4E $01 $4F $01&lt;br /&gt;
 $50 $01 $51 $01 $52 $01 $53 $01 $54 $01 $55 $01 $56 $01 $57 $01&lt;br /&gt;
 $58 $01 $59 $01 $5A $01 $5B $01 $5C $01 $5D $01 $5E $01 $5F $01&lt;br /&gt;
 $60 $01 $61 $01 $62 $01 $63 $01 $64 $01 $65 $01 $66 $01 $67 $01&lt;br /&gt;
 $68 $01 $69 $01 $6A $01 $6B $01 $6C $01 $6D $01 $6E $01 $6F $01&lt;br /&gt;
 $70 $01 $71 $01 $72 $01 $73 $01 $74 $01 $75 $01 $76 $01 $77 $01&lt;br /&gt;
 $78 $01 $79 $01 $7A $01 $7B $01 $7C $01 $7D $01 $7E $01 $7F $01&lt;br /&gt;
 $80 $01 $81 $01 $82 $01 $83 $01 $84 $01 $85 $01 $86 $01 $87 $01&lt;br /&gt;
 $88 $01 $89 $01 $8A $01 $8B $01 $8C $01 $8D $01 $8E $01 $8F $01&lt;br /&gt;
 $90 $01 $91 $01 $92 $01 $93 $01 $94 $01 $95 $01 $96 $01 $97 $01&lt;br /&gt;
 $98 $01 $99 $01 $9A $01 $9B $01 $9C $01 $9D $01 $9E $01 $9F $01&lt;br /&gt;
 $A0 $01 $A1 $01 $A2 $01 $A3 $01 $A4 $01 $A5 $01 $A6 $01 $A7 $01&lt;br /&gt;
 $A8 $01 $A9 $01 $AA $01 $AB $01 $AC $01 $AD $01 $AE $01 $AF $01&lt;br /&gt;
 $B0 $01 $B1 $01 $B2 $01 $B3 $01 $B4 $01 $B5 $01 $B6 $01 $B7 $01&lt;br /&gt;
 $B8 $01 $B9 $01 $BA $01 $BB $01 $BC $01 $BD $01 $BE $01 $BF $01&lt;br /&gt;
 $C0 $01 $C1 $01 $C2 $01 $C3 $01 $C4 $01 $C5 $01 $C6 $01 $C7 $01&lt;br /&gt;
 $C8 $01 $C9 $01 $CA $01 $CB $01 $CC $01 $CD $01 $CE $01 $CF $01&lt;br /&gt;
 $D0 $01 $D1 $01 $D2 $01 $D3 $01 $D4 $01 $D5 $01 $D6 $01 $D7 $01&lt;br /&gt;
 $D8 $01 $D9 $01 $DA $01 $DB $01 $DC $01 $DD $01 $DE $01 $DF $01&lt;br /&gt;
 $E0 $01 $E1 $01 $E2 $01 $E3 $01 $E4 $01 $E5 $01 $E6 $01 $E7 $01&lt;br /&gt;
 $E8 $01 $E9 $01 $EA $01 $EB $01 $EC $01 $ED $01 $EE $01 $EF $01&lt;br /&gt;
 $F0 $01 $F1 $01 $F2 $01 $F3 $01 $F4 $01 $F5 $01 $F6 $01 $F7 $01&lt;br /&gt;
 $F8 $01 $F9 $01 $FA $01 $FB $01 $FC $01 $FD $01&lt;br /&gt;
&lt;br /&gt;
Using this example we can see the unusual manner in which ID games read bits within bytes. As an example consider the character $80; in binary this is &#039;10000000&#039; However, following this path using the dictionary given above will output the character $01 (00000001). Instead the bits must be read in reverse order. Doing so will lead to the following nodes starting at the root node: 254(root) -&amp;gt; 252 -&amp;gt; 248 -&amp;gt; 240 -&amp;gt; 224 -&amp;gt; 192 -&amp;gt; 128 -&amp;gt; 0(terminal node for characters $00 and $80)&lt;br /&gt;
&lt;br /&gt;
== Source code ==&lt;br /&gt;
&lt;br /&gt;
Some example code is available in various languages showing how to decompress (and in some cases compress) files using the Huffman algorithm.&lt;br /&gt;
&lt;br /&gt;
=== QuickBasic ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; DANGEROUS DAVE 2 - IN THE HAUNTED MANSION - Huffman Decompressor&lt;br /&gt;
&#039;  - by Napalm with thanks to Adurdin&#039;s work on ModKeen&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; This source is Public Domain, please credit me if you use it.&lt;br /&gt;
&#039;&lt;br /&gt;
&#039;&lt;br /&gt;
DECLARE SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING)&lt;br /&gt;
&lt;br /&gt;
TYPE NODE&lt;br /&gt;
        BIT0 AS INTEGER&lt;br /&gt;
        BIT1 AS INTEGER&lt;br /&gt;
END TYPE&lt;br /&gt;
&lt;br /&gt;
&#039; Input filename, output filename&lt;br /&gt;
HUFFDECOMPRESS &amp;quot;TITLE1.DD2&amp;quot;, &amp;quot;TITLE1.PIC&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING) &#039; by Napalm&lt;br /&gt;
	DIM INFILE AS INTEGER, OUTFILE AS INTEGER, I AS INTEGER&lt;br /&gt;
	DIM SIG AS LONG, OUTLEN AS LONG, BITMASK AS INTEGER&lt;br /&gt;
	DIM CURNODE AS INTEGER, NEXTNODE AS INTEGER&lt;br /&gt;
	DIM CHRIN AS STRING * 1, CHROUT AS STRING * 1&lt;br /&gt;
	DIM NODES(0 TO 254) AS NODE&lt;br /&gt;
&lt;br /&gt;
	&#039; Open input file&lt;br /&gt;
	INFILE = FREEFILE&lt;br /&gt;
	OPEN INNAME FOR BINARY ACCESS READ AS INFILE&lt;br /&gt;
       &lt;br /&gt;
	&#039; Check file signature&lt;br /&gt;
	GET INFILE, , SIG&lt;br /&gt;
	IF SIG &amp;lt;&amp;gt; &amp;amp;H46465548 THEN &#039; Hex for: HUFF in little endian&lt;br /&gt;
		PRINT &amp;quot;INVALID FILE!&amp;quot;&lt;br /&gt;
		EXIT SUB&lt;br /&gt;
	END IF&lt;br /&gt;
       &lt;br /&gt;
	&#039; Get output length&lt;br /&gt;
	OUTLEN = 0&lt;br /&gt;
	GET INFILE, , OUTLEN&lt;br /&gt;
       &lt;br /&gt;
	&#039; Read in the Huffman binary tree&lt;br /&gt;
	FOR I = 0 TO 254&lt;br /&gt;
		GET INFILE, , NODES(I).BIT0&lt;br /&gt;
		GET INFILE, , NODES(I).BIT1&lt;br /&gt;
	NEXT I&lt;br /&gt;
&lt;br /&gt;
	&#039; Open output file&lt;br /&gt;
	OUTFILE = FREEFILE&lt;br /&gt;
	OPEN OUTNAME FOR BINARY ACCESS WRITE AS OUTFILE&lt;br /&gt;
&lt;br /&gt;
	&#039; Decompress input data using binary tree&lt;br /&gt;
	CURNODE = 254&lt;br /&gt;
	DO&lt;br /&gt;
		BITMASK = 0&lt;br /&gt;
		GET INFILE, , CHRIN&lt;br /&gt;
		DO&lt;br /&gt;
			&#039; Decide which node to travel down depending on&lt;br /&gt;
			&#039;   input bits from CHRIN.&lt;br /&gt;
			IF ASC(CHRIN) AND 2 ^ BITMASK THEN&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT1&lt;br /&gt;
			ELSE&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT0&lt;br /&gt;
			END IF&lt;br /&gt;
		       &lt;br /&gt;
			&#039; Is this next node another part of the tree or&lt;br /&gt;
			&#039;   is it a end node? Less than 256 mean end node.&lt;br /&gt;
			IF NEXTNODE &amp;lt; 256 THEN&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Get output char from end node and save.&lt;br /&gt;
				CHROUT = CHR$(NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
				PUT OUTFILE, , CHROUT&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Amend output length and start from top of&lt;br /&gt;
				&#039;   binary tree.&lt;br /&gt;
				OUTLEN = OUTLEN - 1&lt;br /&gt;
				CURNODE = 254&lt;br /&gt;
&lt;br /&gt;
			ELSE&lt;br /&gt;
				&#039; Travel to next node&lt;br /&gt;
				CURNODE = (NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
&lt;br /&gt;
			END IF&lt;br /&gt;
&lt;br /&gt;
			&#039; Move to next input bit&lt;br /&gt;
			BITMASK = BITMASK + 1&lt;br /&gt;
		LOOP WHILE BITMASK &amp;lt; 8 AND OUTLEN &amp;gt; 0&lt;br /&gt;
		&#039; Loop while we still need to output data&lt;br /&gt;
	LOOP WHILE OUTLEN &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
	&#039; Clean up&lt;br /&gt;
	CLOSE OUTFILE&lt;br /&gt;
	CLOSE INFILE&lt;br /&gt;
&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
SUB MAKHUF &#039;Mak a degenerate huffman tree, store as string huffq&lt;br /&gt;
	OPEN &amp;quot;HUFF.DD2&amp;quot; FOR BINARY AS #8&lt;br /&gt;
	aq = &amp;quot;HUFF&amp;quot;&lt;br /&gt;
	PUT #8, 1, aq&lt;br /&gt;
	x = 9&lt;br /&gt;
	FOR t = 0 TO 255&lt;br /&gt;
		b = t&lt;br /&gt;
		va = 0&lt;br /&gt;
		vb = 0&lt;br /&gt;
		vc = 0&lt;br /&gt;
		vd = 0&lt;br /&gt;
		ve = 0&lt;br /&gt;
		vf = 0&lt;br /&gt;
		vg = 0&lt;br /&gt;
		vh = 0&lt;br /&gt;
		IF b &amp;gt; 127 THEN LET va = va + 1&lt;br /&gt;
		b = b MOD 128&lt;br /&gt;
		IF b &amp;gt; 63 THEN LET vb = vb + 1&lt;br /&gt;
		b = b MOD 64&lt;br /&gt;
		IF b &amp;gt; 31 THEN LET vc = vc + 1&lt;br /&gt;
		b = b MOD 32&lt;br /&gt;
		IF b &amp;gt; 15 THEN LET vd = vd + 1&lt;br /&gt;
		b = b MOD 16&lt;br /&gt;
		IF b &amp;gt; 7 THEN LET ve = ve + 1&lt;br /&gt;
		b = b MOD 8&lt;br /&gt;
		IF b &amp;gt; 3 THEN LET vf = vf + 1&lt;br /&gt;
		b = b MOD 4&lt;br /&gt;
		IF b &amp;gt; 1 THEN LET vg = vg + 1&lt;br /&gt;
		b = b MOD 2&lt;br /&gt;
		IF b = 1 THEN LET vh = vh + 1&lt;br /&gt;
		b = (vh * 128) + (vg * 64) + (vf * 32) + (16 * ve) + (8 * vd) + (4 * vc) + (2 * vb) + va&lt;br /&gt;
		aq = MKI$(b)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	FOR t = 0 TO 253&lt;br /&gt;
		aq = MKI$(t + 256)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	GET #8, 1, huffq&lt;br /&gt;
	CLOSE #8&lt;br /&gt;
	KILL &amp;quot;HUFF.DD2&amp;quot;&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Visual Basic .NET ===&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree representation ====&lt;br /&gt;
&lt;br /&gt;
This class, BinaryTreeNode, represents a binary tree whose branch nodes carry no value, like a Huffman dictionary tree.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;Public Class BinaryTreeNode(Of T)&lt;br /&gt;
    &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
    Private Branch As Boolean&lt;br /&gt;
    Private Children As BinaryTreeNode(Of T)()&lt;br /&gt;
    Private HoldValue As T&lt;br /&gt;
    Public Sub New(LeafValue As T)&lt;br /&gt;
        Branch = False&lt;br /&gt;
        HoldValue = LeafValue&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public Sub New(LeftChild As BinaryTreeNode(Of T), RightChild As BinaryTreeNode(Of T))&lt;br /&gt;
        Branch = True&lt;br /&gt;
        Children = {LeftChild, RightChild}&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public ReadOnly Property HasValue As Boolean&lt;br /&gt;
        Get&lt;br /&gt;
            Return Not Branch&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Value As T&lt;br /&gt;
        Get&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return HoldValue&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As T)&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            HoldValue = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Child(Side As ChildSide) As BinaryTreeNode(Of T)&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return Children(Side)&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As BinaryTreeNode(Of T))&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Children(Side) = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Enum ChildSide As Byte&lt;br /&gt;
        Left = 0&lt;br /&gt;
        Right = 1&lt;br /&gt;
    End Enum&lt;br /&gt;
    Public ReadOnly Property Count As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Children(0).Count + Children(1).Count&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public ReadOnly Property Depth As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Math.Max(Children(0).Depth, Children(1).Depth) + 1&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Overrides Function ToString() As String&lt;br /&gt;
        Return &amp;quot;{Count = &amp;quot; &amp;amp; Count &amp;amp; &amp;quot;, Depth = &amp;quot; &amp;amp; Depth &amp;amp; &amp;quot;}&amp;quot;&lt;br /&gt;
    End Function&lt;br /&gt;
End Class&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree reading ====&lt;br /&gt;
&lt;br /&gt;
This piece of code will read in a stored Huffman dictionary in the format described at the top of this article and store it in a BinaryTreeNode(Of Byte) as shown above.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;        &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
        Dim fDict As New IO.FileStream(DictionaryFile, IO.FileMode.Open)&lt;br /&gt;
        Dim raw(254) As Tuple(Of UShort, UShort)&lt;br /&gt;
        For x = 0 To 254&lt;br /&gt;
            raw(x) = Tuple.Create(ReadUShort(fDict), ReadUShort(fDict))&lt;br /&gt;
        Next&lt;br /&gt;
        fDict.Close()&lt;br /&gt;
        Dim GenerateTree As Func(Of UShort, BinaryTreeNode(Of Byte))&lt;br /&gt;
        GenerateTree = Function(NextNode As UShort) As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           Dim n As Tuple(Of UShort, UShort) = raw(NextNode)&lt;br /&gt;
                           Dim a, b As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           If n.Item1 &amp;lt; 256 Then&lt;br /&gt;
                               a = New BinaryTreeNode(Of Byte)(n.Item1)&lt;br /&gt;
                           Else&lt;br /&gt;
                               a = GenerateTree(n.Item1 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           If n.Item2 &amp;lt; 256 Then&lt;br /&gt;
                               b = New BinaryTreeNode(Of Byte)(n.Item2)&lt;br /&gt;
                           Else&lt;br /&gt;
                               b = GenerateTree(n.Item2 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           Return New BinaryTreeNode(Of Byte)(a, b)&lt;br /&gt;
                       End Function&lt;br /&gt;
        Dim dict As BinaryTreeNode(Of Byte) = GenerateTree(254)&lt;br /&gt;
        fDict.Close()&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Code examples]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6847</id>
		<title>Huffman Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6847"/>
		<updated>2016-05-24T09:32:37Z</updated>

		<summary type="html">&lt;p&gt;Levellass: More rewrite&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-byte in, 1-bit out&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|The Blues Brothers}}&lt;br /&gt;
   {{Game|Catacomb 3-D}}&lt;br /&gt;
   {{Game|Commander Keen Dreams}}&lt;br /&gt;
   {{Game|Dangerous Dave 2}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Huffman Compression]] is a compression algorithm used in many classic games. It is about as efficient as LZW or RLE compression, with many games using the three formats simultaneously.&lt;br /&gt;
&lt;br /&gt;
Huffman compression involves making/reading a &#039;&#039;dictionary&#039;&#039; of 256 entries, one for each possible 1-byte character.  This is organised in the form of a &#039;&#039;binary tree&#039;&#039; which is basically formed by taking the two lowest frequency characters and combining them into a new entry with their added frequencies and repeating until all entries are reduced to one &#039;&#039;root node&#039;&#039;.  After the dictionary is created, every character of data is replaced with the corresponding bit representation from the tree.&lt;br /&gt;
&lt;br /&gt;
Any Huffman compressed data will thus be associated with a dictionary file (internal or external) used to decompress it. This page will explain the various aspects of Huffman compression using the example text &amp;quot;She sells seashells by the sea shore.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Frequency tables==&lt;br /&gt;
&lt;br /&gt;
In order to compress data using Huffman compression the compressor must build a &#039;frequency table&#039; of all the elements it wishes to compress. In most cases this will be the 256 values a single byte can take, though it need not be limited to this. (Due to the binary nature of the compression method, sets of elements that match powers of 2 are both easiest and most efficient to compress.) The data is scanned and each occurrence of a given value. Taking the letters in our example sentence we can construct the following frequency table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Char   Freq&lt;br /&gt;
 &#039;s&#039;      7&lt;br /&gt;
 &#039;e&#039;      7&lt;br /&gt;
 &#039; &#039;      6&lt;br /&gt;
 &#039;h&#039;      4&lt;br /&gt;
 &#039;l&#039;      4&lt;br /&gt;
 &#039;a&#039;      2&lt;br /&gt;
 &#039;S&#039;      1&lt;br /&gt;
 &#039;b&#039;      1&lt;br /&gt;
 &#039;o&#039;      1&lt;br /&gt;
 &#039;r&#039;      1&lt;br /&gt;
 &#039;t&#039;      1&lt;br /&gt;
 &#039;y&#039;      1&lt;br /&gt;
 &#039;.&#039;      1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Binary Tree==&lt;br /&gt;
&lt;br /&gt;
The binary tree is core to how Huffman compression compresses data. This is done by constructing a &#039;binary tree&#039;, so named because of its branching structure. Each branching point or &#039;node&#039; has two options, &#039;left&#039; and &#039;right&#039; which lead either to another node or a character. The tree is constructed so that every character can be placed upon it and every path ends in a character. &lt;br /&gt;
&lt;br /&gt;
This is done by first building a point of origin, &#039;root node&#039; and the adding further nodes from there. Using our example we can build the following binary tree simply by listing the nodes alphabetically (and using &#039;_&#039; to stand in for the space for clarity):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           [Root]&lt;br /&gt;
         ____|_______&lt;br /&gt;
       /             \&lt;br /&gt;
     __|__            |&lt;br /&gt;
    /      \        /   \&lt;br /&gt;
    |       |       |    .&lt;br /&gt;
  /   \   /   \   /   \&lt;br /&gt;
  |   |   |   |   |   |&lt;br /&gt;
 / \ / \ / \ / \ / \ / \&lt;br /&gt;
 _ S a b e h l o r s t y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On this tree we can use &#039;L&#039; to specify a left path and &#039;R&#039; to specify a right. As such the letter &#039;a&#039; is represented by &#039;LLRL&#039; and &#039;y&#039; by &#039;RLRR&#039;. Note that since the number of different characters is not a power of two (E.g. 16) not all paths from the root to a character are the same length, one is considerably shorter. The &#039;.&#039; character is represented by simply &#039;RR&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that &#039;R&#039; and &#039;L&#039; are &#039;0&#039; and &#039;1&#039; each 8-bit character in the original text can be represented by just 4 bits on average, halving the message length. This is far from optimal however and there is a specific procedure used to construct an optimal tree for the shortest message length. To do this advantage is taken of the fact that paths can be different lengths. If one set of paths is made a bit shorter at the expense of making a smaller set of paths a bit longer then the overall message will be made shorter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Constructing an optimal tree===&lt;br /&gt;
&lt;br /&gt;
The first step in creating an optimal tree again is to create a &#039;root node&#039;. To populate its two options the compressor repeatedly divides the frequency table. This is done by starting with the most common character and seeing if it contains more occurrences than the rest of the table combined. If not then the second most common character is added and so on.&lt;br /&gt;
&lt;br /&gt;
In our example there are a total of 37 characters. Three characters make up more than half of this, &#039;s&#039;, &#039;e&#039; and &#039; &#039;. Because of the binary structure of the tree however &#039;&#039;four&#039;&#039; options are needed here so &#039;h&#039; is also included. All of these characters are placed on the left option of the root node while the remaining characters are placed on the right.&lt;br /&gt;
&lt;br /&gt;
The next step creates a new node with left and right options and repeats the process. The two most common characters of the four, &#039;s&#039; and &#039;e&#039; go to the left branch of this new node. A third node is created and, now that there are only two options, each is given a branch. The tree now looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  [Root]&lt;br /&gt;
    / \&lt;br /&gt;
    |  l, a, etc&lt;br /&gt;
   / \&lt;br /&gt;
   | _, h&lt;br /&gt;
 /  \&lt;br /&gt;
 s  e&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the character &#039;s&#039; can be represented as LLL and &#039;e&#039; as LLR.&lt;br /&gt;
&lt;br /&gt;
The compressor now moves &#039;up&#039; to the previous node which still has a branch with more than one option in it. Another node is created and, since there are only two options, one is assigned to each branch. Te compressor then returns to the root node to deal with the right half of the tree. When it has assigned very character to a node the following optimal tree is produced:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      ___[Root]____&lt;br /&gt;
     /             \&lt;br /&gt;
    _|_         ___|_______&lt;br /&gt;
   /   \       /           \&lt;br /&gt;
   |   |       |            |&lt;br /&gt;
 /  \ / \     / \          / \&lt;br /&gt;
 s  e _ h    l   |        |   |&lt;br /&gt;
                / \      / \ / \&lt;br /&gt;
               a  |      o r t |&lt;br /&gt;
                 / \          / \&lt;br /&gt;
                 S b         y  .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that 4 characters now have paths that are just 3 choices long while 4 have paths 4 choices long and 4 have paths 5 choices long. Overall the average path length is the same as our previous tree. However 24 occurrences are one choice shorter, 5 are identical,  3 are one choice longer and &#039;.&#039; is three choices longer. This gives us a compressed message that is  a total of 18 choices (or bits) shorter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Labeling the tree===&lt;br /&gt;
&lt;br /&gt;
Now that a tree has been constructed it needs to be labelled in some form so that it can be stored as data either in the decompressor or to be sent with the compressed code. There are two major issues, what system to use when assigning numbers to the various nodes, and what bit value, 0 or 1, to assign to left or right options.&lt;br /&gt;
&lt;br /&gt;
The most common (but far from unique) system is to label nodes from the &#039;bottom&#039; of the tree to the top, going left-to-right across each &#039;layer&#039; of the tree. (In our example the node that leads to &#039;S&#039; and &#039;b&#039; would thus be the first numbered node.) Nodes are usually numbered starting with 0 and ending with the root node having the highest number. Our tree would be numbered as follows using this system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      ____[11]_____&lt;br /&gt;
     /             \&lt;br /&gt;
    [9]         __[10]_____&lt;br /&gt;
   /   \       /           \&lt;br /&gt;
  [5] [6]     [7]          [8]&lt;br /&gt;
 /  \ / \     / \          / \&lt;br /&gt;
 s  e _ h    l  [2]      [3] [4]&lt;br /&gt;
                / \      / \ / \&lt;br /&gt;
               a [0]     o r t[1]&lt;br /&gt;
                 / \          / \&lt;br /&gt;
                 S b         y  .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually the left branch is given a bit value of 0 and the right branch a bit value of 1. Using this scheme &#039;s&#039; in our example resides on node 1 and is represented by the bit string &#039;000&#039; The complete compressed message in bit form is now &amp;lt;tt&amp;gt;10110 011 001 010 000 001 100 100 000 010 000 001 1010 000 011 001 100 100 000 010 10111 11110 010 1110 011 001 010 000 001 1010 010 000 011 1100 1101 001 11111&amp;lt;/tt&amp;gt; or in bytes &amp;lt;tt&amp;gt;$B3 $28 $19 $02 $06 $83 $32 $05 $7F $2E $65 $03 $48 $3C $D3 $F0&amp;lt;/tt&amp;gt; (The final byte is padded with nul bits.) This is a total of 16 bytes used for a 37 byte message.&lt;br /&gt;
&lt;br /&gt;
===Standard tree size===&lt;br /&gt;
&lt;br /&gt;
The most common implementation of Huffman compression is &#039;1 byte in, 1 bit out&#039;. This involves compressing one byte of data at a time and converting it into a bitstream. In this case the compressor expects to find 256 different possible values of data. This requires a tree with 255 nodes, including the root, and an average path length of 8 choices.&lt;br /&gt;
&lt;br /&gt;
This is not the only possibility however and Huffman can compress data in words or dwords or in more exotic manners. {{Game|Commander Keen Dreams}} for example combines Huffman with LZW compression, building a binary tree of a fixed size and filling it with the most recently encountered strings of bits.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The dictionary==&lt;br /&gt;
&lt;br /&gt;
Often the binary tree must be stored in some form, usually called a &#039;&#039;dictionary&#039;&#039;. This will either be fixed and known by both the compressor and decompressor. (Which minimizes individual message sizes but can limit compression efficiency overall.) or tailored for each message and sent with said message.&lt;br /&gt;
&lt;br /&gt;
Dictionary format is quite standard. It is merely a numerical list of nodes (however they have been labelled.) starting with node 0 and ending with the root. Each node usually taking up four bytes, two bytes per branch. Each branch will have one byte dedicated to identifying if it leads to another node or a character and the other byte identifying the node or character. Usually &#039;0&#039; identifies the option asleading to a character and &#039;1&#039; to another node, but again this can be reversed.&lt;br /&gt;
&lt;br /&gt;
Using this system, our example tree could be stored as either of the two following:&lt;br /&gt;
&lt;br /&gt;
    0S0b 0y0. 0a10 0o0r 0t11 0s0e 0_0h 0l12 1314 1516 1718 19110&lt;br /&gt;
&lt;br /&gt;
    $00 $53 $00 $62 $00 $79 $00 $2E $00 $6F $00 $72 $00 $74 $01 $01 $00 $73 $00 $65 $00 $20 $00 $68...&lt;br /&gt;
     -   S   -   b   -   y   -   .   -   o   -   r   -   t   |  n1   -   s    -  e   -   _   -   h ...&lt;br /&gt;
         (node 0)         (node 1)       (node 3)        (node 4)        (node 5)      (node 6)    ...&lt;br /&gt;
    &lt;br /&gt;
The dictionary is thus usually 1020 bytes long, containing 255 nodes of 4 bytes each, though again this can vary depending on how readable the dictionary is to humans and whether or not the dictionary itself is compressed.&lt;br /&gt;
&lt;br /&gt;
==Huffman implementation in ID Software games==&lt;br /&gt;
&lt;br /&gt;
Games created by Id Software  have a shared but distinct implementation of Huffman compression.&lt;br /&gt;
&lt;br /&gt;
In older games such as {{Game|Dangerous Dave 2}} the dictionary and data are included together in one file. First is a four-byte header,, &#039;HUFF&#039; followed by four bytes that give the decompressed size of the data (for memory purposes.). Following that is the dictionary, 1020 bytes in length then the compressed data.&lt;br /&gt;
&lt;br /&gt;
In newer games (such as [[Commander Keen 4-6]] or [[Wolfenstein 3-D]]) the data is stored in an external file which consists of a number of concatenated &#039;chunks&#039;, each chunk beginning with a dword giving its decompressed size (again for memory purposes.). These chunks are addressed by an internal or external &#039;header&#039; file consisting of a series of three (or sometimes four) byte offsets to the start of various chunks in the data file. (The end of the header is easily found as the last entry is the length of the data file.) The dictionary is 1024 bytes long and stored in the executable.&lt;br /&gt;
&lt;br /&gt;
The dictionary consists of 254 nodes (in newr games plus four null bytes of padding) and there are two or three dictionaries stored in the executable depending on the game. The end of these dictionaries can be found by looking for node 254 which universally consists of the string &amp;lt;tt&amp;gt;$00 $00 $FD $01&amp;lt;/tt&amp;gt; due to the fact that the byte &amp;lt;tt&amp;gt;$00&amp;lt;/tt&amp;gt; is the single most common character in game data and thus always occupies the left branch of the root node.&lt;br /&gt;
&lt;br /&gt;
The data itself is read byte-by-byte in the normal fashion &#039;&#039;but with the order of bits in every byte being reversed&#039;&#039;. The following 1020 bytes constitute the complete &#039;trivial&#039; Huffman dictionary for this implementation, that is, one that does not compress the data at all:&lt;br /&gt;
&lt;br /&gt;
 $00 $00 $80 $00 $40 $00 $C0 $00 $20 $00 $A0 $00 $60 $00 $E0 $00&lt;br /&gt;
 $10 $00 $90 $00 $50 $00 $D0 $00 $30 $00 $B0 $00 $70 $00 $F0 $00&lt;br /&gt;
 $08 $00 $88 $00 $48 $00 $C8 $00 $28 $00 $A8 $00 $68 $00 $E8 $00&lt;br /&gt;
 $18 $00 $98 $00 $58 $00 $D8 $00 $38 $00 $B8 $00 $78 $00 $F8 $00&lt;br /&gt;
 $04 $00 $84 $00 $44 $00 $C4 $00 $24 $00 $A4 $00 $64 $00 $E4 $00&lt;br /&gt;
 $14 $00 $94 $00 $54 $00 $D4 $00 $34 $00 $B4 $00 $74 $00 $F4 $00&lt;br /&gt;
 $0C $00 $8C $00 $4C $00 $CC $00 $2C $00 $AC $00 $6C $00 $EC $00&lt;br /&gt;
 $1C $00 $9C $00 $5C $00 $DC $00 $3C $00 $BC $00 $7C $00 $FC $00&lt;br /&gt;
 $02 $00 $82 $00 $42 $00 $C2 $00 $22 $00 $A2 $00 $62 $00 $E2 $00&lt;br /&gt;
 $12 $00 $92 $00 $52 $00 $D2 $00 $32 $00 $B2 $00 $72 $00 $F2 $00&lt;br /&gt;
 $0A $00 $8A $00 $4A $00 $CA $00 $2A $00 $AA $00 $6A $00 $EA $00&lt;br /&gt;
 $1A $00 $9A $00 $5A $00 $DA $00 $3A $00 $BA $00 $7A $00 $FA $00&lt;br /&gt;
 $06 $00 $86 $00 $46 $00 $C6 $00 $26 $00 $A6 $00 $66 $00 $E6 $00&lt;br /&gt;
 $16 $00 $96 $00 $56 $00 $D6 $00 $36 $00 $B6 $00 $76 $00 $F6 $00&lt;br /&gt;
 $0E $00 $8E $00 $4E $00 $CE $00 $2E $00 $AE $00 $6E $00 $EE $00&lt;br /&gt;
 $1E $00 $9E $00 $5E $00 $DE $00 $3E $00 $BE $00 $7E $00 $FE $00&lt;br /&gt;
 $01 $00 $81 $00 $41 $00 $C1 $00 $21 $00 $A1 $00 $61 $00 $E1 $00&lt;br /&gt;
 $11 $00 $91 $00 $51 $00 $D1 $00 $31 $00 $B1 $00 $71 $00 $F1 $00&lt;br /&gt;
 $09 $00 $89 $00 $49 $00 $C9 $00 $29 $00 $A9 $00 $69 $00 $E9 $00&lt;br /&gt;
 $19 $00 $99 $00 $59 $00 $D9 $00 $39 $00 $B9 $00 $79 $00 $F9 $00&lt;br /&gt;
 $05 $00 $85 $00 $45 $00 $C5 $00 $25 $00 $A5 $00 $65 $00 $E5 $00&lt;br /&gt;
 $15 $00 $95 $00 $55 $00 $D5 $00 $35 $00 $B5 $00 $75 $00 $F5 $00&lt;br /&gt;
 $0D $00 $8D $00 $4D $00 $CD $00 $2D $00 $AD $00 $6D $00 $ED $00&lt;br /&gt;
 $1D $00 $9D $00 $5D $00 $DD $00 $3D $00 $BD $00 $7D $00 $FD $00&lt;br /&gt;
 $03 $00 $83 $00 $43 $00 $C3 $00 $23 $00 $A3 $00 $63 $00 $E3 $00&lt;br /&gt;
 $13 $00 $93 $00 $53 $00 $D3 $00 $33 $00 $B3 $00 $73 $00 $F3 $00&lt;br /&gt;
 $0B $00 $8B $00 $4B $00 $CB $00 $2B $00 $AB $00 $6B $00 $EB $00&lt;br /&gt;
 $1B $00 $9B $00 $5B $00 $DB $00 $3B $00 $BB $00 $7B $00 $FB $00&lt;br /&gt;
 $07 $00 $87 $00 $47 $00 $C7 $00 $27 $00 $A7 $00 $67 $00 $E7 $00&lt;br /&gt;
 $17 $00 $97 $00 $57 $00 $D7 $00 $37 $00 $B7 $00 $77 $00 $F7 $00&lt;br /&gt;
 $0F $00 $8F $00 $4F $00 $CF $00 $2F $00 $AF $00 $6F $00 $EF $00&lt;br /&gt;
 $1F $00 $9F $00 $5F $00 $DF $00 $3F $00 $BF $00 $7F $00 $FF $00&lt;br /&gt;
 $00 $01 $01 $01 $02 $01 $03 $01 $04 $01 $05 $01 $06 $01 $07 $01&lt;br /&gt;
 $08 $01 $09 $01 $0A $01 $0B $01 $0C $01 $0D $01 $0E $01 $0F $01&lt;br /&gt;
 $10 $01 $11 $01 $12 $01 $13 $01 $14 $01 $15 $01 $16 $01 $17 $01&lt;br /&gt;
 $18 $01 $19 $01 $1A $01 $1B $01 $1C $01 $1D $01 $1E $01 $1F $01&lt;br /&gt;
 $20 $01 $21 $01 $22 $01 $23 $01 $24 $01 $25 $01 $26 $01 $27 $01&lt;br /&gt;
 $28 $01 $29 $01 $2A $01 $2B $01 $2C $01 $2D $01 $2E $01 $2F $01&lt;br /&gt;
 $30 $01 $31 $01 $32 $01 $33 $01 $34 $01 $35 $01 $36 $01 $37 $01&lt;br /&gt;
 $38 $01 $39 $01 $3A $01 $3B $01 $3C $01 $3D $01 $3E $01 $3F $01&lt;br /&gt;
 $40 $01 $41 $01 $42 $01 $43 $01 $44 $01 $45 $01 $46 $01 $47 $01&lt;br /&gt;
 $48 $01 $49 $01 $4A $01 $4B $01 $4C $01 $4D $01 $4E $01 $4F $01&lt;br /&gt;
 $50 $01 $51 $01 $52 $01 $53 $01 $54 $01 $55 $01 $56 $01 $57 $01&lt;br /&gt;
 $58 $01 $59 $01 $5A $01 $5B $01 $5C $01 $5D $01 $5E $01 $5F $01&lt;br /&gt;
 $60 $01 $61 $01 $62 $01 $63 $01 $64 $01 $65 $01 $66 $01 $67 $01&lt;br /&gt;
 $68 $01 $69 $01 $6A $01 $6B $01 $6C $01 $6D $01 $6E $01 $6F $01&lt;br /&gt;
 $70 $01 $71 $01 $72 $01 $73 $01 $74 $01 $75 $01 $76 $01 $77 $01&lt;br /&gt;
 $78 $01 $79 $01 $7A $01 $7B $01 $7C $01 $7D $01 $7E $01 $7F $01&lt;br /&gt;
 $80 $01 $81 $01 $82 $01 $83 $01 $84 $01 $85 $01 $86 $01 $87 $01&lt;br /&gt;
 $88 $01 $89 $01 $8A $01 $8B $01 $8C $01 $8D $01 $8E $01 $8F $01&lt;br /&gt;
 $90 $01 $91 $01 $92 $01 $93 $01 $94 $01 $95 $01 $96 $01 $97 $01&lt;br /&gt;
 $98 $01 $99 $01 $9A $01 $9B $01 $9C $01 $9D $01 $9E $01 $9F $01&lt;br /&gt;
 $A0 $01 $A1 $01 $A2 $01 $A3 $01 $A4 $01 $A5 $01 $A6 $01 $A7 $01&lt;br /&gt;
 $A8 $01 $A9 $01 $AA $01 $AB $01 $AC $01 $AD $01 $AE $01 $AF $01&lt;br /&gt;
 $B0 $01 $B1 $01 $B2 $01 $B3 $01 $B4 $01 $B5 $01 $B6 $01 $B7 $01&lt;br /&gt;
 $B8 $01 $B9 $01 $BA $01 $BB $01 $BC $01 $BD $01 $BE $01 $BF $01&lt;br /&gt;
 $C0 $01 $C1 $01 $C2 $01 $C3 $01 $C4 $01 $C5 $01 $C6 $01 $C7 $01&lt;br /&gt;
 $C8 $01 $C9 $01 $CA $01 $CB $01 $CC $01 $CD $01 $CE $01 $CF $01&lt;br /&gt;
 $D0 $01 $D1 $01 $D2 $01 $D3 $01 $D4 $01 $D5 $01 $D6 $01 $D7 $01&lt;br /&gt;
 $D8 $01 $D9 $01 $DA $01 $DB $01 $DC $01 $DD $01 $DE $01 $DF $01&lt;br /&gt;
 $E0 $01 $E1 $01 $E2 $01 $E3 $01 $E4 $01 $E5 $01 $E6 $01 $E7 $01&lt;br /&gt;
 $E8 $01 $E9 $01 $EA $01 $EB $01 $EC $01 $ED $01 $EE $01 $EF $01&lt;br /&gt;
 $F0 $01 $F1 $01 $F2 $01 $F3 $01 $F4 $01 $F5 $01 $F6 $01 $F7 $01&lt;br /&gt;
 $F8 $01 $F9 $01 $FA $01 $FB $01 $FC $01 $FD $01&lt;br /&gt;
&lt;br /&gt;
This is a useful example to use since it has a number of unique features. Firstly the paths to any given terminal node are all the same length, 8 bits. Secondly the &#039;byte reversal&#039; can easily be seen in that the path to each terminal node is the &#039;&#039;reverse&#039;&#039; of the character it represents. And finally the nodes are arranged in a logical order with an easily seen pattern; the first half of the tree consists of terminal nodes, the second half of branch nodes. (Of the second half the first half of &#039;&#039;that&#039;&#039; consists of branch nodes that lead to terminal nodes while the second half consists of branch nodes to two branch nodes and so on.)&lt;br /&gt;
&lt;br /&gt;
As an example the character $80 (128 or 10000000) can be expected to be represented by the path &#039;00000001&#039; and as such be the second node in the tree. Starting at the root node and following the leftmost path until the last step takes us to the following nodes: 254(root) -&amp;gt; 252 -&amp;gt; 248 -&amp;gt; 240 -&amp;gt; 224 -&amp;gt; 192 -&amp;gt; 128 -&amp;gt; 0(terminal node for characters $00 and $80)&lt;br /&gt;
&lt;br /&gt;
== Source code ==&lt;br /&gt;
&lt;br /&gt;
Some example code is available in various languages showing how to decompress (and in some cases compress) files using the Huffman algorithm.&lt;br /&gt;
&lt;br /&gt;
=== QuickBasic ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; DANGEROUS DAVE 2 - IN THE HAUNTED MANSION - Huffman Decompressor&lt;br /&gt;
&#039;  - by Napalm with thanks to Adurdin&#039;s work on ModKeen&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; This source is Public Domain, please credit me if you use it.&lt;br /&gt;
&#039;&lt;br /&gt;
&#039;&lt;br /&gt;
DECLARE SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING)&lt;br /&gt;
&lt;br /&gt;
TYPE NODE&lt;br /&gt;
        BIT0 AS INTEGER&lt;br /&gt;
        BIT1 AS INTEGER&lt;br /&gt;
END TYPE&lt;br /&gt;
&lt;br /&gt;
&#039; Test Function&lt;br /&gt;
HUFFDECOMPRESS &amp;quot;TITLE1.DD2&amp;quot;, &amp;quot;TITLE1.PIC&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING) &#039; by Napalm&lt;br /&gt;
	DIM INFILE AS INTEGER, OUTFILE AS INTEGER, I AS INTEGER&lt;br /&gt;
	DIM SIG AS LONG, OUTLEN AS LONG, BITMASK AS INTEGER&lt;br /&gt;
	DIM CURNODE AS INTEGER, NEXTNODE AS INTEGER&lt;br /&gt;
	DIM CHRIN AS STRING * 1, CHROUT AS STRING * 1&lt;br /&gt;
	DIM NODES(0 TO 254) AS NODE&lt;br /&gt;
&lt;br /&gt;
	&#039; Open input file&lt;br /&gt;
	INFILE = FREEFILE&lt;br /&gt;
	OPEN INNAME FOR BINARY ACCESS READ AS INFILE&lt;br /&gt;
       &lt;br /&gt;
	&#039; Check file signature&lt;br /&gt;
	GET INFILE, , SIG&lt;br /&gt;
	IF SIG &amp;lt;&amp;gt; &amp;amp;H46465548 THEN &#039; Hex for: HUFF in little endian&lt;br /&gt;
		PRINT &amp;quot;INVALID FILE!&amp;quot;&lt;br /&gt;
		EXIT SUB&lt;br /&gt;
	END IF&lt;br /&gt;
       &lt;br /&gt;
	&#039; Get output length&lt;br /&gt;
	OUTLEN = 0&lt;br /&gt;
	GET INFILE, , OUTLEN&lt;br /&gt;
       &lt;br /&gt;
	&#039; Read in the huffman binary tree&lt;br /&gt;
	FOR I = 0 TO 254&lt;br /&gt;
		GET INFILE, , NODES(I).BIT0&lt;br /&gt;
		GET INFILE, , NODES(I).BIT1&lt;br /&gt;
	NEXT I&lt;br /&gt;
&lt;br /&gt;
	&#039; Open output file&lt;br /&gt;
	OUTFILE = FREEFILE&lt;br /&gt;
	OPEN OUTNAME FOR BINARY ACCESS WRITE AS OUTFILE&lt;br /&gt;
&lt;br /&gt;
	&#039; Decompress input data using binary tree&lt;br /&gt;
	CURNODE = 254&lt;br /&gt;
	DO&lt;br /&gt;
		BITMASK = 0&lt;br /&gt;
		GET INFILE, , CHRIN&lt;br /&gt;
		DO&lt;br /&gt;
			&#039; Decide which node to travel down depending on&lt;br /&gt;
			&#039;   input bits from CHRIN.&lt;br /&gt;
			IF ASC(CHRIN) AND 2 ^ BITMASK THEN&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT1&lt;br /&gt;
			ELSE&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT0&lt;br /&gt;
			END IF&lt;br /&gt;
		       &lt;br /&gt;
			&#039; Is this next node another part of the tree or&lt;br /&gt;
			&#039;   is it a end node? Less than 256 mean end node.&lt;br /&gt;
			IF NEXTNODE &amp;lt; 256 THEN&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Get output char from end node and save.&lt;br /&gt;
				CHROUT = CHR$(NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
				PUT OUTFILE, , CHROUT&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Amend output length and start from top of&lt;br /&gt;
				&#039;   binary tree.&lt;br /&gt;
				OUTLEN = OUTLEN - 1&lt;br /&gt;
				CURNODE = 254&lt;br /&gt;
&lt;br /&gt;
			ELSE&lt;br /&gt;
				&#039; Travel to next node&lt;br /&gt;
				CURNODE = (NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
&lt;br /&gt;
			END IF&lt;br /&gt;
&lt;br /&gt;
			&#039; Move to next input bit&lt;br /&gt;
			BITMASK = BITMASK + 1&lt;br /&gt;
		LOOP WHILE BITMASK &amp;lt; 8 AND OUTLEN &amp;gt; 0&lt;br /&gt;
		&#039; Loop while we still need to output data&lt;br /&gt;
	LOOP WHILE OUTLEN &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
	&#039; Clean up&lt;br /&gt;
	CLOSE OUTFILE&lt;br /&gt;
	CLOSE INFILE&lt;br /&gt;
&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
SUB MAKHUF &#039;Mak a degenerate huffman tree, store as string huffq&lt;br /&gt;
	OPEN &amp;quot;HUFF.DD2&amp;quot; FOR BINARY AS #8&lt;br /&gt;
	aq = &amp;quot;HUFF&amp;quot;&lt;br /&gt;
	PUT #8, 1, aq&lt;br /&gt;
	x = 9&lt;br /&gt;
	FOR t = 0 TO 255&lt;br /&gt;
		b = t&lt;br /&gt;
		va = 0&lt;br /&gt;
		vb = 0&lt;br /&gt;
		vc = 0&lt;br /&gt;
		vd = 0&lt;br /&gt;
		ve = 0&lt;br /&gt;
		vf = 0&lt;br /&gt;
		vg = 0&lt;br /&gt;
		vh = 0&lt;br /&gt;
		IF b &amp;gt; 127 THEN LET va = va + 1&lt;br /&gt;
		b = b MOD 128&lt;br /&gt;
		IF b &amp;gt; 63 THEN LET vb = vb + 1&lt;br /&gt;
		b = b MOD 64&lt;br /&gt;
		IF b &amp;gt; 31 THEN LET vc = vc + 1&lt;br /&gt;
		b = b MOD 32&lt;br /&gt;
		IF b &amp;gt; 15 THEN LET vd = vd + 1&lt;br /&gt;
		b = b MOD 16&lt;br /&gt;
		IF b &amp;gt; 7 THEN LET ve = ve + 1&lt;br /&gt;
		b = b MOD 8&lt;br /&gt;
		IF b &amp;gt; 3 THEN LET vf = vf + 1&lt;br /&gt;
		b = b MOD 4&lt;br /&gt;
		IF b &amp;gt; 1 THEN LET vg = vg + 1&lt;br /&gt;
		b = b MOD 2&lt;br /&gt;
		IF b = 1 THEN LET vh = vh + 1&lt;br /&gt;
		b = (vh * 128) + (vg * 64) + (vf * 32) + (16 * ve) + (8 * vd) + (4 * vc) + (2 * vb) + va&lt;br /&gt;
		aq = MKI$(b)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	FOR t = 0 TO 253&lt;br /&gt;
		aq = MKI$(t + 256)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	GET #8, 1, huffq&lt;br /&gt;
	CLOSE #8&lt;br /&gt;
	KILL &amp;quot;HUFF.DD2&amp;quot;&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Visual Basic .NET ===&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree representation ====&lt;br /&gt;
&lt;br /&gt;
This class, BinaryTreeNode, represents a binary tree whose branch nodes carry no value, like a Huffman dictionary tree.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;Public Class BinaryTreeNode(Of T)&lt;br /&gt;
    &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
    Private Branch As Boolean&lt;br /&gt;
    Private Children As BinaryTreeNode(Of T)()&lt;br /&gt;
    Private HoldValue As T&lt;br /&gt;
    Public Sub New(LeafValue As T)&lt;br /&gt;
        Branch = False&lt;br /&gt;
        HoldValue = LeafValue&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public Sub New(LeftChild As BinaryTreeNode(Of T), RightChild As BinaryTreeNode(Of T))&lt;br /&gt;
        Branch = True&lt;br /&gt;
        Children = {LeftChild, RightChild}&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public ReadOnly Property HasValue As Boolean&lt;br /&gt;
        Get&lt;br /&gt;
            Return Not Branch&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Value As T&lt;br /&gt;
        Get&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return HoldValue&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As T)&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            HoldValue = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Child(Side As ChildSide) As BinaryTreeNode(Of T)&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return Children(Side)&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As BinaryTreeNode(Of T))&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Children(Side) = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Enum ChildSide As Byte&lt;br /&gt;
        Left = 0&lt;br /&gt;
        Right = 1&lt;br /&gt;
    End Enum&lt;br /&gt;
    Public ReadOnly Property Count As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Children(0).Count + Children(1).Count&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public ReadOnly Property Depth As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Math.Max(Children(0).Depth, Children(1).Depth) + 1&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Overrides Function ToString() As String&lt;br /&gt;
        Return &amp;quot;{Count = &amp;quot; &amp;amp; Count &amp;amp; &amp;quot;, Depth = &amp;quot; &amp;amp; Depth &amp;amp; &amp;quot;}&amp;quot;&lt;br /&gt;
    End Function&lt;br /&gt;
End Class&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree reading ====&lt;br /&gt;
&lt;br /&gt;
This piece of code will read in a stored Huffman dictionary in the format described at the top of this article and store it in a BinaryTreeNode(Of Byte) as shown above.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;        &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
        Dim fDict As New IO.FileStream(DictionaryFile, IO.FileMode.Open)&lt;br /&gt;
        Dim raw(254) As Tuple(Of UShort, UShort)&lt;br /&gt;
        For x = 0 To 254&lt;br /&gt;
            raw(x) = Tuple.Create(ReadUShort(fDict), ReadUShort(fDict))&lt;br /&gt;
        Next&lt;br /&gt;
        fDict.Close()&lt;br /&gt;
        Dim GenerateTree As Func(Of UShort, BinaryTreeNode(Of Byte))&lt;br /&gt;
        GenerateTree = Function(NextNode As UShort) As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           Dim n As Tuple(Of UShort, UShort) = raw(NextNode)&lt;br /&gt;
                           Dim a, b As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           If n.Item1 &amp;lt; 256 Then&lt;br /&gt;
                               a = New BinaryTreeNode(Of Byte)(n.Item1)&lt;br /&gt;
                           Else&lt;br /&gt;
                               a = GenerateTree(n.Item1 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           If n.Item2 &amp;lt; 256 Then&lt;br /&gt;
                               b = New BinaryTreeNode(Of Byte)(n.Item2)&lt;br /&gt;
                           Else&lt;br /&gt;
                               b = GenerateTree(n.Item2 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           Return New BinaryTreeNode(Of Byte)(a, b)&lt;br /&gt;
                       End Function&lt;br /&gt;
        Dim dict As BinaryTreeNode(Of Byte) = GenerateTree(254)&lt;br /&gt;
        fDict.Close()&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Code examples]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6846</id>
		<title>Huffman Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6846"/>
		<updated>2016-05-24T08:42:37Z</updated>

		<summary type="html">&lt;p&gt;Levellass: First part or rewrite&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-byte in, 1-bit out&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|The Blues Brothers}}&lt;br /&gt;
   {{Game|Catacomb 3-D}}&lt;br /&gt;
   {{Game|Commander Keen Dreams}}&lt;br /&gt;
   {{Game|Dangerous Dave 2}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Huffman Compression]] is a compression algorithm used in many classic games. It is about as efficient as LZW or RLE compression, with many games using the three formats simultaneously.&lt;br /&gt;
&lt;br /&gt;
Huffman compression involves making/reading a &#039;&#039;dictionary&#039;&#039; of 256 entries, one for each possible 1-byte character.  This is organised in the form of a &#039;&#039;binary tree&#039;&#039; which is basically formed by taking the two lowest frequency characters and combining them into a new entry with their added frequencies and repeating until all entries are reduced to one &#039;&#039;root node&#039;&#039;.  After the dictionary is created, every character of data is replaced with the corresponding bit representation from the tree.&lt;br /&gt;
&lt;br /&gt;
Any Huffman compressed data will thus be associated with a dictionary file (internal or external) used to decompress it. This page will explain the various aspects of Huffman compression using the example text &amp;quot;She sells seashells by the sea shore.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Frequency tables==&lt;br /&gt;
&lt;br /&gt;
In order to compress data using Huffman compression the compressor must build a &#039;frequency table&#039; of all the elements it wishes to compress. In most cases this will be the 256 values a single byte can take, though it need not be limited to this. (Due to the binary nature of the compression method, sets of elements that match powers of 2 are both easiest and most efficient to compress.) The data is scanned and each occurrence of a given value. Taking the letters in our example sentence we can construct the following frequency table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Char   Freq&lt;br /&gt;
 &#039;s&#039;      7&lt;br /&gt;
 &#039;e&#039;      7&lt;br /&gt;
 &#039; &#039;      6&lt;br /&gt;
 &#039;h&#039;      4&lt;br /&gt;
 &#039;l&#039;      4&lt;br /&gt;
 &#039;a&#039;      2&lt;br /&gt;
 &#039;S&#039;      1&lt;br /&gt;
 &#039;b&#039;      1&lt;br /&gt;
 &#039;o&#039;      1&lt;br /&gt;
 &#039;r&#039;      1&lt;br /&gt;
 &#039;t&#039;      1&lt;br /&gt;
 &#039;y&#039;      1&lt;br /&gt;
 &#039;.&#039;      1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Binary Tree==&lt;br /&gt;
&lt;br /&gt;
The binary tree is core to how Huffman compression compresses data. This is done by constructing a &#039;binary tree&#039;, so named because of its branching structure. Each branching point or &#039;node&#039; has two options, &#039;left&#039; and &#039;right&#039; which lead either to another node or a character. The tree is constructed so that every character can be placed upon it and every path ends in a character. &lt;br /&gt;
&lt;br /&gt;
This is done by first building a point of origin, &#039;root node&#039; and the adding further nodes from there. Using our example we can build the following binary tree simply by listing the nodes alphabetically (and using &#039;_&#039; to stand in for the space for clarity):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           [Root]&lt;br /&gt;
         ____|_______&lt;br /&gt;
       /             \&lt;br /&gt;
     __|__            |&lt;br /&gt;
    /      \        /   \&lt;br /&gt;
    |       |       |    .&lt;br /&gt;
  /   \   /   \   /   \&lt;br /&gt;
  |   |   |   |   |   |&lt;br /&gt;
 / \ / \ / \ / \ / \ / \&lt;br /&gt;
 _ S a b e h l o r s t y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On this tree we can use &#039;L&#039; to specify a left path and &#039;R&#039; to specify a right. As such the letter &#039;a&#039; is represented by &#039;LLRL&#039; and &#039;y&#039; by &#039;RLRR&#039;. Note that since the number of different characters is not a power of two (E.g. 16) not all paths from the root to a character are the same length, one is considerably shorter. The &#039;.&#039; character is represented by simply &#039;RR&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that &#039;R&#039; and &#039;L&#039; are &#039;0&#039; and &#039;1&#039; each 8-bit character in the original text can be represented by just 4 bits on average, halving the message length. This is far from optimal however and there is a specific procedure used to construct an optimal tree for the shortest message length. To do this advantage is taken of the fact that paths can be different lengths. If one set of paths is made a bit shorter at the expense of making a smaller set of paths a bit longer then the overall message will be made shorter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Constructing an optimal tree===&lt;br /&gt;
&lt;br /&gt;
The first step in creating an optimal tree again is to create a &#039;root node&#039;. To populate its two options the compressor repeatedly divides the frequency table. This is done by starting with the most common character and seeing if it contains more occurrences than the rest of the table combined. If not then the second most common character is added and so on.&lt;br /&gt;
&lt;br /&gt;
In our example there are a total of 37 characters. Three characters make up more than half of this, &#039;s&#039;, &#039;e&#039; and &#039; &#039;. Because of the binary structure of the tree however &#039;&#039;four&#039;&#039; options are needed here so &#039;h&#039; is also included. All of these characters are placed on the left option of the root node while the remaining characters are placed on the right.&lt;br /&gt;
&lt;br /&gt;
The next step creates a new node with left and right options and repeats the process. The two most common characters of the four, &#039;s&#039; and &#039;e&#039; go to the left branch of this new node. A third node is created and, now that there are only two options, each is given a branch. The tree now looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  [Root]&lt;br /&gt;
    / \&lt;br /&gt;
    |  l, a, etc&lt;br /&gt;
   / \&lt;br /&gt;
   | _, h&lt;br /&gt;
 /  \&lt;br /&gt;
 s  e&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the character &#039;s&#039; can be represented as LLL and &#039;e&#039; as LLR.&lt;br /&gt;
&lt;br /&gt;
The compressor now moves &#039;up&#039; to the previous node which still has a branch with more than one option in it. Another node is created and, since there are only two options, one is assigned to each branch. Te compressor then returns to the root node to deal with the right half of the tree. When it has assigned very character to a node the following optimal tree is produced:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      ___[Root]____&lt;br /&gt;
     /             \&lt;br /&gt;
    _|_         ___|_______&lt;br /&gt;
   /   \       /           \&lt;br /&gt;
   |   |       |            |&lt;br /&gt;
 /  \ / \     / \          / \&lt;br /&gt;
 s  e _ h    l   |        |   |&lt;br /&gt;
                / \      / \ / \&lt;br /&gt;
               a  |      o r t |&lt;br /&gt;
                 / \          / \&lt;br /&gt;
                 S b         y  .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that 4 characters now have paths that are just 3 choices long while 4 have paths 4 choices long and 4 have paths 5 choices long. Overall the average path length is the same as our previous tree. However 24 occurrences are one choice shorter, 5 are identical,  3 are one choice longer and &#039;.&#039; is three choices longer. This gives us a compressed message that is  a total of 18 choices (or bits) shorter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Labeling the tree===&lt;br /&gt;
&lt;br /&gt;
Now that a tree has been constructed it needs to be labelled in some form so that it can be stored as data either in the decompressor or to be sent with the compressed code. There are two major issues, what system to use when assigning numbers to the various nodes, and what bit value, 0 or 1, to assign to left or right options.&lt;br /&gt;
&lt;br /&gt;
The most common (but far from unique) system is to label nodes from the &#039;bottom&#039; of the tree to the top, going left-to-right across each &#039;layer&#039; of the tree. (In our example the node that leads to &#039;y&#039; and &#039;.&#039; would thus be the first numbered node.) Nodes are usually numbered starting with 0 and ending with the root node having the highest number.&lt;br /&gt;
&lt;br /&gt;
Usually the left branch is given a bit value of 0 and the right branch a bit value of 1. Using this scheme &#039;s&#039; in our example resides on node 1 and is represented by the bit string &#039;000&#039; The complete compressed message is now &#039;10110-011-001-010-000-001-100-100-000-010-000-001-1010-000-011-001-100-100-000-010-10111-11110-010-1110-011-001-010-000-001-1010-010-000-011-1100-1101-001-11111&#039; or in bytes &amp;lt;tt&amp;gt;$B3 $28 $19 $02 $06 $83 $32 $05 $7F $2E $65 $03 $48 $3C $D3 $F0&amp;lt;/tt&amp;gt; (The final byte is padded with nul bits.) This is a total of 16 bytes used for a 37 byte message.&lt;br /&gt;
&lt;br /&gt;
==Nodes==&lt;br /&gt;
&lt;br /&gt;
The binary tree must be stored in some form, usually called a &#039;&#039;dictionary&#039;&#039;. The format varies from game to game, but is usually broadly along these lines. The tree will have 254 nodes (for all the one byte characters in game data) stored as two &#039;branches&#039; of that node, usually taking up 4 bytes each, but sometimes 3. The second part is either 0 or 1, and says whether that branch goes to a character (0) or another node (1).  The first part is the value of either that character or that node. (For the usual 4-byte implementation each part is a byte.)&lt;br /&gt;
&lt;br /&gt;
In the Huffman table then we can expect to see each possible character TWICE, once as a character, once as a node reference. Note that the nodes are numbered from 0-253, NOT 1-254. The order of the nodes doesn&#039;t matter, only how they are connected.&lt;br /&gt;
&lt;br /&gt;
The root node is ALWAYS node 254 (number 253!) and should always be something like $xx $yy $00 $00 (Since 0 is the most common character it is closest to the root.) It will also tend to be at the end of the dictionary, since most programs find it easier to write their dictionaries from bottom to top. This can often be used to find Huffman dictionaries in files, if you know what you are looking for.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&lt;br /&gt;
Compress the word &amp;quot;HUFFMAN&amp;quot;.  For simplicity, we will not use the usual 256 character tree, but rather something a bit smaller. (Huffman trees can be any size, the concept is the same.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Frequencies are:&amp;lt;br/&amp;gt;1: H,U,M,A,N&amp;lt;br/&amp;gt;2: F&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Make a binary tree: (here left = 0 and right = 1)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  [Root node]&lt;br /&gt;
     /   \&lt;br /&gt;
   [0]   [1] &lt;br /&gt;
   / \   / \&lt;br /&gt;
   F N [2] [3]&lt;br /&gt;
       / \ / \&lt;br /&gt;
       M A H U&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The first letter is &#039;H&#039;; this on the tree is &amp;lt;tt&amp;gt;110&amp;lt;/tt&amp;gt; The next letter is &#039;U&#039; which is &amp;lt;tt&amp;gt;111&amp;lt;/tt&amp;gt;.  The third letter is &#039;F&#039; which is &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt; and so on (notice common letters have shorter strings?)  The final output in bits is &amp;lt;tt&amp;gt;110111000010010101&amp;lt;/tt&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is not of course the optimum Huffman tree, but that doesn&#039;t matter in this case, ANY tree will do. As bytes the output is thus: &amp;lt;tt&amp;gt;11011100 00100101 01000000&amp;lt;/tt&amp;gt; (the end bit is padded with nulls) or &amp;lt;tt&amp;gt;$DC $25 $40&amp;lt;/tt&amp;gt;.  We have a reduction in size from 7 bytes to 3, over 50%!  Sadly, we then need to include the Huffman table (the &#039;&#039;dictionary&#039;&#039;) in some form.&lt;br /&gt;
&lt;br /&gt;
In general a dictionary is built up by listing each node sequentially starting at 0 and ending with the root.&lt;br /&gt;
&lt;br /&gt;
A possibility for storing the dictionary might be:&lt;br /&gt;
&lt;br /&gt;
    $00 $46 $00 $4E   $01 $02 $01 $03   $00 $4D $00 $41   $00 $48 $00 $55   $01 $01 $01 $00&lt;br /&gt;
     -   F   -   N     -   -   -   -     -   M   -   A     -   H   -   U     -   -   -   -&lt;br /&gt;
       (node 0)          (node 1)          (node 2)          (node 3)          (Root node)&lt;br /&gt;
&lt;br /&gt;
In &lt;br /&gt;
&lt;br /&gt;
Here we have numbered the nodes starting at the root as 254 and labelled every other node from 0-3 going left to right and top to bottom.  This dictionary is stored &#039;&#039;bottom to top&#039;&#039; left to right. The first four bytes belong to node 0, the next four to node 2, the next to node 3, the next to node 1 and the final four bytes belonging to the root node. This somewhat &#039;reversed&#039; method of storage as opposed to labeling is used in the Keen executables and is a result of how trees were built in one direction then read and stored in the other.&lt;br /&gt;
&lt;br /&gt;
To decompress the data we use the tree again starting at the root node and reading the data bit by bit. So the first three bits are &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; which leads us down the tree to character &#039;H&#039;, then &amp;lt;tt&amp;gt;000&amp;lt;/tt&amp;gt; which leads us to &#039;U&#039; and so on.&lt;br /&gt;
&lt;br /&gt;
==Huffman implementation in ID Software games==&lt;br /&gt;
&lt;br /&gt;
Games created by Id Software (such as [[Commander Keen 4-6]] or [[Wolfenstein 3-D]]) have a shared but distinct implementation of Huffman compression. The dictionary consists of 1020 bytes (254 nodes plus for null bytes of padding) and there are two or three dictionaries stored in the executable depending on game. (The end of these can be found by looking for node 254 which usually consists of the string $00 $00 $FD $01)&lt;br /&gt;
&lt;br /&gt;
The data itself is stored in an external file which consists of a number of concatenated &#039;chunks&#039;, each chunk beginning with a dword giving its decompressed size. There is also an internal &#039;header&#039; file consisting of a series of three (or sometimes four) byte offsets to the start of various chunks in the data file. (The end of this can be found as the last entry is the length of the data file.)&lt;br /&gt;
&lt;br /&gt;
The data itself is read byte-by-byte in the normal fashion &#039;&#039;but with the order of bits in every byte being reversed&#039;&#039;. The following 1020 bytes constitute the complete &#039;trivial&#039; Huffman dictionary for this implementation, that is, one that does not compress the data at all:&lt;br /&gt;
&lt;br /&gt;
 $00 $00 $80 $00 $40 $00 $C0 $00 $20 $00 $A0 $00 $60 $00 $E0 $00&lt;br /&gt;
 $10 $00 $90 $00 $50 $00 $D0 $00 $30 $00 $B0 $00 $70 $00 $F0 $00&lt;br /&gt;
 $08 $00 $88 $00 $48 $00 $C8 $00 $28 $00 $A8 $00 $68 $00 $E8 $00&lt;br /&gt;
 $18 $00 $98 $00 $58 $00 $D8 $00 $38 $00 $B8 $00 $78 $00 $F8 $00&lt;br /&gt;
 $04 $00 $84 $00 $44 $00 $C4 $00 $24 $00 $A4 $00 $64 $00 $E4 $00&lt;br /&gt;
 $14 $00 $94 $00 $54 $00 $D4 $00 $34 $00 $B4 $00 $74 $00 $F4 $00&lt;br /&gt;
 $0C $00 $8C $00 $4C $00 $CC $00 $2C $00 $AC $00 $6C $00 $EC $00&lt;br /&gt;
 $1C $00 $9C $00 $5C $00 $DC $00 $3C $00 $BC $00 $7C $00 $FC $00&lt;br /&gt;
 $02 $00 $82 $00 $42 $00 $C2 $00 $22 $00 $A2 $00 $62 $00 $E2 $00&lt;br /&gt;
 $12 $00 $92 $00 $52 $00 $D2 $00 $32 $00 $B2 $00 $72 $00 $F2 $00&lt;br /&gt;
 $0A $00 $8A $00 $4A $00 $CA $00 $2A $00 $AA $00 $6A $00 $EA $00&lt;br /&gt;
 $1A $00 $9A $00 $5A $00 $DA $00 $3A $00 $BA $00 $7A $00 $FA $00&lt;br /&gt;
 $06 $00 $86 $00 $46 $00 $C6 $00 $26 $00 $A6 $00 $66 $00 $E6 $00&lt;br /&gt;
 $16 $00 $96 $00 $56 $00 $D6 $00 $36 $00 $B6 $00 $76 $00 $F6 $00&lt;br /&gt;
 $0E $00 $8E $00 $4E $00 $CE $00 $2E $00 $AE $00 $6E $00 $EE $00&lt;br /&gt;
 $1E $00 $9E $00 $5E $00 $DE $00 $3E $00 $BE $00 $7E $00 $FE $00&lt;br /&gt;
 $01 $00 $81 $00 $41 $00 $C1 $00 $21 $00 $A1 $00 $61 $00 $E1 $00&lt;br /&gt;
 $11 $00 $91 $00 $51 $00 $D1 $00 $31 $00 $B1 $00 $71 $00 $F1 $00&lt;br /&gt;
 $09 $00 $89 $00 $49 $00 $C9 $00 $29 $00 $A9 $00 $69 $00 $E9 $00&lt;br /&gt;
 $19 $00 $99 $00 $59 $00 $D9 $00 $39 $00 $B9 $00 $79 $00 $F9 $00&lt;br /&gt;
 $05 $00 $85 $00 $45 $00 $C5 $00 $25 $00 $A5 $00 $65 $00 $E5 $00&lt;br /&gt;
 $15 $00 $95 $00 $55 $00 $D5 $00 $35 $00 $B5 $00 $75 $00 $F5 $00&lt;br /&gt;
 $0D $00 $8D $00 $4D $00 $CD $00 $2D $00 $AD $00 $6D $00 $ED $00&lt;br /&gt;
 $1D $00 $9D $00 $5D $00 $DD $00 $3D $00 $BD $00 $7D $00 $FD $00&lt;br /&gt;
 $03 $00 $83 $00 $43 $00 $C3 $00 $23 $00 $A3 $00 $63 $00 $E3 $00&lt;br /&gt;
 $13 $00 $93 $00 $53 $00 $D3 $00 $33 $00 $B3 $00 $73 $00 $F3 $00&lt;br /&gt;
 $0B $00 $8B $00 $4B $00 $CB $00 $2B $00 $AB $00 $6B $00 $EB $00&lt;br /&gt;
 $1B $00 $9B $00 $5B $00 $DB $00 $3B $00 $BB $00 $7B $00 $FB $00&lt;br /&gt;
 $07 $00 $87 $00 $47 $00 $C7 $00 $27 $00 $A7 $00 $67 $00 $E7 $00&lt;br /&gt;
 $17 $00 $97 $00 $57 $00 $D7 $00 $37 $00 $B7 $00 $77 $00 $F7 $00&lt;br /&gt;
 $0F $00 $8F $00 $4F $00 $CF $00 $2F $00 $AF $00 $6F $00 $EF $00&lt;br /&gt;
 $1F $00 $9F $00 $5F $00 $DF $00 $3F $00 $BF $00 $7F $00 $FF $00&lt;br /&gt;
 $00 $01 $01 $01 $02 $01 $03 $01 $04 $01 $05 $01 $06 $01 $07 $01&lt;br /&gt;
 $08 $01 $09 $01 $0A $01 $0B $01 $0C $01 $0D $01 $0E $01 $0F $01&lt;br /&gt;
 $10 $01 $11 $01 $12 $01 $13 $01 $14 $01 $15 $01 $16 $01 $17 $01&lt;br /&gt;
 $18 $01 $19 $01 $1A $01 $1B $01 $1C $01 $1D $01 $1E $01 $1F $01&lt;br /&gt;
 $20 $01 $21 $01 $22 $01 $23 $01 $24 $01 $25 $01 $26 $01 $27 $01&lt;br /&gt;
 $28 $01 $29 $01 $2A $01 $2B $01 $2C $01 $2D $01 $2E $01 $2F $01&lt;br /&gt;
 $30 $01 $31 $01 $32 $01 $33 $01 $34 $01 $35 $01 $36 $01 $37 $01&lt;br /&gt;
 $38 $01 $39 $01 $3A $01 $3B $01 $3C $01 $3D $01 $3E $01 $3F $01&lt;br /&gt;
 $40 $01 $41 $01 $42 $01 $43 $01 $44 $01 $45 $01 $46 $01 $47 $01&lt;br /&gt;
 $48 $01 $49 $01 $4A $01 $4B $01 $4C $01 $4D $01 $4E $01 $4F $01&lt;br /&gt;
 $50 $01 $51 $01 $52 $01 $53 $01 $54 $01 $55 $01 $56 $01 $57 $01&lt;br /&gt;
 $58 $01 $59 $01 $5A $01 $5B $01 $5C $01 $5D $01 $5E $01 $5F $01&lt;br /&gt;
 $60 $01 $61 $01 $62 $01 $63 $01 $64 $01 $65 $01 $66 $01 $67 $01&lt;br /&gt;
 $68 $01 $69 $01 $6A $01 $6B $01 $6C $01 $6D $01 $6E $01 $6F $01&lt;br /&gt;
 $70 $01 $71 $01 $72 $01 $73 $01 $74 $01 $75 $01 $76 $01 $77 $01&lt;br /&gt;
 $78 $01 $79 $01 $7A $01 $7B $01 $7C $01 $7D $01 $7E $01 $7F $01&lt;br /&gt;
 $80 $01 $81 $01 $82 $01 $83 $01 $84 $01 $85 $01 $86 $01 $87 $01&lt;br /&gt;
 $88 $01 $89 $01 $8A $01 $8B $01 $8C $01 $8D $01 $8E $01 $8F $01&lt;br /&gt;
 $90 $01 $91 $01 $92 $01 $93 $01 $94 $01 $95 $01 $96 $01 $97 $01&lt;br /&gt;
 $98 $01 $99 $01 $9A $01 $9B $01 $9C $01 $9D $01 $9E $01 $9F $01&lt;br /&gt;
 $A0 $01 $A1 $01 $A2 $01 $A3 $01 $A4 $01 $A5 $01 $A6 $01 $A7 $01&lt;br /&gt;
 $A8 $01 $A9 $01 $AA $01 $AB $01 $AC $01 $AD $01 $AE $01 $AF $01&lt;br /&gt;
 $B0 $01 $B1 $01 $B2 $01 $B3 $01 $B4 $01 $B5 $01 $B6 $01 $B7 $01&lt;br /&gt;
 $B8 $01 $B9 $01 $BA $01 $BB $01 $BC $01 $BD $01 $BE $01 $BF $01&lt;br /&gt;
 $C0 $01 $C1 $01 $C2 $01 $C3 $01 $C4 $01 $C5 $01 $C6 $01 $C7 $01&lt;br /&gt;
 $C8 $01 $C9 $01 $CA $01 $CB $01 $CC $01 $CD $01 $CE $01 $CF $01&lt;br /&gt;
 $D0 $01 $D1 $01 $D2 $01 $D3 $01 $D4 $01 $D5 $01 $D6 $01 $D7 $01&lt;br /&gt;
 $D8 $01 $D9 $01 $DA $01 $DB $01 $DC $01 $DD $01 $DE $01 $DF $01&lt;br /&gt;
 $E0 $01 $E1 $01 $E2 $01 $E3 $01 $E4 $01 $E5 $01 $E6 $01 $E7 $01&lt;br /&gt;
 $E8 $01 $E9 $01 $EA $01 $EB $01 $EC $01 $ED $01 $EE $01 $EF $01&lt;br /&gt;
 $F0 $01 $F1 $01 $F2 $01 $F3 $01 $F4 $01 $F5 $01 $F6 $01 $F7 $01&lt;br /&gt;
 $F8 $01 $F9 $01 $FA $01 $FB $01 $FC $01 $FD $01&lt;br /&gt;
&lt;br /&gt;
This is a useful example to use since it has a number of unique features. Firstly the paths to any given terminal node are all the same length, 8 bits. Secondly the &#039;byte reversal&#039; can easily be seen in that the path to each terminal node is the &#039;&#039;reverse&#039;&#039; of the character it represents. And finally the nodes are arranged in a logical order with an easily seen pattern; the first half of the tree consists of terminal nodes, the second half of branch nodes. (Of the second half the first half of &#039;&#039;that&#039;&#039; consists of branch nodes that lead to terminal nodes while the second half consists of branch nodes to two branch nodes and so on.)&lt;br /&gt;
&lt;br /&gt;
As an example the character $80 (128 or 10000000) can be expected to be represented by the path &#039;00000001&#039; and as such be the second node in the tree. Starting at the root node and following the leftmost path until the last step takes us to the following nodes: 254(root) -&amp;gt; 252 -&amp;gt; 248 -&amp;gt; 240 -&amp;gt; 224 -&amp;gt; 192 -&amp;gt; 128 -&amp;gt; 0(terminal node for characters $00 and $80)&lt;br /&gt;
&lt;br /&gt;
== Source code ==&lt;br /&gt;
&lt;br /&gt;
Some example code is available in various languages showing how to decompress (and in some cases compress) files using the Huffman algorithm.&lt;br /&gt;
&lt;br /&gt;
=== QuickBasic ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; DANGEROUS DAVE 2 - IN THE HAUNTED MANSION - Huffman Decompressor&lt;br /&gt;
&#039;  - by Napalm with thanks to Adurdin&#039;s work on ModKeen&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; This source is Public Domain, please credit me if you use it.&lt;br /&gt;
&#039;&lt;br /&gt;
&#039;&lt;br /&gt;
DECLARE SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING)&lt;br /&gt;
&lt;br /&gt;
TYPE NODE&lt;br /&gt;
        BIT0 AS INTEGER&lt;br /&gt;
        BIT1 AS INTEGER&lt;br /&gt;
END TYPE&lt;br /&gt;
&lt;br /&gt;
&#039; Test Function&lt;br /&gt;
HUFFDECOMPRESS &amp;quot;TITLE1.DD2&amp;quot;, &amp;quot;TITLE1.PIC&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING) &#039; by Napalm&lt;br /&gt;
	DIM INFILE AS INTEGER, OUTFILE AS INTEGER, I AS INTEGER&lt;br /&gt;
	DIM SIG AS LONG, OUTLEN AS LONG, BITMASK AS INTEGER&lt;br /&gt;
	DIM CURNODE AS INTEGER, NEXTNODE AS INTEGER&lt;br /&gt;
	DIM CHRIN AS STRING * 1, CHROUT AS STRING * 1&lt;br /&gt;
	DIM NODES(0 TO 254) AS NODE&lt;br /&gt;
&lt;br /&gt;
	&#039; Open input file&lt;br /&gt;
	INFILE = FREEFILE&lt;br /&gt;
	OPEN INNAME FOR BINARY ACCESS READ AS INFILE&lt;br /&gt;
       &lt;br /&gt;
	&#039; Check file signature&lt;br /&gt;
	GET INFILE, , SIG&lt;br /&gt;
	IF SIG &amp;lt;&amp;gt; &amp;amp;H46465548 THEN &#039; Hex for: HUFF in little endian&lt;br /&gt;
		PRINT &amp;quot;INVALID FILE!&amp;quot;&lt;br /&gt;
		EXIT SUB&lt;br /&gt;
	END IF&lt;br /&gt;
       &lt;br /&gt;
	&#039; Get output length&lt;br /&gt;
	OUTLEN = 0&lt;br /&gt;
	GET INFILE, , OUTLEN&lt;br /&gt;
       &lt;br /&gt;
	&#039; Read in the huffman binary tree&lt;br /&gt;
	FOR I = 0 TO 254&lt;br /&gt;
		GET INFILE, , NODES(I).BIT0&lt;br /&gt;
		GET INFILE, , NODES(I).BIT1&lt;br /&gt;
	NEXT I&lt;br /&gt;
&lt;br /&gt;
	&#039; Open output file&lt;br /&gt;
	OUTFILE = FREEFILE&lt;br /&gt;
	OPEN OUTNAME FOR BINARY ACCESS WRITE AS OUTFILE&lt;br /&gt;
&lt;br /&gt;
	&#039; Decompress input data using binary tree&lt;br /&gt;
	CURNODE = 254&lt;br /&gt;
	DO&lt;br /&gt;
		BITMASK = 0&lt;br /&gt;
		GET INFILE, , CHRIN&lt;br /&gt;
		DO&lt;br /&gt;
			&#039; Decide which node to travel down depending on&lt;br /&gt;
			&#039;   input bits from CHRIN.&lt;br /&gt;
			IF ASC(CHRIN) AND 2 ^ BITMASK THEN&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT1&lt;br /&gt;
			ELSE&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT0&lt;br /&gt;
			END IF&lt;br /&gt;
		       &lt;br /&gt;
			&#039; Is this next node another part of the tree or&lt;br /&gt;
			&#039;   is it a end node? Less than 256 mean end node.&lt;br /&gt;
			IF NEXTNODE &amp;lt; 256 THEN&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Get output char from end node and save.&lt;br /&gt;
				CHROUT = CHR$(NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
				PUT OUTFILE, , CHROUT&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Amend output length and start from top of&lt;br /&gt;
				&#039;   binary tree.&lt;br /&gt;
				OUTLEN = OUTLEN - 1&lt;br /&gt;
				CURNODE = 254&lt;br /&gt;
&lt;br /&gt;
			ELSE&lt;br /&gt;
				&#039; Travel to next node&lt;br /&gt;
				CURNODE = (NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
&lt;br /&gt;
			END IF&lt;br /&gt;
&lt;br /&gt;
			&#039; Move to next input bit&lt;br /&gt;
			BITMASK = BITMASK + 1&lt;br /&gt;
		LOOP WHILE BITMASK &amp;lt; 8 AND OUTLEN &amp;gt; 0&lt;br /&gt;
		&#039; Loop while we still need to output data&lt;br /&gt;
	LOOP WHILE OUTLEN &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
	&#039; Clean up&lt;br /&gt;
	CLOSE OUTFILE&lt;br /&gt;
	CLOSE INFILE&lt;br /&gt;
&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
SUB MAKHUF &#039;Mak a degenerate huffman tree, store as string huffq&lt;br /&gt;
	OPEN &amp;quot;HUFF.DD2&amp;quot; FOR BINARY AS #8&lt;br /&gt;
	aq = &amp;quot;HUFF&amp;quot;&lt;br /&gt;
	PUT #8, 1, aq&lt;br /&gt;
	x = 9&lt;br /&gt;
	FOR t = 0 TO 255&lt;br /&gt;
		b = t&lt;br /&gt;
		va = 0&lt;br /&gt;
		vb = 0&lt;br /&gt;
		vc = 0&lt;br /&gt;
		vd = 0&lt;br /&gt;
		ve = 0&lt;br /&gt;
		vf = 0&lt;br /&gt;
		vg = 0&lt;br /&gt;
		vh = 0&lt;br /&gt;
		IF b &amp;gt; 127 THEN LET va = va + 1&lt;br /&gt;
		b = b MOD 128&lt;br /&gt;
		IF b &amp;gt; 63 THEN LET vb = vb + 1&lt;br /&gt;
		b = b MOD 64&lt;br /&gt;
		IF b &amp;gt; 31 THEN LET vc = vc + 1&lt;br /&gt;
		b = b MOD 32&lt;br /&gt;
		IF b &amp;gt; 15 THEN LET vd = vd + 1&lt;br /&gt;
		b = b MOD 16&lt;br /&gt;
		IF b &amp;gt; 7 THEN LET ve = ve + 1&lt;br /&gt;
		b = b MOD 8&lt;br /&gt;
		IF b &amp;gt; 3 THEN LET vf = vf + 1&lt;br /&gt;
		b = b MOD 4&lt;br /&gt;
		IF b &amp;gt; 1 THEN LET vg = vg + 1&lt;br /&gt;
		b = b MOD 2&lt;br /&gt;
		IF b = 1 THEN LET vh = vh + 1&lt;br /&gt;
		b = (vh * 128) + (vg * 64) + (vf * 32) + (16 * ve) + (8 * vd) + (4 * vc) + (2 * vb) + va&lt;br /&gt;
		aq = MKI$(b)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	FOR t = 0 TO 253&lt;br /&gt;
		aq = MKI$(t + 256)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	GET #8, 1, huffq&lt;br /&gt;
	CLOSE #8&lt;br /&gt;
	KILL &amp;quot;HUFF.DD2&amp;quot;&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Visual Basic .NET ===&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree representation ====&lt;br /&gt;
&lt;br /&gt;
This class, BinaryTreeNode, represents a binary tree whose branch nodes carry no value, like a Huffman dictionary tree.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;Public Class BinaryTreeNode(Of T)&lt;br /&gt;
    &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
    Private Branch As Boolean&lt;br /&gt;
    Private Children As BinaryTreeNode(Of T)()&lt;br /&gt;
    Private HoldValue As T&lt;br /&gt;
    Public Sub New(LeafValue As T)&lt;br /&gt;
        Branch = False&lt;br /&gt;
        HoldValue = LeafValue&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public Sub New(LeftChild As BinaryTreeNode(Of T), RightChild As BinaryTreeNode(Of T))&lt;br /&gt;
        Branch = True&lt;br /&gt;
        Children = {LeftChild, RightChild}&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public ReadOnly Property HasValue As Boolean&lt;br /&gt;
        Get&lt;br /&gt;
            Return Not Branch&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Value As T&lt;br /&gt;
        Get&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return HoldValue&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As T)&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            HoldValue = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Child(Side As ChildSide) As BinaryTreeNode(Of T)&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return Children(Side)&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As BinaryTreeNode(Of T))&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Children(Side) = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Enum ChildSide As Byte&lt;br /&gt;
        Left = 0&lt;br /&gt;
        Right = 1&lt;br /&gt;
    End Enum&lt;br /&gt;
    Public ReadOnly Property Count As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Children(0).Count + Children(1).Count&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public ReadOnly Property Depth As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Math.Max(Children(0).Depth, Children(1).Depth) + 1&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Overrides Function ToString() As String&lt;br /&gt;
        Return &amp;quot;{Count = &amp;quot; &amp;amp; Count &amp;amp; &amp;quot;, Depth = &amp;quot; &amp;amp; Depth &amp;amp; &amp;quot;}&amp;quot;&lt;br /&gt;
    End Function&lt;br /&gt;
End Class&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree reading ====&lt;br /&gt;
&lt;br /&gt;
This piece of code will read in a stored Huffman dictionary in the format described at the top of this article and store it in a BinaryTreeNode(Of Byte) as shown above.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;        &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
        Dim fDict As New IO.FileStream(DictionaryFile, IO.FileMode.Open)&lt;br /&gt;
        Dim raw(254) As Tuple(Of UShort, UShort)&lt;br /&gt;
        For x = 0 To 254&lt;br /&gt;
            raw(x) = Tuple.Create(ReadUShort(fDict), ReadUShort(fDict))&lt;br /&gt;
        Next&lt;br /&gt;
        fDict.Close()&lt;br /&gt;
        Dim GenerateTree As Func(Of UShort, BinaryTreeNode(Of Byte))&lt;br /&gt;
        GenerateTree = Function(NextNode As UShort) As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           Dim n As Tuple(Of UShort, UShort) = raw(NextNode)&lt;br /&gt;
                           Dim a, b As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           If n.Item1 &amp;lt; 256 Then&lt;br /&gt;
                               a = New BinaryTreeNode(Of Byte)(n.Item1)&lt;br /&gt;
                           Else&lt;br /&gt;
                               a = GenerateTree(n.Item1 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           If n.Item2 &amp;lt; 256 Then&lt;br /&gt;
                               b = New BinaryTreeNode(Of Byte)(n.Item2)&lt;br /&gt;
                           Else&lt;br /&gt;
                               b = GenerateTree(n.Item2 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           Return New BinaryTreeNode(Of Byte)(a, b)&lt;br /&gt;
                       End Function&lt;br /&gt;
        Dim dict As BinaryTreeNode(Of Byte) = GenerateTree(254)&lt;br /&gt;
        fDict.Close()&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Code examples]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6845</id>
		<title>Huffman Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6845"/>
		<updated>2016-05-24T06:47:43Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Partial rewrite save&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-byte in, 1-bit out&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|The Blues Brothers}}&lt;br /&gt;
   {{Game|Catacomb 3-D}}&lt;br /&gt;
   {{Game|Commander Keen Dreams}}&lt;br /&gt;
   {{Game|Dangerous Dave 2}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Huffman Compression]] is a compression algorithm used in many classic games. It is about as efficient as LZW or RLE compression, with many games using the three formats simultaneously.&lt;br /&gt;
&lt;br /&gt;
Huffman compression involves making/reading a &#039;&#039;dictionary&#039;&#039; of 256 entries, one for each possible 1-byte character.  This is organised in the form of a &#039;&#039;binary tree&#039;&#039; which is basically formed by taking the two lowest frequency characters and combining them into a new entry with their added frequencies and repeating until all entries are reduced to one &#039;&#039;root node&#039;&#039;.  After the dictionary is created, every character of data is replaced with the corresponding bit representation from the tree.&lt;br /&gt;
&lt;br /&gt;
Any Huffman compressed data will thus be associated with a dictionary file (internal or external) used to decompress it. This page will explain the various aspects of Huffman compression using the example text &amp;quot;She sells seashells by the sea shore.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Frequency tables==&lt;br /&gt;
&lt;br /&gt;
In order to compress data using Huffman compression the compressor must build a &#039;frequency table&#039; of all the elements it wishes to compress. In most cases this will be the 256 values a single byte can take, though it need not be limited to this. (Due to the binary nature of the compression method, sets of elements that match powers of 2 are both easiest and most efficient to compress.) The data is scanned and each occurrence of a given value. Taking the letters in our example sentence we can construct the following frequency table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Char   Freq&lt;br /&gt;
 &#039;s&#039;      7&lt;br /&gt;
 &#039;e&#039;      7&lt;br /&gt;
 &#039; &#039;      6&lt;br /&gt;
 &#039;l&#039;      4&lt;br /&gt;
 &#039;a&#039;      2&lt;br /&gt;
 &#039;h&#039;      2&lt;br /&gt;
 &#039;S&#039;      1&lt;br /&gt;
 &#039;b&#039;      1&lt;br /&gt;
 &#039;o&#039;      1&lt;br /&gt;
 &#039;r&#039;      1&lt;br /&gt;
 &#039;t&#039;      1&lt;br /&gt;
 &#039;y&#039;      1&lt;br /&gt;
 &#039;.&#039;      1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Binary Tree==&lt;br /&gt;
&lt;br /&gt;
The binary tree is core to how Huffman compression compresses data. It relies on the fact that in random data only a few characters will be common while most will not. Representing more common characters in a shorter form will thus save space even if it comes at the cost of representing rarer characters in a longer form. Specifically if the total number of occurrences of a character to be shortened outnumber all the characters that will have to be lengthened then shortening that character&#039;s representation will save space.&lt;br /&gt;
&lt;br /&gt;
This is done by constructing a &#039;binary tree&#039;, so named because of its branching structure. The first step in doing this is to create a &#039;root&#039;. This root will have two possible options, left and right which will lead to further branching points. To build an optimum tree the compressor looks at the most frequent character and sees if it is more common than all the other characters combined. (For long chunks of text this is usually the space character.)&lt;br /&gt;
&lt;br /&gt;
In our example this is &#039;s&#039;, occurring 7 times. It is not however more common than all the remaining letters. In this case the compressor gives the root two options, &amp;quot;left&amp;quot; and &amp;quot;right&amp;quot;, both leading to other options. (Otherwise it would give the root an option that led to the most common character.)&lt;br /&gt;
&lt;br /&gt;
Next the compressor works on the newly created options, leftmost first. Now it splits the frequency table in half. The most common characters will be considered for the left node, the least common for the right. In our example the table is split into 2 sets of 7 options. (With only 13 entries a &#039;dummy option&#039; with frequency 0 is created to allow the division.) Again &#039;s&#039; in not common enough so the splitting repeats. (This requires the creation of &#039;&#039;another&#039;&#039; dummy option, but &#039;&#039;again&#039;&#039; in the lowest frequency half of the table which must &#039;donate&#039; its most frequent member to the higher frequency half of the table.)&lt;br /&gt;
&lt;br /&gt;
 &#039;s&#039;      7&lt;br /&gt;
 &#039;e&#039;      7&lt;br /&gt;
 &#039; &#039;      6&lt;br /&gt;
 &#039;l&#039;      4&lt;br /&gt;
 &#039;a&#039;      2&lt;br /&gt;
 &#039;h&#039;      2&lt;br /&gt;
 &#039;S&#039;      1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nodes==&lt;br /&gt;
&lt;br /&gt;
The binary tree must be stored in some form, usually called a &#039;&#039;dictionary&#039;&#039;. The format varies from game to game, but is usually broadly along these lines. The tree will have 254 nodes (for all the one byte characters in game data) stored as two &#039;branches&#039; of that node, usually taking up 4 bytes each, but sometimes 3. The second part is either 0 or 1, and says whether that branch goes to a character (0) or another node (1).  The first part is the value of either that character or that node. (For the usual 4-byte implementation each part is a byte.)&lt;br /&gt;
&lt;br /&gt;
In the Huffman table then we can expect to see each possible character TWICE, once as a character, once as a node reference. Note that the nodes are numbered from 0-253, NOT 1-254. The order of the nodes doesn&#039;t matter, only how they are connected.&lt;br /&gt;
&lt;br /&gt;
The root node is ALWAYS node 254 (number 253!) and should always be something like $xx $yy $00 $00 (Since 0 is the most common character it is closest to the root.) It will also tend to be at the end of the dictionary, since most programs find it easier to write their dictionaries from bottom to top. This can often be used to find Huffman dictionaries in files, if you know what you are looking for.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&lt;br /&gt;
Compress the word &amp;quot;HUFFMAN&amp;quot;.  For simplicity, we will not use the usual 256 character tree, but rather something a bit smaller. (Huffman trees can be any size, the concept is the same.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Frequencies are:&amp;lt;br/&amp;gt;1: H,U,M,A,N&amp;lt;br/&amp;gt;2: F&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Make a binary tree: (here left = 0 and right = 1)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  [Root node]&lt;br /&gt;
     /   \&lt;br /&gt;
   [0]   [1] &lt;br /&gt;
   / \   / \&lt;br /&gt;
   F N [2] [3]&lt;br /&gt;
       / \ / \&lt;br /&gt;
       M A H U&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The first letter is &#039;H&#039;; this on the tree is &amp;lt;tt&amp;gt;110&amp;lt;/tt&amp;gt; The next letter is &#039;U&#039; which is &amp;lt;tt&amp;gt;111&amp;lt;/tt&amp;gt;.  The third letter is &#039;F&#039; which is &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt; and so on (notice common letters have shorter strings?)  The final output in bits is &amp;lt;tt&amp;gt;110111000010010101&amp;lt;/tt&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is not of course the optimum Huffman tree, but that doesn&#039;t matter in this case, ANY tree will do. As bytes the output is thus: &amp;lt;tt&amp;gt;11011100 00100101 01000000&amp;lt;/tt&amp;gt; (the end bit is padded with nulls) or &amp;lt;tt&amp;gt;$DC $25 $40&amp;lt;/tt&amp;gt;.  We have a reduction in size from 7 bytes to 3, over 50%!  Sadly, we then need to include the Huffman table (the &#039;&#039;dictionary&#039;&#039;) in some form.&lt;br /&gt;
&lt;br /&gt;
In general a dictionary is built up by listing each node sequentially starting at 0 and ending with the root.&lt;br /&gt;
&lt;br /&gt;
A possibility for storing the dictionary might be:&lt;br /&gt;
&lt;br /&gt;
    $00 $46 $00 $4E   $01 $02 $01 $03   $00 $4D $00 $41   $00 $48 $00 $55   $01 $01 $01 $00&lt;br /&gt;
     -   F   -   N     -   -   -   -     -   M   -   A     -   H   -   U     -   -   -   -&lt;br /&gt;
       (node 0)          (node 1)          (node 2)          (node 3)          (Root node)&lt;br /&gt;
&lt;br /&gt;
In &lt;br /&gt;
&lt;br /&gt;
Here we have numbered the nodes starting at the root as 254 and labelled every other node from 0-3 going left to right and top to bottom.  This dictionary is stored &#039;&#039;bottom to top&#039;&#039; left to right. The first four bytes belong to node 0, the next four to node 2, the next to node 3, the next to node 1 and the final four bytes belonging to the root node. This somewhat &#039;reversed&#039; method of storage as opposed to labeling is used in the Keen executables and is a result of how trees were built in one direction then read and stored in the other.&lt;br /&gt;
&lt;br /&gt;
To decompress the data we use the tree again starting at the root node and reading the data bit by bit. So the first three bits are &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; which leads us down the tree to character &#039;H&#039;, then &amp;lt;tt&amp;gt;000&amp;lt;/tt&amp;gt; which leads us to &#039;U&#039; and so on.&lt;br /&gt;
&lt;br /&gt;
==Huffman implementation in ID Software games==&lt;br /&gt;
&lt;br /&gt;
Games created by Id Software (such as [[Commander Keen 4-6]] or [[Wolfenstein 3-D]]) have a shared but distinct implementation of Huffman compression. The dictionary consists of 1020 bytes (254 nodes plus for null bytes of padding) and there are two or three dictionaries stored in the executable depending on game. (The end of these can be found by looking for node 254 which usually consists of the string $00 $00 $FD $01)&lt;br /&gt;
&lt;br /&gt;
The data itself is stored in an external file which consists of a number of concatenated &#039;chunks&#039;, each chunk beginning with a dword giving its decompressed size. There is also an internal &#039;header&#039; file consisting of a series of three (or sometimes four) byte offsets to the start of various chunks in the data file. (The end of this can be found as the last entry is the length of the data file.)&lt;br /&gt;
&lt;br /&gt;
The data itself is read byte-by-byte in the normal fashion &#039;&#039;but with the order of bits in every byte being reversed&#039;&#039;. The following 1020 bytes constitute the complete &#039;trivial&#039; Huffman dictionary for this implementation, that is, one that does not compress the data at all:&lt;br /&gt;
&lt;br /&gt;
 $00 $00 $80 $00 $40 $00 $C0 $00 $20 $00 $A0 $00 $60 $00 $E0 $00&lt;br /&gt;
 $10 $00 $90 $00 $50 $00 $D0 $00 $30 $00 $B0 $00 $70 $00 $F0 $00&lt;br /&gt;
 $08 $00 $88 $00 $48 $00 $C8 $00 $28 $00 $A8 $00 $68 $00 $E8 $00&lt;br /&gt;
 $18 $00 $98 $00 $58 $00 $D8 $00 $38 $00 $B8 $00 $78 $00 $F8 $00&lt;br /&gt;
 $04 $00 $84 $00 $44 $00 $C4 $00 $24 $00 $A4 $00 $64 $00 $E4 $00&lt;br /&gt;
 $14 $00 $94 $00 $54 $00 $D4 $00 $34 $00 $B4 $00 $74 $00 $F4 $00&lt;br /&gt;
 $0C $00 $8C $00 $4C $00 $CC $00 $2C $00 $AC $00 $6C $00 $EC $00&lt;br /&gt;
 $1C $00 $9C $00 $5C $00 $DC $00 $3C $00 $BC $00 $7C $00 $FC $00&lt;br /&gt;
 $02 $00 $82 $00 $42 $00 $C2 $00 $22 $00 $A2 $00 $62 $00 $E2 $00&lt;br /&gt;
 $12 $00 $92 $00 $52 $00 $D2 $00 $32 $00 $B2 $00 $72 $00 $F2 $00&lt;br /&gt;
 $0A $00 $8A $00 $4A $00 $CA $00 $2A $00 $AA $00 $6A $00 $EA $00&lt;br /&gt;
 $1A $00 $9A $00 $5A $00 $DA $00 $3A $00 $BA $00 $7A $00 $FA $00&lt;br /&gt;
 $06 $00 $86 $00 $46 $00 $C6 $00 $26 $00 $A6 $00 $66 $00 $E6 $00&lt;br /&gt;
 $16 $00 $96 $00 $56 $00 $D6 $00 $36 $00 $B6 $00 $76 $00 $F6 $00&lt;br /&gt;
 $0E $00 $8E $00 $4E $00 $CE $00 $2E $00 $AE $00 $6E $00 $EE $00&lt;br /&gt;
 $1E $00 $9E $00 $5E $00 $DE $00 $3E $00 $BE $00 $7E $00 $FE $00&lt;br /&gt;
 $01 $00 $81 $00 $41 $00 $C1 $00 $21 $00 $A1 $00 $61 $00 $E1 $00&lt;br /&gt;
 $11 $00 $91 $00 $51 $00 $D1 $00 $31 $00 $B1 $00 $71 $00 $F1 $00&lt;br /&gt;
 $09 $00 $89 $00 $49 $00 $C9 $00 $29 $00 $A9 $00 $69 $00 $E9 $00&lt;br /&gt;
 $19 $00 $99 $00 $59 $00 $D9 $00 $39 $00 $B9 $00 $79 $00 $F9 $00&lt;br /&gt;
 $05 $00 $85 $00 $45 $00 $C5 $00 $25 $00 $A5 $00 $65 $00 $E5 $00&lt;br /&gt;
 $15 $00 $95 $00 $55 $00 $D5 $00 $35 $00 $B5 $00 $75 $00 $F5 $00&lt;br /&gt;
 $0D $00 $8D $00 $4D $00 $CD $00 $2D $00 $AD $00 $6D $00 $ED $00&lt;br /&gt;
 $1D $00 $9D $00 $5D $00 $DD $00 $3D $00 $BD $00 $7D $00 $FD $00&lt;br /&gt;
 $03 $00 $83 $00 $43 $00 $C3 $00 $23 $00 $A3 $00 $63 $00 $E3 $00&lt;br /&gt;
 $13 $00 $93 $00 $53 $00 $D3 $00 $33 $00 $B3 $00 $73 $00 $F3 $00&lt;br /&gt;
 $0B $00 $8B $00 $4B $00 $CB $00 $2B $00 $AB $00 $6B $00 $EB $00&lt;br /&gt;
 $1B $00 $9B $00 $5B $00 $DB $00 $3B $00 $BB $00 $7B $00 $FB $00&lt;br /&gt;
 $07 $00 $87 $00 $47 $00 $C7 $00 $27 $00 $A7 $00 $67 $00 $E7 $00&lt;br /&gt;
 $17 $00 $97 $00 $57 $00 $D7 $00 $37 $00 $B7 $00 $77 $00 $F7 $00&lt;br /&gt;
 $0F $00 $8F $00 $4F $00 $CF $00 $2F $00 $AF $00 $6F $00 $EF $00&lt;br /&gt;
 $1F $00 $9F $00 $5F $00 $DF $00 $3F $00 $BF $00 $7F $00 $FF $00&lt;br /&gt;
 $00 $01 $01 $01 $02 $01 $03 $01 $04 $01 $05 $01 $06 $01 $07 $01&lt;br /&gt;
 $08 $01 $09 $01 $0A $01 $0B $01 $0C $01 $0D $01 $0E $01 $0F $01&lt;br /&gt;
 $10 $01 $11 $01 $12 $01 $13 $01 $14 $01 $15 $01 $16 $01 $17 $01&lt;br /&gt;
 $18 $01 $19 $01 $1A $01 $1B $01 $1C $01 $1D $01 $1E $01 $1F $01&lt;br /&gt;
 $20 $01 $21 $01 $22 $01 $23 $01 $24 $01 $25 $01 $26 $01 $27 $01&lt;br /&gt;
 $28 $01 $29 $01 $2A $01 $2B $01 $2C $01 $2D $01 $2E $01 $2F $01&lt;br /&gt;
 $30 $01 $31 $01 $32 $01 $33 $01 $34 $01 $35 $01 $36 $01 $37 $01&lt;br /&gt;
 $38 $01 $39 $01 $3A $01 $3B $01 $3C $01 $3D $01 $3E $01 $3F $01&lt;br /&gt;
 $40 $01 $41 $01 $42 $01 $43 $01 $44 $01 $45 $01 $46 $01 $47 $01&lt;br /&gt;
 $48 $01 $49 $01 $4A $01 $4B $01 $4C $01 $4D $01 $4E $01 $4F $01&lt;br /&gt;
 $50 $01 $51 $01 $52 $01 $53 $01 $54 $01 $55 $01 $56 $01 $57 $01&lt;br /&gt;
 $58 $01 $59 $01 $5A $01 $5B $01 $5C $01 $5D $01 $5E $01 $5F $01&lt;br /&gt;
 $60 $01 $61 $01 $62 $01 $63 $01 $64 $01 $65 $01 $66 $01 $67 $01&lt;br /&gt;
 $68 $01 $69 $01 $6A $01 $6B $01 $6C $01 $6D $01 $6E $01 $6F $01&lt;br /&gt;
 $70 $01 $71 $01 $72 $01 $73 $01 $74 $01 $75 $01 $76 $01 $77 $01&lt;br /&gt;
 $78 $01 $79 $01 $7A $01 $7B $01 $7C $01 $7D $01 $7E $01 $7F $01&lt;br /&gt;
 $80 $01 $81 $01 $82 $01 $83 $01 $84 $01 $85 $01 $86 $01 $87 $01&lt;br /&gt;
 $88 $01 $89 $01 $8A $01 $8B $01 $8C $01 $8D $01 $8E $01 $8F $01&lt;br /&gt;
 $90 $01 $91 $01 $92 $01 $93 $01 $94 $01 $95 $01 $96 $01 $97 $01&lt;br /&gt;
 $98 $01 $99 $01 $9A $01 $9B $01 $9C $01 $9D $01 $9E $01 $9F $01&lt;br /&gt;
 $A0 $01 $A1 $01 $A2 $01 $A3 $01 $A4 $01 $A5 $01 $A6 $01 $A7 $01&lt;br /&gt;
 $A8 $01 $A9 $01 $AA $01 $AB $01 $AC $01 $AD $01 $AE $01 $AF $01&lt;br /&gt;
 $B0 $01 $B1 $01 $B2 $01 $B3 $01 $B4 $01 $B5 $01 $B6 $01 $B7 $01&lt;br /&gt;
 $B8 $01 $B9 $01 $BA $01 $BB $01 $BC $01 $BD $01 $BE $01 $BF $01&lt;br /&gt;
 $C0 $01 $C1 $01 $C2 $01 $C3 $01 $C4 $01 $C5 $01 $C6 $01 $C7 $01&lt;br /&gt;
 $C8 $01 $C9 $01 $CA $01 $CB $01 $CC $01 $CD $01 $CE $01 $CF $01&lt;br /&gt;
 $D0 $01 $D1 $01 $D2 $01 $D3 $01 $D4 $01 $D5 $01 $D6 $01 $D7 $01&lt;br /&gt;
 $D8 $01 $D9 $01 $DA $01 $DB $01 $DC $01 $DD $01 $DE $01 $DF $01&lt;br /&gt;
 $E0 $01 $E1 $01 $E2 $01 $E3 $01 $E4 $01 $E5 $01 $E6 $01 $E7 $01&lt;br /&gt;
 $E8 $01 $E9 $01 $EA $01 $EB $01 $EC $01 $ED $01 $EE $01 $EF $01&lt;br /&gt;
 $F0 $01 $F1 $01 $F2 $01 $F3 $01 $F4 $01 $F5 $01 $F6 $01 $F7 $01&lt;br /&gt;
 $F8 $01 $F9 $01 $FA $01 $FB $01 $FC $01 $FD $01&lt;br /&gt;
&lt;br /&gt;
This is a useful example to use since it has a number of unique features. Firstly the paths to any given terminal node are all the same length, 8 bits. Secondly the &#039;byte reversal&#039; can easily be seen in that the path to each terminal node is the &#039;&#039;reverse&#039;&#039; of the character it represents. And finally the nodes are arranged in a logical order with an easily seen pattern; the first half of the tree consists of terminal nodes, the second half of branch nodes. (Of the second half the first half of &#039;&#039;that&#039;&#039; consists of branch nodes that lead to terminal nodes while the second half consists of branch nodes to two branch nodes and so on.)&lt;br /&gt;
&lt;br /&gt;
As an example the character $80 (128 or 10000000) can be expected to be represented by the path &#039;00000001&#039; and as such be the second node in the tree. Starting at the root node and following the leftmost path until the last step takes us to the following nodes: 254(root) -&amp;gt; 252 -&amp;gt; 248 -&amp;gt; 240 -&amp;gt; 224 -&amp;gt; 192 -&amp;gt; 128 -&amp;gt; 0(terminal node for characters $00 and $80)&lt;br /&gt;
&lt;br /&gt;
== Source code ==&lt;br /&gt;
&lt;br /&gt;
Some example code is available in various languages showing how to decompress (and in some cases compress) files using the Huffman algorithm.&lt;br /&gt;
&lt;br /&gt;
=== QuickBasic ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; DANGEROUS DAVE 2 - IN THE HAUNTED MANSION - Huffman Decompressor&lt;br /&gt;
&#039;  - by Napalm with thanks to Adurdin&#039;s work on ModKeen&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; This source is Public Domain, please credit me if you use it.&lt;br /&gt;
&#039;&lt;br /&gt;
&#039;&lt;br /&gt;
DECLARE SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING)&lt;br /&gt;
&lt;br /&gt;
TYPE NODE&lt;br /&gt;
        BIT0 AS INTEGER&lt;br /&gt;
        BIT1 AS INTEGER&lt;br /&gt;
END TYPE&lt;br /&gt;
&lt;br /&gt;
&#039; Test Function&lt;br /&gt;
HUFFDECOMPRESS &amp;quot;TITLE1.DD2&amp;quot;, &amp;quot;TITLE1.PIC&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING) &#039; by Napalm&lt;br /&gt;
	DIM INFILE AS INTEGER, OUTFILE AS INTEGER, I AS INTEGER&lt;br /&gt;
	DIM SIG AS LONG, OUTLEN AS LONG, BITMASK AS INTEGER&lt;br /&gt;
	DIM CURNODE AS INTEGER, NEXTNODE AS INTEGER&lt;br /&gt;
	DIM CHRIN AS STRING * 1, CHROUT AS STRING * 1&lt;br /&gt;
	DIM NODES(0 TO 254) AS NODE&lt;br /&gt;
&lt;br /&gt;
	&#039; Open input file&lt;br /&gt;
	INFILE = FREEFILE&lt;br /&gt;
	OPEN INNAME FOR BINARY ACCESS READ AS INFILE&lt;br /&gt;
       &lt;br /&gt;
	&#039; Check file signature&lt;br /&gt;
	GET INFILE, , SIG&lt;br /&gt;
	IF SIG &amp;lt;&amp;gt; &amp;amp;H46465548 THEN &#039; Hex for: HUFF in little endian&lt;br /&gt;
		PRINT &amp;quot;INVALID FILE!&amp;quot;&lt;br /&gt;
		EXIT SUB&lt;br /&gt;
	END IF&lt;br /&gt;
       &lt;br /&gt;
	&#039; Get output length&lt;br /&gt;
	OUTLEN = 0&lt;br /&gt;
	GET INFILE, , OUTLEN&lt;br /&gt;
       &lt;br /&gt;
	&#039; Read in the huffman binary tree&lt;br /&gt;
	FOR I = 0 TO 254&lt;br /&gt;
		GET INFILE, , NODES(I).BIT0&lt;br /&gt;
		GET INFILE, , NODES(I).BIT1&lt;br /&gt;
	NEXT I&lt;br /&gt;
&lt;br /&gt;
	&#039; Open output file&lt;br /&gt;
	OUTFILE = FREEFILE&lt;br /&gt;
	OPEN OUTNAME FOR BINARY ACCESS WRITE AS OUTFILE&lt;br /&gt;
&lt;br /&gt;
	&#039; Decompress input data using binary tree&lt;br /&gt;
	CURNODE = 254&lt;br /&gt;
	DO&lt;br /&gt;
		BITMASK = 0&lt;br /&gt;
		GET INFILE, , CHRIN&lt;br /&gt;
		DO&lt;br /&gt;
			&#039; Decide which node to travel down depending on&lt;br /&gt;
			&#039;   input bits from CHRIN.&lt;br /&gt;
			IF ASC(CHRIN) AND 2 ^ BITMASK THEN&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT1&lt;br /&gt;
			ELSE&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT0&lt;br /&gt;
			END IF&lt;br /&gt;
		       &lt;br /&gt;
			&#039; Is this next node another part of the tree or&lt;br /&gt;
			&#039;   is it a end node? Less than 256 mean end node.&lt;br /&gt;
			IF NEXTNODE &amp;lt; 256 THEN&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Get output char from end node and save.&lt;br /&gt;
				CHROUT = CHR$(NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
				PUT OUTFILE, , CHROUT&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Amend output length and start from top of&lt;br /&gt;
				&#039;   binary tree.&lt;br /&gt;
				OUTLEN = OUTLEN - 1&lt;br /&gt;
				CURNODE = 254&lt;br /&gt;
&lt;br /&gt;
			ELSE&lt;br /&gt;
				&#039; Travel to next node&lt;br /&gt;
				CURNODE = (NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
&lt;br /&gt;
			END IF&lt;br /&gt;
&lt;br /&gt;
			&#039; Move to next input bit&lt;br /&gt;
			BITMASK = BITMASK + 1&lt;br /&gt;
		LOOP WHILE BITMASK &amp;lt; 8 AND OUTLEN &amp;gt; 0&lt;br /&gt;
		&#039; Loop while we still need to output data&lt;br /&gt;
	LOOP WHILE OUTLEN &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
	&#039; Clean up&lt;br /&gt;
	CLOSE OUTFILE&lt;br /&gt;
	CLOSE INFILE&lt;br /&gt;
&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
SUB MAKHUF &#039;Mak a degenerate huffman tree, store as string huffq&lt;br /&gt;
	OPEN &amp;quot;HUFF.DD2&amp;quot; FOR BINARY AS #8&lt;br /&gt;
	aq = &amp;quot;HUFF&amp;quot;&lt;br /&gt;
	PUT #8, 1, aq&lt;br /&gt;
	x = 9&lt;br /&gt;
	FOR t = 0 TO 255&lt;br /&gt;
		b = t&lt;br /&gt;
		va = 0&lt;br /&gt;
		vb = 0&lt;br /&gt;
		vc = 0&lt;br /&gt;
		vd = 0&lt;br /&gt;
		ve = 0&lt;br /&gt;
		vf = 0&lt;br /&gt;
		vg = 0&lt;br /&gt;
		vh = 0&lt;br /&gt;
		IF b &amp;gt; 127 THEN LET va = va + 1&lt;br /&gt;
		b = b MOD 128&lt;br /&gt;
		IF b &amp;gt; 63 THEN LET vb = vb + 1&lt;br /&gt;
		b = b MOD 64&lt;br /&gt;
		IF b &amp;gt; 31 THEN LET vc = vc + 1&lt;br /&gt;
		b = b MOD 32&lt;br /&gt;
		IF b &amp;gt; 15 THEN LET vd = vd + 1&lt;br /&gt;
		b = b MOD 16&lt;br /&gt;
		IF b &amp;gt; 7 THEN LET ve = ve + 1&lt;br /&gt;
		b = b MOD 8&lt;br /&gt;
		IF b &amp;gt; 3 THEN LET vf = vf + 1&lt;br /&gt;
		b = b MOD 4&lt;br /&gt;
		IF b &amp;gt; 1 THEN LET vg = vg + 1&lt;br /&gt;
		b = b MOD 2&lt;br /&gt;
		IF b = 1 THEN LET vh = vh + 1&lt;br /&gt;
		b = (vh * 128) + (vg * 64) + (vf * 32) + (16 * ve) + (8 * vd) + (4 * vc) + (2 * vb) + va&lt;br /&gt;
		aq = MKI$(b)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	FOR t = 0 TO 253&lt;br /&gt;
		aq = MKI$(t + 256)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	GET #8, 1, huffq&lt;br /&gt;
	CLOSE #8&lt;br /&gt;
	KILL &amp;quot;HUFF.DD2&amp;quot;&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Visual Basic .NET ===&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree representation ====&lt;br /&gt;
&lt;br /&gt;
This class, BinaryTreeNode, represents a binary tree whose branch nodes carry no value, like a Huffman dictionary tree.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;Public Class BinaryTreeNode(Of T)&lt;br /&gt;
    &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
    Private Branch As Boolean&lt;br /&gt;
    Private Children As BinaryTreeNode(Of T)()&lt;br /&gt;
    Private HoldValue As T&lt;br /&gt;
    Public Sub New(LeafValue As T)&lt;br /&gt;
        Branch = False&lt;br /&gt;
        HoldValue = LeafValue&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public Sub New(LeftChild As BinaryTreeNode(Of T), RightChild As BinaryTreeNode(Of T))&lt;br /&gt;
        Branch = True&lt;br /&gt;
        Children = {LeftChild, RightChild}&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public ReadOnly Property HasValue As Boolean&lt;br /&gt;
        Get&lt;br /&gt;
            Return Not Branch&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Value As T&lt;br /&gt;
        Get&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return HoldValue&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As T)&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            HoldValue = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Child(Side As ChildSide) As BinaryTreeNode(Of T)&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return Children(Side)&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As BinaryTreeNode(Of T))&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Children(Side) = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Enum ChildSide As Byte&lt;br /&gt;
        Left = 0&lt;br /&gt;
        Right = 1&lt;br /&gt;
    End Enum&lt;br /&gt;
    Public ReadOnly Property Count As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Children(0).Count + Children(1).Count&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public ReadOnly Property Depth As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Math.Max(Children(0).Depth, Children(1).Depth) + 1&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Overrides Function ToString() As String&lt;br /&gt;
        Return &amp;quot;{Count = &amp;quot; &amp;amp; Count &amp;amp; &amp;quot;, Depth = &amp;quot; &amp;amp; Depth &amp;amp; &amp;quot;}&amp;quot;&lt;br /&gt;
    End Function&lt;br /&gt;
End Class&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree reading ====&lt;br /&gt;
&lt;br /&gt;
This piece of code will read in a stored Huffman dictionary in the format described at the top of this article and store it in a BinaryTreeNode(Of Byte) as shown above.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;        &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
        Dim fDict As New IO.FileStream(DictionaryFile, IO.FileMode.Open)&lt;br /&gt;
        Dim raw(254) As Tuple(Of UShort, UShort)&lt;br /&gt;
        For x = 0 To 254&lt;br /&gt;
            raw(x) = Tuple.Create(ReadUShort(fDict), ReadUShort(fDict))&lt;br /&gt;
        Next&lt;br /&gt;
        fDict.Close()&lt;br /&gt;
        Dim GenerateTree As Func(Of UShort, BinaryTreeNode(Of Byte))&lt;br /&gt;
        GenerateTree = Function(NextNode As UShort) As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           Dim n As Tuple(Of UShort, UShort) = raw(NextNode)&lt;br /&gt;
                           Dim a, b As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           If n.Item1 &amp;lt; 256 Then&lt;br /&gt;
                               a = New BinaryTreeNode(Of Byte)(n.Item1)&lt;br /&gt;
                           Else&lt;br /&gt;
                               a = GenerateTree(n.Item1 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           If n.Item2 &amp;lt; 256 Then&lt;br /&gt;
                               b = New BinaryTreeNode(Of Byte)(n.Item2)&lt;br /&gt;
                           Else&lt;br /&gt;
                               b = GenerateTree(n.Item2 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           Return New BinaryTreeNode(Of Byte)(a, b)&lt;br /&gt;
                       End Function&lt;br /&gt;
        Dim dict As BinaryTreeNode(Of Byte) = GenerateTree(254)&lt;br /&gt;
        fDict.Close()&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Code examples]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6841</id>
		<title>Huffman Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=6841"/>
		<updated>2016-05-23T09:23:07Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Reword example and more clearly label nodes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Compression Infobox&lt;br /&gt;
 | Type = Stream&lt;br /&gt;
 | UnitSize = 1-byte in, 1-bit out&lt;br /&gt;
 | Games =&lt;br /&gt;
   {{Game|The Blues Brothers}}&lt;br /&gt;
   {{Game|Catacomb 3-D}}&lt;br /&gt;
   {{Game|Commander Keen Dreams}}&lt;br /&gt;
   {{Game|Dangerous Dave 2}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Huffman Compression]] is a compression algorithm used in many classic games. It is about as efficient as LZW or RLE compression, with many games using the three formats simultaneously.&lt;br /&gt;
&lt;br /&gt;
Huffman compression involves making/reading a &#039;&#039;dictionary&#039;&#039; of 256 entries, one for each possible 1-byte character.  This is organised in the form of a &#039;&#039;binary tree&#039;&#039; which is basically formed by taking the two lowest frequency characters and combining them into a new entry with their added frequencies and repeating until all entries are reduced to one &#039;&#039;root node&#039;&#039;.  After the dictionary is created, every character of data is replaced with the corresponding bit representation from the tree.&lt;br /&gt;
&lt;br /&gt;
Any Huffman compressed data will thus be associated with a dictionary file (internal or external) used to decompress it.&lt;br /&gt;
&lt;br /&gt;
==Nodes==&lt;br /&gt;
&lt;br /&gt;
The binary tree must be stored in some form, usually called a &#039;&#039;dictionary&#039;&#039;. The format varies from game to game, but is usually broadly along these lines. The tree will have 254 nodes (for all the one byte characters in game data) stored as two &#039;branches&#039; of that node, usually taking up 4 bytes each, but sometimes 3. The second part is either 0 or 1, and says whether that branch goes to a character (0) or another node (1).  The first part is the value of either that character or that node. (For the usual 4-byte implementation each part is a byte.)&lt;br /&gt;
&lt;br /&gt;
In the Huffman table then we can expect to see each possible character TWICE, once as a character, once as a node reference. Note that the nodes are numbered from 0-253, NOT 1-254. The order of the nodes doesn&#039;t matter, only how they are connected.&lt;br /&gt;
&lt;br /&gt;
The root node is ALWAYS node 254 (number 253!) and should always be something like $xx $yy $00 $00 (Since 0 is the most common character it is closest to the root.) It will also tend to be at the end of the dictionary, since most programs find it easier to write their dictionaries from bottom to top. This can often be used to find Huffman dictionaries in files, if you know what you are looking for.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&lt;br /&gt;
Compress the word &amp;quot;HUFFMAN&amp;quot;.  For simplicity, we will not use the usual 256 character tree, but rather something a bit smaller. (Huffman trees can be any size, the concept is the same.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Frequencies are:&amp;lt;br/&amp;gt;1: H,U,M,A,N&amp;lt;br/&amp;gt;2: F&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Make a binary tree: (here left = 0 and right = 1)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &#039;Root node&#039;&lt;br /&gt;
     [254] &lt;br /&gt;
      / \&lt;br /&gt;
     /  [1] &lt;br /&gt;
    /   / \&lt;br /&gt;
  [0] [2] [3]&lt;br /&gt;
  / \ / \ / \&lt;br /&gt;
  F N M A H U&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The first letter is &#039;H&#039;; this on the tree is &amp;lt;tt&amp;gt;110&amp;lt;/tt&amp;gt; The next letter is &#039;U&#039; which is &amp;lt;tt&amp;gt;111&amp;lt;/tt&amp;gt;.  The third letter is &#039;F&#039; which is &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt; and so on (notice common letters have shorter strings?)  The final output in bits is &amp;lt;tt&amp;gt;110111000010010101&amp;lt;/tt&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is not of course the optimum Huffman tree, but that doesn&#039;t matter, ANY tree will do. As bytes the output is thus: &amp;lt;tt&amp;gt;11011100 00100101 01000000&amp;lt;/tt&amp;gt; (the end bit is padded with nulls) or &amp;lt;tt&amp;gt;$DC $25 $40&amp;lt;/tt&amp;gt;.  We have a reduction in size from 7 bytes to 3, over 50%!  Sadly, we then need to include the Huffman table (the &#039;&#039;dictionary&#039;&#039;) in some form.&lt;br /&gt;
&lt;br /&gt;
A possibility for storing the dictionary might be: &amp;lt;tt&amp;gt;$00 $46 $00 $4E $00 $4D $00 $41 $00 $48 $00 $55 $01 $02 $01 $03 $01 $01 $01 $00&amp;lt;/tt&amp;gt;.  Here we have numbered the nodes starting at the root as 254 and labelled every other node from 0-3 going left to right and top to bottom. (Notice node 0 is shown in the example on the same level as nodes 2 and 3, it is actually a level higher, with node 1.) This dictionary is stored &#039;&#039;bottom to top&#039;&#039; left to right. The first four bytes belong to node 0, the next four to node 2, the next to node 3, the next to node 1 and the final four bytes belonging to the root node. This somewhat &#039;reversed&#039; method of storage as opposed to labeling is used in the Keen executables and is a result of how trees were built in one direction then read and stored in the other.&lt;br /&gt;
&lt;br /&gt;
To decompress the data we use the tree again starting at the root node and reading the data bit by bit. So the first three bits are &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; which leads us down the tree to character &#039;H&#039;, then &amp;lt;tt&amp;gt;000&amp;lt;/tt&amp;gt; which leads us to &#039;U&#039; and so on.&lt;br /&gt;
&lt;br /&gt;
==Huffman implementation in ID Software games==&lt;br /&gt;
&lt;br /&gt;
Games created by Id Software (such as [[Commander Keen 4-6]] or [[Wolfenstein 3-D]]) have a shared but distinct implementation of Huffman compression. The dictionary consists of 1020 bytes (254 nodes plus for null bytes of padding) and there are two or three dictionaries stored in the executable depending on game. (The end of these can be found by looking for node 254 which usually consists of the string $00 $00 $FD $01)&lt;br /&gt;
&lt;br /&gt;
The data itself is stored in an external file which consists of a number of concatenated &#039;chunks&#039;, each chunk beginning with a dword giving its decompressed size. There is also an internal &#039;header&#039; file consisting of a series of three (or sometimes four) byte offsets to the start of various chunks in the data file. (The end of this can be found as the last entry is the length of the data file.)&lt;br /&gt;
&lt;br /&gt;
The data itself is read byte-by-byte in the normal fashion &#039;&#039;but with the order of bits in every byte being reversed&#039;&#039;. The following 1020 bytes constitute the complete &#039;trivial&#039; Huffman dictionary for this implementation, that is, one that does not compress the data at all:&lt;br /&gt;
&lt;br /&gt;
 $00 $00 $80 $00 $40 $00 $C0 $00 $20 $00 $A0 $00 $60 $00 $E0 $00&lt;br /&gt;
 $10 $00 $90 $00 $50 $00 $D0 $00 $30 $00 $B0 $00 $70 $00 $F0 $00&lt;br /&gt;
 $08 $00 $88 $00 $48 $00 $C8 $00 $28 $00 $A8 $00 $68 $00 $E8 $00&lt;br /&gt;
 $18 $00 $98 $00 $58 $00 $D8 $00 $38 $00 $B8 $00 $78 $00 $F8 $00&lt;br /&gt;
 $04 $00 $84 $00 $44 $00 $C4 $00 $24 $00 $A4 $00 $64 $00 $E4 $00&lt;br /&gt;
 $14 $00 $94 $00 $54 $00 $D4 $00 $34 $00 $B4 $00 $74 $00 $F4 $00&lt;br /&gt;
 $0C $00 $8C $00 $4C $00 $CC $00 $2C $00 $AC $00 $6C $00 $EC $00&lt;br /&gt;
 $1C $00 $9C $00 $5C $00 $DC $00 $3C $00 $BC $00 $7C $00 $FC $00&lt;br /&gt;
 $02 $00 $82 $00 $42 $00 $C2 $00 $22 $00 $A2 $00 $62 $00 $E2 $00&lt;br /&gt;
 $12 $00 $92 $00 $52 $00 $D2 $00 $32 $00 $B2 $00 $72 $00 $F2 $00&lt;br /&gt;
 $0A $00 $8A $00 $4A $00 $CA $00 $2A $00 $AA $00 $6A $00 $EA $00&lt;br /&gt;
 $1A $00 $9A $00 $5A $00 $DA $00 $3A $00 $BA $00 $7A $00 $FA $00&lt;br /&gt;
 $06 $00 $86 $00 $46 $00 $C6 $00 $26 $00 $A6 $00 $66 $00 $E6 $00&lt;br /&gt;
 $16 $00 $96 $00 $56 $00 $D6 $00 $36 $00 $B6 $00 $76 $00 $F6 $00&lt;br /&gt;
 $0E $00 $8E $00 $4E $00 $CE $00 $2E $00 $AE $00 $6E $00 $EE $00&lt;br /&gt;
 $1E $00 $9E $00 $5E $00 $DE $00 $3E $00 $BE $00 $7E $00 $FE $00&lt;br /&gt;
 $01 $00 $81 $00 $41 $00 $C1 $00 $21 $00 $A1 $00 $61 $00 $E1 $00&lt;br /&gt;
 $11 $00 $91 $00 $51 $00 $D1 $00 $31 $00 $B1 $00 $71 $00 $F1 $00&lt;br /&gt;
 $09 $00 $89 $00 $49 $00 $C9 $00 $29 $00 $A9 $00 $69 $00 $E9 $00&lt;br /&gt;
 $19 $00 $99 $00 $59 $00 $D9 $00 $39 $00 $B9 $00 $79 $00 $F9 $00&lt;br /&gt;
 $05 $00 $85 $00 $45 $00 $C5 $00 $25 $00 $A5 $00 $65 $00 $E5 $00&lt;br /&gt;
 $15 $00 $95 $00 $55 $00 $D5 $00 $35 $00 $B5 $00 $75 $00 $F5 $00&lt;br /&gt;
 $0D $00 $8D $00 $4D $00 $CD $00 $2D $00 $AD $00 $6D $00 $ED $00&lt;br /&gt;
 $1D $00 $9D $00 $5D $00 $DD $00 $3D $00 $BD $00 $7D $00 $FD $00&lt;br /&gt;
 $03 $00 $83 $00 $43 $00 $C3 $00 $23 $00 $A3 $00 $63 $00 $E3 $00&lt;br /&gt;
 $13 $00 $93 $00 $53 $00 $D3 $00 $33 $00 $B3 $00 $73 $00 $F3 $00&lt;br /&gt;
 $0B $00 $8B $00 $4B $00 $CB $00 $2B $00 $AB $00 $6B $00 $EB $00&lt;br /&gt;
 $1B $00 $9B $00 $5B $00 $DB $00 $3B $00 $BB $00 $7B $00 $FB $00&lt;br /&gt;
 $07 $00 $87 $00 $47 $00 $C7 $00 $27 $00 $A7 $00 $67 $00 $E7 $00&lt;br /&gt;
 $17 $00 $97 $00 $57 $00 $D7 $00 $37 $00 $B7 $00 $77 $00 $F7 $00&lt;br /&gt;
 $0F $00 $8F $00 $4F $00 $CF $00 $2F $00 $AF $00 $6F $00 $EF $00&lt;br /&gt;
 $1F $00 $9F $00 $5F $00 $DF $00 $3F $00 $BF $00 $7F $00 $FF $00&lt;br /&gt;
 $00 $01 $01 $01 $02 $01 $03 $01 $04 $01 $05 $01 $06 $01 $07 $01&lt;br /&gt;
 $08 $01 $09 $01 $0A $01 $0B $01 $0C $01 $0D $01 $0E $01 $0F $01&lt;br /&gt;
 $10 $01 $11 $01 $12 $01 $13 $01 $14 $01 $15 $01 $16 $01 $17 $01&lt;br /&gt;
 $18 $01 $19 $01 $1A $01 $1B $01 $1C $01 $1D $01 $1E $01 $1F $01&lt;br /&gt;
 $20 $01 $21 $01 $22 $01 $23 $01 $24 $01 $25 $01 $26 $01 $27 $01&lt;br /&gt;
 $28 $01 $29 $01 $2A $01 $2B $01 $2C $01 $2D $01 $2E $01 $2F $01&lt;br /&gt;
 $30 $01 $31 $01 $32 $01 $33 $01 $34 $01 $35 $01 $36 $01 $37 $01&lt;br /&gt;
 $38 $01 $39 $01 $3A $01 $3B $01 $3C $01 $3D $01 $3E $01 $3F $01&lt;br /&gt;
 $40 $01 $41 $01 $42 $01 $43 $01 $44 $01 $45 $01 $46 $01 $47 $01&lt;br /&gt;
 $48 $01 $49 $01 $4A $01 $4B $01 $4C $01 $4D $01 $4E $01 $4F $01&lt;br /&gt;
 $50 $01 $51 $01 $52 $01 $53 $01 $54 $01 $55 $01 $56 $01 $57 $01&lt;br /&gt;
 $58 $01 $59 $01 $5A $01 $5B $01 $5C $01 $5D $01 $5E $01 $5F $01&lt;br /&gt;
 $60 $01 $61 $01 $62 $01 $63 $01 $64 $01 $65 $01 $66 $01 $67 $01&lt;br /&gt;
 $68 $01 $69 $01 $6A $01 $6B $01 $6C $01 $6D $01 $6E $01 $6F $01&lt;br /&gt;
 $70 $01 $71 $01 $72 $01 $73 $01 $74 $01 $75 $01 $76 $01 $77 $01&lt;br /&gt;
 $78 $01 $79 $01 $7A $01 $7B $01 $7C $01 $7D $01 $7E $01 $7F $01&lt;br /&gt;
 $80 $01 $81 $01 $82 $01 $83 $01 $84 $01 $85 $01 $86 $01 $87 $01&lt;br /&gt;
 $88 $01 $89 $01 $8A $01 $8B $01 $8C $01 $8D $01 $8E $01 $8F $01&lt;br /&gt;
 $90 $01 $91 $01 $92 $01 $93 $01 $94 $01 $95 $01 $96 $01 $97 $01&lt;br /&gt;
 $98 $01 $99 $01 $9A $01 $9B $01 $9C $01 $9D $01 $9E $01 $9F $01&lt;br /&gt;
 $A0 $01 $A1 $01 $A2 $01 $A3 $01 $A4 $01 $A5 $01 $A6 $01 $A7 $01&lt;br /&gt;
 $A8 $01 $A9 $01 $AA $01 $AB $01 $AC $01 $AD $01 $AE $01 $AF $01&lt;br /&gt;
 $B0 $01 $B1 $01 $B2 $01 $B3 $01 $B4 $01 $B5 $01 $B6 $01 $B7 $01&lt;br /&gt;
 $B8 $01 $B9 $01 $BA $01 $BB $01 $BC $01 $BD $01 $BE $01 $BF $01&lt;br /&gt;
 $C0 $01 $C1 $01 $C2 $01 $C3 $01 $C4 $01 $C5 $01 $C6 $01 $C7 $01&lt;br /&gt;
 $C8 $01 $C9 $01 $CA $01 $CB $01 $CC $01 $CD $01 $CE $01 $CF $01&lt;br /&gt;
 $D0 $01 $D1 $01 $D2 $01 $D3 $01 $D4 $01 $D5 $01 $D6 $01 $D7 $01&lt;br /&gt;
 $D8 $01 $D9 $01 $DA $01 $DB $01 $DC $01 $DD $01 $DE $01 $DF $01&lt;br /&gt;
 $E0 $01 $E1 $01 $E2 $01 $E3 $01 $E4 $01 $E5 $01 $E6 $01 $E7 $01&lt;br /&gt;
 $E8 $01 $E9 $01 $EA $01 $EB $01 $EC $01 $ED $01 $EE $01 $EF $01&lt;br /&gt;
 $F0 $01 $F1 $01 $F2 $01 $F3 $01 $F4 $01 $F5 $01 $F6 $01 $F7 $01&lt;br /&gt;
 $F8 $01 $F9 $01 $FA $01 $FB $01 $FC $01 $FD $01&lt;br /&gt;
&lt;br /&gt;
This is a useful example to use since it has a number of unique features. Firstly the paths to any given terminal node are all the same length, 8 bits. Secondly the &#039;byte reversal&#039; can easily be seen in that the path to each terminal node is the &#039;&#039;reverse&#039;&#039; of the character it represents. And finally the nodes are arranged in a logical order with an easily seen pattern; the first half of the tree consists of terminal nodes, the second half of branch nodes. (Of the second half the first half of &#039;&#039;that&#039;&#039; consists of branch nodes that lead to terminal nodes while the second half consists of branch nodes to two branch nodes and so on.)&lt;br /&gt;
&lt;br /&gt;
As an example the character $80 (128 or 10000000) can be expected to be represented by the path &#039;00000001&#039; and as such be the second node in the tree. Starting at the root node and following the leftmost path until the last step takes us to the following nodes: 254(root) -&amp;gt; 252 -&amp;gt; 248 -&amp;gt; 240 -&amp;gt; 224 -&amp;gt; 192 -&amp;gt; 128 -&amp;gt; 0(terminal node for characters $00 and $80)&lt;br /&gt;
&lt;br /&gt;
== Source code ==&lt;br /&gt;
&lt;br /&gt;
Some example code is available in various languages showing how to decompress (and in some cases compress) files using the Huffman algorithm.&lt;br /&gt;
&lt;br /&gt;
=== QuickBasic ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; DANGEROUS DAVE 2 - IN THE HAUNTED MANSION - Huffman Decompressor&lt;br /&gt;
&#039;  - by Napalm with thanks to Adurdin&#039;s work on ModKeen&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; This source is Public Domain, please credit me if you use it.&lt;br /&gt;
&#039;&lt;br /&gt;
&#039;&lt;br /&gt;
DECLARE SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING)&lt;br /&gt;
&lt;br /&gt;
TYPE NODE&lt;br /&gt;
        BIT0 AS INTEGER&lt;br /&gt;
        BIT1 AS INTEGER&lt;br /&gt;
END TYPE&lt;br /&gt;
&lt;br /&gt;
&#039; Test Function&lt;br /&gt;
HUFFDECOMPRESS &amp;quot;TITLE1.DD2&amp;quot;, &amp;quot;TITLE1.PIC&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING) &#039; by Napalm&lt;br /&gt;
	DIM INFILE AS INTEGER, OUTFILE AS INTEGER, I AS INTEGER&lt;br /&gt;
	DIM SIG AS LONG, OUTLEN AS LONG, BITMASK AS INTEGER&lt;br /&gt;
	DIM CURNODE AS INTEGER, NEXTNODE AS INTEGER&lt;br /&gt;
	DIM CHRIN AS STRING * 1, CHROUT AS STRING * 1&lt;br /&gt;
	DIM NODES(0 TO 254) AS NODE&lt;br /&gt;
&lt;br /&gt;
	&#039; Open input file&lt;br /&gt;
	INFILE = FREEFILE&lt;br /&gt;
	OPEN INNAME FOR BINARY ACCESS READ AS INFILE&lt;br /&gt;
       &lt;br /&gt;
	&#039; Check file signature&lt;br /&gt;
	GET INFILE, , SIG&lt;br /&gt;
	IF SIG &amp;lt;&amp;gt; &amp;amp;H46465548 THEN &#039; Hex for: HUFF in little endian&lt;br /&gt;
		PRINT &amp;quot;INVALID FILE!&amp;quot;&lt;br /&gt;
		EXIT SUB&lt;br /&gt;
	END IF&lt;br /&gt;
       &lt;br /&gt;
	&#039; Get output length&lt;br /&gt;
	OUTLEN = 0&lt;br /&gt;
	GET INFILE, , OUTLEN&lt;br /&gt;
       &lt;br /&gt;
	&#039; Read in the huffman binary tree&lt;br /&gt;
	FOR I = 0 TO 254&lt;br /&gt;
		GET INFILE, , NODES(I).BIT0&lt;br /&gt;
		GET INFILE, , NODES(I).BIT1&lt;br /&gt;
	NEXT I&lt;br /&gt;
&lt;br /&gt;
	&#039; Open output file&lt;br /&gt;
	OUTFILE = FREEFILE&lt;br /&gt;
	OPEN OUTNAME FOR BINARY ACCESS WRITE AS OUTFILE&lt;br /&gt;
&lt;br /&gt;
	&#039; Decompress input data using binary tree&lt;br /&gt;
	CURNODE = 254&lt;br /&gt;
	DO&lt;br /&gt;
		BITMASK = 0&lt;br /&gt;
		GET INFILE, , CHRIN&lt;br /&gt;
		DO&lt;br /&gt;
			&#039; Decide which node to travel down depending on&lt;br /&gt;
			&#039;   input bits from CHRIN.&lt;br /&gt;
			IF ASC(CHRIN) AND 2 ^ BITMASK THEN&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT1&lt;br /&gt;
			ELSE&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT0&lt;br /&gt;
			END IF&lt;br /&gt;
		       &lt;br /&gt;
			&#039; Is this next node another part of the tree or&lt;br /&gt;
			&#039;   is it a end node? Less than 256 mean end node.&lt;br /&gt;
			IF NEXTNODE &amp;lt; 256 THEN&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Get output char from end node and save.&lt;br /&gt;
				CHROUT = CHR$(NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
				PUT OUTFILE, , CHROUT&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Amend output length and start from top of&lt;br /&gt;
				&#039;   binary tree.&lt;br /&gt;
				OUTLEN = OUTLEN - 1&lt;br /&gt;
				CURNODE = 254&lt;br /&gt;
&lt;br /&gt;
			ELSE&lt;br /&gt;
				&#039; Travel to next node&lt;br /&gt;
				CURNODE = (NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
&lt;br /&gt;
			END IF&lt;br /&gt;
&lt;br /&gt;
			&#039; Move to next input bit&lt;br /&gt;
			BITMASK = BITMASK + 1&lt;br /&gt;
		LOOP WHILE BITMASK &amp;lt; 8 AND OUTLEN &amp;gt; 0&lt;br /&gt;
		&#039; Loop while we still need to output data&lt;br /&gt;
	LOOP WHILE OUTLEN &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
	&#039; Clean up&lt;br /&gt;
	CLOSE OUTFILE&lt;br /&gt;
	CLOSE INFILE&lt;br /&gt;
&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
SUB MAKHUF &#039;Mak a degenerate huffman tree, store as string huffq&lt;br /&gt;
	OPEN &amp;quot;HUFF.DD2&amp;quot; FOR BINARY AS #8&lt;br /&gt;
	aq = &amp;quot;HUFF&amp;quot;&lt;br /&gt;
	PUT #8, 1, aq&lt;br /&gt;
	x = 9&lt;br /&gt;
	FOR t = 0 TO 255&lt;br /&gt;
		b = t&lt;br /&gt;
		va = 0&lt;br /&gt;
		vb = 0&lt;br /&gt;
		vc = 0&lt;br /&gt;
		vd = 0&lt;br /&gt;
		ve = 0&lt;br /&gt;
		vf = 0&lt;br /&gt;
		vg = 0&lt;br /&gt;
		vh = 0&lt;br /&gt;
		IF b &amp;gt; 127 THEN LET va = va + 1&lt;br /&gt;
		b = b MOD 128&lt;br /&gt;
		IF b &amp;gt; 63 THEN LET vb = vb + 1&lt;br /&gt;
		b = b MOD 64&lt;br /&gt;
		IF b &amp;gt; 31 THEN LET vc = vc + 1&lt;br /&gt;
		b = b MOD 32&lt;br /&gt;
		IF b &amp;gt; 15 THEN LET vd = vd + 1&lt;br /&gt;
		b = b MOD 16&lt;br /&gt;
		IF b &amp;gt; 7 THEN LET ve = ve + 1&lt;br /&gt;
		b = b MOD 8&lt;br /&gt;
		IF b &amp;gt; 3 THEN LET vf = vf + 1&lt;br /&gt;
		b = b MOD 4&lt;br /&gt;
		IF b &amp;gt; 1 THEN LET vg = vg + 1&lt;br /&gt;
		b = b MOD 2&lt;br /&gt;
		IF b = 1 THEN LET vh = vh + 1&lt;br /&gt;
		b = (vh * 128) + (vg * 64) + (vf * 32) + (16 * ve) + (8 * vd) + (4 * vc) + (2 * vb) + va&lt;br /&gt;
		aq = MKI$(b)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	FOR t = 0 TO 253&lt;br /&gt;
		aq = MKI$(t + 256)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	GET #8, 1, huffq&lt;br /&gt;
	CLOSE #8&lt;br /&gt;
	KILL &amp;quot;HUFF.DD2&amp;quot;&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Visual Basic .NET ===&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree representation ====&lt;br /&gt;
&lt;br /&gt;
This class, BinaryTreeNode, represents a binary tree whose branch nodes carry no value, like a Huffman dictionary tree.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;Public Class BinaryTreeNode(Of T)&lt;br /&gt;
    &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
    Private Branch As Boolean&lt;br /&gt;
    Private Children As BinaryTreeNode(Of T)()&lt;br /&gt;
    Private HoldValue As T&lt;br /&gt;
    Public Sub New(LeafValue As T)&lt;br /&gt;
        Branch = False&lt;br /&gt;
        HoldValue = LeafValue&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public Sub New(LeftChild As BinaryTreeNode(Of T), RightChild As BinaryTreeNode(Of T))&lt;br /&gt;
        Branch = True&lt;br /&gt;
        Children = {LeftChild, RightChild}&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public ReadOnly Property HasValue As Boolean&lt;br /&gt;
        Get&lt;br /&gt;
            Return Not Branch&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Value As T&lt;br /&gt;
        Get&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return HoldValue&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As T)&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            HoldValue = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Child(Side As ChildSide) As BinaryTreeNode(Of T)&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return Children(Side)&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As BinaryTreeNode(Of T))&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Children(Side) = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Enum ChildSide As Byte&lt;br /&gt;
        Left = 0&lt;br /&gt;
        Right = 1&lt;br /&gt;
    End Enum&lt;br /&gt;
    Public ReadOnly Property Count As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Children(0).Count + Children(1).Count&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public ReadOnly Property Depth As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Math.Max(Children(0).Depth, Children(1).Depth) + 1&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Overrides Function ToString() As String&lt;br /&gt;
        Return &amp;quot;{Count = &amp;quot; &amp;amp; Count &amp;amp; &amp;quot;, Depth = &amp;quot; &amp;amp; Depth &amp;amp; &amp;quot;}&amp;quot;&lt;br /&gt;
    End Function&lt;br /&gt;
End Class&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree reading ====&lt;br /&gt;
&lt;br /&gt;
This piece of code will read in a stored Huffman dictionary in the format described at the top of this article and store it in a BinaryTreeNode(Of Byte) as shown above.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;        &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
        Dim fDict As New IO.FileStream(DictionaryFile, IO.FileMode.Open)&lt;br /&gt;
        Dim raw(254) As Tuple(Of UShort, UShort)&lt;br /&gt;
        For x = 0 To 254&lt;br /&gt;
            raw(x) = Tuple.Create(ReadUShort(fDict), ReadUShort(fDict))&lt;br /&gt;
        Next&lt;br /&gt;
        fDict.Close()&lt;br /&gt;
        Dim GenerateTree As Func(Of UShort, BinaryTreeNode(Of Byte))&lt;br /&gt;
        GenerateTree = Function(NextNode As UShort) As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           Dim n As Tuple(Of UShort, UShort) = raw(NextNode)&lt;br /&gt;
                           Dim a, b As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           If n.Item1 &amp;lt; 256 Then&lt;br /&gt;
                               a = New BinaryTreeNode(Of Byte)(n.Item1)&lt;br /&gt;
                           Else&lt;br /&gt;
                               a = GenerateTree(n.Item1 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           If n.Item2 &amp;lt; 256 Then&lt;br /&gt;
                               b = New BinaryTreeNode(Of Byte)(n.Item2)&lt;br /&gt;
                           Else&lt;br /&gt;
                               b = GenerateTree(n.Item2 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           Return New BinaryTreeNode(Of Byte)(a, b)&lt;br /&gt;
                       End Function&lt;br /&gt;
        Dim dict As BinaryTreeNode(Of Byte) = GenerateTree(254)&lt;br /&gt;
        fDict.Close()&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Code examples]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=5100</id>
		<title>Huffman Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=5100"/>
		<updated>2014-01-06T00:34:05Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add more data on the Keen implementation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Huffman Compression]] is a compression algorithm used in many classic games. It is about as efficient as LZW or RLE compression, with many games using the three formats simultaneously.&lt;br /&gt;
&lt;br /&gt;
Huffman compression involves making/reading a &#039;&#039;dictionary&#039;&#039; of 256 entries, one for each possible 1-byte character.  This is organised in the form of a &#039;&#039;binary tree&#039;&#039; which is basically formed by taking the two lowest frequency characters and combining them into a new entry with their added frequencies and repeating until all entries are reduced to one &#039;&#039;root node&#039;&#039;.  After the dictionary is created, every character of data is replaced with the corresponding bit representation from the tree.&lt;br /&gt;
&lt;br /&gt;
Any Huffman compressed data will thus be associated with a dictionary file (internal or external) used to decompress it.&lt;br /&gt;
&lt;br /&gt;
==Nodes==&lt;br /&gt;
&lt;br /&gt;
The binary tree must be stored in some form, usually called a &#039;&#039;dictionary&#039;&#039;. The format varies from game to game, but is usually broadly along these lines. The tree will have 254 nodes (for all the one byte characters in game data) stored as two &#039;branches&#039; of that node, usually taking up 4 bytes each, but sometimes 3. The second part is either 0 or 1, and says whether that branch goes to a character (0) or another node (1).  The first part is the value of either that character or that node. (For the usual 4-byte implementation each part is a byte.)&lt;br /&gt;
&lt;br /&gt;
In the Huffman table then we can expect to see each possible character TWICE, once as a character, once as a node reference. Note that the nodes are numbered from 0-253, NOT 1-254. The order of the nodes doesn&#039;t matter, only how they are connected.&lt;br /&gt;
&lt;br /&gt;
The root node is ALWAYS node 254 (number 253!) and should always be something like $xx $yy $00 $00 (Since 0 is the most common character it is closest to the root.) It will also tend to be at the end of the dictionary, since most programs find it easier to write their dictionaries from bottom to top. This can often be used to find Huffman dictionaries in files, if you know what you are looking for.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&lt;br /&gt;
Compress the word &amp;quot;HUFFMAN&amp;quot;.  For simplicity, we will not use the usual 256 character tree, but rather something a bit smaller. (Huffman trees can be any size, the concept is the same.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Frequencies are:&amp;lt;br/&amp;gt;1: H,U,M,A,N&amp;lt;br/&amp;gt;2: F&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Make a binary tree: (here left = 0 and right = 1)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &#039;Root node&#039;&lt;br /&gt;
       * &lt;br /&gt;
      / \&lt;br /&gt;
     /   * &lt;br /&gt;
    /   / \&lt;br /&gt;
   *   *   *&lt;br /&gt;
  / \ / \ / \&lt;br /&gt;
  F N M A H U&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The first letter is &#039;H&#039;; this on the tree is &amp;lt;tt&amp;gt;110&amp;lt;/tt&amp;gt; The next letter is &#039;U&#039; which is &amp;lt;tt&amp;gt;111&amp;lt;/tt&amp;gt;.  The third letter is &#039;F&#039; which is &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt; and so on (notice common letters have shorter strings?)  The final output in bits is &amp;lt;tt&amp;gt;110111000010010101&amp;lt;/tt&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is not of course the optimum Huffman tree, but that doesn&#039;t matter, ANY tree will do. As bytes the output is thus: &amp;lt;tt&amp;gt;11011100 00100101 01000000&amp;lt;/tt&amp;gt; (the end bit is padded with nulls) or &amp;lt;tt&amp;gt;$DC $25 $40&amp;lt;/tt&amp;gt;.  We have a reduction in size from 7 bytes to 3, over 50%!  Sadly, we then need to include the Huffman table (the &#039;&#039;dictionary&#039;&#039;) in some form.&lt;br /&gt;
&lt;br /&gt;
A possibility for storing the dictionary might be: &amp;lt;tt&amp;gt;$00 $46 $00 $4E $00 $4D $00 $41 $00 $48 $00 $55 $01 $02 $01 $03 $01 $01 $01 $00&amp;lt;/tt&amp;gt;.  Here we have numbered the nodes starting at the root as 254 and labelled every other node from 0-4 going left to right and top to bottom. (If this is hard to see, try drawing things out on a piece of paper, the first 12 bytes are the bottom 3 nodes, all pointing to characters, and the last 8 bytes are the top two nodes, all pointing to other nodes.) This is the format used in Keen 4-6 executables.&lt;br /&gt;
&lt;br /&gt;
To decompress the data we use the tree again starting at the root node and reading the data bit by bit. So the first three bits are &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; which leads us down the tree to character &#039;H&#039;, then &amp;lt;tt&amp;gt;000&amp;lt;/tt&amp;gt; which leads us to &#039;U&#039; and so on.&lt;br /&gt;
&lt;br /&gt;
==Huffman implementation in ID Software games==&lt;br /&gt;
&lt;br /&gt;
Games created by Id Software (such as [[Commander Keen 4-6]] or [[Wolfenstein 3-D]]) have a shared but distinct implementation of Huffman compression. The dictionary consists of 1020 bytes (254 nodes plus for null bytes of padding) and there are two or three dictionaries stored in the executable depending on game. (The end of these can be found by looking for node 254 which usually consists of the string $00 $00 $FD $01)&lt;br /&gt;
&lt;br /&gt;
The data itself is stored in an external file which consists of a number of concatenated &#039;chunks&#039;, each chunk beginning with a dword giving its decompressed size. There is also an internal &#039;header&#039; file consisting of a series of three (or sometimes four) byte offsets to the start of various chunks in the data file. (The end of this can be found as the last entry is the length of the data file.)&lt;br /&gt;
&lt;br /&gt;
The data itself is read byte-by-byte in the normal fashion &#039;&#039;but with the order of bits in every byte being reversed&#039;&#039;. The following 1020 bytes constitute the complete &#039;trivial&#039; Huffman dictionary for this implementation, that is, one that does not compress the data at all:&lt;br /&gt;
&lt;br /&gt;
 $00 $00 $80 $00 $40 $00 $C0 $00 $20 $00 $A0 $00 $60 $00 $E0 $00&lt;br /&gt;
 $10 $00 $90 $00 $50 $00 $D0 $00 $30 $00 $B0 $00 $70 $00 $F0 $00&lt;br /&gt;
 $08 $00 $88 $00 $48 $00 $C8 $00 $28 $00 $A8 $00 $68 $00 $E8 $00&lt;br /&gt;
 $18 $00 $98 $00 $58 $00 $D8 $00 $38 $00 $B8 $00 $78 $00 $F8 $00&lt;br /&gt;
 $04 $00 $84 $00 $44 $00 $C4 $00 $24 $00 $A4 $00 $64 $00 $E4 $00&lt;br /&gt;
 $14 $00 $94 $00 $54 $00 $D4 $00 $34 $00 $B4 $00 $74 $00 $F4 $00&lt;br /&gt;
 $0C $00 $8C $00 $4C $00 $CC $00 $2C $00 $AC $00 $6C $00 $EC $00&lt;br /&gt;
 $1C $00 $9C $00 $5C $00 $DC $00 $3C $00 $BC $00 $7C $00 $FC $00&lt;br /&gt;
 $02 $00 $82 $00 $42 $00 $C2 $00 $22 $00 $A2 $00 $62 $00 $E2 $00&lt;br /&gt;
 $12 $00 $92 $00 $52 $00 $D2 $00 $32 $00 $B2 $00 $72 $00 $F2 $00&lt;br /&gt;
 $0A $00 $8A $00 $4A $00 $CA $00 $2A $00 $AA $00 $6A $00 $EA $00&lt;br /&gt;
 $1A $00 $9A $00 $5A $00 $DA $00 $3A $00 $BA $00 $7A $00 $FA $00&lt;br /&gt;
 $06 $00 $86 $00 $46 $00 $C6 $00 $26 $00 $A6 $00 $66 $00 $E6 $00&lt;br /&gt;
 $16 $00 $96 $00 $56 $00 $D6 $00 $36 $00 $B6 $00 $76 $00 $F6 $00&lt;br /&gt;
 $0E $00 $8E $00 $4E $00 $CE $00 $2E $00 $AE $00 $6E $00 $EE $00&lt;br /&gt;
 $1E $00 $9E $00 $5E $00 $DE $00 $3E $00 $BE $00 $7E $00 $FE $00&lt;br /&gt;
 $01 $00 $81 $00 $41 $00 $C1 $00 $21 $00 $A1 $00 $61 $00 $E1 $00&lt;br /&gt;
 $11 $00 $91 $00 $51 $00 $D1 $00 $31 $00 $B1 $00 $71 $00 $F1 $00&lt;br /&gt;
 $09 $00 $89 $00 $49 $00 $C9 $00 $29 $00 $A9 $00 $69 $00 $E9 $00&lt;br /&gt;
 $19 $00 $99 $00 $59 $00 $D9 $00 $39 $00 $B9 $00 $79 $00 $F9 $00&lt;br /&gt;
 $05 $00 $85 $00 $45 $00 $C5 $00 $25 $00 $A5 $00 $65 $00 $E5 $00&lt;br /&gt;
 $15 $00 $95 $00 $55 $00 $D5 $00 $35 $00 $B5 $00 $75 $00 $F5 $00&lt;br /&gt;
 $0D $00 $8D $00 $4D $00 $CD $00 $2D $00 $AD $00 $6D $00 $ED $00&lt;br /&gt;
 $1D $00 $9D $00 $5D $00 $DD $00 $3D $00 $BD $00 $7D $00 $FD $00&lt;br /&gt;
 $03 $00 $83 $00 $43 $00 $C3 $00 $23 $00 $A3 $00 $63 $00 $E3 $00&lt;br /&gt;
 $13 $00 $93 $00 $53 $00 $D3 $00 $33 $00 $B3 $00 $73 $00 $F3 $00&lt;br /&gt;
 $0B $00 $8B $00 $4B $00 $CB $00 $2B $00 $AB $00 $6B $00 $EB $00&lt;br /&gt;
 $1B $00 $9B $00 $5B $00 $DB $00 $3B $00 $BB $00 $7B $00 $FB $00&lt;br /&gt;
 $07 $00 $87 $00 $47 $00 $C7 $00 $27 $00 $A7 $00 $67 $00 $E7 $00&lt;br /&gt;
 $17 $00 $97 $00 $57 $00 $D7 $00 $37 $00 $B7 $00 $77 $00 $F7 $00&lt;br /&gt;
 $0F $00 $8F $00 $4F $00 $CF $00 $2F $00 $AF $00 $6F $00 $EF $00&lt;br /&gt;
 $1F $00 $9F $00 $5F $00 $DF $00 $3F $00 $BF $00 $7F $00 $FF $00&lt;br /&gt;
 $00 $01 $01 $01 $02 $01 $03 $01 $04 $01 $05 $01 $06 $01 $07 $01&lt;br /&gt;
 $08 $01 $09 $01 $0A $01 $0B $01 $0C $01 $0D $01 $0E $01 $0F $01&lt;br /&gt;
 $10 $01 $11 $01 $12 $01 $13 $01 $14 $01 $15 $01 $16 $01 $17 $01&lt;br /&gt;
 $18 $01 $19 $01 $1A $01 $1B $01 $1C $01 $1D $01 $1E $01 $1F $01&lt;br /&gt;
 $20 $01 $21 $01 $22 $01 $23 $01 $24 $01 $25 $01 $26 $01 $27 $01&lt;br /&gt;
 $28 $01 $29 $01 $2A $01 $2B $01 $2C $01 $2D $01 $2E $01 $2F $01&lt;br /&gt;
 $30 $01 $31 $01 $32 $01 $33 $01 $34 $01 $35 $01 $36 $01 $37 $01&lt;br /&gt;
 $38 $01 $39 $01 $3A $01 $3B $01 $3C $01 $3D $01 $3E $01 $3F $01&lt;br /&gt;
 $40 $01 $41 $01 $42 $01 $43 $01 $44 $01 $45 $01 $46 $01 $47 $01&lt;br /&gt;
 $48 $01 $49 $01 $4A $01 $4B $01 $4C $01 $4D $01 $4E $01 $4F $01&lt;br /&gt;
 $50 $01 $51 $01 $52 $01 $53 $01 $54 $01 $55 $01 $56 $01 $57 $01&lt;br /&gt;
 $58 $01 $59 $01 $5A $01 $5B $01 $5C $01 $5D $01 $5E $01 $5F $01&lt;br /&gt;
 $60 $01 $61 $01 $62 $01 $63 $01 $64 $01 $65 $01 $66 $01 $67 $01&lt;br /&gt;
 $68 $01 $69 $01 $6A $01 $6B $01 $6C $01 $6D $01 $6E $01 $6F $01&lt;br /&gt;
 $70 $01 $71 $01 $72 $01 $73 $01 $74 $01 $75 $01 $76 $01 $77 $01&lt;br /&gt;
 $78 $01 $79 $01 $7A $01 $7B $01 $7C $01 $7D $01 $7E $01 $7F $01&lt;br /&gt;
 $80 $01 $81 $01 $82 $01 $83 $01 $84 $01 $85 $01 $86 $01 $87 $01&lt;br /&gt;
 $88 $01 $89 $01 $8A $01 $8B $01 $8C $01 $8D $01 $8E $01 $8F $01&lt;br /&gt;
 $90 $01 $91 $01 $92 $01 $93 $01 $94 $01 $95 $01 $96 $01 $97 $01&lt;br /&gt;
 $98 $01 $99 $01 $9A $01 $9B $01 $9C $01 $9D $01 $9E $01 $9F $01&lt;br /&gt;
 $A0 $01 $A1 $01 $A2 $01 $A3 $01 $A4 $01 $A5 $01 $A6 $01 $A7 $01&lt;br /&gt;
 $A8 $01 $A9 $01 $AA $01 $AB $01 $AC $01 $AD $01 $AE $01 $AF $01&lt;br /&gt;
 $B0 $01 $B1 $01 $B2 $01 $B3 $01 $B4 $01 $B5 $01 $B6 $01 $B7 $01&lt;br /&gt;
 $B8 $01 $B9 $01 $BA $01 $BB $01 $BC $01 $BD $01 $BE $01 $BF $01&lt;br /&gt;
 $C0 $01 $C1 $01 $C2 $01 $C3 $01 $C4 $01 $C5 $01 $C6 $01 $C7 $01&lt;br /&gt;
 $C8 $01 $C9 $01 $CA $01 $CB $01 $CC $01 $CD $01 $CE $01 $CF $01&lt;br /&gt;
 $D0 $01 $D1 $01 $D2 $01 $D3 $01 $D4 $01 $D5 $01 $D6 $01 $D7 $01&lt;br /&gt;
 $D8 $01 $D9 $01 $DA $01 $DB $01 $DC $01 $DD $01 $DE $01 $DF $01&lt;br /&gt;
 $E0 $01 $E1 $01 $E2 $01 $E3 $01 $E4 $01 $E5 $01 $E6 $01 $E7 $01&lt;br /&gt;
 $E8 $01 $E9 $01 $EA $01 $EB $01 $EC $01 $ED $01 $EE $01 $EF $01&lt;br /&gt;
 $F0 $01 $F1 $01 $F2 $01 $F3 $01 $F4 $01 $F5 $01 $F6 $01 $F7 $01&lt;br /&gt;
 $F8 $01 $F9 $01 $FA $01 $FB $01 $FC $01 $FD $01&lt;br /&gt;
&lt;br /&gt;
This is a useful example to use since it has a number of unique features. Firstly the paths to any given terminal node are all the same length, 8 bits. Secondly the &#039;byte reversal&#039; can easily be seen in that the path to each terminal node is the &#039;&#039;reverse&#039;&#039; of the character it represents. And finally the nodes are arranged in a logical order with an easily seen pattern; the first half of the tree consists of terminal nodes, the second half of branch nodes. (Of the second half the first half of &#039;&#039;that&#039;&#039; consists of branch nodes that lead to terminal nodes while the second half consists of branch nodes to two branch nodes and so on.)&lt;br /&gt;
&lt;br /&gt;
As an example the character $80 (128 or 10000000) can be expected to be represented by the path &#039;00000001&#039; and as such be the second node in the tree. Starting at the root node and following the leftmost path until the last step takes us to the following nodes: 254(root) -&amp;gt; 252 -&amp;gt; 248 -&amp;gt; 240 -&amp;gt; 224 -&amp;gt; 192 -&amp;gt; 128 -&amp;gt; 0(terminal node for characters $00 and $80)&lt;br /&gt;
&lt;br /&gt;
== Source code ==&lt;br /&gt;
&lt;br /&gt;
Some example code is available in various languages showing how to decompress (and in some cases compress) files using the Huffman algorithm.&lt;br /&gt;
&lt;br /&gt;
=== QuickBasic ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; DANGEROUS DAVE 2 - IN THE HAUNTED MANSION - Huffman Decompressor&lt;br /&gt;
&#039;  - by Napalm with thanks to Adurdin&#039;s work on ModKeen&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; This source is Public Domain, please credit me if you use it.&lt;br /&gt;
&#039;&lt;br /&gt;
&#039;&lt;br /&gt;
DECLARE SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING)&lt;br /&gt;
&lt;br /&gt;
TYPE NODE&lt;br /&gt;
        BIT0 AS INTEGER&lt;br /&gt;
        BIT1 AS INTEGER&lt;br /&gt;
END TYPE&lt;br /&gt;
&lt;br /&gt;
&#039; Test Function&lt;br /&gt;
HUFFDECOMPRESS &amp;quot;TITLE1.DD2&amp;quot;, &amp;quot;TITLE1.PIC&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING) &#039; by Napalm&lt;br /&gt;
	DIM INFILE AS INTEGER, OUTFILE AS INTEGER, I AS INTEGER&lt;br /&gt;
	DIM SIG AS LONG, OUTLEN AS LONG, BITMASK AS INTEGER&lt;br /&gt;
	DIM CURNODE AS INTEGER, NEXTNODE AS INTEGER&lt;br /&gt;
	DIM CHRIN AS STRING * 1, CHROUT AS STRING * 1&lt;br /&gt;
	DIM NODES(0 TO 254) AS NODE&lt;br /&gt;
&lt;br /&gt;
	&#039; Open input file&lt;br /&gt;
	INFILE = FREEFILE&lt;br /&gt;
	OPEN INNAME FOR BINARY ACCESS READ AS INFILE&lt;br /&gt;
       &lt;br /&gt;
	&#039; Check file signature&lt;br /&gt;
	GET INFILE, , SIG&lt;br /&gt;
	IF SIG &amp;lt;&amp;gt; &amp;amp;H46465548 THEN &#039; Hex for: HUFF in little endian&lt;br /&gt;
		PRINT &amp;quot;INVALID FILE!&amp;quot;&lt;br /&gt;
		EXIT SUB&lt;br /&gt;
	END IF&lt;br /&gt;
       &lt;br /&gt;
	&#039; Get output length&lt;br /&gt;
	OUTLEN = 0&lt;br /&gt;
	GET INFILE, , OUTLEN&lt;br /&gt;
       &lt;br /&gt;
	&#039; Read in the huffman binary tree&lt;br /&gt;
	FOR I = 0 TO 254&lt;br /&gt;
		GET INFILE, , NODES(I).BIT0&lt;br /&gt;
		GET INFILE, , NODES(I).BIT1&lt;br /&gt;
	NEXT I&lt;br /&gt;
&lt;br /&gt;
	&#039; Open output file&lt;br /&gt;
	OUTFILE = FREEFILE&lt;br /&gt;
	OPEN OUTNAME FOR BINARY ACCESS WRITE AS OUTFILE&lt;br /&gt;
&lt;br /&gt;
	&#039; Decompress input data using binary tree&lt;br /&gt;
	CURNODE = 254&lt;br /&gt;
	DO&lt;br /&gt;
		BITMASK = 0&lt;br /&gt;
		GET INFILE, , CHRIN&lt;br /&gt;
		DO&lt;br /&gt;
			&#039; Decide which node to travel down depending on&lt;br /&gt;
			&#039;   input bits from CHRIN.&lt;br /&gt;
			IF ASC(CHRIN) AND 2 ^ BITMASK THEN&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT1&lt;br /&gt;
			ELSE&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT0&lt;br /&gt;
			END IF&lt;br /&gt;
		       &lt;br /&gt;
			&#039; Is this next node another part of the tree or&lt;br /&gt;
			&#039;   is it a end node? Less than 256 mean end node.&lt;br /&gt;
			IF NEXTNODE &amp;lt; 256 THEN&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Get output char from end node and save.&lt;br /&gt;
				CHROUT = CHR$(NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
				PUT OUTFILE, , CHROUT&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Amend output length and start from top of&lt;br /&gt;
				&#039;   binary tree.&lt;br /&gt;
				OUTLEN = OUTLEN - 1&lt;br /&gt;
				CURNODE = 254&lt;br /&gt;
&lt;br /&gt;
			ELSE&lt;br /&gt;
				&#039; Travel to next node&lt;br /&gt;
				CURNODE = (NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
&lt;br /&gt;
			END IF&lt;br /&gt;
&lt;br /&gt;
			&#039; Move to next input bit&lt;br /&gt;
			BITMASK = BITMASK + 1&lt;br /&gt;
		LOOP WHILE BITMASK &amp;lt; 8 AND OUTLEN &amp;gt; 0&lt;br /&gt;
		&#039; Loop while we still need to output data&lt;br /&gt;
	LOOP WHILE OUTLEN &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
	&#039; Clean up&lt;br /&gt;
	CLOSE OUTFILE&lt;br /&gt;
	CLOSE INFILE&lt;br /&gt;
&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
SUB MAKHUF &#039;Mak a degenerate huffman tree, store as string huffq&lt;br /&gt;
	OPEN &amp;quot;HUFF.DD2&amp;quot; FOR BINARY AS #8&lt;br /&gt;
	aq = &amp;quot;HUFF&amp;quot;&lt;br /&gt;
	PUT #8, 1, aq&lt;br /&gt;
	x = 9&lt;br /&gt;
	FOR t = 0 TO 255&lt;br /&gt;
		b = t&lt;br /&gt;
		va = 0&lt;br /&gt;
		vb = 0&lt;br /&gt;
		vc = 0&lt;br /&gt;
		vd = 0&lt;br /&gt;
		ve = 0&lt;br /&gt;
		vf = 0&lt;br /&gt;
		vg = 0&lt;br /&gt;
		vh = 0&lt;br /&gt;
		IF b &amp;gt; 127 THEN LET va = va + 1&lt;br /&gt;
		b = b MOD 128&lt;br /&gt;
		IF b &amp;gt; 63 THEN LET vb = vb + 1&lt;br /&gt;
		b = b MOD 64&lt;br /&gt;
		IF b &amp;gt; 31 THEN LET vc = vc + 1&lt;br /&gt;
		b = b MOD 32&lt;br /&gt;
		IF b &amp;gt; 15 THEN LET vd = vd + 1&lt;br /&gt;
		b = b MOD 16&lt;br /&gt;
		IF b &amp;gt; 7 THEN LET ve = ve + 1&lt;br /&gt;
		b = b MOD 8&lt;br /&gt;
		IF b &amp;gt; 3 THEN LET vf = vf + 1&lt;br /&gt;
		b = b MOD 4&lt;br /&gt;
		IF b &amp;gt; 1 THEN LET vg = vg + 1&lt;br /&gt;
		b = b MOD 2&lt;br /&gt;
		IF b = 1 THEN LET vh = vh + 1&lt;br /&gt;
		b = (vh * 128) + (vg * 64) + (vf * 32) + (16 * ve) + (8 * vd) + (4 * vc) + (2 * vb) + va&lt;br /&gt;
		aq = MKI$(b)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	FOR t = 0 TO 253&lt;br /&gt;
		aq = MKI$(t + 256)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	GET #8, 1, huffq&lt;br /&gt;
	CLOSE #8&lt;br /&gt;
	KILL &amp;quot;HUFF.DD2&amp;quot;&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Visual Basic .NET ===&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree representation ====&lt;br /&gt;
&lt;br /&gt;
This class, BinaryTreeNode, represents a binary tree whose branch nodes carry no value, like a Huffman dictionary tree.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;Public Class BinaryTreeNode(Of T)&lt;br /&gt;
    &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
    Private Branch As Boolean&lt;br /&gt;
    Private Children As BinaryTreeNode(Of T)()&lt;br /&gt;
    Private HoldValue As T&lt;br /&gt;
    Public Sub New(LeafValue As T)&lt;br /&gt;
        Branch = False&lt;br /&gt;
        HoldValue = LeafValue&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public Sub New(LeftChild As BinaryTreeNode(Of T), RightChild As BinaryTreeNode(Of T))&lt;br /&gt;
        Branch = True&lt;br /&gt;
        Children = {LeftChild, RightChild}&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public ReadOnly Property HasValue As Boolean&lt;br /&gt;
        Get&lt;br /&gt;
            Return Not Branch&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Value As T&lt;br /&gt;
        Get&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return HoldValue&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As T)&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            HoldValue = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Child(Side As ChildSide) As BinaryTreeNode(Of T)&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return Children(Side)&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As BinaryTreeNode(Of T))&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Children(Side) = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Enum ChildSide As Byte&lt;br /&gt;
        Left = 0&lt;br /&gt;
        Right = 1&lt;br /&gt;
    End Enum&lt;br /&gt;
    Public ReadOnly Property Count As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Children(0).Count + Children(1).Count&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public ReadOnly Property Depth As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Math.Max(Children(0).Depth, Children(1).Depth) + 1&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Overrides Function ToString() As String&lt;br /&gt;
        Return &amp;quot;{Count = &amp;quot; &amp;amp; Count &amp;amp; &amp;quot;, Depth = &amp;quot; &amp;amp; Depth &amp;amp; &amp;quot;}&amp;quot;&lt;br /&gt;
    End Function&lt;br /&gt;
End Class&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree reading ====&lt;br /&gt;
&lt;br /&gt;
This piece of code will read in a stored Huffman dictionary in the format described at the top of this article and store it in a BinaryTreeNode(Of Byte) as shown above.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;        &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
        Dim fDict As New IO.FileStream(DictionaryFile, IO.FileMode.Open)&lt;br /&gt;
        Dim raw(254) As Tuple(Of UShort, UShort)&lt;br /&gt;
        For x = 0 To 254&lt;br /&gt;
            raw(x) = Tuple.Create(ReadUShort(fDict), ReadUShort(fDict))&lt;br /&gt;
        Next&lt;br /&gt;
        fDict.Close()&lt;br /&gt;
        Dim GenerateTree As Func(Of UShort, BinaryTreeNode(Of Byte))&lt;br /&gt;
        GenerateTree = Function(NextNode As UShort) As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           Dim n As Tuple(Of UShort, UShort) = raw(NextNode)&lt;br /&gt;
                           Dim a, b As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           If n.Item1 &amp;lt; 256 Then&lt;br /&gt;
                               a = New BinaryTreeNode(Of Byte)(n.Item1)&lt;br /&gt;
                           Else&lt;br /&gt;
                               a = GenerateTree(n.Item1 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           If n.Item2 &amp;lt; 256 Then&lt;br /&gt;
                               b = New BinaryTreeNode(Of Byte)(n.Item2)&lt;br /&gt;
                           Else&lt;br /&gt;
                               b = GenerateTree(n.Item2 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           Return New BinaryTreeNode(Of Byte)(a, b)&lt;br /&gt;
                       End Function&lt;br /&gt;
        Dim dict As BinaryTreeNode(Of Byte) = GenerateTree(254)&lt;br /&gt;
        fDict.Close()&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:File Formats]]&lt;br /&gt;
[[Category:Compressed Files]]&lt;br /&gt;
[[Category:Huffman Compression]]&lt;br /&gt;
[[Category:Compression Algorithms]]&lt;br /&gt;
[[Category:Code examples]]&lt;br /&gt;
[[Category:Dangerous Dave 2]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=5094</id>
		<title>Huffman Compression</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Huffman_Compression&amp;diff=5094"/>
		<updated>2014-01-02T03:38:42Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add second example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Huffman Compression]] is a compression algorithm used in many classic games. It is about as efficient as LZW or RLE compression, with many games using the three formats simultaneously.&lt;br /&gt;
&lt;br /&gt;
Huffman compression involves making/reading a &#039;&#039;dictionary&#039;&#039; of 256 entries, one for each possible 1-byte character.  This is organised in the form of a &#039;&#039;binary tree&#039;&#039; which is basically formed by taking the two lowest frequency characters and combining them into a new entry with their added frequencies and repeating until all entries are reduced to one &#039;&#039;root node&#039;&#039;.  After the dictionary is created, every character of data is replaced with the corresponding bit representation from the tree.&lt;br /&gt;
&lt;br /&gt;
Any Huffman compressed data will thus be associated with a dictionary file (internal or external) used to decompress it.&lt;br /&gt;
&lt;br /&gt;
==Nodes==&lt;br /&gt;
&lt;br /&gt;
The binary tree must be stored in some form, usually called a &#039;&#039;dictionary&#039;&#039;. The format varies from game to game, but is usually broadly along these lines. The tree will have 254 nodes (for all the one byte characters in game data) stored as two &#039;branches&#039; of that node, usually taking up 4 bytes each, but sometimes 3. The second part is either 0 or 1, and says whether that branch goes to a character (0) or another node (1).  The first part is the value of either that character or that node. (For the usual 4-byte implementation each part is a byte.)&lt;br /&gt;
&lt;br /&gt;
In the Huffman table then we can expect to see each possible character TWICE, once as a character, once as a node reference. Note that the nodes are numbered from 0-253, NOT 1-254. The order of the nodes doesn&#039;t matter, only how they are connected.&lt;br /&gt;
&lt;br /&gt;
The root node is ALWAYS node 254 (number 253!) and should always be something like $xx $yy $00 $00 (Since 0 is the most common character it is closest to the root.) It will also tend to be at the end of the dictionary, since most programs find it easier to write their dictionaries from bottom to top. This can often be used to find Huffman dictionaries in files, if you know what you are looking for.&lt;br /&gt;
&lt;br /&gt;
==Example 1==&lt;br /&gt;
&lt;br /&gt;
Compress the word &amp;quot;HUFFMAN&amp;quot;.  For simplicity, we will not use the usual 256 character tree, but rather something a bit smaller. (Huffman trees can be any size, the concept is the same.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Frequencies are:&amp;lt;br/&amp;gt;1: H,U,M,A,N&amp;lt;br/&amp;gt;2: F&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Make a binary tree: (here left = 0 and right = 1)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &#039;Root node&#039;&lt;br /&gt;
       * &lt;br /&gt;
      / \&lt;br /&gt;
     /   * &lt;br /&gt;
    /   / \&lt;br /&gt;
   *   *   *&lt;br /&gt;
  / \ / \ / \&lt;br /&gt;
  F N M A H U&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The first letter is &#039;H&#039;; this on the tree is &amp;lt;tt&amp;gt;110&amp;lt;/tt&amp;gt; The next letter is &#039;U&#039; which is &amp;lt;tt&amp;gt;111&amp;lt;/tt&amp;gt;.  The third letter is &#039;F&#039; which is &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt; and so on (notice common letters have shorter strings?)  The final output in bits is &amp;lt;tt&amp;gt;110111000010010101&amp;lt;/tt&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is not of course the optimum Huffman tree, but that doesn&#039;t matter, ANY tree will do. As bytes the output is thus: &amp;lt;tt&amp;gt;11011100 00100101 01000000&amp;lt;/tt&amp;gt; (the end bit is padded with nulls) or &amp;lt;tt&amp;gt;$DC $25 $40&amp;lt;/tt&amp;gt;.  We have a reduction in size from 7 bytes to 3, over 50%!  Sadly, we then need to include the Huffman table (the &#039;&#039;dictionary&#039;&#039;) in some form.&lt;br /&gt;
&lt;br /&gt;
A possibility for storing the dictionary might be: &amp;lt;tt&amp;gt;$00 $46 $00 $4E $00 $4D $00 $41 $00 $48 $00 $55 $01 $02 $01 $03 $01 $01 $01 $00&amp;lt;/tt&amp;gt;.  Here we have numbered the nodes starting at the root as 254 and labelled every other node from 0-4 going left to right and top to bottom. (If this is hard to see, try drawing things out on a piece of paper, the first 12 bytes are the bottom 3 nodes, all pointing to characters, and the last 8 bytes are the top two nodes, all pointing to other nodes.) This is the format used in Keen 4-6 executables.&lt;br /&gt;
&lt;br /&gt;
To decompress the data we use the tree again starting at the root node and reading the data bit by bit. So the first three bits are &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; which leads us down the tree to character &#039;H&#039;, then &amp;lt;tt&amp;gt;000&amp;lt;/tt&amp;gt; which leads us to &#039;U&#039; and so on.&lt;br /&gt;
&lt;br /&gt;
==Example 2==&lt;br /&gt;
&lt;br /&gt;
The following 1020 bytes constitute the complete &#039;trivial&#039; Huffman dictionary, that is, one that does not compress the data at all:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 $00 $00 $80 $00 $40 $00 $C0 $00 $20 $00 $A0 $00 $60 $00 $E0 $00&lt;br /&gt;
 $10 $00 $90 $00 $50 $00 $D0 $00 $30 $00 $B0 $00 $70 $00 $F0 $00&lt;br /&gt;
 $08 $00 $88 $00 $48 $00 $C8 $00 $28 $00 $A8 $00 $68 $00 $E8 $00&lt;br /&gt;
 $18 $00 $98 $00 $58 $00 $D8 $00 $38 $00 $B8 $00 $78 $00 $F8 $00&lt;br /&gt;
 $04 $00 $84 $00 $44 $00 $C4 $00 $24 $00 $A4 $00 $64 $00 $E4 $00&lt;br /&gt;
 $14 $00 $94 $00 $54 $00 $D4 $00 $34 $00 $B4 $00 $74 $00 $F4 $00&lt;br /&gt;
 $0C $00 $8C $00 $4C $00 $CC $00 $2C $00 $AC $00 $6C $00 $EC $00&lt;br /&gt;
 $1C $00 $9C $00 $5C $00 $DC $00 $3C $00 $BC $00 $7C $00 $FC $00&lt;br /&gt;
 $02 $00 $82 $00 $42 $00 $C2 $00 $22 $00 $A2 $00 $62 $00 $E2 $00&lt;br /&gt;
 $12 $00 $92 $00 $52 $00 $D2 $00 $32 $00 $B2 $00 $72 $00 $F2 $00&lt;br /&gt;
 $0A $00 $8A $00 $4A $00 $CA $00 $2A $00 $AA $00 $6A $00 $EA $00&lt;br /&gt;
 $1A $00 $9A $00 $5A $00 $DA $00 $3A $00 $BA $00 $7A $00 $FA $00&lt;br /&gt;
 $06 $00 $86 $00 $46 $00 $C6 $00 $26 $00 $A6 $00 $66 $00 $E6 $00&lt;br /&gt;
 $16 $00 $96 $00 $56 $00 $D6 $00 $36 $00 $B6 $00 $76 $00 $F6 $00&lt;br /&gt;
 $0E $00 $8E $00 $4E $00 $CE $00 $2E $00 $AE $00 $6E $00 $EE $00&lt;br /&gt;
 $1E $00 $9E $00 $5E $00 $DE $00 $3E $00 $BE $00 $7E $00 $FE $00&lt;br /&gt;
 $01 $00 $81 $00 $41 $00 $C1 $00 $21 $00 $A1 $00 $61 $00 $E1 $00&lt;br /&gt;
 $11 $00 $91 $00 $51 $00 $D1 $00 $31 $00 $B1 $00 $71 $00 $F1 $00&lt;br /&gt;
 $09 $00 $89 $00 $49 $00 $C9 $00 $29 $00 $A9 $00 $69 $00 $E9 $00&lt;br /&gt;
 $19 $00 $99 $00 $59 $00 $D9 $00 $39 $00 $B9 $00 $79 $00 $F9 $00&lt;br /&gt;
 $05 $00 $85 $00 $45 $00 $C5 $00 $25 $00 $A5 $00 $65 $00 $E5 $00&lt;br /&gt;
 $15 $00 $95 $00 $55 $00 $D5 $00 $35 $00 $B5 $00 $75 $00 $F5 $00&lt;br /&gt;
 $0D $00 $8D $00 $4D $00 $CD $00 $2D $00 $AD $00 $6D $00 $ED $00&lt;br /&gt;
 $1D $00 $9D $00 $5D $00 $DD $00 $3D $00 $BD $00 $7D $00 $FD $00&lt;br /&gt;
 $03 $00 $83 $00 $43 $00 $C3 $00 $23 $00 $A3 $00 $63 $00 $E3 $00&lt;br /&gt;
 $13 $00 $93 $00 $53 $00 $D3 $00 $33 $00 $B3 $00 $73 $00 $F3 $00&lt;br /&gt;
 $0B $00 $8B $00 $4B $00 $CB $00 $2B $00 $AB $00 $6B $00 $EB $00&lt;br /&gt;
 $1B $00 $9B $00 $5B $00 $DB $00 $3B $00 $BB $00 $7B $00 $FB $00&lt;br /&gt;
 $07 $00 $87 $00 $47 $00 $C7 $00 $27 $00 $A7 $00 $67 $00 $E7 $00&lt;br /&gt;
 $17 $00 $97 $00 $57 $00 $D7 $00 $37 $00 $B7 $00 $77 $00 $F7 $00&lt;br /&gt;
 $0F $00 $8F $00 $4F $00 $CF $00 $2F $00 $AF $00 $6F $00 $EF $00&lt;br /&gt;
 $1F $00 $9F $00 $5F $00 $DF $00 $3F $00 $BF $00 $7F $00 $FF $00&lt;br /&gt;
 $00 $01 $01 $01 $02 $01 $03 $01 $04 $01 $05 $01 $06 $01 $07 $01&lt;br /&gt;
 $08 $01 $09 $01 $0A $01 $0B $01 $0C $01 $0D $01 $0E $01 $0F $01&lt;br /&gt;
 $10 $01 $11 $01 $12 $01 $13 $01 $14 $01 $15 $01 $16 $01 $17 $01&lt;br /&gt;
 $18 $01 $19 $01 $1A $01 $1B $01 $1C $01 $1D $01 $1E $01 $1F $01&lt;br /&gt;
 $20 $01 $21 $01 $22 $01 $23 $01 $24 $01 $25 $01 $26 $01 $27 $01&lt;br /&gt;
 $28 $01 $29 $01 $2A $01 $2B $01 $2C $01 $2D $01 $2E $01 $2F $01&lt;br /&gt;
 $30 $01 $31 $01 $32 $01 $33 $01 $34 $01 $35 $01 $36 $01 $37 $01&lt;br /&gt;
 $38 $01 $39 $01 $3A $01 $3B $01 $3C $01 $3D $01 $3E $01 $3F $01&lt;br /&gt;
 $40 $01 $41 $01 $42 $01 $43 $01 $44 $01 $45 $01 $46 $01 $47 $01&lt;br /&gt;
 $48 $01 $49 $01 $4A $01 $4B $01 $4C $01 $4D $01 $4E $01 $4F $01&lt;br /&gt;
 $50 $01 $51 $01 $52 $01 $53 $01 $54 $01 $55 $01 $56 $01 $57 $01&lt;br /&gt;
 $58 $01 $59 $01 $5A $01 $5B $01 $5C $01 $5D $01 $5E $01 $5F $01&lt;br /&gt;
 $60 $01 $61 $01 $62 $01 $63 $01 $64 $01 $65 $01 $66 $01 $67 $01&lt;br /&gt;
 $68 $01 $69 $01 $6A $01 $6B $01 $6C $01 $6D $01 $6E $01 $6F $01&lt;br /&gt;
 $70 $01 $71 $01 $72 $01 $73 $01 $74 $01 $75 $01 $76 $01 $77 $01&lt;br /&gt;
 $78 $01 $79 $01 $7A $01 $7B $01 $7C $01 $7D $01 $7E $01 $7F $01&lt;br /&gt;
 $80 $01 $81 $01 $82 $01 $83 $01 $84 $01 $85 $01 $86 $01 $87 $01&lt;br /&gt;
 $88 $01 $89 $01 $8A $01 $8B $01 $8C $01 $8D $01 $8E $01 $8F $01&lt;br /&gt;
 $90 $01 $91 $01 $92 $01 $93 $01 $94 $01 $95 $01 $96 $01 $97 $01&lt;br /&gt;
 $98 $01 $99 $01 $9A $01 $9B $01 $9C $01 $9D $01 $9E $01 $9F $01&lt;br /&gt;
 $A0 $01 $A1 $01 $A2 $01 $A3 $01 $A4 $01 $A5 $01 $A6 $01 $A7 $01&lt;br /&gt;
 $A8 $01 $A9 $01 $AA $01 $AB $01 $AC $01 $AD $01 $AE $01 $AF $01&lt;br /&gt;
 $B0 $01 $B1 $01 $B2 $01 $B3 $01 $B4 $01 $B5 $01 $B6 $01 $B7 $01&lt;br /&gt;
 $B8 $01 $B9 $01 $BA $01 $BB $01 $BC $01 $BD $01 $BE $01 $BF $01&lt;br /&gt;
 $C0 $01 $C1 $01 $C2 $01 $C3 $01 $C4 $01 $C5 $01 $C6 $01 $C7 $01&lt;br /&gt;
 $C8 $01 $C9 $01 $CA $01 $CB $01 $CC $01 $CD $01 $CE $01 $CF $01&lt;br /&gt;
 $D0 $01 $D1 $01 $D2 $01 $D3 $01 $D4 $01 $D5 $01 $D6 $01 $D7 $01&lt;br /&gt;
 $D8 $01 $D9 $01 $DA $01 $DB $01 $DC $01 $DD $01 $DE $01 $DF $01&lt;br /&gt;
 $E0 $01 $E1 $01 $E2 $01 $E3 $01 $E4 $01 $E5 $01 $E6 $01 $E7 $01&lt;br /&gt;
 $E8 $01 $E9 $01 $EA $01 $EB $01 $EC $01 $ED $01 $EE $01 $EF $01&lt;br /&gt;
 $F0 $01 $F1 $01 $F2 $01 $F3 $01 $F4 $01 $F5 $01 $F6 $01 $F7 $01&lt;br /&gt;
 $F8 $01 $F9 $01 $FA $01 $FB $01 $FC $01 $FD $01&lt;br /&gt;
&lt;br /&gt;
This is a useful example to use since it has a number of unique features. Firstly the paths to any given terminal node are all the same length, 8 bits. Secondly the path to each terminal node is the &#039;&#039;reverse&#039;&#039; of the character it represents. And finally the nodes are arranged in a logical order with an easily seen pattern; the first half of the tree consists of terminal nodes, the second half of branch nodes. (Of the second half the first half of &#039;&#039;that&#039;&#039; consists of branch nodes that lead to terminal nodes while the second half consists of branch nodes to two branch nodes and so on.)&lt;br /&gt;
&lt;br /&gt;
As an example the character $80 (128 or 10000000) can be expected to be represented by the path &#039;00000001&#039; and as such be the second node in the tree. Starting at the root node and following the leftmost path until the last step takes us to the following nodes: 254(root) -&amp;gt; 252 -&amp;gt; 248 -&amp;gt; 240 -&amp;gt; 224 -&amp;gt; 192 -&amp;gt; 128 -&amp;gt; 0(terminal node for characters $00 and $80)&lt;br /&gt;
&lt;br /&gt;
== Source code ==&lt;br /&gt;
&lt;br /&gt;
Some example code is available in various languages showing how to decompress (and in some cases compress) files using the Huffman algorithm.&lt;br /&gt;
&lt;br /&gt;
=== QuickBasic ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; DANGEROUS DAVE 2 - IN THE HAUNTED MANSION - Huffman Decompressor&lt;br /&gt;
&#039;  - by Napalm with thanks to Adurdin&#039;s work on ModKeen&lt;br /&gt;
&#039;&lt;br /&gt;
&#039; This source is Public Domain, please credit me if you use it.&lt;br /&gt;
&#039;&lt;br /&gt;
&#039;&lt;br /&gt;
DECLARE SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING)&lt;br /&gt;
&lt;br /&gt;
TYPE NODE&lt;br /&gt;
        BIT0 AS INTEGER&lt;br /&gt;
        BIT1 AS INTEGER&lt;br /&gt;
END TYPE&lt;br /&gt;
&lt;br /&gt;
&#039; Test Function&lt;br /&gt;
HUFFDECOMPRESS &amp;quot;TITLE1.DD2&amp;quot;, &amp;quot;TITLE1.PIC&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SUB HUFFDECOMPRESS (INNAME AS STRING, OUTNAME AS STRING) &#039; by Napalm&lt;br /&gt;
	DIM INFILE AS INTEGER, OUTFILE AS INTEGER, I AS INTEGER&lt;br /&gt;
	DIM SIG AS LONG, OUTLEN AS LONG, BITMASK AS INTEGER&lt;br /&gt;
	DIM CURNODE AS INTEGER, NEXTNODE AS INTEGER&lt;br /&gt;
	DIM CHRIN AS STRING * 1, CHROUT AS STRING * 1&lt;br /&gt;
	DIM NODES(0 TO 254) AS NODE&lt;br /&gt;
&lt;br /&gt;
	&#039; Open input file&lt;br /&gt;
	INFILE = FREEFILE&lt;br /&gt;
	OPEN INNAME FOR BINARY ACCESS READ AS INFILE&lt;br /&gt;
       &lt;br /&gt;
	&#039; Check file signature&lt;br /&gt;
	GET INFILE, , SIG&lt;br /&gt;
	IF SIG &amp;lt;&amp;gt; &amp;amp;H46465548 THEN &#039; Hex for: HUFF in little endian&lt;br /&gt;
		PRINT &amp;quot;INVALID FILE!&amp;quot;&lt;br /&gt;
		EXIT SUB&lt;br /&gt;
	END IF&lt;br /&gt;
       &lt;br /&gt;
	&#039; Get output length&lt;br /&gt;
	OUTLEN = 0&lt;br /&gt;
	GET INFILE, , OUTLEN&lt;br /&gt;
       &lt;br /&gt;
	&#039; Read in the huffman binary tree&lt;br /&gt;
	FOR I = 0 TO 254&lt;br /&gt;
		GET INFILE, , NODES(I).BIT0&lt;br /&gt;
		GET INFILE, , NODES(I).BIT1&lt;br /&gt;
	NEXT I&lt;br /&gt;
&lt;br /&gt;
	&#039; Open output file&lt;br /&gt;
	OUTFILE = FREEFILE&lt;br /&gt;
	OPEN OUTNAME FOR BINARY ACCESS WRITE AS OUTFILE&lt;br /&gt;
&lt;br /&gt;
	&#039; Decompress input data using binary tree&lt;br /&gt;
	CURNODE = 254&lt;br /&gt;
	DO&lt;br /&gt;
		BITMASK = 0&lt;br /&gt;
		GET INFILE, , CHRIN&lt;br /&gt;
		DO&lt;br /&gt;
			&#039; Decide which node to travel down depending on&lt;br /&gt;
			&#039;   input bits from CHRIN.&lt;br /&gt;
			IF ASC(CHRIN) AND 2 ^ BITMASK THEN&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT1&lt;br /&gt;
			ELSE&lt;br /&gt;
				NEXTNODE = NODES(CURNODE).BIT0&lt;br /&gt;
			END IF&lt;br /&gt;
		       &lt;br /&gt;
			&#039; Is this next node another part of the tree or&lt;br /&gt;
			&#039;   is it a end node? Less than 256 mean end node.&lt;br /&gt;
			IF NEXTNODE &amp;lt; 256 THEN&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Get output char from end node and save.&lt;br /&gt;
				CHROUT = CHR$(NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
				PUT OUTFILE, , CHROUT&lt;br /&gt;
			       &lt;br /&gt;
				&#039; Amend output length and start from top of&lt;br /&gt;
				&#039;   binary tree.&lt;br /&gt;
				OUTLEN = OUTLEN - 1&lt;br /&gt;
				CURNODE = 254&lt;br /&gt;
&lt;br /&gt;
			ELSE&lt;br /&gt;
				&#039; Travel to next node&lt;br /&gt;
				CURNODE = (NEXTNODE AND &amp;amp;HFF)&lt;br /&gt;
&lt;br /&gt;
			END IF&lt;br /&gt;
&lt;br /&gt;
			&#039; Move to next input bit&lt;br /&gt;
			BITMASK = BITMASK + 1&lt;br /&gt;
		LOOP WHILE BITMASK &amp;lt; 8 AND OUTLEN &amp;gt; 0&lt;br /&gt;
		&#039; Loop while we still need to output data&lt;br /&gt;
	LOOP WHILE OUTLEN &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
	&#039; Clean up&lt;br /&gt;
	CLOSE OUTFILE&lt;br /&gt;
	CLOSE INFILE&lt;br /&gt;
&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;qbasic&amp;quot;&amp;gt;&lt;br /&gt;
SUB MAKHUF &#039;Mak a degenerate huffman tree, store as string huffq&lt;br /&gt;
	OPEN &amp;quot;HUFF.DD2&amp;quot; FOR BINARY AS #8&lt;br /&gt;
	aq = &amp;quot;HUFF&amp;quot;&lt;br /&gt;
	PUT #8, 1, aq&lt;br /&gt;
	x = 9&lt;br /&gt;
	FOR t = 0 TO 255&lt;br /&gt;
		b = t&lt;br /&gt;
		va = 0&lt;br /&gt;
		vb = 0&lt;br /&gt;
		vc = 0&lt;br /&gt;
		vd = 0&lt;br /&gt;
		ve = 0&lt;br /&gt;
		vf = 0&lt;br /&gt;
		vg = 0&lt;br /&gt;
		vh = 0&lt;br /&gt;
		IF b &amp;gt; 127 THEN LET va = va + 1&lt;br /&gt;
		b = b MOD 128&lt;br /&gt;
		IF b &amp;gt; 63 THEN LET vb = vb + 1&lt;br /&gt;
		b = b MOD 64&lt;br /&gt;
		IF b &amp;gt; 31 THEN LET vc = vc + 1&lt;br /&gt;
		b = b MOD 32&lt;br /&gt;
		IF b &amp;gt; 15 THEN LET vd = vd + 1&lt;br /&gt;
		b = b MOD 16&lt;br /&gt;
		IF b &amp;gt; 7 THEN LET ve = ve + 1&lt;br /&gt;
		b = b MOD 8&lt;br /&gt;
		IF b &amp;gt; 3 THEN LET vf = vf + 1&lt;br /&gt;
		b = b MOD 4&lt;br /&gt;
		IF b &amp;gt; 1 THEN LET vg = vg + 1&lt;br /&gt;
		b = b MOD 2&lt;br /&gt;
		IF b = 1 THEN LET vh = vh + 1&lt;br /&gt;
		b = (vh * 128) + (vg * 64) + (vf * 32) + (16 * ve) + (8 * vd) + (4 * vc) + (2 * vb) + va&lt;br /&gt;
		aq = MKI$(b)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	FOR t = 0 TO 253&lt;br /&gt;
		aq = MKI$(t + 256)&lt;br /&gt;
		PUT #8, x, aq&lt;br /&gt;
		x = x + 2&lt;br /&gt;
	NEXT t&lt;br /&gt;
	GET #8, 1, huffq&lt;br /&gt;
	CLOSE #8&lt;br /&gt;
	KILL &amp;quot;HUFF.DD2&amp;quot;&lt;br /&gt;
END SUB&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Visual Basic .NET ===&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree representation ====&lt;br /&gt;
&lt;br /&gt;
This class, BinaryTreeNode, represents a binary tree whose branch nodes carry no value, like a Huffman dictionary tree.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;Public Class BinaryTreeNode(Of T)&lt;br /&gt;
    &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
    Private Branch As Boolean&lt;br /&gt;
    Private Children As BinaryTreeNode(Of T)()&lt;br /&gt;
    Private HoldValue As T&lt;br /&gt;
    Public Sub New(LeafValue As T)&lt;br /&gt;
        Branch = False&lt;br /&gt;
        HoldValue = LeafValue&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public Sub New(LeftChild As BinaryTreeNode(Of T), RightChild As BinaryTreeNode(Of T))&lt;br /&gt;
        Branch = True&lt;br /&gt;
        Children = {LeftChild, RightChild}&lt;br /&gt;
    End Sub&lt;br /&gt;
    Public Property Value As T&lt;br /&gt;
        Get&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return HoldValue&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As T)&lt;br /&gt;
            If Branch Then Throw New InvalidOperationException&lt;br /&gt;
            HoldValue = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Property Child(Side As ChildSide) As BinaryTreeNode(Of T)&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Return Children(Side)&lt;br /&gt;
        End Get&lt;br /&gt;
        Set(value As BinaryTreeNode(Of T))&lt;br /&gt;
            If Not Branch Then Throw New InvalidOperationException&lt;br /&gt;
            Children(Side) = value&lt;br /&gt;
        End Set&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Enum ChildSide As Byte&lt;br /&gt;
        Left = 0&lt;br /&gt;
        Right = 0&lt;br /&gt;
    End Enum&lt;br /&gt;
    Public ReadOnly Property Count As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Children(0).Count + Children(1).Count&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public ReadOnly Property Depth As Integer&lt;br /&gt;
        Get&lt;br /&gt;
            If Not Branch Then Return 1&lt;br /&gt;
            Return Math.Max(Children(0).Depth, Children(1).Depth) + 1&lt;br /&gt;
        End Get&lt;br /&gt;
    End Property&lt;br /&gt;
    Public Overrides Function ToString() As String&lt;br /&gt;
        Return &amp;quot;{Count = &amp;quot; &amp;amp; Count &amp;amp; &amp;quot;, Depth = &amp;quot; &amp;amp; Depth &amp;amp; &amp;quot;}&amp;quot;&lt;br /&gt;
    End Function&lt;br /&gt;
End Class&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Huffman tree reading ====&lt;br /&gt;
&lt;br /&gt;
This piece of code will read in a stored Huffman dictionary in the format described at the top of this article and store it in a BinaryTreeNode(Of Byte) as shown above.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;vbnet&amp;quot;&amp;gt;        &#039; By Fleexy, public domain, credit where credit is due&lt;br /&gt;
        Dim fDict As New IO.FileStream(DictionaryFile, IO.FileMode.Open)&lt;br /&gt;
        Dim raw(254) As Tuple(Of UShort, UShort)&lt;br /&gt;
        For x = 0 To 254&lt;br /&gt;
            raw(x) = Tuple.Create(ReadUShort(fDict), ReadUShort(fDict))&lt;br /&gt;
        Next&lt;br /&gt;
        fDict.Close()&lt;br /&gt;
        Dim GenerateTree As Func(Of UShort, BinaryTreeNode(Of Byte))&lt;br /&gt;
        GenerateTree = Function(NextNode As UShort) As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           Dim n As Tuple(Of UShort, UShort) = raw(NextNode)&lt;br /&gt;
                           Dim a, b As BinaryTreeNode(Of Byte)&lt;br /&gt;
                           If n.Item1 &amp;lt; 256 Then&lt;br /&gt;
                               a = New BinaryTreeNode(Of Byte)(n.Item1)&lt;br /&gt;
                           Else&lt;br /&gt;
                               a = GenerateTree(n.Item1 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           If n.Item2 &amp;lt; 256 Then&lt;br /&gt;
                               b = New BinaryTreeNode(Of Byte)(n.Item2)&lt;br /&gt;
                           Else&lt;br /&gt;
                               b = GenerateTree(n.Item2 - 256)&lt;br /&gt;
                           End If&lt;br /&gt;
                           Return New BinaryTreeNode(Of Byte)(a, b)&lt;br /&gt;
                       End Function&lt;br /&gt;
        Dim dict As BinaryTreeNode(Of Byte) = GenerateTree(254)&lt;br /&gt;
        fDict.Close()&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:File Formats]]&lt;br /&gt;
[[Category:Compressed Files]]&lt;br /&gt;
[[Category:Huffman Compression]]&lt;br /&gt;
[[Category:Compression Algorithms]]&lt;br /&gt;
[[Category:Code examples]]&lt;br /&gt;
[[Category:Dangerous Dave 2]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=Cosmo%27s_Cosmic_Adventure&amp;diff=4601</id>
		<title>Cosmo&#039;s Cosmic Adventure</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=Cosmo%27s_Cosmic_Adventure&amp;diff=4601"/>
		<updated>2013-04-06T09:34:59Z</updated>

		<summary type="html">&lt;p&gt;Levellass: Add Cosgraph link, change some game stuff that is now editable.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Game Infobox&lt;br /&gt;
 | Levels = Edit&lt;br /&gt;
 | Tiles = Edit&lt;br /&gt;
 | Sprites = Edit&lt;br /&gt;
 | Fullscreen = Edit&lt;br /&gt;
 | Sound = Edit&lt;br /&gt;
 | Music = Edit&lt;br /&gt;
 | Text = No&lt;br /&gt;
 | Story = No&lt;br /&gt;
 | Interface = No&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;Cosmo&#039;s Cosmic Adventure&#039;&#039;&#039;, also known simply as Cosmo, is a three part series chronicling the adventures of Cosmo, a small, green sucker-handed alien boy who is seeking his parents after a meteor collision forces them to land their ship on a dangerous and uncharted planet.&lt;br /&gt;
&lt;br /&gt;
The Cosmo engine was later updated and used for [[Duke Nukem II]], so the two games share a number of file formats.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
{{BeginFileFormatTools|Type=game}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [[Camoto]]&lt;br /&gt;
| Platform = Linux console/GUI&lt;br /&gt;
| grp = Edit&lt;br /&gt;
| map = Edit&lt;br /&gt;
| gfx = Edit&lt;br /&gt;
| mus = Edit&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://www.shikadi.net/wiki/files/moddingwiki/tools/cosmo/cosedit.zip CosEdit]&lt;br /&gt;
| Platform = DOS GUI&lt;br /&gt;
| grp = No&lt;br /&gt;
| map = Edit&lt;br /&gt;
| gfx = No&lt;br /&gt;
| mus = No&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://www.shikadi.net/wiki/files/moddingwiki/tools/cosmo/cosmedit10.zip Cosmo Edit]&lt;br /&gt;
| Platform = DOS console&lt;br /&gt;
| grp = No&lt;br /&gt;
| map = Edit&lt;br /&gt;
| gfx = No&lt;br /&gt;
| mus = No&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [http://www.shikadi.net/wiki/files/moddingwiki/tools/cosmo/textract.zip TExtract]&lt;br /&gt;
| Platform = DOS console&lt;br /&gt;
| grp = Read&lt;br /&gt;
| map = No&lt;br /&gt;
| gfx = No&lt;br /&gt;
| mus = No&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = Wombat&lt;br /&gt;
| Platform = Windows GUI&lt;br /&gt;
| grp = Read&lt;br /&gt;
| map = Read&lt;br /&gt;
| gfx = Read&lt;br /&gt;
| mus = Read&lt;br /&gt;
| sfx = No&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{FileFormatTool&lt;br /&gt;
| Name = [https://dl.dropbox.com/u/3940020/COSGRAPH-working.zip Cosgraph]&lt;br /&gt;
| Platform = Windows GUI&lt;br /&gt;
| grp = Read&lt;br /&gt;
| map = No&lt;br /&gt;
| gfx = Edit&lt;br /&gt;
| mus = Edit&lt;br /&gt;
| sfx = Edit&lt;br /&gt;
| txt = No&lt;br /&gt;
| sav = No&lt;br /&gt;
| exe = No&lt;br /&gt;
}}&lt;br /&gt;
{{EndFileFormatTools}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== File formats ==&lt;br /&gt;
&lt;br /&gt;
This section lists the major file formats used in the game.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Use!!Format!!Details&lt;br /&gt;
|-&lt;br /&gt;
| Backgrounds || [[Raw EGA data#Planar|Full-screen planar EGA]] || 32,000 byte &amp;lt;tt&amp;gt;*.MNI&amp;lt;/tt&amp;gt; files are 320x200 full-screen images (in four planes: blue, green, red, intensity).  &amp;lt;tt&amp;gt;TITLE1.MNI&amp;lt;/tt&amp;gt; is the image on the right, which is in this format.&lt;br /&gt;
|-&lt;br /&gt;
| Exit screen || [[B800 Text]] || 4000-byte &amp;lt;tt&amp;gt;*.MNI&amp;lt;/tt&amp;gt; files are text screens shown at exit (e.g. &amp;lt;tt&amp;gt;NOMEMORY.MNI&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Graphics || [[Cosmo Tileset Format]] || &amp;lt;tt&amp;gt;ACTORS.MNI&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;BD*.MNI&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CARTOON.MNI&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;MASKTILE.MNI&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;PLAYER.MNI&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;TILES.MNI&amp;lt;/tt&amp;gt; are all tilesets&lt;br /&gt;
|-&lt;br /&gt;
| Tile attributes || [[Cosmo Tile Attributes]] || Format of the &amp;lt;tt&amp;gt;TILEATTR.MNI&amp;lt;/tt&amp;gt; file&lt;br /&gt;
|-&lt;br /&gt;
| Group || [[VOL Format]] || group file storing the game data (both the &amp;lt;tt&amp;gt;*.VOL&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;*.STN&amp;lt;/tt&amp;gt; files are in this format.)&lt;br /&gt;
|-&lt;br /&gt;
| Levels || [[Cosmo Level Format]] || &amp;lt;tt&amp;gt;A*.MNI&amp;lt;/tt&amp;gt; are game levels.&lt;br /&gt;
|-&lt;br /&gt;
| Messages || - || Text is contained in the executable in all episodes, but in Cosmo 1 &amp;amp; 2, the executable is compressed by [[LZEXE]], and can be uncompressed with [[UNLZEXE]].&lt;br /&gt;
|-&lt;br /&gt;
| Music || [[IMF Format]] || Most of the &amp;lt;tt&amp;gt;M*.MNI&amp;lt;/tt&amp;gt; files are music files, e.g. &amp;lt;tt&amp;gt;MHAPPY.MNI&amp;lt;/tt&amp;gt;) - see [[#Notes]] below&lt;br /&gt;
|-&lt;br /&gt;
| Sounds || [[Inverse Frequency Sound format]] || &amp;lt;tt&amp;gt;SOUNDSx.MNI&amp;lt;/tt&amp;gt; files are in this format, there are three per episode&lt;br /&gt;
|-&lt;br /&gt;
| Saves || [[Cosmo Savegame Format]] || &amp;lt;tt&amp;gt;COSMOx.SVx&amp;lt;/tt&amp;gt; are saved games.  &amp;lt;tt&amp;gt;COSMOx.SVT&amp;lt;/tt&amp;gt; is a temporary save written at the start of each level&lt;br /&gt;
|-&lt;br /&gt;
| Tile info || [[Cosmo Tileinfo Format]] || How to lay out the actor tiles.  &amp;lt;tt&amp;gt;ACTRINFO.MNI&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;PLYRINFO.MNI&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;CARTINFO.MNI&amp;lt;/tt&amp;gt; are in this format&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&lt;br /&gt;
* In the original Cosmo Engine, the graphics memory is allocated after the memory used for storing the IMF file loaded for the current level. This has the unfortunate side effect of corrupting the entire tileset graphics table in memory, turning the graphics into random colours when a complex IMF file is loaded.  This is because the data from the IMF file overflows its allocated memory and overwrites the start of the tileset data.  Of course this only happens in memory, so the corruption is not permanent upon exiting.  The corruption will occur whenever that particular over-sized IMF file is loaded, but the corruption will completely disappear if the IMF file is removed from the [[:Category:Group Files|group file]] or replaced with a less-complex version (i.e. by reducing the number of notes.)  This does not appear to affect how the program runs, only affecting the tileset graphics. The overflow limit appears to be around 40K, which is above the size of nearly all Apogee IMF files, but not at the limit of IMF file size (64K for type-1, or effectively unlimited for type-0 as used in Cosmo.)&lt;br /&gt;
&lt;br /&gt;
* The game reads from the VOL and STN files in preference to the current directory.  Any game files in the current directory will not be read while the VOL/STN is present.  To modify a file, it will either need to be imported back into the VOL/STN, or the VOL/STN should have its entire contents extracted into the game folder and then be removed or renamed.&lt;br /&gt;
&lt;br /&gt;
* A directory path (relative to the current directory) can be given on the command line.  Any files that the game writes (saved games, high scores, etc.) will be written to this folder instead.  This is probably to allow running the game directly from read-only media like a CD.&lt;br /&gt;
&lt;br /&gt;
[[Category:Apogee]]&lt;br /&gt;
[[Category:Sidescroller]]&lt;/div&gt;</summary>
		<author><name>Levellass</name></author>
	</entry>
</feed>