-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathImploder_file_formats.html
799 lines (770 loc) · 73.1 KB
/
Imploder_file_formats.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
<!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&feed=atom" />
<link rel="stylesheet" href="http://www.exotica.org.uk/mediawiki/load.php?debug=false&lang=en-gb&modules=ext.geshi.language.c%7Cmediawiki.legacy.commonPrint%2Cshared%7Cmediawiki.skinning.content.externallinks%7Cmediawiki.skinning.interface%7Cmediawiki.ui.button%7Cskins.monobook.styles&only=styles&skin=exotica&*" />
<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&lang=en-gb&modules=site&only=styles&skin=exotica&*" />
<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&lang=en-gb&modules=startup&only=scripts&skin=exotica&*"></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&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 <stdlib.h></span>
<span class="co2">#include <stdio.h></span>
<span class="co2">#include <string.h></span>
<span class="co2">#include "explode.c"</span>
 
<span class="kw4">char</span> <span class="sy0">*</span>defimp<span class="br0">(</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">)</span>
<span class="br0">{</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>
 
<span class="sy0">*</span>out_ptr <span class="sy0">=</span> NULL<span class="sy0">;</span>
 
<span class="kw1">if</span> <span class="br0">(</span>in_len <span class="sy0"><</span> <span class="nu12">0x30</span><span class="br0">)</span> <span class="kw1">return</span> <span class="st0">"too short to be a FImp file"</span><span class="sy0">;</span>
 
id <span class="sy0">=</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x00</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">24</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x01</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">16</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x02</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">8</span><span class="br0">)</span> <span class="sy0">|</span> in<span class="br0">[</span><span class="nu12">0x03</span><span class="br0">]</span><span class="sy0">;</span>
out_len <span class="sy0">=</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x04</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">24</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x05</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">16</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x06</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">8</span><span class="br0">)</span> <span class="sy0">|</span> in<span class="br0">[</span><span class="nu12">0x07</span><span class="br0">]</span><span class="sy0">;</span>
end_off <span class="sy0">=</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x08</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">24</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x09</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">16</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>in<span class="br0">[</span><span class="nu12">0x0A</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">8</span><span class="br0">)</span> <span class="sy0">|</span> in<span class="br0">[</span><span class="nu12">0x0B</span><span class="br0">]</span><span class="sy0">;</span>
 
<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">(</span>id <span class="sy0">!=</span> <span class="nu12">0x494d5021</span> <span class="sy0">&&</span> id <span class="sy0">!=</span> <span class="nu12">0x41544e21</span> <span class="sy0">&&</span> id <span class="sy0">!=</span> <span class="nu12">0x42445049</span> <span class="sy0">&&</span>
id <span class="sy0">!=</span> <span class="nu12">0x43484649</span> <span class="sy0">&&</span> id <span class="sy0">!=</span> <span class="nu12">0x44757061</span> <span class="sy0">&&</span> id <span class="sy0">!=</span> <span class="nu12">0x4544414d</span> <span class="sy0">&&</span>
id <span class="sy0">!=</span> <span class="nu12">0x464c5421</span> <span class="sy0">&&</span> id <span class="sy0">!=</span> <span class="nu12">0x4d2e482e</span> <span class="sy0">&&</span> id <span class="sy0">!=</span> <span class="nu12">0x50415241</span> <span class="sy0">&&</span>
id <span class="sy0">!=</span> <span class="nu12">0x52444339</span><span class="br0">)</span>
<span class="kw1">return</span> <span class="st0">"unknown file format"</span><span class="sy0">;</span>
 
<span class="coMULTI">/* sanity checks */</span>
<span class="kw1">if</span> <span class="br0">(</span>end_off <span class="sy0">&</span> <span class="nu0">1</span><span class="br0">)</span> <span class="kw1">return</span> <span class="st0">"compressed size not even"</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>end_off <span class="sy0"><</span> <span class="nu0">14</span><span class="br0">)</span> <span class="kw1">return</span> <span class="st0">"compressed size too short"</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>end_off <span class="sy0">+</span> <span class="nu12">0x2E</span><span class="br0">)</span> <span class="sy0">></span> in_len<span class="br0">)</span> <span class="kw1">return</span> <span class="st0">"not enough input data"</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>end_off <span class="sy0">+</span> <span class="nu12">0x26</span><span class="br0">)</span> <span class="sy0">></span> out_len<span class="br0">)</span> <span class="kw1">return</span> <span class="st0">"output length less than input"</span><span class="sy0">;</span>
 
