Files
docs/Imploder_file_formats.html

799 lines
73 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en-GB" dir="ltr" class="client-nojs">
<head>
<meta charset="UTF-8" />
<title>Imploder file formats - ExoticA</title>
<meta name="generator" content="MediaWiki 1.24.0" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="search" type="application/opensearchdescription+xml" href="/mediawiki/opensearch_desc.php" title="ExoticA (en-gb)" />
<link rel="EditURI" type="application/rsd+xml" href="http://www.exotica.org.uk/mediawiki/api.php?action=rsd" />
<link rel="alternate" hreflang="x-default" href="/wiki/Imploder_file_formats" />
<link rel="copyright" href="http://creativecommons.org/licenses/by-sa/3.0/" />
<link rel="alternate" type="application/atom+xml" title="ExoticA Recent Wiki Changes Atom Feed" href="/mediawiki/index.php?title=Special:RecentChanges&amp;feed=atom" />
<link rel="stylesheet" href="http://www.exotica.org.uk/mediawiki/load.php?debug=false&amp;lang=en-gb&amp;modules=ext.geshi.language.c%7Cmediawiki.legacy.commonPrint%2Cshared%7Cmediawiki.skinning.content.externallinks%7Cmediawiki.skinning.interface%7Cmediawiki.ui.button%7Cskins.monobook.styles&amp;only=styles&amp;skin=exotica&amp;*" />
<link rel="stylesheet" href="/mediawiki/extensions/ExoticA/assets/main.css" media="screen" />
<!--[if lt IE 7]><link rel="stylesheet" href="/mediawiki/extensions/ExoticA/assets/IE60Fixes.css" media="screen" /><![endif]-->
<!--[if lt IE 8]><link rel="stylesheet" href="/mediawiki/extensions/ExoticA/assets/IEFixes.css" media="screen" /><![endif]--><meta name="ResourceLoaderDynamicStyles" content="" />
<link rel="stylesheet" href="http://www.exotica.org.uk/mediawiki/load.php?debug=false&amp;lang=en-gb&amp;modules=site&amp;only=styles&amp;skin=exotica&amp;*" />
<style>a:lang(ar),a:lang(kk-arab),a:lang(mzn),a:lang(ps),a:lang(ur){text-decoration:none}
/* cache key: exoticawiki:resourceloader:filter:minify-css:7:39ffd8cfea7fb46d8c7ca54fceab52e6 */</style>
<script src="http://www.exotica.org.uk/mediawiki/load.php?debug=false&amp;lang=en-gb&amp;modules=startup&amp;only=scripts&amp;skin=exotica&amp;*"></script>
<script>if(window.mw){
mw.config.set({"wgCanonicalNamespace":"","wgCanonicalSpecialPageName":false,"wgNamespaceNumber":0,"wgPageName":"Imploder_file_formats","wgTitle":"Imploder file formats","wgCurRevisionId":81077,"wgRevisionId":81077,"wgArticleId":14649,"wgIsArticle":true,"wgIsRedirect":false,"wgAction":"view","wgUserName":null,"wgUserGroups":["*"],"wgCategories":["File formats"],"wgBreakFrames":false,"wgPageContentLanguage":"en-gb","wgPageContentModel":"wikitext","wgSeparatorTransformTable":["",""],"wgDigitTransformTable":["",""],"wgDefaultDateFormat":"dmy","wgMonthNames":["","January","February","March","April","May","June","July","August","September","October","November","December"],"wgMonthNamesShort":["","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"wgRelevantPageName":"Imploder_file_formats","wgIsProbablyEditable":false,"wgRestrictionEdit":[],"wgRestrictionMove":[],"wgWikiEditorEnabledModules":{"toolbar":true,"dialogs":true,"hidesig":true,"preview":false,"previewDialog":false,"publish":false}});
}</script><script>if(window.mw){
mw.loader.implement("user.options",function($,jQuery){mw.user.options.set({"ccmeonemails":0,"cols":80,"date":"default","diffonly":0,"disablemail":0,"editfont":"default","editondblclick":0,"editsectiononrightclick":0,"enotifminoredits":0,"enotifrevealaddr":0,"enotifusertalkpages":1,"enotifwatchlistpages":1,"extendwatchlist":0,"fancysig":0,"forceeditsummary":0,"gender":"unknown","hideminor":0,"hidepatrolled":0,"imagesize":2,"math":1,"minordefault":0,"newpageshidepatrolled":0,"nickname":"","norollbackdiff":0,"numberheadings":0,"previewonfirst":0,"previewontop":1,"rcdays":30,"rclimit":50,"rows":25,"showhiddencats":0,"shownumberswatching":1,"showtoolbar":1,"skin":"exotica","stubthreshold":0,"thumbsize":5,"underline":2,"uselivepreview":0,"usenewrc":0,"watchcreations":1,"watchdefault":1,"watchdeletion":0,"watchlistdays":3,"watchlisthideanons":0,"watchlisthidebots":0,"watchlisthideliu":0,"watchlisthideminor":0,"watchlisthideown":0,"watchlisthidepatrolled":0,"watchmoves":0,"watchrollback":0,
"wllimit":250,"useeditwarning":1,"prefershttps":1,"usebetatoolbar":1,"usebetatoolbar-cgd":1,"usenavigabletoc":0,"language":"en-gb","variant-gan":"gan","variant-iu":"iu","variant-kk":"kk","variant-ku":"ku","variant-shi":"shi","variant-sr":"sr","variant-tg":"tg","variant-uz":"uz","variant-zh":"zh","searchNs0":true,"searchNs1":false,"searchNs2":false,"searchNs3":false,"searchNs4":false,"searchNs5":false,"searchNs6":false,"searchNs7":false,"searchNs8":false,"searchNs9":false,"searchNs10":false,"searchNs11":false,"searchNs12":false,"searchNs13":false,"searchNs14":false,"searchNs15":false,"variant":"en-gb"});},{},{});mw.loader.implement("user.tokens",function($,jQuery){mw.user.tokens.set({"editToken":"+\\","patrolToken":"+\\","watchToken":"+\\"});},{},{});
/* cache key: exoticawiki:resourceloader:filter:minify-js:7:e5b3381aa532aa485b73682aaa7f9ca1 */
}</script>
<script>if(window.mw){
mw.loader.load(["mediawiki.page.startup","mediawiki.legacy.wikibits","mediawiki.legacy.ajax"]);
}</script>
</head>
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-Imploder_file_formats skin-ExoticA action-view">
<div id="globalWrapper">
<div id="menu_bar" class="noprint">
<img class="wb_gadgets" src="/mediawiki/extensions/ExoticA/assets/screengadgets.png" alt="" />
</div>
<div id="logo_bar" class="noprint">
<div id="logo"><a href="/wiki/Main_Page" title="Main Page"><img src="/mediawiki/extensions/ExoticA/assets/themes/chaos_engine/logo.png" width="400" height="140" alt="ExoticA" /></a></div>
<div id="montage" style="margin-left: 400px; _margin-left: 397px; background-image: url(/mediawiki/extensions/ExoticA/assets/themes/chaos_engine/montage_1.png);">
<div id="trans" style="background-image: url(/mediawiki/extensions/ExoticA/assets/themes/chaos_engine/trans.png); _background-image: none; _filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',src='/mediawiki/extensions/ExoticA/assets/themes/chaos_engine/trans.png' );"></div></div>
</div>
<div style="position: relative; width: 100%;">
<div class="wb_window_top noprint">
<img class="wb_gadgets" src="/mediawiki/extensions/ExoticA/assets/screengadgets.png" alt="" />
<span class="wb_title">ExoticA Wiki</span>
</div>
<div class="wb_window">
<div id="content" class="mw-body" role="main">
<a id="top"></a>
<h1 id="firstHeading" class="firstHeading" lang="en-GB"><span dir="auto">Imploder file formats</span></h1>
<div id="bodyContent" class="mw-body-content">
<div id="siteSub">From ExoticA</div>
<div id="contentSub"></div>
<div id="jump-to-nav" class="mw-jump">Jump to: <a href="#column-one">navigation</a>, <a href="#searchInput">search</a></div>
<!-- start content -->
<div id="mw-content-text" lang="en-GB" dir="ltr" class="mw-content-ltr"><p>These are the file formats used by <a href="/wiki/The_Imploder" title="The Imploder">The Imploder</a> and related utilities.
</p><p>In this document, all multi-byte values are stored in the big-endian format.
</p>
<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
<ul>
<li class="toclevel-1 tocsection-1"><a href="#The_Imploder"><span class="tocnumber">1</span> <span class="toctext">The Imploder</span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#DImp"><span class="tocnumber">2</span> <span class="toctext">DImp</span></a>
<ul>
<li class="toclevel-2 tocsection-3"><a href="#Overall_DImp_file_format"><span class="tocnumber">2.1</span> <span class="toctext">Overall DImp file format</span></a></li>
<li class="toclevel-2 tocsection-4"><a href="#DImp_header"><span class="tocnumber">2.2</span> <span class="toctext">DImp header</span></a></li>
<li class="toclevel-2 tocsection-5"><a href="#DImp_information_table"><span class="tocnumber">2.3</span> <span class="toctext">DImp information table</span></a></li>
<li class="toclevel-2 tocsection-6"><a href="#DImp_text_message"><span class="tocnumber">2.4</span> <span class="toctext">DImp text message</span></a></li>
<li class="toclevel-2 tocsection-7"><a href="#DImp_cylinder"><span class="tocnumber">2.5</span> <span class="toctext">DImp cylinder</span></a></li>
<li class="toclevel-2 tocsection-8"><a href="#DImp_checksum_format"><span class="tocnumber">2.6</span> <span class="toctext">DImp checksum format</span></a></li>
</ul>
</li>
<li class="toclevel-1 tocsection-9"><a href="#FImp"><span class="tocnumber">3</span> <span class="toctext">FImp</span></a>
<ul>
<li class="toclevel-2 tocsection-10"><a href="#Re-ordering_the_data_for_decompression"><span class="tocnumber">3.1</span> <span class="toctext">Re-ordering the data for decompression</span></a></li>
<li class="toclevel-2 tocsection-11"><a href="#Example_code"><span class="tocnumber">3.2</span> <span class="toctext">Example code</span></a></li>
</ul>
</li>
<li class="toclevel-1 tocsection-12"><a href="#Explosion"><span class="tocnumber">4</span> <span class="toctext">Explosion</span></a>
<ul>
<li class="toclevel-2 tocsection-13"><a href="#Example_code_2"><span class="tocnumber">4.1</span> <span class="toctext">Example code</span></a></li>
</ul>
</li>
</ul>
</div>
<h2><span class="mw-headline" id="The_Imploder">The Imploder</span></h2>
<p>This section has still to be written. The Imploder creates compressed executable files that self-unpack when run. There are several variations: normal Imploder (sub-variants: 3.1, 3.1 pure and 4.0), library Imploder which uses the external "explode.library" (sub-variants: 3.1 and 4.0) and overlayed Imploder which loads the executable at the same time as decrunching it. The compression code is the same as the Disk Imploder and File Imploder, but the Amiga executable file structure has to be reconstituted as well. MC680x0 code to do this can be found <a rel="nofollow" class="external text" href="http://libxad.cvs.sourceforge.net/*checkout*/libxad/libxfd/source/master/slaves/Imploder.a?revision=1.2&amp;content-type=text%2Fplain">here</a>.
</p>
<h2><span class="mw-headline" id="DImp">DImp</span></h2>
<p>The purpose of the Disk Imploder is to compress the raw disk structure of standard Amiga disks with the Imploder compression algorithm. The file extension ".DMP" is used for a standard Disk Imploder file, the extension ".DEX" is used for a self-extracting Disk Imploder file.
</p>
<h3><span class="mw-headline" id="Overall_DImp_file_format">Overall DImp file format</span></h3>
<p>The regular Disk Imploder format is given below. The self-extracting format is simply the same data, preceded by an Amiga executable that will extract the data. An Amiga executable always begins with the 32-bit value 0x3F3 (1011 in decimal). DImp 1.00 self-extracting files have the DImp data at offset 3856 decimal. DImp 2.27 self-extracting files have the DImp data at offset 5796 decimal. For other versions, you should search the entire executable for the "DIMP" identifier of the header.
</p><p>The regular DImp format comprises the following sections, stored consecutively without gaps, and in the order given.
</p>
<ul><li> <a href="#DImp_header">DImp header</a></li>
<li> <a href="#DImp_information_table">DImp information table</a></li>
<li> An optional <a href="#DImp_text_message">DImp text message</a></li>
<li> Zero or more <a href="#DImp_cylinder">DImp cylinders</a></li></ul>
<h3><span class="mw-headline" id="DImp_header">DImp header</span></h3>
<p>The DImp header has two 32-bit values. First, the identifing value 0x44494D50, or "DIMP" in ASCII. Secondly, the length of the information table to follow, in bytes. It must be between 4 and 404.
</p>
<h3><span class="mw-headline" id="DImp_information_table">DImp information table</span></h3>
<p>The DImp information table has all metadata regarding the compression and disk structure. The overall length of the table is 404 (0x194) bytes. If the table length given in the header section is less than 404, then only that number of bytes should be retrieved from the DImp file, the remaining bytes must be filled in with zeroes. The table format is as follows:
</p>
<table class="infotable">
<tr>
<th>Offset</th>
<th>Length</th>
<th>Description
</th></tr>
<tr>
<td>0x00</td>
<td>4</td>
<td>This is a checksum of all data in the information table, except this checksum field itself. In other words, the checksum of 400 (0x190) bytes of data from offset 0x004 to offset 0x193, inclusive. See the <a href="#DImp_checksum_format">checksum format</a> for more information.
</td></tr>
<tr>
<td>0x04</td>
<td>2</td>
<td>This is the level of compression used. As all levels can be unpacked with the same code, it is not needed.
</td></tr>
<tr>
<td>0x06</td>
<td>10</td>
<td>This is an 80 bit bitfield, one bit for each possible cylinder on the compressed disk. The most significant bit of byte 0 represents cylinder 0. The least significant bit of byte 0 represents cylinder 7. The least significant bit of byte 9 represents cylinder 79. If a bit is set, the corresponding cylinder is stored in the DImp file. If a bit is not set, the cylinder is not stored in the DImp file.
</td></tr>
<tr>
<td>0x10</td>
<td>28</td>
<td>This is an explosion table. It stores the state required for the decompressor to unpack the <a href="#DImp_text_message">text message</a>, if present. The actual structure comprises 8 16-bit values used as "base offsets" and 12 8-bit values used as "number of extra bits to read".
</td></tr>
<tr>
<td>0x2C</td>
<td>28</td>
<td>This is another explosion table, which stores the state required for the decompressor to unpack a cylinder. All cylinders use the same explosion table.
</td></tr>
<tr>
<td>0x48</td>
<td>4</td>
<td>This is the compressed length of the <a href="#DImp_text_message">text message</a>. If it is 0, there is no text message present.
</td></tr>
<tr>
<td>0x4C</td>
<td>4</td>
<td>This is the uncompressed length of the <a href="#DImp_text_message">text message</a>.
</td></tr>
<tr>
<td>0x50</td>
<td>4</td>
<td>This is a checksum of the text message, when uncompressed. See the <a href="#DImp_checksum_format">checksum format</a> for more information.
</td></tr>
<tr>
<td>0x54</td>
<td>320</td>
<td>This is an array of 80 32-bit values, one for each cylinder. See the <a href="#DImp_cylinder">cylinder section</a> for more information.
</td></tr></table>
<h3><span class="mw-headline" id="DImp_text_message">DImp text message</span></h3>
<p>The text message, if present in the DImp file, is simply a stream of Imploder compressed data. The length of this compressed stream is given in the information table at offset 0x4C. The length of the stream when uncompressed is given at offset 0x48. If either of these two values are zero, there is no text message present. The stream should be decompressed with the <a href="#Explosion">explosion algorithm</a>, using the explosion table at offset 0x10 in the information table. The resulting uncompressed stream is expected to be printable ISO-8859-1 text, but may feature ANSI codes and Amiga <tt>console.device</tt> specific escape codes.
</p>
<h3><span class="mw-headline" id="DImp_cylinder">DImp cylinder</span></h3>
<p>At this point in the DImp file, anything between 0 and 80 compressed streams are present. Each compressed stream is individually sized and represents one cylinder of an Amiga disk. They are ordered from cylinder 0 to cylinder 79. If a cylinder is not present in the DImp file, it uses no bytes in this section of the DImp file.
</p><p>An Amiga disk has two sides, 80 tracks, and 11 sectors per track. Each sector is 512 bytes in length. So, a cylinder comprises 22 512-byte sectors, or exactly 11264 bytes of data. The track number is the same for all sectors in a cylinder, and the uncompressed cylinder data is broken into 512 byte sectors in this order: sector 0 on side 0, sector 0 on side 1, sector 1 on side 0, sector 1 on side 1, sector 2 on side 0, sector 2 on side 1, and so on until sector 10 on side 1.
</p><p>To determine if a cylinder is present in the DImp file, first check the disk bitmap at offset 0x06 in the information table. If the appropriate bit is 0, that cylinder is not present. If the bit is set, then take the appropriate 32 bit entry from the cylinder information array at offset 0x54 in the information table, and interpret it as follows:
</p>
<ol><li>If the entry is 0x00000000, then the cylinder is not present in the file, despite what the disk bitmap said. This happens when an error occurs while reading the disk at compression time.</li>
<li>If the entry is 0xFFFFFFFF, then the cylinder comprises nothing but zeros. Assume the cylinder expands to 11264 zero bytes, and does not use any bytes from this part of the DImp file for its definition.</li>
<li>In all other cases, the entry must be broken into the most significant 16 bits and the least significant 16 bits.
<ul><li> The most significant 16 bits are the compressed size of this cylinder, in bytes. If this value is more than the uncompressed length of a cylinder, 11264, then something is wrong. The DImp utility exits with the message "wierd info-table entry" in this scenario. If this value is exactly 11264, the cylinder is stored uncompressed. Otherwise, the cylinder data is a stream of Imploder compressed data. The uncompressed length of this data is 11264 bytes. The stream should be decompressed with the <a href="#Explosion">explosion algorithm</a>, using the explosion table at offset 0x2C in the information table.</li>
<li> The least significant 16 bits are the least significant 16 bits of the checksum on the cylinder's bytes stored in the file. See the <a href="#DImp_checksum_format">checksum format</a> for more information.</li></ul></li></ol>
<h3><span class="mw-headline" id="DImp_checksum_format">DImp checksum format</span></h3>
<p>If the length of the data to be checksummed in bytes is not a multiple of 2, assume that the length is one byte longer, and that byte's value is 0. The byte's location is at the very end of the checksummed data.
</p><p>To derive the checksum, interpret the data to be checksummed as a contiguous array of 16-bit, unsigned, big-endian values. Compute the sum of all these values, then add 7. The least significant 32 bits of the result are the checksum value.
</p>
<h2><span class="mw-headline" id="FImp">FImp</span></h2>
<p>FImp compresses a single file into the following format:
</p>
<table class="infotable">
<tr>
<th>Offset</th>
<th>Length</th>
<th>Description
</th></tr>
<tr>
<td>0x00</td>
<td>4</td>
<td>The identifying value 0x494D5021, or "IMP!" in ASCII. Clones of the FImp format use the IDs "ATN!", "BDPI", "CHFI", "Dupa", "EDAM", "FLT!", "M.H.", "PARA" and "RDC9". <a rel="nofollow" class="external autonumber" href="http://libxad.cvs.sourceforge.net/viewvc/libxad/libxfd/source/master/slaves/Imploder.a?view=markup#l_1368">[1]</a> <a rel="nofollow" class="external autonumber" href="http://www.amiga-stuff.com/crunchers-id.html">[2]</a>
</td></tr>
<tr>
<td>0x04</td>
<td>4</td>
<td>The uncompressed length of the file, in bytes.
</td></tr>
<tr>
<td>0x08</td>
<td>4</td>
<td>The offset of the following compressed data section: <i>endoffset</i>. Always even.
</td></tr>
<tr>
<td>0x0C</td>
<td><i>endoffset</i> - 0x0C</td>
<td>The compressed data section.
</td></tr>
<tr>
<td><i>endoffset</i></td>
<td>4</td>
<td>Compressed data longword 3.
</td></tr>
<tr>
<td><i>endoffset</i> + 0x04</td>
<td>4</td>
<td>Compressed data longword 2.
</td></tr>
<tr>
<td><i>endoffset</i> + 0x08</td>
<td>4</td>
<td>Compressed data longword 1.
</td></tr>
<tr>
<td><i>endoffset</i> + 0x0C</td>
<td>4</td>
<td>The initial literal run length.
</td></tr>
<tr>
<td><i>endoffset</i> + 0x10</td>
<td>2</td>
<td>Bit 15 is an indicator of compressed data length; bits 7-0 are the first byte of the compressed data ("initial bit-buffer").
</td></tr>
<tr>
<td><i>endoffset</i> + 0x12</td>
<td>28</td>
<td>The explosion table (8 16-bit values and 12 8-bit values)
</td></tr>
<tr>
<td><i>endoffset</i> + 0x2E</td>
<td>4</td>
<td>Unknown; appears to be a checksum of the preceding bytes, but out by a little.
</td></tr></table>
<h3><span class="mw-headline" id="Re-ordering_the_data_for_decompression">Re-ordering the data for decompression</span></h3>
<p>The compressed data is not immediately decompressable. The format is designed such that you can load the file, including headers, into a single decompression buffer and decompress it in-place. Because of this, it uses the three longwords (4 bytes each) of the header information as a place to put compressed data, rather than "wasting" 12 bytes.
</p><p>To reconstitute the data so it can be decompressed with the explosion algorithm, order the data as follows:
</p>
<table class="infotable">
<tr>
<th>Offset</th>
<th>Length</th>
<th>Contents
</th></tr>
<tr>
<td>0x00</td>
<td>4</td>
<td>Compressed data longword 1
</td></tr>
<tr>
<td>0x04</td>
<td>4</td>
<td>Compressed data longword 2
</td></tr>
<tr>
<td>0x08</td>
<td>4</td>
<td>Compressed data longword 3
</td></tr>
<tr>
<td>0x0C</td>
<td><i>endoffset</i> - 0x0C</td>
<td>Compressed data section (maybe includes initial bit-buffer)
</td></tr>
<tr>
<td><i>endoffset</i></td>
<td>4</td>
<td>Initial literal run length
</td></tr>
<tr>
<td><i>endoffset</i> + 0x04</td>
<td>1</td>
<td>initial bit-buffer, if not in compressed data section
</td></tr></table>
<p>In a "normal" compressed stream, the first five bytes (at the end of the stream; the stream is read backwards) are the first literal run length and the initial byte for the bit buffer. If the length of the input data is odd, then the 1-byte "initial bit-buffer" is placed after the 4-byte "first literal run" in memory. This way, the 4-byte run is at an even memory address, so it can be read directly by the MC680x0. If the length of the input data is even, then the "initial bit-buffer" comes before the 4-byte "first literal run", so the 4-byte run is still at an even memory address.
</p><p>In FImp, <i>endoffset</i> is always even, however the length of the compressed data is not always even. So this information is stored in the bit-buffer word. Check the bit-buffer's top bit (bit 15). If it is set, then the length of the compressed data is odd. Place the lower 8 bits of the bit-buffer word as a byte after the initial-literal-run-length and decompress the data with an input length of <i>endoffset</i> + 5. However, if bit 15 is not set, then the length of the compressed data is even, and the final byte of the compressed data section is padding. Write the initial bit-buffer's lower 8 bits into the final byte of the compressed data section (<i>endoffset</i> - 1) and decompress the data with an input length of <i>endoffset</i> + 4.
</p>
<h3><span class="mw-headline" id="Example_code">Example code</span></h3>
<p>The following standard C program will decompress FImp files. It requires the C code of the explosion algorithm, listed below, to be included in a file called "explode.c".
</p>
<table class="infotable collapsible collapsed">
<tr>
<th> defimp.c
</th></tr>
<tr>
<td> <div dir="ltr" class="mw-geshi mw-code mw-content-ltr"><div class="c source-c"><pre class="de1"><span class="coMULTI">/* This code is placed in the Public Domain by its author, Stuart Caie */</span>
<span class="co2">#include &lt;stdlib.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;string.h&gt;</span>
<span class="co2">#include &quot;explode.c&quot;</span>
&#160;
<span class="kw4">char</span> <span class="sy0">*</span>defimp<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">*</span>in<span class="sy0">,</span> <span class="kw4">unsigned</span> <span class="kw4">int</span> in_len<span class="sy0">,</span>
<span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">**</span>out_ptr<span class="sy0">,</span> <span class="kw4">unsigned</span> <span class="kw4">int</span> <span class="sy0">*</span>out_len_ptr<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
<span class="kw4">unsigned</span> <span class="kw4">int</span> id<span class="sy0">,</span> end_off<span class="sy0">,</span> out_len<span class="sy0">,</span> ok<span class="sy0">;</span>
<span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">*</span>out<span class="sy0">;</span>
&#160;
<span class="sy0">*</span>out_ptr <span class="sy0">=</span> NULL<span class="sy0">;</span>
&#160;
<span class="kw1">if</span> <span class="br0">&#40;</span>in_len <span class="sy0">&lt;</span> <span class="nu12">0x30</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="st0">&quot;too short to be a FImp file&quot;</span><span class="sy0">;</span>
&#160;
id <span class="sy0">=</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x00</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">24</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x01</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">16</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x02</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">8</span><span class="br0">&#41;</span> <span class="sy0">|</span> in<span class="br0">&#91;</span><span class="nu12">0x03</span><span class="br0">&#93;</span><span class="sy0">;</span>
out_len <span class="sy0">=</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x04</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">24</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x05</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">16</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x06</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">8</span><span class="br0">&#41;</span> <span class="sy0">|</span> in<span class="br0">&#91;</span><span class="nu12">0x07</span><span class="br0">&#93;</span><span class="sy0">;</span>
end_off <span class="sy0">=</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x08</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">24</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x09</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">16</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span><span class="nu12">0x0A</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">8</span><span class="br0">&#41;</span> <span class="sy0">|</span> in<span class="br0">&#91;</span><span class="nu12">0x0B</span><span class="br0">&#93;</span><span class="sy0">;</span>
&#160;
<span class="coMULTI">/* check for magic ID 'IMP!', or one of the other IDs used by Imploder
clones; ATN!, BDPI, CHFI, Dupa, EDAM, FLT!, M.H., PARA and RDC9 */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>id <span class="sy0">!=</span> <span class="nu12">0x494d5021</span> <span class="sy0">&amp;&amp;</span> id <span class="sy0">!=</span> <span class="nu12">0x41544e21</span> <span class="sy0">&amp;&amp;</span> id <span class="sy0">!=</span> <span class="nu12">0x42445049</span> <span class="sy0">&amp;&amp;</span>
id <span class="sy0">!=</span> <span class="nu12">0x43484649</span> <span class="sy0">&amp;&amp;</span> id <span class="sy0">!=</span> <span class="nu12">0x44757061</span> <span class="sy0">&amp;&amp;</span> id <span class="sy0">!=</span> <span class="nu12">0x4544414d</span> <span class="sy0">&amp;&amp;</span>
id <span class="sy0">!=</span> <span class="nu12">0x464c5421</span> <span class="sy0">&amp;&amp;</span> id <span class="sy0">!=</span> <span class="nu12">0x4d2e482e</span> <span class="sy0">&amp;&amp;</span> id <span class="sy0">!=</span> <span class="nu12">0x50415241</span> <span class="sy0">&amp;&amp;</span>
id <span class="sy0">!=</span> <span class="nu12">0x52444339</span><span class="br0">&#41;</span>
<span class="kw1">return</span> <span class="st0">&quot;unknown file format&quot;</span><span class="sy0">;</span>
&#160;
<span class="coMULTI">/* sanity checks */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>end_off <span class="sy0">&amp;</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="st0">&quot;compressed size not even&quot;</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>end_off <span class="sy0">&lt;</span> <span class="nu0">14</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="st0">&quot;compressed size too short&quot;</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>end_off <span class="sy0">+</span> <span class="nu12">0x2E</span><span class="br0">&#41;</span> <span class="sy0">&gt;</span> in_len<span class="br0">&#41;</span> <span class="kw1">return</span> <span class="st0">&quot;not enough input data&quot;</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>end_off <span class="sy0">+</span> <span class="nu12">0x26</span><span class="br0">&#41;</span> <span class="sy0">&gt;</span> out_len<span class="br0">&#41;</span> <span class="kw1">return</span> <span class="st0">&quot;output length less than input&quot;</span><span class="sy0">;</span>
&#160;
<span class="coMULTI">/* allocate memory */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="br0">&#40;</span>out <span class="sy0">=</span> <span class="kw3">malloc</span><span class="br0">&#40;</span>out_len<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="st0">&quot;can't allocate memory&quot;</span><span class="sy0">;</span>
<span class="sy0">*</span>out_ptr <span class="sy0">=</span> out<span class="sy0">;</span>
<span class="sy0">*</span>out_len_ptr <span class="sy0">=</span> out_len<span class="sy0">;</span>
&#160;
<span class="coMULTI">/* copy input data into output buffer */</span>
<span class="kw3">memcpy</span><span class="br0">&#40;</span><span class="sy0">&amp;</span>out<span class="br0">&#91;</span><span class="nu12">0x00</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="sy0">&amp;</span>in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x08</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">memcpy</span><span class="br0">&#40;</span><span class="sy0">&amp;</span>out<span class="br0">&#91;</span><span class="nu12">0x04</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="sy0">&amp;</span>in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x04</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">memcpy</span><span class="br0">&#40;</span><span class="sy0">&amp;</span>out<span class="br0">&#91;</span><span class="nu12">0x08</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="sy0">&amp;</span>in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x00</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">memcpy</span><span class="br0">&#40;</span><span class="sy0">&amp;</span>out<span class="br0">&#91;</span><span class="nu12">0x0C</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="sy0">&amp;</span>in<span class="br0">&#91;</span><span class="nu12">0x0C</span><span class="br0">&#93;</span><span class="sy0">,</span> end_off <span class="sy0">-</span> <span class="nu12">0x0C</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">memcpy</span><span class="br0">&#40;</span><span class="sy0">&amp;</span>out<span class="br0">&#91;</span>end_off<span class="br0">&#93;</span><span class="sy0">,</span> <span class="sy0">&amp;</span>in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x0C</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span>
&#160;
<span class="kw1">if</span> <span class="br0">&#40;</span>in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x10</span><span class="br0">&#93;</span> <span class="sy0">&amp;</span> <span class="nu12">0x80</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
out<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu0">4</span><span class="br0">&#93;</span> <span class="sy0">=</span> in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x11</span><span class="br0">&#93;</span><span class="sy0">;</span>
ok <span class="sy0">=</span> explode<span class="br0">&#40;</span>out<span class="sy0">,</span> <span class="sy0">&amp;</span>in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x12</span><span class="br0">&#93;</span><span class="sy0">,</span> end_off <span class="sy0">+</span> <span class="nu0">5</span><span class="sy0">,</span> out_len<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
out<span class="br0">&#91;</span>end_off <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x11</span><span class="br0">&#93;</span><span class="sy0">;</span>
ok <span class="sy0">=</span> explode<span class="br0">&#40;</span>out<span class="sy0">,</span> <span class="sy0">&amp;</span>in<span class="br0">&#91;</span>end_off <span class="sy0">+</span> <span class="nu12">0x12</span><span class="br0">&#93;</span><span class="sy0">,</span> end_off <span class="sy0">+</span> <span class="nu0">4</span><span class="sy0">,</span> out_len<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="kw1">return</span> ok <span class="sy0">?</span> NULL <span class="sy0">:</span> <span class="st0">&quot;can't deplode&quot;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="kw4">size_t</span> filelen<span class="sy0">;</span>
<span class="kw4">void</span> <span class="sy0">*</span>loadfile<span class="br0">&#40;</span><span class="kw4">char</span> <span class="sy0">*</span>name<span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw4">void</span> <span class="sy0">*</span>mem <span class="sy0">=</span> NULL<span class="sy0">;</span> FILE <span class="sy0">*</span>fd<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>fd <span class="sy0">=</span> <span class="kw3">fopen</span><span class="br0">&#40;</span>name<span class="sy0">,</span> <span class="st0">&quot;rb&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw3">fseek</span><span class="br0">&#40;</span>fd<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SEEK_END<span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>filelen <span class="sy0">=</span> <span class="kw3">ftell</span><span class="br0">&#40;</span>fd<span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span><span class="kw3">fseek</span><span class="br0">&#40;</span>fd<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SEEK_SET<span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>mem <span class="sy0">=</span> <span class="kw3">malloc</span><span class="br0">&#40;</span>filelen<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">fread</span><span class="br0">&#40;</span>mem<span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> filelen<span class="sy0">,</span> fd<span class="br0">&#41;</span> <span class="sy0">&lt;</span> filelen<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw3">free</span><span class="br0">&#40;</span>mem<span class="br0">&#41;</span><span class="sy0">;</span> mem <span class="sy0">=</span> NULL<span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
<span class="kw3">fclose</span><span class="br0">&#40;</span>fd<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="kw1">return</span> mem<span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="kw4">int</span> savefile<span class="br0">&#40;</span><span class="kw4">char</span> <span class="sy0">*</span>name<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>mem<span class="sy0">,</span> <span class="kw4">size_t</span> length<span class="br0">&#41;</span> <span class="br0">&#123;</span>
FILE <span class="sy0">*</span>fd <span class="sy0">=</span> <span class="kw3">fopen</span><span class="br0">&#40;</span>name<span class="sy0">,</span> <span class="st0">&quot;wb&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw4">int</span> ok <span class="sy0">=</span> fd <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span><span class="kw3">fwrite</span><span class="br0">&#40;</span>mem<span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> length<span class="sy0">,</span> fd<span class="br0">&#41;</span> <span class="sy0">==</span> length<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>fd<span class="br0">&#41;</span> <span class="kw3">fclose</span><span class="br0">&#40;</span>fd<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">return</span> ok<span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="kw4">int</span> main<span class="br0">&#40;</span><span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">*</span>in <span class="sy0">=</span> NULL<span class="sy0">,</span> <span class="sy0">*</span>out <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">unsigned</span> <span class="kw4">int</span> out_len<span class="sy0">;</span>
<span class="kw4">char</span> <span class="sy0">*</span>msg<span class="sy0">;</span>
&#160;
<span class="kw1">if</span> <span class="br0">&#40;</span>argc <span class="sy0">!=</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw3">fprintf</span><span class="br0">&#40;</span>stderr<span class="sy0">,</span> <span class="st0">&quot;Usage:&#160;%s &lt;input file&gt; &lt;output file&gt;<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="coMULTI">/* load file */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="br0">&#40;</span>in <span class="sy0">=</span> loadfile<span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw3">perror</span><span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="coMULTI">/* deplode file */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>msg <span class="sy0">=</span> defimp<span class="br0">&#40;</span>in<span class="sy0">,</span> filelen<span class="sy0">,</span> <span class="sy0">&amp;</span>out<span class="sy0">,</span> <span class="sy0">&amp;</span>out_len<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw3">fprintf</span><span class="br0">&#40;</span>stderr<span class="sy0">,</span> <span class="st0">&quot;%s:&#160;%s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">,</span> msg<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">free</span><span class="br0">&#40;</span>in<span class="br0">&#41;</span><span class="sy0">;</span> <span class="kw3">free</span><span class="br0">&#40;</span>out<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="coMULTI">/* save output */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>savefile<span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">,</span> out<span class="sy0">,</span> out_len<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw3">free</span><span class="br0">&#40;</span>in<span class="br0">&#41;</span><span class="sy0">;</span> <span class="kw3">free</span><span class="br0">&#40;</span>out<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">perror</span><span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="kw3">free</span><span class="br0">&#40;</span>in<span class="br0">&#41;</span><span class="sy0">;</span> <span class="kw3">free</span><span class="br0">&#40;</span>out<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>
</td></tr></table>
<h2><span class="mw-headline" id="Explosion">Explosion</span></h2>
<p>The "implosion" (compression) algorithm, common to all three formats, is a LZ77-family compressor with static Huffman coding. It creates Imploder compressed data. The "explosion" algorithm is the decompressor for Imploder compressed data. It will be described in full in a later version of this document. For now, only C source code is available.
</p>
<h3><span class="mw-headline" id="Example_code_2">Example code</span></h3>
<table class="infotable collapsible collapsed">
<tr>
<th> explode.c
</th></tr>
<tr>
<td> <div dir="ltr" class="mw-geshi mw-code mw-content-ltr"><div class="c source-c"><pre class="de1"><span class="coMULTI">/* This code is placed in the Public Domain by its author, Stuart Caie */</span>
&#160;
<span class="coMULTI">/* macro which obtains the next bit from the input bitstream, from MSB to
* LSB, and sets the &quot;bit&quot; variable with the result. If 8 bits have been
* read, fetches another byte from the input bytestream. Equivalent to the
* following M680x0 code:
*
* add.b d3,d3
* bne.b gotbit
* move.b -(a3),d3
* addx.b d3,d3
* gotbit:
*/</span>
<span class="co2">#define EXPLODE_GETBIT do { \
bit = bit_buffer &amp; 0x80; \
bit_buffer &lt;&lt;= 1; \
if (!bit_buffer) { \
bit2 = bit; \
bit_buffer = *--i; \
bit = bit_buffer &amp; 0x80; \
bit_buffer &lt;&lt;= 1; \
if (bit2) bit_buffer++; \
} \
} while (0)</span>
&#160;
<span class="kw4">static</span> <span class="kw4">unsigned</span> <span class="kw4">char</span> explode_literal_base<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#123;</span>
<span class="nu0">6</span><span class="sy0">,</span> <span class="nu0">10</span><span class="sy0">,</span> <span class="nu0">10</span><span class="sy0">,</span> <span class="nu0">18</span>
<span class="br0">&#125;</span><span class="sy0">;</span>
&#160;
<span class="kw4">static</span> <span class="kw4">unsigned</span> <span class="kw4">char</span> explode_literal_extrabits<span class="br0">&#91;</span><span class="nu0">12</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#123;</span>
<span class="nu0">1</span><span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span>
<span class="nu0">2</span><span class="sy0">,</span> <span class="nu0">3</span><span class="sy0">,</span> <span class="nu0">3</span><span class="sy0">,</span> <span class="nu0">4</span><span class="sy0">,</span>
<span class="nu0">4</span><span class="sy0">,</span> <span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">7</span><span class="sy0">,</span> <span class="nu0">14</span>
<span class="br0">&#125;</span><span class="sy0">;</span>
&#160;
<span class="coMULTI">/**
* Decompresses a stream of Imploder-compressed data.
*
* @param buffer a buffer that is large enough to contain all the
* decompressed data. On entry, the buffer should
* contain the entire Imploder-compressed stream at
* offset 0. On successful exit, the buffer will
* contain the decompressed data at offset 0. The
* original buffer contents will be overwritten.
*
* @param table an explosion table, consisting of 8 16-bit
* big-endian &quot;base offset&quot; values and 12 8-bit
* &quot;extra bits&quot; values.
* @param comp_len the compressed length of the data
* @param uncomp_len the decompressed length of the data
*
* @return zero on error, non-zero on success. If successful, the
* buffer contains the decompressed data.
*/</span>
<span class="kw4">int</span> explode<span class="br0">&#40;</span><span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">*</span>buffer<span class="sy0">,</span>
<span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">*</span>table<span class="sy0">,</span>
<span class="kw4">unsigned</span> <span class="kw4">int</span> comp_len<span class="sy0">,</span>
<span class="kw4">unsigned</span> <span class="kw4">int</span> uncomp_len<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
<span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">*</span>i <span class="sy0">=</span> buffer <span class="sy0">+</span> comp_len <span class="sy0">-</span> <span class="nu0">5</span><span class="sy0">;</span> <span class="coMULTI">/* input pointer */</span>
<span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">*</span>o <span class="sy0">=</span> buffer <span class="sy0">+</span> uncomp_len<span class="sy0">;</span> <span class="coMULTI">/* output pointer */</span>
<span class="kw4">unsigned</span> <span class="kw4">char</span> <span class="sy0">*</span>match<span class="sy0">;</span> <span class="coMULTI">/* match pointer */</span>
<span class="kw4">unsigned</span> <span class="kw4">char</span> bit_buffer<span class="sy0">,</span> bit<span class="sy0">,</span> bit2<span class="sy0">;</span>
<span class="kw4">unsigned</span> <span class="kw4">int</span> literal_len<span class="sy0">,</span> match_len<span class="sy0">,</span> selector<span class="sy0">,</span> x<span class="sy0">,</span> y<span class="sy0">;</span>
<span class="kw4">unsigned</span> <span class="kw4">int</span> match_base<span class="br0">&#91;</span><span class="nu0">8</span><span class="br0">&#93;</span><span class="sy0">;</span>
&#160;
<span class="coMULTI">/* read the 'base' part of the explosion table into native byte order,
* for speed */</span>
<span class="kw1">for</span> <span class="br0">&#40;</span>x <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> x <span class="sy0">&lt;</span> <span class="nu0">8</span><span class="sy0">;</span> x<span class="sy0">++</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
match_base<span class="br0">&#91;</span>x<span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#40;</span>table<span class="br0">&#91;</span>x<span class="sy0">*</span><span class="nu0">2</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">8</span><span class="br0">&#41;</span> <span class="sy0">|</span> table<span class="br0">&#91;</span>x<span class="sy0">*</span><span class="nu0">2</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="coMULTI">/* get initial bit buffer contents, and first literal length */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>comp_len <span class="sy0">&amp;</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
bit_buffer <span class="sy0">=</span> i<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span><span class="sy0">;</span>
literal_len <span class="sy0">=</span> <span class="br0">&#40;</span>i<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">24</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>i<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">16</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>i<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">8</span><span class="br0">&#41;</span> <span class="sy0">|</span> i<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
bit_buffer <span class="sy0">=</span> i<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span>
literal_len <span class="sy0">=</span> <span class="br0">&#40;</span>i<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">24</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>i<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">16</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="br0">&#40;</span>i<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span> <span class="sy0">&lt;&lt;</span> <span class="nu0">8</span><span class="br0">&#41;</span> <span class="sy0">|</span> i<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="kw1">while</span> <span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="coMULTI">/* copy literal run */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>o <span class="sy0">-</span> buffer<span class="br0">&#41;</span> <span class="sy0">&lt;</span> literal_len<span class="br0">&#41;</span> <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="coMULTI">/* enough space? */</span>
<span class="kw1">while</span> <span class="br0">&#40;</span>literal_len<span class="sy0">--</span><span class="br0">&#41;</span> <span class="sy0">*--</span>o <span class="sy0">=</span> <span class="sy0">*--</span>i<span class="sy0">;</span>
&#160;
<span class="coMULTI">/* main exit point - after the literal copy */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>o <span class="sy0">&lt;=</span> buffer<span class="br0">&#41;</span> <span class="kw2">break</span><span class="sy0">;</span>
&#160;
<span class="coMULTI">/* static Huffman encoding of the match length and selector:
*
* 0 -&gt; selector = 0, match_len = 1
* 10 -&gt; selector = 1, match_len = 2
* 110 -&gt; selector = 2, match_len = 3
* 1110 -&gt; selector = 3, match_len = 4
* 11110 -&gt; selector = 3, match_len = 5 + next three bits (5-12)
* 11111 -&gt; selector = 3, match_len = (next input byte)-1 (0-254)
*
*/</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
selector <span class="sy0">=</span> <span class="nu0">3</span><span class="sy0">;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
match_len <span class="sy0">=</span> <span class="sy0">*--</span>i<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>match_len <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="coMULTI">/* bad input */</span>
match_len<span class="sy0">--;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
match_len <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> EXPLODE_GETBIT<span class="sy0">;</span> <span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> match_len<span class="sy0">++;</span>
match_len <span class="sy0">&lt;&lt;=</span> <span class="nu0">1</span><span class="sy0">;</span> EXPLODE_GETBIT<span class="sy0">;</span> <span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> match_len<span class="sy0">++;</span>
match_len <span class="sy0">&lt;&lt;=</span> <span class="nu0">1</span><span class="sy0">;</span> EXPLODE_GETBIT<span class="sy0">;</span> <span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> match_len<span class="sy0">++;</span>
match_len <span class="sy0">+=</span> <span class="nu0">5</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
match_len <span class="sy0">=</span> <span class="nu0">4</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
selector <span class="sy0">=</span> <span class="nu0">2</span><span class="sy0">;</span>
match_len <span class="sy0">=</span> <span class="nu0">3</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
selector <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span>
match_len <span class="sy0">=</span> <span class="nu0">2</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
selector <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
match_len <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="coMULTI">/* another Huffman tuple, for deciding the base value (y) and number
* of extra bits required from the input stream (x) to create the
* length of the next literal run. Selector is 0-3, as previously
* obtained.
*
* 0 -&gt; base = 0, extra = {1,1,1,1}[selector]
* 10 -&gt; base = 2, extra = {2,3,3,4}[selector]
* 11 -&gt; base = {6,10,10,18}[selector] extra = {4,5,7,14}[selector]
*/</span>
y <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
x <span class="sy0">=</span> selector<span class="sy0">;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
y <span class="sy0">=</span> explode_literal_base<span class="br0">&#91;</span>x<span class="br0">&#93;</span><span class="sy0">;</span>
x <span class="sy0">+=</span> <span class="nu0">8</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
y <span class="sy0">=</span> <span class="nu0">2</span><span class="sy0">;</span>
x <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
x <span class="sy0">=</span> explode_literal_extrabits<span class="br0">&#91;</span>x<span class="br0">&#93;</span><span class="sy0">;</span>
&#160;
<span class="coMULTI">/* next literal run length: read [x] bits and add [y] */</span>
literal_len <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="kw1">while</span> <span class="br0">&#40;</span>x<span class="sy0">--</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
literal_len <span class="sy0">&lt;&lt;=</span> <span class="nu0">1</span><span class="sy0">;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> literal_len<span class="sy0">++;</span>
<span class="br0">&#125;</span>
literal_len <span class="sy0">+=</span> y<span class="sy0">;</span>
&#160;
&#160;
<span class="coMULTI">/* another Huffman tuple, for deciding the match distance: _base and
* _extra are from the explosion table, as passed into the explode
* function.
*
* 0 -&gt; base = 1 extra = _extra[selector + 0]
* 10 -&gt; base = 1 + _base[selector + 0] extra = _extra[selector + 4]
* 11 -&gt; base = 1 + _base[selector + 4] extra = _extra[selector + 8]
*/</span>
match <span class="sy0">=</span> o <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
x <span class="sy0">=</span> selector<span class="sy0">;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> <span class="br0">&#123;</span>
match <span class="sy0">+=</span> match_base<span class="br0">&#91;</span>selector <span class="sy0">+</span> <span class="nu0">4</span><span class="br0">&#93;</span><span class="sy0">;</span>
x <span class="sy0">+=</span> <span class="nu0">8</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="br0">&#123;</span>
match <span class="sy0">+=</span> match_base<span class="br0">&#91;</span>selector<span class="br0">&#93;</span><span class="sy0">;</span>
x <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
x <span class="sy0">=</span> table<span class="br0">&#91;</span>x <span class="sy0">+</span> <span class="nu0">16</span><span class="br0">&#93;</span><span class="sy0">;</span>
&#160;
<span class="coMULTI">/* obtain the value of the next [x] extra bits and
* add it to the match offset */</span>
y <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="kw1">while</span> <span class="br0">&#40;</span>x<span class="sy0">--</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
y <span class="sy0">&lt;&lt;=</span> <span class="nu0">1</span><span class="sy0">;</span> EXPLODE_GETBIT<span class="sy0">;</span> <span class="kw1">if</span> <span class="br0">&#40;</span>bit<span class="br0">&#41;</span> y<span class="sy0">++;</span>
<span class="br0">&#125;</span>
match <span class="sy0">+=</span> y<span class="sy0">;</span>
&#160;
<span class="coMULTI">/* copy match */</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>o <span class="sy0">-</span> buffer<span class="br0">&#41;</span> <span class="sy0">&lt;</span> match_len<span class="br0">&#41;</span> <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="coMULTI">/* enough space? */</span>
<span class="kw1">do</span> <span class="br0">&#123;</span> <span class="sy0">*--</span>o <span class="sy0">=</span> <span class="sy0">*--</span>match<span class="sy0">;</span> <span class="br0">&#125;</span> <span class="kw1">while</span> <span class="br0">&#40;</span>match_len<span class="sy0">--</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&#160;
<span class="coMULTI">/* return 1 if we used up all input bytes (as we should) */</span>
<span class="kw1">return</span> <span class="br0">&#40;</span>i <span class="sy0">==</span> buffer<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>
</td></tr></table>
<!--
NewPP limit report
CPU time usage: 0.112 seconds
Real time usage: 0.126 seconds
Preprocessor visited node count: 63/1000000
Preprocessor generated node count: 96/1000000
Postexpand include size: 0/2097152 bytes
Template argument size: 0/2097152 bytes
Highest expansion depth: 2/40
Expensive parser function count: 0/100
-->
<!-- Saved in parser cache with key exoticawiki:pcache:idhash:14649-0!*!0!!en-gb!*!* and timestamp 20150325022614 and revision id 81077
-->
</div><div class="printfooter">
Retrieved from <a dir="ltr" href="http://www.exotica.org.uk/mediawiki/index.php?title=Imploder_file_formats&amp;oldid=81077">http://www.exotica.org.uk/mediawiki/index.php?title=Imploder_file_formats&amp;oldid=81077</a></div>
<div id='catlinks' class='catlinks'><div id="mw-normal-catlinks" class="mw-normal-catlinks"><a href="/wiki/Special:Categories" title="Special:Categories">Category</a>: <ul><li><a href="/wiki/Category:File_formats" title="Category:File formats">File formats</a></li></ul></div></div> <!-- end content -->
<div class="visualClear"></div>
</div>
</div>
<div id="p-cactions" class="portlet">
<h3>Views</h3>
<div class="pBody">
<ul>
<li id="ca-nstab-main" class="selected"><a href="/wiki/Imploder_file_formats" title="View the content page [c]" accesskey="c">Page</a></li>
<li id="ca-talk" class="new"><a href="/mediawiki/index.php?title=Talk:Imploder_file_formats&amp;action=edit&amp;redlink=1" title="Discussion about the content page [t]" accesskey="t">Discussion</a></li>
<li id="ca-viewsource"><a href="/mediawiki/index.php?title=Imploder_file_formats&amp;action=edit" title="This page is protected.&#10;You can view its source [e]" accesskey="e">View source</a></li>
<li id="ca-history"><a href="/mediawiki/index.php?title=Imploder_file_formats&amp;action=history" rel="archives" title="Past revisions of this page [h]" accesskey="h">History</a></li>
</ul>
</div>
</div>
</div>
</div>
<ul id="p-menus" class="noprint">
<li class="generated-sidebar portlet" id="p-navigation"> <a href="#" >Navigation</a>
<ul>
<li id="n-mainpage"><a href="/wiki/Main_Page" title="Visit the main page [z]" accesskey="z">Main Page</a></li>
<li id="n-recentchanges"><a href="/wiki/Special:RecentChanges" title="A list of recent changes in the wiki [r]" accesskey="r">Recent changes</a></li>
<li id="n-latestnews"><a href="/wiki/News" title="Read the latest handwritten news">Latest News</a></li>
<li id="n-forum"><a href="http://www.exotica.org.uk/forum/" rel="nofollow" title="Join in discussions on our forum.">Forum</a></li>
<li id="n-randompage"><a href="/wiki/Special:Random" title="Load a random page [x]" accesskey="x">Random page</a></li>
<li id="n-help"><a href="https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents" title="The place to find out">Help</a></li>
</ul>
</li>
<li><a href="#">Tools</a>
<ul>
<li id="t-whatlinkshere"><a href="/wiki/Special:WhatLinksHere/Imploder_file_formats" title="A list of all wiki pages that link here [j]" accesskey="j">What links here</a></li> <li id="t-recentchangeslinked"><a href="/wiki/Special:RecentChangesLinked/Imploder_file_formats" title="Recent changes in pages linked from this page [k]" accesskey="k">Related changes</a></li> <li id="t-specialpages"><a href="/wiki/Special:SpecialPages" title="A list of all special pages [q]" accesskey="q">Special pages</a></li> <li id="t-print"><a href="/mediawiki/index.php?title=Imploder_file_formats&amp;printable=yes" rel="alternate" title="Printable version of this page [p]" accesskey="p">Printable version</a></li> <li id="t-permalink"><a href="/mediawiki/index.php?title=Imploder_file_formats&amp;oldid=81077" title="Permanent link to this revision of the page">Permanent link</a></li> <li id="t-info"><a href="/mediawiki/index.php?title=Imploder_file_formats&amp;action=info">Page information</a></li> </ul>
</li>
<li><a href="#">Personal tools</a>
<ul>
<li id="pt-createaccount"><a href="/mediawiki/index.php?title=Special:UserLogin&amp;returnto=Imploder+file+formats&amp;type=signup">Create account</a></li>
<li id="pt-login"><a href="/mediawiki/index.php?title=Special:UserLogin&amp;returnto=Imploder+file+formats" title="You are required to log in to edit pages on ExoticA. [o]" accesskey="o">Log in</a></li>
</ul>
</li>
<li id="searchMenu"><a href="#">Search</a>
<ul>
<li>
<div id="searchBody">
<form action="/mediawiki/index.php" id="searchform">
<input type='hidden' name="title" value="Special:Search"/>
<input type="search" name="search" placeholder="Search" title="Search ExoticA [f]" accesskey="f" id="searchInput" />
<input type="submit" name="go" value="Go to" title="Go to a page with this exact name if exists" id="searchGoButton" class="searchButton" />&#160;
<input type="submit" name="fulltext" value="Search" title="Search the pages for this text" id="mw-searchButton" class="searchButton" />
</form>
</div>
<p>Press search to match the entered keywords or use <strong>Go to</strong> to jump directly to a matching page name</p>
</li>
</ul>
</li>
</ul>
<div class="visualClear"></div>
<div class="wb_window_top noprint" id="footer_window">
<img class="wb_gadgets" src="/mediawiki/extensions/ExoticA/assets/screengadgets.png" alt="" />
<span class="wb_title">Footer</span>
</div>
<div class="wb_window">
<div id="footer" role="contentinfo">
<div id="f-copyrightico">
<a href="http://creativecommons.org/licenses/by-sa/3.0/"><img src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" alt="Attribution-ShareAlike 3.0 Unported" width="88" height="31" /></a> </div>
<div id="f-poweredbyico">
<a href="//www.mediawiki.org/"><img src="/mediawiki/resources/assets/poweredby_mediawiki_88x31.png" alt="Powered by MediaWiki" width="88" height="31" /></a> </div>
<ul id="f-list">
<li id="lastmod"> This page was last modified on 18 October 2009, at 22:28.</li>
<li id="viewcount">This page has been accessed 2,650 times.</li>
<li id="copyright"><p>Unless otherwise specified above, text is available under <a class="external" rel="nofollow" href="http://creativecommons.org/licenses/by-sa/3.0/">Attribution-ShareAlike 3.0 Unported</a>.<br />
Images and files may contain a separate licence, so please check before using.<br />See <a href="/wiki/ExoticA:Copyrights">Copyrights</a> for more information.
</p>
<p>
Hosting provided by <a href="http://www.mythic-beasts.com" target="_top">Mythic-Beasts</a>. See the <a href="/wiki/ExoticA:Hosting">Hosting Information</a> page for more details.
</p></li>
<li id="about"><a href="/wiki/ExoticA:About" title="ExoticA:About">About ExoticA</a></li>
<li id="disclaimer"><a href="/wiki/ExoticA:General_disclaimer" title="ExoticA:General disclaimer">Disclaimers</a></li>
<li><a href="#" class="cc-privacy-link">Privacy settings</a></li>
</ul>
<br />
</div>
</div>
</div>
<!-- add to any js -->
<script type="text/plain" class="cc-onconsent-social" src="http://static.addtoany.com/menu/page.js"></script>
<!-- end addtoany js -->
<!-- Begin Cookie Consent plugin by Silktide - http://silktide.com/cookieconsent -->
<link rel="stylesheet" type="text/css" href="http://assets.cookieconsent.silktide.com/current/style.min.css"/>
<script type="text/javascript" src="http://assets.cookieconsent.silktide.com/current/plugin.min.js"></script>
<script type="text/javascript">
// <![CDATA[
cc.initialise({
cookies: {
analytics: {},
social: {},
necessary: {}
},
settings: {
consenttype: "implicit",
bannerPosition: "bottom",
hideprivacysettingstab: true
}
});
// ]]>
</script>
<!-- End Cookie Consent plugin -->
<!-- google analytics -->
<script type="text/plain" class="cc-onconsent-analytics">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-3563842-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement( 'script' ); ga.type = 'text/javascript'; ga.async = true;
ga.src = ( 'https:' == document.location.protocol ? 'https://ssl' : 'http://www' ) + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName( 'script' )[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- end google analytics -->
<script>/*<![CDATA[*/window.jQuery && jQuery.ready();/*]]>*/</script><script>if(window.mw){
mw.loader.state({"site":"loading","user":"ready","user.groups":"ready"});
}</script>
<script>if(window.mw){
mw.loader.load(["mediawiki.toc","mediawiki.action.view.postEdit","mediawiki.user","mediawiki.hidpi","mediawiki.page.ready","mediawiki.searchSuggest","skins.exotica"],null,true);
}</script>
<script>if(window.mw){
document.write("\u003Cscript src=\"http://www.exotica.org.uk/mediawiki/load.php?debug=false\u0026amp;lang=en-gb\u0026amp;modules=site\u0026amp;only=scripts\u0026amp;skin=exotica\u0026amp;*\"\u003E\u003C/script\u003E");
}</script>
<script>if(window.mw){
mw.config.set({"wgBackendResponseTime":390});
}</script></body><!-- Cached 20150325022614 -->
</html>