<span class="coMULTI">/* allocate memory */</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="br0">(</span>out <span class="sy0">=</span> <span class="kw3">malloc</span><span class="br0">(</span>out_len<span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> <span class="kw1">return</span> <span class="st0">"can't allocate memory"</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>
 
<span class="coMULTI">/* copy input data into output buffer */</span>
<span class="kw3">memcpy</span><span class="br0">(</span><span class="sy0">&</span>out<span class="br0">[</span><span class="nu12">0x00</span><span class="br0">]</span><span class="sy0">,</span> <span class="sy0">&</span>in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x08</span><span class="br0">]</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">)</span><span class="sy0">;</span>
<span class="kw3">memcpy</span><span class="br0">(</span><span class="sy0">&</span>out<span class="br0">[</span><span class="nu12">0x04</span><span class="br0">]</span><span class="sy0">,</span> <span class="sy0">&</span>in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x04</span><span class="br0">]</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">)</span><span class="sy0">;</span>
<span class="kw3">memcpy</span><span class="br0">(</span><span class="sy0">&</span>out<span class="br0">[</span><span class="nu12">0x08</span><span class="br0">]</span><span class="sy0">,</span> <span class="sy0">&</span>in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x00</span><span class="br0">]</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">)</span><span class="sy0">;</span>
<span class="kw3">memcpy</span><span class="br0">(</span><span class="sy0">&</span>out<span class="br0">[</span><span class="nu12">0x0C</span><span class="br0">]</span><span class="sy0">,</span> <span class="sy0">&</span>in<span class="br0">[</span><span class="nu12">0x0C</span><span class="br0">]</span><span class="sy0">,</span> end_off <span class="sy0">-</span> <span class="nu12">0x0C</span><span class="br0">)</span><span class="sy0">;</span>
<span class="kw3">memcpy</span><span class="br0">(</span><span class="sy0">&</span>out<span class="br0">[</span>end_off<span class="br0">]</span><span class="sy0">,</span> <span class="sy0">&</span>in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x0C</span><span class="br0">]</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">)</span><span class="sy0">;</span>
 
<span class="kw1">if</span> <span class="br0">(</span>in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x10</span><span class="br0">]</span> <span class="sy0">&</span> <span class="nu12">0x80</span><span class="br0">)</span> <span class="br0">{</span>
out<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu0">4</span><span class="br0">]</span> <span class="sy0">=</span> in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x11</span><span class="br0">]</span><span class="sy0">;</span>
ok <span class="sy0">=</span> explode<span class="br0">(</span>out<span class="sy0">,</span> <span class="sy0">&</span>in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x12</span><span class="br0">]</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">)</span><span class="sy0">;</span>
<span class="br0">}</span>
<span class="kw1">else</span> <span class="br0">{</span>
out<span class="br0">[</span>end_off <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">]</span> <span class="sy0">=</span> in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x11</span><span class="br0">]</span><span class="sy0">;</span>
ok <span class="sy0">=</span> explode<span class="br0">(</span>out<span class="sy0">,</span> <span class="sy0">&</span>in<span class="br0">[</span>end_off <span class="sy0">+</span> <span class="nu12">0x12</span><span class="br0">]</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">)</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="kw1">return</span> ok <span class="sy0">?</span> NULL <span class="sy0">:</span> <span class="st0">"can't deplode"</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="kw4">size_t</span> filelen<span class="sy0">;</span>
<span class="kw4">void</span> <span class="sy0">*</span>loadfile<span class="br0">(</span><span class="kw4">char</span> <span class="sy0">*</span>name<span class="br0">)</span> <span class="br0">{</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">(</span><span class="br0">(</span>fd <span class="sy0">=</span> <span class="kw3">fopen</span><span class="br0">(</span>name<span class="sy0">,</span> <span class="st0">"rb"</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span><span class="kw3">fseek</span><span class="br0">(</span>fd<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SEEK_END<span class="br0">)</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">)</span> <span class="sy0">&&</span> <span class="br0">(</span>filelen <span class="sy0">=</span> <span class="kw3">ftell</span><span class="br0">(</span>fd<span class="br0">)</span><span class="br0">)</span>
<span class="sy0">&&</span> <span class="br0">(</span><span class="kw3">fseek</span><span class="br0">(</span>fd<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SEEK_SET<span class="br0">)</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">)</span> <span class="sy0">&&</span> <span class="br0">(</span>mem <span class="sy0">=</span> <span class="kw3">malloc</span><span class="br0">(</span>filelen<span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="kw3">fread</span><span class="br0">(</span>mem<span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> filelen<span class="sy0">,</span> fd<span class="br0">)</span> <span class="sy0"><</span> filelen<span class="br0">)</span> <span class="br0">{</span> <span class="kw3">free</span><span class="br0">(</span>mem<span class="br0">)</span><span class="sy0">;</span> mem <span class="sy0">=</span> NULL<span class="sy0">;</span> <span class="br0">}</span>
<span class="br0">}</span>
<span class="kw3">fclose</span><span class="br0">(</span>fd<span class="br0">)</span><span class="sy0">;</span>
<span class="br0">}</span>
<span class="kw1">return</span> mem<span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="kw4">int</span> savefile<span class="br0">(</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">)</span> <span class="br0">{</span>
FILE <span class="sy0">*</span>fd <span class="sy0">=</span> <span class="kw3">fopen</span><span class="br0">(</span>name<span class="sy0">,</span> <span class="st0">"wb"</span><span class="br0">)</span><span class="sy0">;</span>
<span class="kw4">int</span> ok <span class="sy0">=</span> fd <span class="sy0">&&</span> <span class="br0">(</span><span class="kw3">fwrite</span><span class="br0">(</span>mem<span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> length<span class="sy0">,</span> fd<span class="br0">)</span> <span class="sy0">==</span> length<span class="br0">)</span><span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>fd<span class="br0">)</span> <span class="kw3">fclose</span><span class="br0">(</span>fd<span class="br0">)</span><span class="sy0">;</span>
<span class="kw1">return</span> ok<span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="kw4">int</span> main<span class="br0">(</span><span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">[</span><span class="br0">]</span><span class="br0">)</span> <span class="br0">{</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>
 
<span class="kw1">if</span> <span class="br0">(</span>argc <span class="sy0">!=</span> <span class="nu0">3</span><span class="br0">)</span> <span class="br0">{</span>
<span class="kw3">fprintf</span><span class="br0">(</span>stderr<span class="sy0">,</span> <span class="st0">"Usage: %s <input file> <output file><span class="es1">\n</span>"</span><span class="sy0">,</span> argv<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">)</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="coMULTI">/* load file */</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="br0">(</span>in <span class="sy0">=</span> loadfile<span class="br0">(</span>argv<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
<span class="kw3">perror</span><span class="br0">(</span>argv<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span><span class="br0">)</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="coMULTI">/* deplode file */</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>msg <span class="sy0">=</span> defimp<span class="br0">(</span>in<span class="sy0">,</span> filelen<span class="sy0">,</span> <span class="sy0">&</span>out<span class="sy0">,</span> <span class="sy0">&</span>out_len<span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
<span class="kw3">fprintf</span><span class="br0">(</span>stderr<span class="sy0">,</span> <span class="st0">"%s: %s<span class="es1">\n</span>"</span><span class="sy0">,</span> argv<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span><span class="sy0">,</span> msg<span class="br0">)</span><span class="sy0">;</span>
<span class="kw3">free</span><span class="br0">(</span>in<span class="br0">)</span><span class="sy0">;</span> <span class="kw3">free</span><span class="br0">(</span>out<span class="br0">)</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="coMULTI">/* save output */</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span>savefile<span class="br0">(</span>argv<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="sy0">,</span> out<span class="sy0">,</span> out_len<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
<span class="kw3">free</span><span class="br0">(</span>in<span class="br0">)</span><span class="sy0">;</span> <span class="kw3">free</span><span class="br0">(</span>out<span class="br0">)</span><span class="sy0">;</span>
<span class="kw3">perror</span><span class="br0">(</span>argv<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span><span class="br0">)</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="kw3">free</span><span class="br0">(</span>in<span class="br0">)</span><span class="sy0">;</span> <span class="kw3">free</span><span class="br0">(</span>out<span class="br0">)</span><span class="sy0">;</span>
<span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">}</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>
 
<span class="coMULTI">/* macro which obtains the next bit from the input bitstream, from MSB to
* LSB, and sets the "bit" 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 & 0x80; \
bit_buffer <<= 1; \
if (!bit_buffer) { \
bit2 = bit; \
bit_buffer = *--i; \
bit = bit_buffer & 0x80; \
bit_buffer <<= 1; \
if (bit2) bit_buffer++; \
} \
} while (0)</span>
 
<span class="kw4">static</span> <span class="kw4">unsigned</span> <span class="kw4">char</span> explode_literal_base<span class="br0">[</span><span class="nu0">4</span><span class="br0">]</span> <span class="sy0">=</span> <span class="br0">{</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">}</span><span class="sy0">;</span>
 
<span class="kw4">static</span> <span class="kw4">unsigned</span> <span class="kw4">char</span> explode_literal_extrabits<span class="br0">[</span><span class="nu0">12</span><span class="br0">]</span> <span class="sy0">=</span> <span class="br0">{</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">}</span><span class="sy0">;</span>
 
<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 "base offset" values and 12 8-bit
* "extra bits" 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">(</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">)</span>
<span class="br0">{</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">[</span><span class="nu0">8</span><span class="br0">]</span><span class="sy0">;</span>
 
<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">(</span>x <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> x <span class="sy0"><</span> <span class="nu0">8</span><span class="sy0">;</span> x<span class="sy0">++</span><span class="br0">)</span> <span class="br0">{</span>
match_base<span class="br0">[</span>x<span class="br0">]</span> <span class="sy0">=</span> <span class="br0">(</span>table<span class="br0">[</span>x<span class="sy0">*</span><span class="nu0">2</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">8</span><span class="br0">)</span> <span class="sy0">|</span> table<span class="br0">[</span>x<span class="sy0">*</span><span class="nu0">2</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">]</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="coMULTI">/* get initial bit buffer contents, and first literal length */</span>
<span class="kw1">if</span> <span class="br0">(</span>comp_len <span class="sy0">&</span> <span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span>
bit_buffer <span class="sy0">=</span> i<span class="br0">[</span><span class="nu0">4</span><span class="br0">]</span><span class="sy0">;</span>
literal_len <span class="sy0">=</span> <span class="br0">(</span>i<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">24</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>i<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">16</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>i<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">8</span><span class="br0">)</span> <span class="sy0">|</span> i<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy0">;</span>
<span class="br0">}</span>
<span class="kw1">else</span> <span class="br0">{</span>
bit_buffer <span class="sy0">=</span> i<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="sy0">;</span>
literal_len <span class="sy0">=</span> <span class="br0">(</span>i<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">24</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>i<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">16</span><span class="br0">)</span> <span class="sy0">|</span> <span class="br0">(</span>i<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="sy0"><<</span> <span class="nu0">8</span><span class="br0">)</span> <span class="sy0">|</span> i<span class="br0">[</span><span class="nu0">4</span><span class="br0">]</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="kw1">while</span> <span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span>
<span class="coMULTI">/* copy literal run */</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>o <span class="sy0">-</span> buffer<span class="br0">)</span> <span class="sy0"><</span> literal_len<span class="br0">)</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">(</span>literal_len<span class="sy0">--</span><span class="br0">)</span> <span class="sy0">*--</span>o <span class="sy0">=</span> <span class="sy0">*--</span>i<span class="sy0">;</span>
 
<span class="coMULTI">/* main exit point - after the literal copy */</span>
<span class="kw1">if</span> <span class="br0">(</span>o <span class="sy0"><=</span> buffer<span class="br0">)</span> <span class="kw2">break</span><span class="sy0">;</span>
 
<span class="coMULTI">/* static Huffman encoding of the match length and selector:
*
* 0 -> selector = 0, match_len = 1
* 10 -> selector = 1, match_len = 2
* 110 -> selector = 2, match_len = 3
* 1110 -> selector = 3, match_len = 4
* 11110 -> selector = 3, match_len = 5 + next three bits (5-12)
* 11111 -> 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">(</span>bit<span class="br0">)</span> <span class="br0">{</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</span> <span class="br0">{</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</span> <span class="br0">{</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">(</span>bit<span class="br0">)</span> <span class="br0">{</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</span> <span class="br0">{</span>
match_len <span class="sy0">=</span> <span class="sy0">*--</span>i<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>match_len <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">)</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">}</span>
<span class="kw1">else</span> <span class="br0">{</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">(</span>bit<span class="br0">)</span> match_len<span class="sy0">++;</span>
match_len <span class="sy0"><<=</span> <span class="nu0">1</span><span class="sy0">;</span> EXPLODE_GETBIT<span class="sy0">;</span> <span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</span> match_len<span class="sy0">++;</span>
match_len <span class="sy0"><<=</span> <span class="nu0">1</span><span class="sy0">;</span> EXPLODE_GETBIT<span class="sy0">;</span> <span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</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">}</span>
<span class="br0">}</span>
<span class="kw1">else</span> <span class="br0">{</span>
match_len <span class="sy0">=</span> <span class="nu0">4</span><span class="sy0">;</span>
<span class="br0">}</span>
<span class="br0">}</span>
<span class="kw1">else</span> <span class="br0">{</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">}</span>
<span class="br0">}</span>
<span class="kw1">else</span> <span class="br0">{</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">}</span>
<span class="br0">}</span>
<span class="kw1">else</span> <span class="br0">{</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">}</span>
 
<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 -> base = 0, extra = {1,1,1,1}[selector]
* 10 -> base = 2, extra = {2,3,3,4}[selector]
* 11 -> 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">(</span>bit<span class="br0">)</span> <span class="br0">{</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</span> <span class="br0">{</span>
y <span class="sy0">=</span> explode_literal_base<span class="br0">[</span>x<span class="br0">]</span><span class="sy0">;</span>
x <span class="sy0">+=</span> <span class="nu0">8</span><span class="sy0">;</span>
<span class="br0">}</span>
<span class="kw1">else</span> <span class="br0">{</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">}</span>
<span class="br0">}</span>
x <span class="sy0">=</span> explode_literal_extrabits<span class="br0">[</span>x<span class="br0">]</span><span class="sy0">;</span>
 
<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">(</span>x<span class="sy0">--</span><span class="br0">)</span> <span class="br0">{</span>
literal_len <span class="sy0"><<=</span> <span class="nu0">1</span><span class="sy0">;</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</span> literal_len<span class="sy0">++;</span>
<span class="br0">}</span>
literal_len <span class="sy0">+=</span> y<span class="sy0">;</span>
 
 
<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 -> base = 1 extra = _extra[selector + 0]
* 10 -> base = 1 + _base[selector + 0] extra = _extra[selector + 4]
* 11 -> 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">(</span>bit<span class="br0">)</span> <span class="br0">{</span>
EXPLODE_GETBIT<span class="sy0">;</span>
<span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</span> <span class="br0">{</span>
match <span class="sy0">+=</span> match_base<span class="br0">[</span>selector <span class="sy0">+</span> <span class="nu0">4</span><span class="br0">]</span><span class="sy0">;</span>
x <span class="sy0">+=</span> <span class="nu0">8</span><span class="sy0">;</span>
<span class="br0">}</span>
<span class="kw1">else</span> <span class="br0">{</span>
match <span class="sy0">+=</span> match_base<span class="br0">[</span>selector<span class="br0">]</span><span class="sy0">;</span>
x <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
<span class="br0">}</span>
<span class="br0">}</span>
x <span class="sy0">=</span> table<span class="br0">[</span>x <span class="sy0">+</span> <span class="nu0">16</span><span class="br0">]</span><span class="sy0">;</span>
 
<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">(</span>x<span class="sy0">--</span><span class="br0">)</span> <span class="br0">{</span>
y <span class="sy0"><<=</span> <span class="nu0">1</span><span class="sy0">;</span> EXPLODE_GETBIT<span class="sy0">;</span> <span class="kw1">if</span> <span class="br0">(</span>bit<span class="br0">)</span> y<span class="sy0">++;</span>
<span class="br0">}</span>
match <span class="sy0">+=</span> y<span class="sy0">;</span>
 
<span class="coMULTI">/* copy match */</span>
<span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>o <span class="sy0">-</span> buffer<span class="br0">)</span> <span class="sy0"><</span> match_len<span class="br0">)</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">{</span> <span class="sy0">*--</span>o <span class="sy0">=</span> <span class="sy0">*--</span>match<span class="sy0">;</span> <span class="br0">}</span> <span class="kw1">while</span> <span class="br0">(</span>match_len<span class="sy0">--</span><span class="br0">)</span><span class="sy0">;</span>
<span class="br0">}</span>
 
<span class="coMULTI">/* return 1 if we used up all input bytes (as we should) */</span>
<span class="kw1">return</span> <span class="br0">(</span>i <span class="sy0">==</span> buffer<span class="br0">)</span><span class="sy0">;</span>
<span class="br0">}</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
Post‐expand 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&oldid=81077">http://www.exotica.org.uk/mediawiki/index.php?title=Imploder_file_formats&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&action=edit&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&action=edit" title="This page is protected. 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&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&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&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&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&returnto=Imploder+file+formats&type=signup">Create account</a></li>
<li id="pt-login"><a href="/mediawiki/index.php?title=Special:UserLogin&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" /> 
<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>