<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://moddingwiki.shikadi.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dascandy</id>
	<title>ModdingWiki - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://moddingwiki.shikadi.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dascandy"/>
	<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/wiki/Special:Contributions/Dascandy"/>
	<updated>2026-05-14T05:01:56Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.11</generator>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11034</id>
		<title>MegaTech VOL Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11034"/>
		<updated>2023-05-09T07:23:03Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = Unlimited&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = No&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Cobra Mission}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;MegaTech VOL Format&#039;&#039;&#039; is an archive used by [[Cobra Mission]] to store all the game data.  The following .VOL files are included with the game:&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
There is no header.  The format is simply a list of offsets, repeated until the file data begins:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Data type !! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[UINT32LE]] || offset || Offset of this file, relative to start of archive file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Usually the above structure is repeated until it is 256 bytes long (with unused offsets as zero), but it can be smaller (&amp;lt;tt&amp;gt;pcm6.vol&amp;lt;/tt&amp;gt; has a 64 byte header).&lt;br /&gt;
&lt;br /&gt;
The last entry in the list is the file size, followed by zero offsets as needed to pad the list to the required length.&lt;br /&gt;
&lt;br /&gt;
{{TODO|Will the game accept files that lack this padding?}}&lt;br /&gt;
&lt;br /&gt;
== Instances ==&lt;br /&gt;
&lt;br /&gt;
=== Graphics VOL files ===&lt;br /&gt;
* CUT1.VOL&lt;br /&gt;
* CUT2.VOL&lt;br /&gt;
* CUT3.VOL&lt;br /&gt;
* CUTA.VOL&lt;br /&gt;
* ENM.VOL&lt;br /&gt;
* ENMA.VOL&lt;br /&gt;
* MAP.VOL&lt;br /&gt;
* OPENING.VOL&lt;br /&gt;
* PIC1.VOL&lt;br /&gt;
* PIC2.VOL&lt;br /&gt;
* PIC3.VOL&lt;br /&gt;
* PICA.VOL&lt;br /&gt;
&lt;br /&gt;
The listed VOL files contain the graphics for the game.&lt;br /&gt;
* OPENING.VOL contains the graphics for the intro sequence&lt;br /&gt;
* MAP.VOL contains the graphics for the inventory map items.&lt;br /&gt;
{{TODO|Below are assumptions on the other files}}&lt;br /&gt;
* CUT1 - CUTA : Cutscenes&lt;br /&gt;
* ENM - ENMA : Enemy graphics&lt;br /&gt;
* PIC1 - PICA : Inventory items (magazines and photos)&lt;br /&gt;
&lt;br /&gt;
These VOL files contain graphics chunks with the following structure&lt;br /&gt;
&lt;br /&gt;
==== GC Entry ====&lt;br /&gt;
* 00 - 01 : [[UINT16LE]] signature 47 43 &amp;quot;GC&amp;quot;&lt;br /&gt;
* 02 - 03 : [[UINT16LE]] Version 02.00&lt;br /&gt;
* 04 - 05 : [[UINT16LE]] Flag that indicates whether a palette is present.&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Points to the location of the sub-chunk table.&lt;br /&gt;
* 08 - 0B : [[UINT32LE]] Number of sub-chunks in the entry. Very often only 1, but sometimes more.&lt;br /&gt;
* 0C - 0D : [[UINT16LE]] Size of the chunk.&lt;br /&gt;
* 0E      : [[UINT8]] Padding (always 0)&lt;br /&gt;
* 0F      : [[UINT8]] Checksum; add up all the bytes from 00 to 0E and place the 2&#039;s complement of that sum here. To check, add all bytes from 00 to 0F and the result of that should be 0.&lt;br /&gt;
&lt;br /&gt;
If the palette bit is set in the header, a palette will follow. &lt;br /&gt;
* 10 - 2F : The colors are stored as an array[16] of [[UINT16LE]]. See MED.VOL for example code on how to read the palette.&lt;br /&gt;
&lt;br /&gt;
After the palette there&#039;s a subchunk table with N+1 values, where N is the number of subchunks. Each chunk runs from offset[X] to offset[X+1]. For a single chunk file, this has two values.&lt;br /&gt;
* (10 or 30) - xx : Offset pointers in the chunk stored as [[UINT32LE]]. The amount is indicated by the number of sub-chunks, plus one.&lt;br /&gt;
&lt;br /&gt;
===== GC data chunks =====&lt;br /&gt;
The GC data chunks have their own 10-byte header. Preliminary documentation below (not validated yet!):&lt;br /&gt;
* 00 : [[UINT8]] Always 0xA4&lt;br /&gt;
* 01 : [[UINT8]] Probably a checksum.&lt;br /&gt;
* 02 : [[UINT8]] X offset to display at&lt;br /&gt;
* 03 : [[UINT8]] Y offset to display at&lt;br /&gt;
* 04 : [[UINT8]] Width of contained image&lt;br /&gt;
* 05 : [[UINT8]] Height of contained image&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Subchunk size.&lt;br /&gt;
* 08 - 09 : [[UINT16LE]] Always 0?&lt;br /&gt;
&lt;br /&gt;
To follow along, there is a full working implementation at https://github.com/dascandy/cobra .&lt;br /&gt;
&lt;br /&gt;
The data is stored compressed in a style that looks like LZ77 (implicit reference table building) mixed with LZ78 (explicit table building) and Huffman coding. It is a very messy format; it is very easy to get a detail in the implementation wrong.&lt;br /&gt;
&lt;br /&gt;
For the decoder we will need two intermediate buffers for decoding, one called the &amp;quot;bit buffer&amp;quot; of 16 bits, and one called the &amp;quot;nibble buffer&amp;quot; of two 4-bit nibbles. We also need a third 1024-byte buffer to hold up to 256 4-byte samples, to be referenced.&lt;br /&gt;
&lt;br /&gt;
To start, the decoder loads the bit buffer with 16 bits. Every time the last bit is removed from the bit buffer, it loads the next two bytes in the input stream as a 16-bit big endian number into the bit buffer. Bits are removed from the high end one at a time, and are removed until a Huffman code is matched.&lt;br /&gt;
&lt;br /&gt;
The game uses the following Huffman table:&lt;br /&gt;
&lt;br /&gt;
===== Huffman table =====&lt;br /&gt;
* 00 : Copy from back&lt;br /&gt;
* 01 : Copy with Skip Table&lt;br /&gt;
* 10 : Skip single output&lt;br /&gt;
* 110 : Copy and store&lt;br /&gt;
* 1110 : Copy with Move Table&lt;br /&gt;
* 1111 : Copy from backing store&lt;br /&gt;
&lt;br /&gt;
The one simple command in this table is &amp;quot;Skip single output&amp;quot; - it moves the output pointer 4 bytes ahead not changing the output bytes.&lt;br /&gt;
&lt;br /&gt;
===== Nibble buffer =====&lt;br /&gt;
The nibble buffer is loaded when a value is attempted to be read but the table is empty. This differs from the bit buffer which is eagerly loaded. After loading a byte, the low nibble is returned first, and the second time it&#039;s called the high nibble is returned.&lt;br /&gt;
&lt;br /&gt;
===== Backing store =====&lt;br /&gt;
The backing store holds up to 256 entries of 4 bytes each. The table starts empty, and entries are placed from the start with an automatically increasing storage ID - the first one goes in slot 0, the second in slot 1 and so on. They are copied from the backing store a full entry at a time.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy and store&amp;quot; command takes 4 bytes from the input stream and copies them into the next entry in the backing store, and also copies them to the output buffer.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy from backing store&amp;quot; command takes a single byte from the input stream, and copies that entry from the backing store into the output buffer.&lt;br /&gt;
&lt;br /&gt;
===== Copy from back =====&lt;br /&gt;
Most of the game&#039;s graphics refer to output previously generated. It can refer back to the previous line written or to the earlier bits in this line. The copy from back command takes a nibble of data from the nibble buffer to find out what operation to do. All three of these use the same offset lookup table: { -1, -2, -4, -8, 1, 0 }. It splits the values into three regions:&lt;br /&gt;
&lt;br /&gt;
* Below 4: It copies a single entry from the output buffer to the output buffer. It gets the offset from the offset lookup table.&lt;br /&gt;
* Between 4 and 9: It loads a nibble to find out how many entries to copy. It will copy the loaded nibble count plus two, and it uses the offset table as the previous (with the original value minus 4).&lt;br /&gt;
* 10 and above: It sets the number of entries to copy to the remaining entries in the line. It also uses the offset to find where to copy from.&lt;br /&gt;
&lt;br /&gt;
Offsets of 1 and 0 are treated specially; they&#039;re more of a marker value. If the offset is 1, it copies from the adjacent pixel in the previous line instead. If the offset is 0, it skips ahead without writing new output.&lt;br /&gt;
&lt;br /&gt;
===== Copy Skip =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads yet another nibble, and outputs a sequence of 00 and FF bytes depending on the bits set in the nibble - from low bit to high bit, 0xFF for a 1 bit and 0x00 for a 0 bit.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies the corresponding entry from the previous line on the screen.&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it skips ahead a byte in the output.&lt;br /&gt;
&lt;br /&gt;
===== Copy Move =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to copy, increased by 18. The top two bits (shifted right by 6) are used as an index into the offset table mentioned above to find the offset from where to copy.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to target, increased by 18. The top two bits are checked whether to copy the values; if it is not zero it only skips ahead. When they are zero, it copies as many values from the previous line into this line.&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it copies the equivalent byte from the previous output word.&lt;br /&gt;
&lt;br /&gt;
===== Converting the output data from planar =====&lt;br /&gt;
Each &amp;quot;entry&amp;quot; of 4 bytes covers 8 pixels, where each of the bytes contains a single bit for every pixel. As example, let&#039;s take 00 01 03 07 as example inputs:&lt;br /&gt;
&lt;br /&gt;
* 0000 0111 (byte 4)  &lt;br /&gt;
* 0000 0011 (byte 3)  &lt;br /&gt;
* 0000 0001 (byte 2)  &lt;br /&gt;
* 0000 0000 (byte 1)  &lt;br /&gt;
* ----------  &lt;br /&gt;
* 0000 08CE&lt;br /&gt;
&lt;br /&gt;
[[DecodingExample]]&lt;br /&gt;
&lt;br /&gt;
=== EMI.VOL ===&lt;br /&gt;
&lt;br /&gt;
EMI.VOL contains the music for the game, it has 41 chunks of data. The first chunk is exactly 4096 bytes and contains the instruments.&lt;br /&gt;
&lt;br /&gt;
==== Instrument Bank ====&lt;br /&gt;
There are 128 instruments in the chunk and each instrument is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
* Bytes 0 - 7 of each instrument look like FM parameters. {{TODO|Figure out which parameter does what}}&lt;br /&gt;
* Bytes 8 - 9 contain low numbers numbers from 0 - 3. {{TODO|Figure out if these are modulator and carrier wave parameters}}&lt;br /&gt;
* Bytes 10 - 11 contain numbers between 0 and 16. {{TODO|Figure out what these parameters mean}}&lt;br /&gt;
* Bytes 12 - 15 are all zeroes.&lt;br /&gt;
* Byte 16 increments from  0 - 31, after that it decrements from 255 to 160. Changing this seems to change the instrument type. It looks like the first 32 instruments are percussion.&lt;br /&gt;
* Byte 17 contains a number from 0 - 255. {{TODO|Figure out what this byte does.}}&lt;br /&gt;
* Bytes 18 - 23 contain zeroes.&lt;br /&gt;
* Byte 24 - 31 contains a lot of data, but changing this to all zeroes seemingly does not change the music in-game.&lt;br /&gt;
&lt;br /&gt;
The 40 remaining chunks all have the EM header.&lt;br /&gt;
&lt;br /&gt;
==== EM Entry ====&lt;br /&gt;
* 00 - 03 : signature 45 4D 00 06&lt;br /&gt;
* 04 - 05 : Unknown, most of the times 00 00, but values such as 00 03 are also present.{{TODO|Version?}}&lt;br /&gt;
* 06 - 07 : [[UINT16LE]], Start index of title, most of the times 1C 00&lt;br /&gt;
* 08 - 09 : [[UINT16LE]], Offset in the EM chunk where the actual data starts&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], Always the same as the previous [[UINT16LE]]. (Pointing to data offset)&lt;br /&gt;
* 0C - 0D : [[UINT16LE]], The size of the EM chunk&lt;br /&gt;
* 0E - 0F : Unknown, could be initial tempo or volume or something similar. {{TODO|Figure out what this is}}&lt;br /&gt;
&lt;br /&gt;
After this 6 [[UINT16LE]] follow, that indicate the offset in the chunk where data is found for each channel.&lt;br /&gt;
&lt;br /&gt;
6 channels are supported and if there is no data for the channel, the value is 0.&lt;br /&gt;
&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], Index of track 1 in chunk, usually the same as the [[UINT16LE]] from 08-09 and 0A-0B.&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], Index of track 2 in chunk&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], Index of track 3 in chunk&lt;br /&gt;
* 16 - 17 : [[UINT16LE]], Index of track 4 in chunk&lt;br /&gt;
* 18 - 19 : [[UINT16LE]], Index of track 5 in chunk&lt;br /&gt;
* 1A - 1B : [[UINT16LE]], Index of track 6 in chunk&lt;br /&gt;
* 1C : Start of title, if there is no title, the value at this location is FF, otherwise it&#039;s FE. &lt;br /&gt;
&lt;br /&gt;
If there is a title, a zero-terminated string follows, it contains japanese characters and at the end a date when it was converted.&lt;br /&gt;
Finally, it ends with FF.&lt;br /&gt;
&lt;br /&gt;
==== Pattern data ====&lt;br /&gt;
{{TODO|Highly experimental reverse-engineering, https://github.com/BlackStar-EoP/cobra-mission-writer/tree/master/emidump is an attempt to convert these to S3M}}&lt;br /&gt;
&lt;br /&gt;
So far, it seems the pattern data has&lt;br /&gt;
* 2 byte control commands&lt;br /&gt;
* 1 byte control commands&lt;br /&gt;
* 1 byte speed commands&lt;br /&gt;
* note commands&lt;br /&gt;
{{TODO|Check if there are more types, such as 3 or 3 byte commands}}&lt;br /&gt;
&lt;br /&gt;
===== 2 byte control commands =====&lt;br /&gt;
* 0xE4: Unknown&lt;br /&gt;
* 0xE7: Unknown&lt;br /&gt;
* 0xE8: Unknown&lt;br /&gt;
* 0xFB: Unknown&lt;br /&gt;
* 0xFD: Select instrument, byte after this indicates the index of the instrument from the instrument bank.&lt;br /&gt;
* 0xF7: Unknown&lt;br /&gt;
* 0xFA: Unknown&lt;br /&gt;
* 0xFC: Unknown&lt;br /&gt;
&lt;br /&gt;
===== 1 byte control commands ===== &lt;br /&gt;
* 0xCD: Unknown&lt;br /&gt;
* 0xCF: Unknown&lt;br /&gt;
* 0xDC: Unknown&lt;br /&gt;
* 0xDD: Unknown&lt;br /&gt;
* 0xCE: Unknown&lt;br /&gt;
* 0xF8: {{TODO|Loop command?}}&lt;br /&gt;
&lt;br /&gt;
===== 1 byte speed commands =====&lt;br /&gt;
These commands look like a delay command of some sort&lt;br /&gt;
{{TODO|It seems these commands can do more than just have a delay for a note, looks like they can delay for a couple of notes and then return to another speed.}}&lt;br /&gt;
* 0x81: row delay = 2&lt;br /&gt;
* 0x82: row delay = 4&lt;br /&gt;
* 0x83: row delay = 8&lt;br /&gt;
* 0x84: row delay = 16&lt;br /&gt;
* 0x85: row delay = 32&lt;br /&gt;
* 0x86: row delay = 64&lt;br /&gt;
* 0x89: row delay = 12&lt;br /&gt;
* 0x90: row delay = 6&lt;br /&gt;
* 0x8B: row delay = 48&lt;br /&gt;
* 0x8E: row delay = 3&lt;br /&gt;
&lt;br /&gt;
===== 1 byte note commands =====&lt;br /&gt;
The note commands range from 0x00 to 0x7F, where 0x00 is a C, 0x01 is a C-# and so on.&lt;br /&gt;
It seems that 0x00 is used as a dummy note, it does not get played, but increases the delay.&lt;br /&gt;
&lt;br /&gt;
=== MCG.VOL ===&lt;br /&gt;
&lt;br /&gt;
MCG.VOL contains the tilesets for the game. It contains 14 chunks of tile data.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Chunk nr!!Tileset&lt;br /&gt;
|-&lt;br /&gt;
|0||Character sprites&lt;br /&gt;
|-&lt;br /&gt;
|1||Weapon sprites&lt;br /&gt;
|-&lt;br /&gt;
|2||CASTLE tileset&lt;br /&gt;
|-&lt;br /&gt;
|3||AREA1 tileset&lt;br /&gt;
|-&lt;br /&gt;
|4||AREA2 tileset&lt;br /&gt;
|-&lt;br /&gt;
|5||AREA3 tileset&lt;br /&gt;
|-&lt;br /&gt;
|6||AREA4 tileset&lt;br /&gt;
|-&lt;br /&gt;
|7||AREA5 tileset&lt;br /&gt;
|-&lt;br /&gt;
|8||HOUSE tileset&lt;br /&gt;
|-&lt;br /&gt;
|9||BAR tileset&lt;br /&gt;
|-&lt;br /&gt;
|10||CORP tileset&lt;br /&gt;
|-&lt;br /&gt;
|11||BRICK tileset&lt;br /&gt;
|-&lt;br /&gt;
|12||LAB tileset&lt;br /&gt;
|-&lt;br /&gt;
|13||SEASIDE tileset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The header for this file is 64 bytes and contains the offsets for each tileset.&lt;br /&gt;
The tilesets consist of a number of tiles, all are 32x32 pixels, each pixel stored as a byte, making each sprite 1024 bytes.&lt;br /&gt;
&lt;br /&gt;
The palette for the tilesets is found inside each entry inside MED.VOL.&lt;br /&gt;
The colors are stored as an array[16] of [[UINT16LE]].&lt;br /&gt;
For example white is stored as F0FF, this will be read as 0x0FFF, and here the components are 0GRB.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
byte r = (value &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
byte g = value &amp;gt;&amp;gt; 8;&lt;br /&gt;
byte b = value &amp;amp; 0x0F;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will result in values from 0 to 15. Getting the actual color requires 2 shifts, one left of 4 and added to that one right of 2.&lt;br /&gt;
&lt;br /&gt;
Reading all palette entries would look something like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Color parse_color(uint16_t col)&lt;br /&gt;
{&lt;br /&gt;
	byte r = (col &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
	byte g = col &amp;gt;&amp;gt; 8;&lt;br /&gt;
	byte b = col &amp;amp; 0x0F;&lt;br /&gt;
	return Color((r &amp;lt;&amp;lt; 4) + (r &amp;gt;&amp;gt; 2), (g &amp;lt;&amp;lt; 4) + (g &amp;gt;&amp;gt; 2), (b &amp;lt;&amp;lt; 4) + (b &amp;gt;&amp;gt; 2));&lt;br /&gt;
}&lt;br /&gt;
void parse_palette()&lt;br /&gt;
{&lt;br /&gt;
	int pal = 0;&lt;br /&gt;
	for (int i = 32; i &amp;lt; 64; i += 2)&lt;br /&gt;
	{&lt;br /&gt;
		uint16_t color = (m_data[i + 1] &amp;lt;&amp;lt; 8) | m_data[i];&lt;br /&gt;
		m_palette[pal++] = parse_color(color);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MED.VOL ===&lt;br /&gt;
MED.VOL contains all the levels for the game. It contains 54 chunks of map data.&lt;br /&gt;
&lt;br /&gt;
==== MD Entry ====&lt;br /&gt;
Each MD entry inside MED.VOL consists of 5 blocks. The header (96 bytes), a block of unknown data (variable size), the tiledata for all the floors(dependent on size and number of floors), the triggers for all floors (same as the floor sizes, but with most entries 0) and a footer of 256 bytes.&lt;br /&gt;
===== MD Header =====&lt;br /&gt;
* 0 - 6 : signature 4D 44 03 30 02 02 14&lt;br /&gt;
* 7 - 9 : Unknown, most of the times 77 60 00, but values 9F 60 00, FF 60 00 and 8B 60 00 are also found in a few maps&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], the offset inside this MD chunk where the actual map data starts&lt;br /&gt;
* 0C - 0F : [[UINT32LE]], the size of this MD chunk&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], the width (in tiles) of this map&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], the height (in tiles) of this map&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], the number of floors in this map&lt;br /&gt;
* 16 - 1F : Character array, refers to the used tileset (values can be CASTLE, AREA1, AREA2 etc. See MCG.VOL), rest zeroes&lt;br /&gt;
* 20 - 3F : Palette data, 16 colors, each color stored as [[UINT16LE]], colors are stored as 4 bit nibbles.&lt;br /&gt;
* 40 - 5F : Character array, contains 2 names for the map, or for HOUSE types, the area that is referred. A long and a short version seperated by a pipe character.&lt;br /&gt;
&lt;br /&gt;
===== Unknown data block =====&lt;br /&gt;
Unknown data block, usually ranging from 0060 to 0420. The data inside looks the same for all the MD chunks. It looks like a lot of 16 bit integers.&lt;br /&gt;
&lt;br /&gt;
===== Tile data block =====&lt;br /&gt;
The size of the block is width * height * number of floors.&lt;br /&gt;
Each byte corresponds to the tile number in the used tileset.&lt;br /&gt;
The floors are stored sequentially.&lt;br /&gt;
&lt;br /&gt;
===== Triggers block =====&lt;br /&gt;
The same layout as the tile data block, but now most bytes are 00 and the bytes that are not are triggers such as item pickups, stairs, doors etc. &lt;br /&gt;
Unknown what the numbers mean, but exits are usually 0x20, item pickups range in 0x40 and character sprites are usually 0xC0 and higher.&lt;br /&gt;
&lt;br /&gt;
===== Footer =====&lt;br /&gt;
At the end of each MD chunk there are 256 bytes, unknown what the data represents, but it looks like it is related to the trigger block.&lt;br /&gt;
&lt;br /&gt;
=== PCM1.VOL - PCM6.VOL ===&lt;br /&gt;
These files contain PCM data in the form of the [[VOC_Format|Creative Voice Format]]&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
This file format was reverse-engineered by [[User:BlackStar|BlackStar]]. If you find this information helpful in a project you&#039;re working on, please give credit where credit is due.  (A link back to this wiki would be nice too!)&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11033</id>
		<title>MegaTech VOL Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11033"/>
		<updated>2023-05-09T07:21:58Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = Unlimited&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = No&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Cobra Mission}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;MegaTech VOL Format&#039;&#039;&#039; is an archive used by [[Cobra Mission]] to store all the game data.  The following .VOL files are included with the game:&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
There is no header.  The format is simply a list of offsets, repeated until the file data begins:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Data type !! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[UINT32LE]] || offset || Offset of this file, relative to start of archive file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Usually the above structure is repeated until it is 256 bytes long (with unused offsets as zero), but it can be smaller (&amp;lt;tt&amp;gt;pcm6.vol&amp;lt;/tt&amp;gt; has a 64 byte header).&lt;br /&gt;
&lt;br /&gt;
The last entry in the list is the file size, followed by zero offsets as needed to pad the list to the required length.&lt;br /&gt;
&lt;br /&gt;
{{TODO|Will the game accept files that lack this padding?}}&lt;br /&gt;
&lt;br /&gt;
== Instances ==&lt;br /&gt;
&lt;br /&gt;
=== Graphics VOL files ===&lt;br /&gt;
* CUT1.VOL&lt;br /&gt;
* CUT2.VOL&lt;br /&gt;
* CUT3.VOL&lt;br /&gt;
* CUTA.VOL&lt;br /&gt;
* ENM.VOL&lt;br /&gt;
* ENMA.VOL&lt;br /&gt;
* MAP.VOL&lt;br /&gt;
* OPENING.VOL&lt;br /&gt;
* PIC1.VOL&lt;br /&gt;
* PIC2.VOL&lt;br /&gt;
* PIC3.VOL&lt;br /&gt;
* PICA.VOL&lt;br /&gt;
&lt;br /&gt;
The listed VOL files contain the graphics for the game.&lt;br /&gt;
* OPENING.VOL contains the graphics for the intro sequence&lt;br /&gt;
* MAP.VOL contains the graphics for the inventory map items.&lt;br /&gt;
{{TODO|Below are assumptions on the other files}}&lt;br /&gt;
* CUT1 - CUTA : Cutscenes&lt;br /&gt;
* ENM - ENMA : Enemy graphics&lt;br /&gt;
* PIC1 - PICA : Inventory items (magazines and photos)&lt;br /&gt;
&lt;br /&gt;
These VOL files contain graphics chunks with the following structure&lt;br /&gt;
&lt;br /&gt;
==== GC Entry ====&lt;br /&gt;
* 00 - 01 : [[UINT16LE]] signature 47 43 &amp;quot;GC&amp;quot;&lt;br /&gt;
* 02 - 03 : [[UINT16LE]] Version 02.00&lt;br /&gt;
* 04 - 05 : [[UINT16LE]] Flag that indicates whether a palette is present.&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Points to the location of the sub-chunk table.&lt;br /&gt;
* 08 - 0B : [[UINT32LE]] Number of sub-chunks in the entry. Very often only 1, but sometimes more.&lt;br /&gt;
* 0C - 0D : [[UINT16LE]] Size of the chunk.&lt;br /&gt;
* 0E      : [[UINT8]] Padding (always 0)&lt;br /&gt;
* 0F      : [[UINT8]] Checksum; add up all the bytes from 00 to 0E and place the 2&#039;s complement of that sum here. To check, add all bytes from 00 to 0F and the result of that should be 0.&lt;br /&gt;
&lt;br /&gt;
If the palette bit is set in the header, a palette will follow. &lt;br /&gt;
* 10 - 2F : The colors are stored as an array[16] of [[UINT16LE]]. See MED.VOL for example code on how to read the palette.&lt;br /&gt;
&lt;br /&gt;
After the palette there&#039;s a subchunk table with N+1 values, where N is the number of subchunks. Each chunk runs from offset[X] to offset[X+1]. For a single chunk file, this has two values.&lt;br /&gt;
* (10 or 30) - xx : Offset pointers in the chunk stored as [[UINT32LE]]. The amount is indicated by the number of sub-chunks, plus one.&lt;br /&gt;
&lt;br /&gt;
===== GC data chunks =====&lt;br /&gt;
The GC data chunks have their own 10-byte header. Preliminary documentation below (not validated yet!):&lt;br /&gt;
* 00 : [[UINT8]] Always 0xA4&lt;br /&gt;
* 01 : [[UINT8]] Probably a checksum.&lt;br /&gt;
* 02 : [[UINT8]] X offset to display at&lt;br /&gt;
* 03 : [[UINT8]] Y offset to display at&lt;br /&gt;
* 04 : [[UINT8]] Width of contained image&lt;br /&gt;
* 05 : [[UINT8]] Height of contained image&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Subchunk size.&lt;br /&gt;
* 08 - 09 : [[UINT16LE]] Always 0?&lt;br /&gt;
&lt;br /&gt;
In the game the art looks like it contains a lot of dithering and the graphics chunks look like they are storing this in a clever way.&lt;br /&gt;
&lt;br /&gt;
The data is stored compressed in a style that looks like LZ77 (implicit reference table building) mixed with LZ78 (explicit table building) and Huffman coding. It is a very messy format; it is very easy to get a detail in the implementation wrong.&lt;br /&gt;
&lt;br /&gt;
For the decoder we will need two intermediate buffers for decoding, one called the &amp;quot;bit buffer&amp;quot; of 16 bits, and one called the &amp;quot;nibble buffer&amp;quot; of two 4-bit nibbles. We also need a third 1024-byte buffer to hold up to 256 4-byte samples, to be referenced.&lt;br /&gt;
&lt;br /&gt;
To start, the decoder loads the bit buffer with 16 bits. Every time the last bit is removed from the bit buffer, it loads the next two bytes in the input stream as a 16-bit big endian number into the bit buffer. Bits are removed from the high end one at a time, and are removed until a Huffman code is matched.&lt;br /&gt;
&lt;br /&gt;
The game uses the following Huffman table:&lt;br /&gt;
&lt;br /&gt;
===== Huffman table =====&lt;br /&gt;
* 00 : Copy from back&lt;br /&gt;
* 01 : Copy with Skip Table&lt;br /&gt;
* 10 : Skip single output&lt;br /&gt;
* 110 : Copy and store&lt;br /&gt;
* 1110 : Copy with Move Table&lt;br /&gt;
* 1111 : Copy from backing store&lt;br /&gt;
&lt;br /&gt;
The one simple command in this table is &amp;quot;Skip single output&amp;quot; - it moves the output pointer 4 bytes ahead not changing the output bytes.&lt;br /&gt;
&lt;br /&gt;
===== Nibble buffer =====&lt;br /&gt;
The nibble buffer is loaded when a value is attempted to be read but the table is empty. This differs from the bit buffer which is eagerly loaded. After loading a byte, the low nibble is returned first, and the second time it&#039;s called the high nibble is returned.&lt;br /&gt;
&lt;br /&gt;
===== Backing store =====&lt;br /&gt;
The backing store holds up to 256 entries of 4 bytes each. The table starts empty, and entries are placed from the start with an automatically increasing storage ID - the first one goes in slot 0, the second in slot 1 and so on. They are copied from the backing store a full entry at a time.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy and store&amp;quot; command takes 4 bytes from the input stream and copies them into the next entry in the backing store, and also copies them to the output buffer.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy from backing store&amp;quot; command takes a single byte from the input stream, and copies that entry from the backing store into the output buffer.&lt;br /&gt;
&lt;br /&gt;
===== Copy from back =====&lt;br /&gt;
Most of the game&#039;s graphics refer to output previously generated. It can refer back to the previous line written or to the earlier bits in this line. The copy from back command takes a nibble of data from the nibble buffer to find out what operation to do. All three of these use the same offset lookup table: { -1, -2, -4, -8, 1, 0 }. It splits the values into three regions:&lt;br /&gt;
&lt;br /&gt;
* Below 4: It copies a single entry from the output buffer to the output buffer. It gets the offset from the offset lookup table.&lt;br /&gt;
* Between 4 and 9: It loads a nibble to find out how many entries to copy. It will copy the loaded nibble count plus two, and it uses the offset table as the previous (with the original value minus 4).&lt;br /&gt;
* 10 and above: It sets the number of entries to copy to the remaining entries in the line. It also uses the offset to find where to copy from.&lt;br /&gt;
&lt;br /&gt;
Offsets of 1 and 0 are treated specially; they&#039;re more of a marker value. If the offset is 1, it copies from the adjacent pixel in the previous line instead. If the offset is 0, it skips ahead without writing new output.&lt;br /&gt;
&lt;br /&gt;
===== Copy Skip =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads yet another nibble, and outputs a sequence of 00 and FF bytes depending on the bits set in the nibble - from low bit to high bit, 0xFF for a 1 bit and 0x00 for a 0 bit.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies the corresponding entry from the previous line on the screen.&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it skips ahead a byte in the output.&lt;br /&gt;
&lt;br /&gt;
===== Copy Move =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to copy, increased by 18. The top two bits (shifted right by 6) are used as an index into the offset table mentioned above to find the offset from where to copy.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to target, increased by 18. The top two bits are checked whether to copy the values; if it is not zero it only skips ahead. When they are zero, it copies as many values from the previous line into this line.&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it copies the equivalent byte from the previous output word.&lt;br /&gt;
&lt;br /&gt;
===== Converting the output data from planar =====&lt;br /&gt;
Each &amp;quot;entry&amp;quot; of 4 bytes covers 8 pixels, where each of the bytes contains a single bit for every pixel. As example, let&#039;s take 00 01 03 07 as example inputs:&lt;br /&gt;
&lt;br /&gt;
* 0000 0111 (byte 4)  &lt;br /&gt;
* 0000 0011 (byte 3)  &lt;br /&gt;
* 0000 0001 (byte 2)  &lt;br /&gt;
* 0000 0000 (byte 1)  &lt;br /&gt;
* ----------  &lt;br /&gt;
* 0000 08CE&lt;br /&gt;
&lt;br /&gt;
[[DecodingExample]]&lt;br /&gt;
&lt;br /&gt;
=== EMI.VOL ===&lt;br /&gt;
&lt;br /&gt;
EMI.VOL contains the music for the game, it has 41 chunks of data. The first chunk is exactly 4096 bytes and contains the instruments.&lt;br /&gt;
&lt;br /&gt;
==== Instrument Bank ====&lt;br /&gt;
There are 128 instruments in the chunk and each instrument is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
* Bytes 0 - 7 of each instrument look like FM parameters. {{TODO|Figure out which parameter does what}}&lt;br /&gt;
* Bytes 8 - 9 contain low numbers numbers from 0 - 3. {{TODO|Figure out if these are modulator and carrier wave parameters}}&lt;br /&gt;
* Bytes 10 - 11 contain numbers between 0 and 16. {{TODO|Figure out what these parameters mean}}&lt;br /&gt;
* Bytes 12 - 15 are all zeroes.&lt;br /&gt;
* Byte 16 increments from  0 - 31, after that it decrements from 255 to 160. Changing this seems to change the instrument type. It looks like the first 32 instruments are percussion.&lt;br /&gt;
* Byte 17 contains a number from 0 - 255. {{TODO|Figure out what this byte does.}}&lt;br /&gt;
* Bytes 18 - 23 contain zeroes.&lt;br /&gt;
* Byte 24 - 31 contains a lot of data, but changing this to all zeroes seemingly does not change the music in-game.&lt;br /&gt;
&lt;br /&gt;
The 40 remaining chunks all have the EM header.&lt;br /&gt;
&lt;br /&gt;
==== EM Entry ====&lt;br /&gt;
* 00 - 03 : signature 45 4D 00 06&lt;br /&gt;
* 04 - 05 : Unknown, most of the times 00 00, but values such as 00 03 are also present.{{TODO|Version?}}&lt;br /&gt;
* 06 - 07 : [[UINT16LE]], Start index of title, most of the times 1C 00&lt;br /&gt;
* 08 - 09 : [[UINT16LE]], Offset in the EM chunk where the actual data starts&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], Always the same as the previous [[UINT16LE]]. (Pointing to data offset)&lt;br /&gt;
* 0C - 0D : [[UINT16LE]], The size of the EM chunk&lt;br /&gt;
* 0E - 0F : Unknown, could be initial tempo or volume or something similar. {{TODO|Figure out what this is}}&lt;br /&gt;
&lt;br /&gt;
After this 6 [[UINT16LE]] follow, that indicate the offset in the chunk where data is found for each channel.&lt;br /&gt;
&lt;br /&gt;
6 channels are supported and if there is no data for the channel, the value is 0.&lt;br /&gt;
&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], Index of track 1 in chunk, usually the same as the [[UINT16LE]] from 08-09 and 0A-0B.&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], Index of track 2 in chunk&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], Index of track 3 in chunk&lt;br /&gt;
* 16 - 17 : [[UINT16LE]], Index of track 4 in chunk&lt;br /&gt;
* 18 - 19 : [[UINT16LE]], Index of track 5 in chunk&lt;br /&gt;
* 1A - 1B : [[UINT16LE]], Index of track 6 in chunk&lt;br /&gt;
* 1C : Start of title, if there is no title, the value at this location is FF, otherwise it&#039;s FE. &lt;br /&gt;
&lt;br /&gt;
If there is a title, a zero-terminated string follows, it contains japanese characters and at the end a date when it was converted.&lt;br /&gt;
Finally, it ends with FF.&lt;br /&gt;
&lt;br /&gt;
==== Pattern data ====&lt;br /&gt;
{{TODO|Highly experimental reverse-engineering, https://github.com/BlackStar-EoP/cobra-mission-writer/tree/master/emidump is an attempt to convert these to S3M}}&lt;br /&gt;
&lt;br /&gt;
So far, it seems the pattern data has&lt;br /&gt;
* 2 byte control commands&lt;br /&gt;
* 1 byte control commands&lt;br /&gt;
* 1 byte speed commands&lt;br /&gt;
* note commands&lt;br /&gt;
{{TODO|Check if there are more types, such as 3 or 3 byte commands}}&lt;br /&gt;
&lt;br /&gt;
===== 2 byte control commands =====&lt;br /&gt;
* 0xE4: Unknown&lt;br /&gt;
* 0xE7: Unknown&lt;br /&gt;
* 0xE8: Unknown&lt;br /&gt;
* 0xFB: Unknown&lt;br /&gt;
* 0xFD: Select instrument, byte after this indicates the index of the instrument from the instrument bank.&lt;br /&gt;
* 0xF7: Unknown&lt;br /&gt;
* 0xFA: Unknown&lt;br /&gt;
* 0xFC: Unknown&lt;br /&gt;
&lt;br /&gt;
===== 1 byte control commands ===== &lt;br /&gt;
* 0xCD: Unknown&lt;br /&gt;
* 0xCF: Unknown&lt;br /&gt;
* 0xDC: Unknown&lt;br /&gt;
* 0xDD: Unknown&lt;br /&gt;
* 0xCE: Unknown&lt;br /&gt;
* 0xF8: {{TODO|Loop command?}}&lt;br /&gt;
&lt;br /&gt;
===== 1 byte speed commands =====&lt;br /&gt;
These commands look like a delay command of some sort&lt;br /&gt;
{{TODO|It seems these commands can do more than just have a delay for a note, looks like they can delay for a couple of notes and then return to another speed.}}&lt;br /&gt;
* 0x81: row delay = 2&lt;br /&gt;
* 0x82: row delay = 4&lt;br /&gt;
* 0x83: row delay = 8&lt;br /&gt;
* 0x84: row delay = 16&lt;br /&gt;
* 0x85: row delay = 32&lt;br /&gt;
* 0x86: row delay = 64&lt;br /&gt;
* 0x89: row delay = 12&lt;br /&gt;
* 0x90: row delay = 6&lt;br /&gt;
* 0x8B: row delay = 48&lt;br /&gt;
* 0x8E: row delay = 3&lt;br /&gt;
&lt;br /&gt;
===== 1 byte note commands =====&lt;br /&gt;
The note commands range from 0x00 to 0x7F, where 0x00 is a C, 0x01 is a C-# and so on.&lt;br /&gt;
It seems that 0x00 is used as a dummy note, it does not get played, but increases the delay.&lt;br /&gt;
&lt;br /&gt;
=== MCG.VOL ===&lt;br /&gt;
&lt;br /&gt;
MCG.VOL contains the tilesets for the game. It contains 14 chunks of tile data.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Chunk nr!!Tileset&lt;br /&gt;
|-&lt;br /&gt;
|0||Character sprites&lt;br /&gt;
|-&lt;br /&gt;
|1||Weapon sprites&lt;br /&gt;
|-&lt;br /&gt;
|2||CASTLE tileset&lt;br /&gt;
|-&lt;br /&gt;
|3||AREA1 tileset&lt;br /&gt;
|-&lt;br /&gt;
|4||AREA2 tileset&lt;br /&gt;
|-&lt;br /&gt;
|5||AREA3 tileset&lt;br /&gt;
|-&lt;br /&gt;
|6||AREA4 tileset&lt;br /&gt;
|-&lt;br /&gt;
|7||AREA5 tileset&lt;br /&gt;
|-&lt;br /&gt;
|8||HOUSE tileset&lt;br /&gt;
|-&lt;br /&gt;
|9||BAR tileset&lt;br /&gt;
|-&lt;br /&gt;
|10||CORP tileset&lt;br /&gt;
|-&lt;br /&gt;
|11||BRICK tileset&lt;br /&gt;
|-&lt;br /&gt;
|12||LAB tileset&lt;br /&gt;
|-&lt;br /&gt;
|13||SEASIDE tileset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The header for this file is 64 bytes and contains the offsets for each tileset.&lt;br /&gt;
The tilesets consist of a number of tiles, all are 32x32 pixels, each pixel stored as a byte, making each sprite 1024 bytes.&lt;br /&gt;
&lt;br /&gt;
The palette for the tilesets is found inside each entry inside MED.VOL.&lt;br /&gt;
The colors are stored as an array[16] of [[UINT16LE]].&lt;br /&gt;
For example white is stored as F0FF, this will be read as 0x0FFF, and here the components are 0GRB.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
byte r = (value &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
byte g = value &amp;gt;&amp;gt; 8;&lt;br /&gt;
byte b = value &amp;amp; 0x0F;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will result in values from 0 to 15. Getting the actual color requires 2 shifts, one left of 4 and added to that one right of 2.&lt;br /&gt;
&lt;br /&gt;
Reading all palette entries would look something like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Color parse_color(uint16_t col)&lt;br /&gt;
{&lt;br /&gt;
	byte r = (col &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
	byte g = col &amp;gt;&amp;gt; 8;&lt;br /&gt;
	byte b = col &amp;amp; 0x0F;&lt;br /&gt;
	return Color((r &amp;lt;&amp;lt; 4) + (r &amp;gt;&amp;gt; 2), (g &amp;lt;&amp;lt; 4) + (g &amp;gt;&amp;gt; 2), (b &amp;lt;&amp;lt; 4) + (b &amp;gt;&amp;gt; 2));&lt;br /&gt;
}&lt;br /&gt;
void parse_palette()&lt;br /&gt;
{&lt;br /&gt;
	int pal = 0;&lt;br /&gt;
	for (int i = 32; i &amp;lt; 64; i += 2)&lt;br /&gt;
	{&lt;br /&gt;
		uint16_t color = (m_data[i + 1] &amp;lt;&amp;lt; 8) | m_data[i];&lt;br /&gt;
		m_palette[pal++] = parse_color(color);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MED.VOL ===&lt;br /&gt;
MED.VOL contains all the levels for the game. It contains 54 chunks of map data.&lt;br /&gt;
&lt;br /&gt;
==== MD Entry ====&lt;br /&gt;
Each MD entry inside MED.VOL consists of 5 blocks. The header (96 bytes), a block of unknown data (variable size), the tiledata for all the floors(dependent on size and number of floors), the triggers for all floors (same as the floor sizes, but with most entries 0) and a footer of 256 bytes.&lt;br /&gt;
===== MD Header =====&lt;br /&gt;
* 0 - 6 : signature 4D 44 03 30 02 02 14&lt;br /&gt;
* 7 - 9 : Unknown, most of the times 77 60 00, but values 9F 60 00, FF 60 00 and 8B 60 00 are also found in a few maps&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], the offset inside this MD chunk where the actual map data starts&lt;br /&gt;
* 0C - 0F : [[UINT32LE]], the size of this MD chunk&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], the width (in tiles) of this map&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], the height (in tiles) of this map&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], the number of floors in this map&lt;br /&gt;
* 16 - 1F : Character array, refers to the used tileset (values can be CASTLE, AREA1, AREA2 etc. See MCG.VOL), rest zeroes&lt;br /&gt;
* 20 - 3F : Palette data, 16 colors, each color stored as [[UINT16LE]], colors are stored as 4 bit nibbles.&lt;br /&gt;
* 40 - 5F : Character array, contains 2 names for the map, or for HOUSE types, the area that is referred. A long and a short version seperated by a pipe character.&lt;br /&gt;
&lt;br /&gt;
===== Unknown data block =====&lt;br /&gt;
Unknown data block, usually ranging from 0060 to 0420. The data inside looks the same for all the MD chunks. It looks like a lot of 16 bit integers.&lt;br /&gt;
&lt;br /&gt;
===== Tile data block =====&lt;br /&gt;
The size of the block is width * height * number of floors.&lt;br /&gt;
Each byte corresponds to the tile number in the used tileset.&lt;br /&gt;
The floors are stored sequentially.&lt;br /&gt;
&lt;br /&gt;
===== Triggers block =====&lt;br /&gt;
The same layout as the tile data block, but now most bytes are 00 and the bytes that are not are triggers such as item pickups, stairs, doors etc. &lt;br /&gt;
Unknown what the numbers mean, but exits are usually 0x20, item pickups range in 0x40 and character sprites are usually 0xC0 and higher.&lt;br /&gt;
&lt;br /&gt;
===== Footer =====&lt;br /&gt;
At the end of each MD chunk there are 256 bytes, unknown what the data represents, but it looks like it is related to the trigger block.&lt;br /&gt;
&lt;br /&gt;
=== PCM1.VOL - PCM6.VOL ===&lt;br /&gt;
These files contain PCM data in the form of the [[VOC_Format|Creative Voice Format]]&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
This file format was reverse-engineered by [[User:BlackStar|BlackStar]]. If you find this information helpful in a project you&#039;re working on, please give credit where credit is due.  (A link back to this wiki would be nice too!)&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11031</id>
		<title>MegaTech VOL Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11031"/>
		<updated>2023-05-08T20:09:45Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = Unlimited&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = No&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Cobra Mission}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;MegaTech VOL Format&#039;&#039;&#039; is an archive used by [[Cobra Mission]] to store all the game data.  The following .VOL files are included with the game:&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
There is no header.  The format is simply a list of offsets, repeated until the file data begins:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Data type !! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[UINT32LE]] || offset || Offset of this file, relative to start of archive file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Usually the above structure is repeated until it is 256 bytes long (with unused offsets as zero), but it can be smaller (&amp;lt;tt&amp;gt;pcm6.vol&amp;lt;/tt&amp;gt; has a 64 byte header).&lt;br /&gt;
&lt;br /&gt;
The last entry in the list is the file size, followed by zero offsets as needed to pad the list to the required length.&lt;br /&gt;
&lt;br /&gt;
{{TODO|Will the game accept files that lack this padding?}}&lt;br /&gt;
&lt;br /&gt;
== Instances ==&lt;br /&gt;
&lt;br /&gt;
=== Graphics VOL files ===&lt;br /&gt;
* CUT1.VOL&lt;br /&gt;
* CUT2.VOL&lt;br /&gt;
* CUT3.VOL&lt;br /&gt;
* CUTA.VOL&lt;br /&gt;
* ENM.VOL&lt;br /&gt;
* ENMA.VOL&lt;br /&gt;
* MAP.VOL&lt;br /&gt;
* OPENING.VOL&lt;br /&gt;
* PIC1.VOL&lt;br /&gt;
* PIC2.VOL&lt;br /&gt;
* PIC3.VOL&lt;br /&gt;
* PICA.VOL&lt;br /&gt;
&lt;br /&gt;
The listed VOL files contain the graphics for the game.&lt;br /&gt;
* OPENING.VOL contains the graphics for the intro sequence&lt;br /&gt;
* MAP.VOL contains the graphics for the inventory map items.&lt;br /&gt;
{{TODO|Below are assumptions on the other files}}&lt;br /&gt;
* CUT1 - CUTA : Cutscenes&lt;br /&gt;
* ENM - ENMA : Enemy graphics&lt;br /&gt;
* PIC1 - PICA : Inventory items (magazines and photos)&lt;br /&gt;
&lt;br /&gt;
These VOL files contain graphics chunks with the following structure&lt;br /&gt;
&lt;br /&gt;
==== GC Entry ====&lt;br /&gt;
* 00 - 01 : [[UINT16LE]] signature 47 43 &amp;quot;GC&amp;quot;&lt;br /&gt;
* 02 - 03 : [[UINT16LE]] Version 02.00&lt;br /&gt;
* 04 - 05 : [[UINT16LE]] Flag that indicates whether a palette is present.&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Points to the location of the sub-chunk table.&lt;br /&gt;
* 08 - 0B : [[UINT32LE]] Number of sub-chunks in the entry. Very often only 1, but sometimes more.&lt;br /&gt;
* 0C - 0D : [[UINT16LE]] Size of the chunk.&lt;br /&gt;
* 0E      : [[UINT8]] Padding (always 0)&lt;br /&gt;
* 0F      : [[UINT8]] Checksum; add up all the bytes from 00 to 0E and place the 2&#039;s complement of that sum here. To check, add all bytes from 00 to 0F and the result of that should be 0.&lt;br /&gt;
&lt;br /&gt;
If the palette bit is set in the header, a palette will follow. &lt;br /&gt;
* 10 - 2F : The colors are stored as an array[16] of [[UINT16LE]]. See MED.VOL for example code on how to read the palette.&lt;br /&gt;
&lt;br /&gt;
After the palette there&#039;s a subchunk table with N+1 values, where N is the number of subchunks. Each chunk runs from offset[X] to offset[X+1]. For a single chunk file, this has two values.&lt;br /&gt;
* (10 or 30) - xx : Offset pointers in the chunk stored as [[UINT32LE]]. The amount is indicated by the number of sub-chunks, plus one.&lt;br /&gt;
&lt;br /&gt;
===== GC data chunks =====&lt;br /&gt;
The GC data chunks have their own 10-byte header. Preliminary documentation below (not validated yet!):&lt;br /&gt;
* 00 : [[UINT8]] Always 0xA4&lt;br /&gt;
* 01 : [[UINT8]] Probably a checksum.&lt;br /&gt;
* 02 : [[UINT8]] X offset to display at&lt;br /&gt;
* 03 : [[UINT8]] Y offset to display at&lt;br /&gt;
* 04 : [[UINT8]] Width of contained image&lt;br /&gt;
* 05 : [[UINT8]] Height of contained image&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Subchunk size.&lt;br /&gt;
* 08 - 09 : [[UINT16LE]] Always 0?&lt;br /&gt;
&lt;br /&gt;
In the game the art looks like it contains a lot of dithering and the graphics chunks look like they are storing this in a clever way.&lt;br /&gt;
&lt;br /&gt;
The data is stored compressed in a style that looks like LZ77 (implicit reference table building) mixed with LZ78 (explicit table building) and Huffman coding. It is a very messy format; it is very easy to get a detail in the implementation wrong.&lt;br /&gt;
&lt;br /&gt;
For the decoder we will need two intermediate buffers for decoding, one called the &amp;quot;bit buffer&amp;quot; of 16 bits, and one called the &amp;quot;nibble buffer&amp;quot; of two 4-bit nibbles. We also need a third 1024-byte buffer to hold up to 256 4-byte samples, to be referenced.&lt;br /&gt;
&lt;br /&gt;
To start, the decoder loads the bit buffer with 16 bits. Every time the last bit is removed from the bit buffer, it loads the next two bytes in the input stream as a 16-bit big endian number into the bit buffer. Bits are removed from the high end one at a time, and are removed until a Huffman code is matched.&lt;br /&gt;
&lt;br /&gt;
The game uses the following Huffman table:&lt;br /&gt;
&lt;br /&gt;
===== Huffman table =====&lt;br /&gt;
* 00 : Copy from back&lt;br /&gt;
* 01 : Copy with Skip Table&lt;br /&gt;
* 10 : Skip single output&lt;br /&gt;
* 110 : Copy and store&lt;br /&gt;
* 1110 : Copy with Move Table&lt;br /&gt;
* 1111 : Copy from backing store&lt;br /&gt;
&lt;br /&gt;
The one simple command in this table is &amp;quot;Skip single output&amp;quot; - it moves the output pointer 4 bytes ahead not changing the output bytes.&lt;br /&gt;
&lt;br /&gt;
===== Nibble buffer =====&lt;br /&gt;
The nibble buffer is loaded when a value is attempted to be read but the table is empty. This differs from the bit buffer which is eagerly loaded. After loading a byte, the low nibble is returned first, and the second time it&#039;s called the high nibble is returned.&lt;br /&gt;
&lt;br /&gt;
===== Backing store =====&lt;br /&gt;
The backing store holds up to 256 entries of 4 bytes each. The table starts empty, and entries are placed from the start with an automatically increasing storage ID - the first one goes in slot 0, the second in slot 1 and so on. They are copied from the backing store a full entry at a time.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy and store&amp;quot; command takes 4 bytes from the input stream and copies them into the next entry in the backing store, and also copies them to the output buffer.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy from backing store&amp;quot; command takes a single byte from the input stream, and copies that entry from the backing store into the output buffer.&lt;br /&gt;
&lt;br /&gt;
===== Copy from back =====&lt;br /&gt;
Most of the game&#039;s graphics refer to output previously generated. It can refer back to the previous line written or to the earlier bits in this line. The copy from back command takes a nibble of data from the nibble buffer to find out what operation to do. All three of these use the same offset lookup table: { -1, -2, -4, -8, 1, 0 }. It splits the values into three regions:&lt;br /&gt;
&lt;br /&gt;
* Below 4: It copies a single entry from the output buffer to the output buffer. It gets the offset from the offset lookup table.&lt;br /&gt;
* Between 4 and 9: It loads a nibble to find out how many entries to copy. It will copy the loaded nibble count plus two, and it uses the offset table as the previous (with the original value minus 4). If the offset resolves to 0, it effectively just skips this many entries in the output buffer.&lt;br /&gt;
* 10 and above: It sets the number of entries to copy to the remaining entries in the line. It also uses the offset to find where to copy from, and again if the offset is 0 it just skips to the end.&lt;br /&gt;
&lt;br /&gt;
===== Copy Skip =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads yet another nibble, and outputs a sequence of 00 and FF bytes depending on the bits set in the nibble.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies the corresponding entry from the previous line on the screen.&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it skips ahead a byte in the output.&lt;br /&gt;
&lt;br /&gt;
===== Copy Move =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to copy, increased by 18. The top two bits (shifted right by 6) are used as an index into the offset table mentioned above to find the offset from where to copy.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to target, increased by 18. The top two bits are checked whether to copy the values; if it is not zero it only skips ahead. When they are zero, it copies as many values from the previous line into this line.&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it copies the equivalent byte from the previous output word.&lt;br /&gt;
&lt;br /&gt;
===== Converting the output data from planar =====&lt;br /&gt;
Each &amp;quot;entry&amp;quot; of 4 bytes covers 8 pixels, where each of the bytes contains a single bit for every pixel. As example, let&#039;s take 00 01 03 07 as example inputs:&lt;br /&gt;
&lt;br /&gt;
* 0000 0111 (byte 4)  &lt;br /&gt;
* 0000 0011 (byte 3)  &lt;br /&gt;
* 0000 0001 (byte 2)  &lt;br /&gt;
* 0000 0000 (byte 1)  &lt;br /&gt;
* ----------  &lt;br /&gt;
* 0000 08CE&lt;br /&gt;
&lt;br /&gt;
[[DecodingExample]]&lt;br /&gt;
&lt;br /&gt;
=== EMI.VOL ===&lt;br /&gt;
&lt;br /&gt;
EMI.VOL contains the music for the game, it has 41 chunks of data. The first chunk is exactly 4096 bytes and contains the instruments.&lt;br /&gt;
&lt;br /&gt;
==== Instrument Bank ====&lt;br /&gt;
There are 128 instruments in the chunk and each instrument is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
* Bytes 0 - 7 of each instrument look like FM parameters. {{TODO|Figure out which parameter does what}}&lt;br /&gt;
* Bytes 8 - 9 contain low numbers numbers from 0 - 3. {{TODO|Figure out if these are modulator and carrier wave parameters}}&lt;br /&gt;
* Bytes 10 - 11 contain numbers between 0 and 16. {{TODO|Figure out what these parameters mean}}&lt;br /&gt;
* Bytes 12 - 15 are all zeroes.&lt;br /&gt;
* Byte 16 increments from  0 - 31, after that it decrements from 255 to 160. Changing this seems to change the instrument type. It looks like the first 32 instruments are percussion.&lt;br /&gt;
* Byte 17 contains a number from 0 - 255. {{TODO|Figure out what this byte does.}}&lt;br /&gt;
* Bytes 18 - 23 contain zeroes.&lt;br /&gt;
* Byte 24 - 31 contains a lot of data, but changing this to all zeroes seemingly does not change the music in-game.&lt;br /&gt;
&lt;br /&gt;
The 40 remaining chunks all have the EM header.&lt;br /&gt;
&lt;br /&gt;
==== EM Entry ====&lt;br /&gt;
* 00 - 03 : signature 45 4D 00 06&lt;br /&gt;
* 04 - 05 : Unknown, most of the times 00 00, but values such as 00 03 are also present.{{TODO|Version?}}&lt;br /&gt;
* 06 - 07 : [[UINT16LE]], Start index of title, most of the times 1C 00&lt;br /&gt;
* 08 - 09 : [[UINT16LE]], Offset in the EM chunk where the actual data starts&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], Always the same as the previous [[UINT16LE]]. (Pointing to data offset)&lt;br /&gt;
* 0C - 0D : [[UINT16LE]], The size of the EM chunk&lt;br /&gt;
* 0E - 0F : Unknown, could be initial tempo or volume or something similar. {{TODO|Figure out what this is}}&lt;br /&gt;
&lt;br /&gt;
After this 6 [[UINT16LE]] follow, that indicate the offset in the chunk where data is found for each channel.&lt;br /&gt;
&lt;br /&gt;
6 channels are supported and if there is no data for the channel, the value is 0.&lt;br /&gt;
&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], Index of track 1 in chunk, usually the same as the [[UINT16LE]] from 08-09 and 0A-0B.&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], Index of track 2 in chunk&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], Index of track 3 in chunk&lt;br /&gt;
* 16 - 17 : [[UINT16LE]], Index of track 4 in chunk&lt;br /&gt;
* 18 - 19 : [[UINT16LE]], Index of track 5 in chunk&lt;br /&gt;
* 1A - 1B : [[UINT16LE]], Index of track 6 in chunk&lt;br /&gt;
* 1C : Start of title, if there is no title, the value at this location is FF, otherwise it&#039;s FE. &lt;br /&gt;
&lt;br /&gt;
If there is a title, a zero-terminated string follows, it contains japanese characters and at the end a date when it was converted.&lt;br /&gt;
Finally, it ends with FF.&lt;br /&gt;
&lt;br /&gt;
==== Pattern data ====&lt;br /&gt;
{{TODO|Highly experimental reverse-engineering, https://github.com/BlackStar-EoP/cobra-mission-writer/tree/master/emidump is an attempt to convert these to S3M}}&lt;br /&gt;
&lt;br /&gt;
So far, it seems the pattern data has&lt;br /&gt;
* 2 byte control commands&lt;br /&gt;
* 1 byte control commands&lt;br /&gt;
* 1 byte speed commands&lt;br /&gt;
* note commands&lt;br /&gt;
{{TODO|Check if there are more types, such as 3 or 3 byte commands}}&lt;br /&gt;
&lt;br /&gt;
===== 2 byte control commands =====&lt;br /&gt;
* 0xE4: Unknown&lt;br /&gt;
* 0xE7: Unknown&lt;br /&gt;
* 0xE8: Unknown&lt;br /&gt;
* 0xFB: Unknown&lt;br /&gt;
* 0xFD: Select instrument, byte after this indicates the index of the instrument from the instrument bank.&lt;br /&gt;
* 0xF7: Unknown&lt;br /&gt;
* 0xFA: Unknown&lt;br /&gt;
* 0xFC: Unknown&lt;br /&gt;
&lt;br /&gt;
===== 1 byte control commands ===== &lt;br /&gt;
* 0xCD: Unknown&lt;br /&gt;
* 0xCF: Unknown&lt;br /&gt;
* 0xDC: Unknown&lt;br /&gt;
* 0xDD: Unknown&lt;br /&gt;
* 0xCE: Unknown&lt;br /&gt;
* 0xF8: {{TODO|Loop command?}}&lt;br /&gt;
&lt;br /&gt;
===== 1 byte speed commands =====&lt;br /&gt;
These commands look like a delay command of some sort&lt;br /&gt;
{{TODO|It seems these commands can do more than just have a delay for a note, looks like they can delay for a couple of notes and then return to another speed.}}&lt;br /&gt;
* 0x81: row delay = 2&lt;br /&gt;
* 0x82: row delay = 4&lt;br /&gt;
* 0x83: row delay = 8&lt;br /&gt;
* 0x84: row delay = 16&lt;br /&gt;
* 0x85: row delay = 32&lt;br /&gt;
* 0x86: row delay = 64&lt;br /&gt;
* 0x89: row delay = 12&lt;br /&gt;
* 0x90: row delay = 6&lt;br /&gt;
* 0x8B: row delay = 48&lt;br /&gt;
* 0x8E: row delay = 3&lt;br /&gt;
&lt;br /&gt;
===== 1 byte note commands =====&lt;br /&gt;
The note commands range from 0x00 to 0x7F, where 0x00 is a C, 0x01 is a C-# and so on.&lt;br /&gt;
It seems that 0x00 is used as a dummy note, it does not get played, but increases the delay.&lt;br /&gt;
&lt;br /&gt;
=== MCG.VOL ===&lt;br /&gt;
&lt;br /&gt;
MCG.VOL contains the tilesets for the game. It contains 14 chunks of tile data.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Chunk nr!!Tileset&lt;br /&gt;
|-&lt;br /&gt;
|0||Character sprites&lt;br /&gt;
|-&lt;br /&gt;
|1||Weapon sprites&lt;br /&gt;
|-&lt;br /&gt;
|2||CASTLE tileset&lt;br /&gt;
|-&lt;br /&gt;
|3||AREA1 tileset&lt;br /&gt;
|-&lt;br /&gt;
|4||AREA2 tileset&lt;br /&gt;
|-&lt;br /&gt;
|5||AREA3 tileset&lt;br /&gt;
|-&lt;br /&gt;
|6||AREA4 tileset&lt;br /&gt;
|-&lt;br /&gt;
|7||AREA5 tileset&lt;br /&gt;
|-&lt;br /&gt;
|8||HOUSE tileset&lt;br /&gt;
|-&lt;br /&gt;
|9||BAR tileset&lt;br /&gt;
|-&lt;br /&gt;
|10||CORP tileset&lt;br /&gt;
|-&lt;br /&gt;
|11||BRICK tileset&lt;br /&gt;
|-&lt;br /&gt;
|12||LAB tileset&lt;br /&gt;
|-&lt;br /&gt;
|13||SEASIDE tileset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The header for this file is 64 bytes and contains the offsets for each tileset.&lt;br /&gt;
The tilesets consist of a number of tiles, all are 32x32 pixels, each pixel stored as a byte, making each sprite 1024 bytes.&lt;br /&gt;
&lt;br /&gt;
The palette for the tilesets is found inside each entry inside MED.VOL.&lt;br /&gt;
The colors are stored as an array[16] of [[UINT16LE]].&lt;br /&gt;
For example white is stored as F0FF, this will be read as 0x0FFF, and here the components are 0GRB.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
byte r = (value &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
byte g = value &amp;gt;&amp;gt; 8;&lt;br /&gt;
byte b = value &amp;amp; 0x0F;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will result in values from 0 to 15. Getting the actual color requires 2 shifts, one left of 4 and added to that one right of 2.&lt;br /&gt;
&lt;br /&gt;
Reading all palette entries would look something like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Color parse_color(uint16_t col)&lt;br /&gt;
{&lt;br /&gt;
	byte r = (col &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
	byte g = col &amp;gt;&amp;gt; 8;&lt;br /&gt;
	byte b = col &amp;amp; 0x0F;&lt;br /&gt;
	return Color((r &amp;lt;&amp;lt; 4) + (r &amp;gt;&amp;gt; 2), (g &amp;lt;&amp;lt; 4) + (g &amp;gt;&amp;gt; 2), (b &amp;lt;&amp;lt; 4) + (b &amp;gt;&amp;gt; 2));&lt;br /&gt;
}&lt;br /&gt;
void parse_palette()&lt;br /&gt;
{&lt;br /&gt;
	int pal = 0;&lt;br /&gt;
	for (int i = 32; i &amp;lt; 64; i += 2)&lt;br /&gt;
	{&lt;br /&gt;
		uint16_t color = (m_data[i + 1] &amp;lt;&amp;lt; 8) | m_data[i];&lt;br /&gt;
		m_palette[pal++] = parse_color(color);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MED.VOL ===&lt;br /&gt;
MED.VOL contains all the levels for the game. It contains 54 chunks of map data.&lt;br /&gt;
&lt;br /&gt;
==== MD Entry ====&lt;br /&gt;
Each MD entry inside MED.VOL consists of 5 blocks. The header (96 bytes), a block of unknown data (variable size), the tiledata for all the floors(dependent on size and number of floors), the triggers for all floors (same as the floor sizes, but with most entries 0) and a footer of 256 bytes.&lt;br /&gt;
===== MD Header =====&lt;br /&gt;
* 0 - 6 : signature 4D 44 03 30 02 02 14&lt;br /&gt;
* 7 - 9 : Unknown, most of the times 77 60 00, but values 9F 60 00, FF 60 00 and 8B 60 00 are also found in a few maps&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], the offset inside this MD chunk where the actual map data starts&lt;br /&gt;
* 0C - 0F : [[UINT32LE]], the size of this MD chunk&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], the width (in tiles) of this map&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], the height (in tiles) of this map&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], the number of floors in this map&lt;br /&gt;
* 16 - 1F : Character array, refers to the used tileset (values can be CASTLE, AREA1, AREA2 etc. See MCG.VOL), rest zeroes&lt;br /&gt;
* 20 - 3F : Palette data, 16 colors, each color stored as [[UINT16LE]], colors are stored as 4 bit nibbles.&lt;br /&gt;
* 40 - 5F : Character array, contains 2 names for the map, or for HOUSE types, the area that is referred. A long and a short version seperated by a pipe character.&lt;br /&gt;
&lt;br /&gt;
===== Unknown data block =====&lt;br /&gt;
Unknown data block, usually ranging from 0060 to 0420. The data inside looks the same for all the MD chunks. It looks like a lot of 16 bit integers.&lt;br /&gt;
&lt;br /&gt;
===== Tile data block =====&lt;br /&gt;
The size of the block is width * height * number of floors.&lt;br /&gt;
Each byte corresponds to the tile number in the used tileset.&lt;br /&gt;
The floors are stored sequentially.&lt;br /&gt;
&lt;br /&gt;
===== Triggers block =====&lt;br /&gt;
The same layout as the tile data block, but now most bytes are 00 and the bytes that are not are triggers such as item pickups, stairs, doors etc. &lt;br /&gt;
Unknown what the numbers mean, but exits are usually 0x20, item pickups range in 0x40 and character sprites are usually 0xC0 and higher.&lt;br /&gt;
&lt;br /&gt;
===== Footer =====&lt;br /&gt;
At the end of each MD chunk there are 256 bytes, unknown what the data represents, but it looks like it is related to the trigger block.&lt;br /&gt;
&lt;br /&gt;
=== PCM1.VOL - PCM6.VOL ===&lt;br /&gt;
These files contain PCM data in the form of the [[VOC_Format|Creative Voice Format]]&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
This file format was reverse-engineered by [[User:BlackStar|BlackStar]]. If you find this information helpful in a project you&#039;re working on, please give credit where credit is due.  (A link back to this wiki would be nice too!)&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11028</id>
		<title>MegaTech VOL Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11028"/>
		<updated>2023-05-08T19:38:17Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = Unlimited&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = No&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Cobra Mission}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;MegaTech VOL Format&#039;&#039;&#039; is an archive used by [[Cobra Mission]] to store all the game data.  The following .VOL files are included with the game:&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
There is no header.  The format is simply a list of offsets, repeated until the file data begins:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Data type !! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[UINT32LE]] || offset || Offset of this file, relative to start of archive file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Usually the above structure is repeated until it is 256 bytes long (with unused offsets as zero), but it can be smaller (&amp;lt;tt&amp;gt;pcm6.vol&amp;lt;/tt&amp;gt; has a 64 byte header).&lt;br /&gt;
&lt;br /&gt;
The last entry in the list is the file size, followed by zero offsets as needed to pad the list to the required length.&lt;br /&gt;
&lt;br /&gt;
{{TODO|Will the game accept files that lack this padding?}}&lt;br /&gt;
&lt;br /&gt;
== Instances ==&lt;br /&gt;
&lt;br /&gt;
=== Graphics VOL files ===&lt;br /&gt;
* CUT1.VOL&lt;br /&gt;
* CUT2.VOL&lt;br /&gt;
* CUT3.VOL&lt;br /&gt;
* CUTA.VOL&lt;br /&gt;
* ENM.VOL&lt;br /&gt;
* ENMA.VOL&lt;br /&gt;
* MAP.VOL&lt;br /&gt;
* OPENING.VOL&lt;br /&gt;
* PIC1.VOL&lt;br /&gt;
* PIC2.VOL&lt;br /&gt;
* PIC3.VOL&lt;br /&gt;
* PICA.VOL&lt;br /&gt;
&lt;br /&gt;
The listed VOL files contain the graphics for the game.&lt;br /&gt;
* OPENING.VOL contains the graphics for the intro sequence&lt;br /&gt;
* MAP.VOL contains the graphics for the inventory map items.&lt;br /&gt;
{{TODO|Below are assumptions on the other files}}&lt;br /&gt;
* CUT1 - CUTA : Cutscenes&lt;br /&gt;
* ENM - ENMA : Enemy graphics&lt;br /&gt;
* PIC1 - PICA : Inventory items (magazines and photos)&lt;br /&gt;
&lt;br /&gt;
These VOL files contain graphics chunks with the following structure&lt;br /&gt;
&lt;br /&gt;
==== GC Entry ====&lt;br /&gt;
* 00 - 01 : [[UINT16LE]] signature 47 43 &amp;quot;GC&amp;quot;&lt;br /&gt;
* 02 - 03 : [[UINT16LE]] Version 02.00&lt;br /&gt;
* 04 - 05 : [[UINT16LE]] Flag that indicates whether a palette is present.&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Points to the location of the sub-chunk table.&lt;br /&gt;
* 08 - 0B : [[UINT32LE]] Number of sub-chunks in the entry. Very often only 1, but sometimes more.&lt;br /&gt;
* 0C - 0D : [[UINT16LE]] Size of the chunk.&lt;br /&gt;
* 0E      : [[UINT8]] Padding (always 0)&lt;br /&gt;
* 0F      : [[UINT8]] Checksum; add up all the bytes from 00 to 0E and place the 2&#039;s complement of that sum here. To check, add all bytes from 00 to 0F and the result of that should be 0.&lt;br /&gt;
&lt;br /&gt;
If the palette bit is set in the header, a palette will follow. &lt;br /&gt;
* 10 - 2F : The colors are stored as an array[16] of [[UINT16LE]]. See MED.VOL for example code on how to read the palette.&lt;br /&gt;
&lt;br /&gt;
After the palette there&#039;s a subchunk table with N+1 values, where N is the number of subchunks. Each chunk runs from offset[X] to offset[X+1]. For a single chunk file, this has two values.&lt;br /&gt;
* (10 or 30) - xx : Offset pointers in the chunk stored as [[UINT32LE]]. The amount is indicated by the number of sub-chunks, plus one.&lt;br /&gt;
&lt;br /&gt;
===== GC data chunks =====&lt;br /&gt;
The GC data chunks have their own 10-byte header. Preliminary documentation below (not validated yet!):&lt;br /&gt;
* 00 : [[UINT8]] Always 0xA4&lt;br /&gt;
* 01 : [[UINT8]] Probably a checksum.&lt;br /&gt;
* 02 : [[UINT8]] X offset to display at&lt;br /&gt;
* 03 : [[UINT8]] Y offset to display at&lt;br /&gt;
* 04 : [[UINT8]] Width of contained image&lt;br /&gt;
* 05 : [[UINT8]] Height of contained image&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Subchunk size.&lt;br /&gt;
* 08 - 09 : [[UINT16LE]] Always 0?&lt;br /&gt;
&lt;br /&gt;
In the game the art looks like it contains a lot of dithering and the graphics chunks look like they are storing this in a clever way.&lt;br /&gt;
&lt;br /&gt;
The data is stored compressed in a style that looks like LZ77 (implicit reference table building) mixed with LZ78 (explicit table building) and Huffman coding. It is a very messy format; it is very easy to get a detail in the implementation wrong.&lt;br /&gt;
&lt;br /&gt;
For the decoder we will need two intermediate buffers for decoding, one called the &amp;quot;bit buffer&amp;quot; of 16 bits, and one called the &amp;quot;nibble buffer&amp;quot; of two 4-bit nibbles. We also need a third 1024-byte buffer to hold up to 256 4-byte samples, to be referenced.&lt;br /&gt;
&lt;br /&gt;
To start, the decoder loads the bit buffer with 16 bits. Every time the last bit is removed from the bit buffer, it loads the next two bytes in the input stream as a 16-bit big endian number into the bit buffer. Bits are removed from the high end one at a time, and are removed until a Huffman code is matched.&lt;br /&gt;
&lt;br /&gt;
The game uses the following Huffman table:&lt;br /&gt;
&lt;br /&gt;
===== Huffman table =====&lt;br /&gt;
* 00 : Copy from back&lt;br /&gt;
* 01 : Copy with Skip Table&lt;br /&gt;
* 10 : Skip single output&lt;br /&gt;
* 110 : Copy and store&lt;br /&gt;
* 1110 : Copy with Move Table&lt;br /&gt;
* 1111 : Copy from backing store&lt;br /&gt;
&lt;br /&gt;
The one simple command in this table is &amp;quot;Skip single output&amp;quot; - it moves the output pointer 4 bytes ahead not changing the output bytes.&lt;br /&gt;
&lt;br /&gt;
===== Nibble buffer =====&lt;br /&gt;
The nibble buffer is loaded when a value is attempted to be read but the table is empty. This differs from the bit buffer which is eagerly loaded. After loading a byte, the low nibble is returned first, and the second time it&#039;s called the high nibble is returned.&lt;br /&gt;
&lt;br /&gt;
===== Backing store =====&lt;br /&gt;
The backing store holds up to 256 entries of 4 bytes each. The table starts empty, and entries are placed from the start with an automatically increasing storage ID - the first one goes in slot 0, the second in slot 1 and so on. They are copied from the backing store a full entry at a time.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy and store&amp;quot; command takes 4 bytes from the input stream and copies them into the next entry in the backing store, and also copies them to the output buffer.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy from backing store&amp;quot; command takes a single byte from the input stream, and copies that entry from the backing store into the output buffer.&lt;br /&gt;
&lt;br /&gt;
===== Copy from back =====&lt;br /&gt;
Most of the game&#039;s graphics refer to output previously generated. It can refer back to the previous line written or to the earlier bits in this line. The copy from back command takes a nibble of data from the nibble buffer to find out what operation to do. All three of these use the same offset lookup table: { -1, -2, -4, -8, 1, 0 }. It splits the values into three regions:&lt;br /&gt;
&lt;br /&gt;
* Below 4: It copies a single entry from the output buffer to the output buffer. It gets the offset from the offset lookup table.&lt;br /&gt;
* Between 4 and 9: It loads a nibble to find out how many entries to copy. It will copy the loaded nibble count plus two, and it uses the offset table as the previous (with the original value minus 4). If the offset resolves to 0, it effectively just skips this many entries in the output buffer.&lt;br /&gt;
* 10 and above: It sets the number of entries to copy to the remaining entries in the line. It also uses the offset to find where to copy from, and again if the offset is 0 it just skips to the end.&lt;br /&gt;
&lt;br /&gt;
===== Copy Skip =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads yet another nibble, and outputs a sequence of 00 and FF bytes depending on the bits set in the nibble.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies a single value from bp-1A ?&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it skips ahead a byte in the output.&lt;br /&gt;
&lt;br /&gt;
===== Copy Move =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to copy, increased by 17. The top two bits (shifted right by 6) are used as an index into the offset table mentioned above to find the offset from where to copy.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies multiple values from bp-1A ?&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it copies the equivalent byte from the previous output word.&lt;br /&gt;
&lt;br /&gt;
===== Converting the output data from planar =====&lt;br /&gt;
Each &amp;quot;entry&amp;quot; of 4 bytes covers 8 pixels, where each of the bytes contains a single bit for every pixel. As example, let&#039;s take 00 01 03 07 as example inputs:&lt;br /&gt;
&lt;br /&gt;
* 0000 0111 (byte 4)  &lt;br /&gt;
* 0000 0011 (byte 3)  &lt;br /&gt;
* 0000 0001 (byte 2)  &lt;br /&gt;
* 0000 0000 (byte 1)  &lt;br /&gt;
* ----------  &lt;br /&gt;
* 0000 08CE&lt;br /&gt;
&lt;br /&gt;
[[DecodingExample]]&lt;br /&gt;
&lt;br /&gt;
=== EMI.VOL ===&lt;br /&gt;
&lt;br /&gt;
EMI.VOL contains the music for the game, it has 41 chunks of data. The first chunk is exactly 4096 bytes and contains the instruments.&lt;br /&gt;
&lt;br /&gt;
==== Instrument Bank ====&lt;br /&gt;
There are 128 instruments in the chunk and each instrument is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
* Bytes 0 - 7 of each instrument look like FM parameters. {{TODO|Figure out which parameter does what}}&lt;br /&gt;
* Bytes 8 - 9 contain low numbers numbers from 0 - 3. {{TODO|Figure out if these are modulator and carrier wave parameters}}&lt;br /&gt;
* Bytes 10 - 11 contain numbers between 0 and 16. {{TODO|Figure out what these parameters mean}}&lt;br /&gt;
* Bytes 12 - 15 are all zeroes.&lt;br /&gt;
* Byte 16 increments from  0 - 31, after that it decrements from 255 to 160. Changing this seems to change the instrument type. It looks like the first 32 instruments are percussion.&lt;br /&gt;
* Byte 17 contains a number from 0 - 255. {{TODO|Figure out what this byte does.}}&lt;br /&gt;
* Bytes 18 - 23 contain zeroes.&lt;br /&gt;
* Byte 24 - 31 contains a lot of data, but changing this to all zeroes seemingly does not change the music in-game.&lt;br /&gt;
&lt;br /&gt;
The 40 remaining chunks all have the EM header.&lt;br /&gt;
&lt;br /&gt;
==== EM Entry ====&lt;br /&gt;
* 00 - 03 : signature 45 4D 00 06&lt;br /&gt;
* 04 - 05 : Unknown, most of the times 00 00, but values such as 00 03 are also present.{{TODO|Version?}}&lt;br /&gt;
* 06 - 07 : [[UINT16LE]], Start index of title, most of the times 1C 00&lt;br /&gt;
* 08 - 09 : [[UINT16LE]], Offset in the EM chunk where the actual data starts&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], Always the same as the previous [[UINT16LE]]. (Pointing to data offset)&lt;br /&gt;
* 0C - 0D : [[UINT16LE]], The size of the EM chunk&lt;br /&gt;
* 0E - 0F : Unknown, could be initial tempo or volume or something similar. {{TODO|Figure out what this is}}&lt;br /&gt;
&lt;br /&gt;
After this 6 [[UINT16LE]] follow, that indicate the offset in the chunk where data is found for each channel.&lt;br /&gt;
&lt;br /&gt;
6 channels are supported and if there is no data for the channel, the value is 0.&lt;br /&gt;
&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], Index of track 1 in chunk, usually the same as the [[UINT16LE]] from 08-09 and 0A-0B.&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], Index of track 2 in chunk&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], Index of track 3 in chunk&lt;br /&gt;
* 16 - 17 : [[UINT16LE]], Index of track 4 in chunk&lt;br /&gt;
* 18 - 19 : [[UINT16LE]], Index of track 5 in chunk&lt;br /&gt;
* 1A - 1B : [[UINT16LE]], Index of track 6 in chunk&lt;br /&gt;
* 1C : Start of title, if there is no title, the value at this location is FF, otherwise it&#039;s FE. &lt;br /&gt;
&lt;br /&gt;
If there is a title, a zero-terminated string follows, it contains japanese characters and at the end a date when it was converted.&lt;br /&gt;
Finally, it ends with FF.&lt;br /&gt;
&lt;br /&gt;
==== Pattern data ====&lt;br /&gt;
{{TODO|Highly experimental reverse-engineering, https://github.com/BlackStar-EoP/cobra-mission-writer/tree/master/emidump is an attempt to convert these to S3M}}&lt;br /&gt;
&lt;br /&gt;
So far, it seems the pattern data has&lt;br /&gt;
* 2 byte control commands&lt;br /&gt;
* 1 byte control commands&lt;br /&gt;
* 1 byte speed commands&lt;br /&gt;
* note commands&lt;br /&gt;
{{TODO|Check if there are more types, such as 3 or 3 byte commands}}&lt;br /&gt;
&lt;br /&gt;
===== 2 byte control commands =====&lt;br /&gt;
* 0xE4: Unknown&lt;br /&gt;
* 0xE7: Unknown&lt;br /&gt;
* 0xE8: Unknown&lt;br /&gt;
* 0xFB: Unknown&lt;br /&gt;
* 0xFD: Select instrument, byte after this indicates the index of the instrument from the instrument bank.&lt;br /&gt;
* 0xF7: Unknown&lt;br /&gt;
* 0xFA: Unknown&lt;br /&gt;
* 0xFC: Unknown&lt;br /&gt;
&lt;br /&gt;
===== 1 byte control commands ===== &lt;br /&gt;
* 0xCD: Unknown&lt;br /&gt;
* 0xCF: Unknown&lt;br /&gt;
* 0xDC: Unknown&lt;br /&gt;
* 0xDD: Unknown&lt;br /&gt;
* 0xCE: Unknown&lt;br /&gt;
* 0xF8: {{TODO|Loop command?}}&lt;br /&gt;
&lt;br /&gt;
===== 1 byte speed commands =====&lt;br /&gt;
These commands look like a delay command of some sort&lt;br /&gt;
{{TODO|It seems these commands can do more than just have a delay for a note, looks like they can delay for a couple of notes and then return to another speed.}}&lt;br /&gt;
* 0x81: row delay = 2&lt;br /&gt;
* 0x82: row delay = 4&lt;br /&gt;
* 0x83: row delay = 8&lt;br /&gt;
* 0x84: row delay = 16&lt;br /&gt;
* 0x85: row delay = 32&lt;br /&gt;
* 0x86: row delay = 64&lt;br /&gt;
* 0x89: row delay = 12&lt;br /&gt;
* 0x90: row delay = 6&lt;br /&gt;
* 0x8B: row delay = 48&lt;br /&gt;
* 0x8E: row delay = 3&lt;br /&gt;
&lt;br /&gt;
===== 1 byte note commands =====&lt;br /&gt;
The note commands range from 0x00 to 0x7F, where 0x00 is a C, 0x01 is a C-# and so on.&lt;br /&gt;
It seems that 0x00 is used as a dummy note, it does not get played, but increases the delay.&lt;br /&gt;
&lt;br /&gt;
=== MCG.VOL ===&lt;br /&gt;
&lt;br /&gt;
MCG.VOL contains the tilesets for the game. It contains 14 chunks of tile data.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Chunk nr!!Tileset&lt;br /&gt;
|-&lt;br /&gt;
|0||Character sprites&lt;br /&gt;
|-&lt;br /&gt;
|1||Weapon sprites&lt;br /&gt;
|-&lt;br /&gt;
|2||CASTLE tileset&lt;br /&gt;
|-&lt;br /&gt;
|3||AREA1 tileset&lt;br /&gt;
|-&lt;br /&gt;
|4||AREA2 tileset&lt;br /&gt;
|-&lt;br /&gt;
|5||AREA3 tileset&lt;br /&gt;
|-&lt;br /&gt;
|6||AREA4 tileset&lt;br /&gt;
|-&lt;br /&gt;
|7||AREA5 tileset&lt;br /&gt;
|-&lt;br /&gt;
|8||HOUSE tileset&lt;br /&gt;
|-&lt;br /&gt;
|9||BAR tileset&lt;br /&gt;
|-&lt;br /&gt;
|10||CORP tileset&lt;br /&gt;
|-&lt;br /&gt;
|11||BRICK tileset&lt;br /&gt;
|-&lt;br /&gt;
|12||LAB tileset&lt;br /&gt;
|-&lt;br /&gt;
|13||SEASIDE tileset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The header for this file is 64 bytes and contains the offsets for each tileset.&lt;br /&gt;
The tilesets consist of a number of tiles, all are 32x32 pixels, each pixel stored as a byte, making each sprite 1024 bytes.&lt;br /&gt;
&lt;br /&gt;
The palette for the tilesets is found inside each entry inside MED.VOL.&lt;br /&gt;
The colors are stored as an array[16] of [[UINT16LE]].&lt;br /&gt;
For example white is stored as F0FF, this will be read as 0x0FFF, and here the components are 0GRB.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
byte r = (value &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
byte g = value &amp;gt;&amp;gt; 8;&lt;br /&gt;
byte b = value &amp;amp; 0x0F;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will result in values from 0 to 15. Getting the actual color requires 2 shifts, one left of 4 and added to that one right of 2.&lt;br /&gt;
&lt;br /&gt;
Reading all palette entries would look something like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Color parse_color(uint16_t col)&lt;br /&gt;
{&lt;br /&gt;
	byte r = (col &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
	byte g = col &amp;gt;&amp;gt; 8;&lt;br /&gt;
	byte b = col &amp;amp; 0x0F;&lt;br /&gt;
	return Color((r &amp;lt;&amp;lt; 4) + (r &amp;gt;&amp;gt; 2), (g &amp;lt;&amp;lt; 4) + (g &amp;gt;&amp;gt; 2), (b &amp;lt;&amp;lt; 4) + (b &amp;gt;&amp;gt; 2));&lt;br /&gt;
}&lt;br /&gt;
void parse_palette()&lt;br /&gt;
{&lt;br /&gt;
	int pal = 0;&lt;br /&gt;
	for (int i = 32; i &amp;lt; 64; i += 2)&lt;br /&gt;
	{&lt;br /&gt;
		uint16_t color = (m_data[i + 1] &amp;lt;&amp;lt; 8) | m_data[i];&lt;br /&gt;
		m_palette[pal++] = parse_color(color);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MED.VOL ===&lt;br /&gt;
MED.VOL contains all the levels for the game. It contains 54 chunks of map data.&lt;br /&gt;
&lt;br /&gt;
==== MD Entry ====&lt;br /&gt;
Each MD entry inside MED.VOL consists of 5 blocks. The header (96 bytes), a block of unknown data (variable size), the tiledata for all the floors(dependent on size and number of floors), the triggers for all floors (same as the floor sizes, but with most entries 0) and a footer of 256 bytes.&lt;br /&gt;
===== MD Header =====&lt;br /&gt;
* 0 - 6 : signature 4D 44 03 30 02 02 14&lt;br /&gt;
* 7 - 9 : Unknown, most of the times 77 60 00, but values 9F 60 00, FF 60 00 and 8B 60 00 are also found in a few maps&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], the offset inside this MD chunk where the actual map data starts&lt;br /&gt;
* 0C - 0F : [[UINT32LE]], the size of this MD chunk&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], the width (in tiles) of this map&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], the height (in tiles) of this map&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], the number of floors in this map&lt;br /&gt;
* 16 - 1F : Character array, refers to the used tileset (values can be CASTLE, AREA1, AREA2 etc. See MCG.VOL), rest zeroes&lt;br /&gt;
* 20 - 3F : Palette data, 16 colors, each color stored as [[UINT16LE]], colors are stored as 4 bit nibbles.&lt;br /&gt;
* 40 - 5F : Character array, contains 2 names for the map, or for HOUSE types, the area that is referred. A long and a short version seperated by a pipe character.&lt;br /&gt;
&lt;br /&gt;
===== Unknown data block =====&lt;br /&gt;
Unknown data block, usually ranging from 0060 to 0420. The data inside looks the same for all the MD chunks. It looks like a lot of 16 bit integers.&lt;br /&gt;
&lt;br /&gt;
===== Tile data block =====&lt;br /&gt;
The size of the block is width * height * number of floors.&lt;br /&gt;
Each byte corresponds to the tile number in the used tileset.&lt;br /&gt;
The floors are stored sequentially.&lt;br /&gt;
&lt;br /&gt;
===== Triggers block =====&lt;br /&gt;
The same layout as the tile data block, but now most bytes are 00 and the bytes that are not are triggers such as item pickups, stairs, doors etc. &lt;br /&gt;
Unknown what the numbers mean, but exits are usually 0x20, item pickups range in 0x40 and character sprites are usually 0xC0 and higher.&lt;br /&gt;
&lt;br /&gt;
===== Footer =====&lt;br /&gt;
At the end of each MD chunk there are 256 bytes, unknown what the data represents, but it looks like it is related to the trigger block.&lt;br /&gt;
&lt;br /&gt;
=== PCM1.VOL - PCM6.VOL ===&lt;br /&gt;
These files contain PCM data in the form of the [[VOC_Format|Creative Voice Format]]&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
This file format was reverse-engineered by [[User:BlackStar|BlackStar]]. If you find this information helpful in a project you&#039;re working on, please give credit where credit is due.  (A link back to this wiki would be nice too!)&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format/Decoding_Example&amp;diff=11027</id>
		<title>MegaTech VOL Format/Decoding Example</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format/Decoding_Example&amp;diff=11027"/>
		<updated>2023-05-08T19:25:17Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We will be decoding the byte sequence above. To start, we take the first two bytes to preload the bit buffer. The nibble buffer stays empty, and the back buffer is also empty.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1101 1000 1101 1000&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: empty&lt;br /&gt;
* OUTPUT: empty&lt;br /&gt;
* CONSUMED INPUT: d8 d8 &lt;br /&gt;
* REMAINING INPUT: 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
The first command we get is 110, copy 4 bytes from the input to the back buffer and output.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1 1000 1101 1000&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 (1 entry)&lt;br /&gt;
* OUTPUT: 01 01 01 01&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01&lt;br /&gt;
* REMAINING INPUT: e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
The second command is also 110, so we do this same thing again.&lt;br /&gt;
&lt;br /&gt;
* BITS: 00 1101 1000&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0  (2 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0&lt;br /&gt;
* REMAINING INPUT: 55 e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Now, the value we get from the bit buffer is 00. This is an code that needs an additional nibble, so we&#039;ll read it:&lt;br /&gt;
&lt;br /&gt;
* BITS: 1101 1000&lt;br /&gt;
* NIBBLE: 5&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0  (2 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55&lt;br /&gt;
* REMAINING INPUT: e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We got a 5. This lands us in the 4-9 for that one, so we fetch another nibble (5) to get the amount to copy, and use the first 5 (minus 4) to get the offset to read at. That results in 7 values to copy from 2 entries back.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1101 1000&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0  (2 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55&lt;br /&gt;
* REMAINING INPUT: e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Now we get the 110 command twice more. Skipping ahead for those two:&lt;br /&gt;
&lt;br /&gt;
* BITS: 00&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 (4 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21&lt;br /&gt;
* REMAINING INPUT: 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Reading the next command we get a command 00. Before we continue though, the bit buffer is empty and it *first* refills.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1110 1100 0001 1011&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 (4 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21&lt;br /&gt;
* REMAINING INPUT: 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Now we run the second 00 command fetching its data. It needs a nibble to know what offset to run at, and it fetches a 7 for that - same as last, except a larger pointer, going 8 back. It fetches another nibble for the count, and gets the 4 (from the same byte). It will then copy 6 values (4 + 2) from an offset of 8 entries back. The compressor most likely stopped there to avoid copying the interruption.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1110 1100 0001 1011&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 (4 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47&lt;br /&gt;
* REMAINING INPUT: 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We retrieve a command 1110; this refers to the copy move table. We also fetch a nibble to find out which subcommand it runs, and it&#039;s a zero. This copies a number of values from a short distance back. It starts by fetching a full byte - note that we are ignoring the nibble we have in the nibble buffer for this - and we get a 0x46. It splits this into a 2-bit index into the offset table getting an offset of -2, and a 6-bit count of entries to copy (to be increased by 17+1, so 24). We therefore copy from a relative offset of -2 entries, 24 times. &lt;br /&gt;
&lt;br /&gt;
* BITS: 1100 0001 1011&lt;br /&gt;
* NIBBLE: 7&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 (4 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46&lt;br /&gt;
* REMAINING INPUT: b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We get another 110, so we copy an entry to the buffer and output.&lt;br /&gt;
&lt;br /&gt;
* BITS: 0 0001 1011&lt;br /&gt;
* NIBBLE: 7&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 (5 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 b5 b5 ab a1 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 &lt;br /&gt;
* REMAINING INPUT: 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Again, we get a 00, so we copy from the back. We first fetch the nibble value from the nibble buffer now, so we have a 7. The second nibble we fetch is a 5, and we will copy 7 values (from the 5 plus two) from 8 back (from the 7 in the offset table). &lt;br /&gt;
&lt;br /&gt;
* BITS: 001 1011&lt;br /&gt;
* NIBBLE: 5&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 (5 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 b5 b5 ab a1 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55&lt;br /&gt;
* REMAINING INPUT: b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We again get a 00 command, so we take the 5 from the nibble buffer (offset -2) and fetch a new nibble from the input to get 4 values to copy.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1 1011&lt;br /&gt;
* NIBBLE: b&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 (5 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 b5 b5 ab a1 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55&lt;br /&gt;
* REMAINING INPUT: 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Another 110, we copy out 4 values.&lt;br /&gt;
&lt;br /&gt;
* BITS: 11&lt;br /&gt;
* NIBBLE: b&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 81 94 88 94 (6 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 b5 b5 ab a1 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 81 94 88 94&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55 81 94 88 94&lt;br /&gt;
* REMAINING INPUT: 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We fetch two bits, but need more for the command, so we refill the bit buffer mid-command and keep reading.&lt;br /&gt;
&lt;br /&gt;
* BITS: (11) 1011 1000 0011 0111&lt;br /&gt;
* NIBBLE: b&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 81 94 88 94 (6 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 b5 b5 ab a1 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 81 94 88 94&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55 81 94 88 94 37 b8&lt;br /&gt;
* REMAINING INPUT: 00 55 55&lt;br /&gt;
&lt;br /&gt;
We find a 1110, we fetch a nibble to find out what it wants us to do. This time it&#039;s 0xb or 1011 in binary.&lt;br /&gt;
&lt;br /&gt;
* BITS: 11 1000 0011 0111&lt;br /&gt;
* NIBBLE: b&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 81 94 88 94 (6 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 b5 b5 ab a1 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 81 94 88 94 00 55 88 55&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
* REMAINING INPUT: &lt;br /&gt;
&lt;br /&gt;
We&#039;re done (with this part).&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format/Decoding_Example&amp;diff=11026</id>
		<title>MegaTech VOL Format/Decoding Example</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format/Decoding_Example&amp;diff=11026"/>
		<updated>2023-05-08T19:11:13Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: Decoding example for Megatech VOL format GC image.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We will be decoding the byte sequence above. To start, we take the first two bytes to preload the bit buffer. The nibble buffer stays empty, and the back buffer is also empty.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1101 1000 1101 1000&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: empty&lt;br /&gt;
* OUTPUT: empty&lt;br /&gt;
* CONSUMED INPUT: d8 d8 &lt;br /&gt;
* REMAINING INPUT: 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
The first command we get is 110, copy 4 bytes from the input to the back buffer and output.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1 1000 1101 1000&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 (1 entry)&lt;br /&gt;
* OUTPUT: 01 01 01 01&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01&lt;br /&gt;
* REMAINING INPUT: e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
The second command is also 110, so we do this same thing again.&lt;br /&gt;
&lt;br /&gt;
* BITS: 00 1101 1000&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0  (2 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0&lt;br /&gt;
* REMAINING INPUT: 55 e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Now, the value we get from the bit buffer is 00. This is an code that needs an additional nibble, so we&#039;ll read it:&lt;br /&gt;
&lt;br /&gt;
* BITS: 1101 1000&lt;br /&gt;
* NIBBLE: 5&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0  (2 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55&lt;br /&gt;
* REMAINING INPUT: e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We got a 5. This lands us in the 4-9 for that one, so we fetch another nibble (5) to get the amount to copy, and use the first 5 (minus 4) to get the offset to read at. That results in 7 values to copy from 2 entries back.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1101 1000&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0  (2 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55&lt;br /&gt;
* REMAINING INPUT: e3 e3 e2 e2 61 61 a1 21 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Now we get the 110 command twice more. Skipping ahead for those two:&lt;br /&gt;
&lt;br /&gt;
* BITS: 00&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 (4 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21&lt;br /&gt;
* REMAINING INPUT: 1b ec 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Reading the next command we get a command 00. Before we continue though, the bit buffer is empty and it *first* refills.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1110 1100 0001 1011&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 (4 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21&lt;br /&gt;
* REMAINING INPUT: 47 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Now we run the second 00 command fetching its data. It needs a nibble to know what offset to run at, and it fetches a 7 for that - same as last, except a larger pointer, going 8 back. It fetches another nibble for the count, and gets the 4 (from the same byte). It will then copy 6 values (4 + 2) from an offset of 8 entries back. The compressor most likely stopped there to avoid copying the interruption.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1110 1100 0001 1011&lt;br /&gt;
* NIBBLE: empty&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 (4 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47&lt;br /&gt;
* REMAINING INPUT: 70 46 b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We retrieve a command 1110; this refers to the copy move table. We also fetch a nibble to find out which subcommand it runs, and it&#039;s a zero. This copies a number of values from a short distance back. It starts by fetching a full byte - note that we are ignoring the nibble we have in the nibble buffer for this - and we get a 0x46. It splits this into a 2-bit index into the offset table getting an offset of -2, and a 6-bit count of entries to copy (to be increased by 17, so 23). We therefore copy from a relative offset of -2 entries, 23 times. &lt;br /&gt;
&lt;br /&gt;
* BITS: 1100 0001 1011&lt;br /&gt;
* NIBBLE: 7&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 (4 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46&lt;br /&gt;
* REMAINING INPUT: b5 b5 ab a1 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We get another 110, so we copy an entry to the buffer and output.&lt;br /&gt;
&lt;br /&gt;
* BITS: 0 0001 1011&lt;br /&gt;
* NIBBLE: 7&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 (5 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 b5 b5 ab a1 &lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 &lt;br /&gt;
* REMAINING INPUT: 55 b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Again, we get a 00, so we copy from the back. We first fetch the nibble value from the nibble buffer now, so we have a 7. The second nibble we fetch is a 5, and we will copy 7 values (from the 5 plus two) from 8 back (from the 7 in the offset table). &lt;br /&gt;
&lt;br /&gt;
* BITS: 001 1011&lt;br /&gt;
* NIBBLE: 5&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 (5 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 b5 b5 ab a1 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55&lt;br /&gt;
* REMAINING INPUT: b2 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We again get a 00 command, so we take the 5 from the nibble buffer (offset -2) and fetch a new nibble from the input to get 4 values to copy.&lt;br /&gt;
&lt;br /&gt;
* BITS: 1 1011&lt;br /&gt;
* NIBBLE: b&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 (5 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 b5 b5 ab a1 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55&lt;br /&gt;
* REMAINING INPUT: 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
Another 110, we copy out 4 values.&lt;br /&gt;
&lt;br /&gt;
* BITS: 11&lt;br /&gt;
* NIBBLE: b&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 81 94 88 94 (6 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 b5 b5 ab a1 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 81 94 88 94&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55 81 94 88 94&lt;br /&gt;
* REMAINING INPUT: 37 b8 00 55 55&lt;br /&gt;
&lt;br /&gt;
We fetch two bits, but need more for the command, so we refill the bit buffer mid-command and keep reading.&lt;br /&gt;
&lt;br /&gt;
* BITS: (11) 1011 1000 0011 0111&lt;br /&gt;
* NIBBLE: b&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 81 94 88 94 (6 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 b5 b5 ab a1 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 81 94 88 94&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55 81 94 88 94 37 b8&lt;br /&gt;
* REMAINING INPUT: 00 55 55&lt;br /&gt;
&lt;br /&gt;
We find a 1110, we fetch a nibble to find out what it wants us to do. This time it&#039;s 0xb or 1011 in binary.&lt;br /&gt;
&lt;br /&gt;
* BITS: 11 1000 0011 0111&lt;br /&gt;
* NIBBLE: b&lt;br /&gt;
* BACKBUFFER: 01 01 01 01 e0 e0 e0 e0 e3 e3 e2 e2 61 61 a1 21 b5 b5 ab a1 81 94 88 94 (6 entries)&lt;br /&gt;
* OUTPUT: 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e3 e3 e2 e2 61 61 a1 21 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 b5 b5 ab a1 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 01 01 01 01 e0 e0 e0 e0 81 94 88 94 00 55 88 55&lt;br /&gt;
* CONSUMED INPUT: d8 d8 01 01 01 01 e0 e0 e0 e0 55 e3 e3 e2 e2 61 61 a1 21 47 70 46 b5 b5 ab a1 55 81 94 88 94 37 b8 00 55 55&lt;br /&gt;
* REMAINING INPUT: &lt;br /&gt;
&lt;br /&gt;
We&#039;re done (with this part).&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11025</id>
		<title>MegaTech VOL Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11025"/>
		<updated>2023-05-08T18:40:14Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = Unlimited&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = No&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Cobra Mission}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;MegaTech VOL Format&#039;&#039;&#039; is an archive used by [[Cobra Mission]] to store all the game data.  The following .VOL files are included with the game:&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
There is no header.  The format is simply a list of offsets, repeated until the file data begins:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Data type !! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[UINT32LE]] || offset || Offset of this file, relative to start of archive file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Usually the above structure is repeated until it is 256 bytes long (with unused offsets as zero), but it can be smaller (&amp;lt;tt&amp;gt;pcm6.vol&amp;lt;/tt&amp;gt; has a 64 byte header).&lt;br /&gt;
&lt;br /&gt;
The last entry in the list is the file size, followed by zero offsets as needed to pad the list to the required length.&lt;br /&gt;
&lt;br /&gt;
{{TODO|Will the game accept files that lack this padding?}}&lt;br /&gt;
&lt;br /&gt;
== Instances ==&lt;br /&gt;
&lt;br /&gt;
=== Graphics VOL files ===&lt;br /&gt;
* CUT1.VOL&lt;br /&gt;
* CUT2.VOL&lt;br /&gt;
* CUT3.VOL&lt;br /&gt;
* CUTA.VOL&lt;br /&gt;
* ENM.VOL&lt;br /&gt;
* ENMA.VOL&lt;br /&gt;
* MAP.VOL&lt;br /&gt;
* OPENING.VOL&lt;br /&gt;
* PIC1.VOL&lt;br /&gt;
* PIC2.VOL&lt;br /&gt;
* PIC3.VOL&lt;br /&gt;
* PICA.VOL&lt;br /&gt;
&lt;br /&gt;
The listed VOL files contain the graphics for the game.&lt;br /&gt;
* OPENING.VOL contains the graphics for the intro sequence&lt;br /&gt;
* MAP.VOL contains the graphics for the inventory map items.&lt;br /&gt;
{{TODO|Below are assumptions on the other files}}&lt;br /&gt;
* CUT1 - CUTA : Cutscenes&lt;br /&gt;
* ENM - ENMA : Enemy graphics&lt;br /&gt;
* PIC1 - PICA : Inventory items (magazines and photos)&lt;br /&gt;
&lt;br /&gt;
These VOL files contain graphics chunks with the following structure&lt;br /&gt;
&lt;br /&gt;
==== GC Entry ====&lt;br /&gt;
* 00 - 01 : [[UINT16LE]] signature 47 43 &amp;quot;GC&amp;quot;&lt;br /&gt;
* 02 - 03 : [[UINT16LE]] Version 02.00&lt;br /&gt;
* 04 - 05 : [[UINT16LE]] Flag that indicates whether a palette is present.&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Points to the location of the sub-chunk table.&lt;br /&gt;
* 08 - 0B : [[UINT32LE]] Number of sub-chunks in the entry. Very often only 1, but sometimes more.&lt;br /&gt;
* 0C - 0D : [[UINT16LE]] Size of the chunk.&lt;br /&gt;
* 0E      : [[UINT8]] Padding (always 0)&lt;br /&gt;
* 0F      : [[UINT8]] Checksum; add up all the bytes from 00 to 0E and place the 2&#039;s complement of that sum here. To check, add all bytes from 00 to 0F and the result of that should be 0.&lt;br /&gt;
&lt;br /&gt;
If the palette bit is set in the header, a palette will follow. &lt;br /&gt;
* 10 - 2F : The colors are stored as an array[16] of [[UINT16LE]]. See MED.VOL for example code on how to read the palette.&lt;br /&gt;
&lt;br /&gt;
After the palette there&#039;s a subchunk table with N+1 values, where N is the number of subchunks. Each chunk runs from offset[X] to offset[X+1]. For a single chunk file, this has two values.&lt;br /&gt;
* (10 or 30) - xx : Offset pointers in the chunk stored as [[UINT32LE]]. The amount is indicated by the number of sub-chunks, plus one.&lt;br /&gt;
&lt;br /&gt;
===== GC data chunks =====&lt;br /&gt;
The GC data chunks have their own 10-byte header. Preliminary documentation below (not validated yet!):&lt;br /&gt;
* 00 : [[UINT8]] Always 0xA4&lt;br /&gt;
* 01 : [[UINT8]] Probably a checksum.&lt;br /&gt;
* 02 : [[UINT8]] X offset to display at&lt;br /&gt;
* 03 : [[UINT8]] Y offset to display at&lt;br /&gt;
* 04 : [[UINT8]] Width of contained image&lt;br /&gt;
* 05 : [[UINT8]] Height of contained image&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Subchunk size.&lt;br /&gt;
* 08 - 09 : [[UINT16LE]] Always 0?&lt;br /&gt;
&lt;br /&gt;
In the game the art looks like it contains a lot of dithering and the graphics chunks look like they are storing this in a clever way.&lt;br /&gt;
&lt;br /&gt;
The data is stored compressed in a style that looks like LZ77 (implicit reference table building) mixed with LZ78 (explicit table building) and Huffman coding. It is a very messy format; it is very easy to get a detail in the implementation wrong.&lt;br /&gt;
&lt;br /&gt;
For the decoder we will need two intermediate buffers for decoding, one called the &amp;quot;bit buffer&amp;quot; of 16 bits, and one called the &amp;quot;nibble buffer&amp;quot; of two 4-bit nibbles. We also need a third 1024-byte buffer to hold up to 256 4-byte samples, to be referenced.&lt;br /&gt;
&lt;br /&gt;
To start, the decoder loads the bit buffer with 16 bits. Every time the last bit is removed from the bit buffer, it loads the next two bytes in the input stream as a 16-bit big endian number into the bit buffer. Bits are removed from the high end one at a time, and are removed until a Huffman code is matched.&lt;br /&gt;
&lt;br /&gt;
The game uses the following Huffman table:&lt;br /&gt;
&lt;br /&gt;
===== Huffman table =====&lt;br /&gt;
* 00 : Copy from back&lt;br /&gt;
* 01 : Copy with Skip Table&lt;br /&gt;
* 10 : Skip single output&lt;br /&gt;
* 110 : Copy and store&lt;br /&gt;
* 1110 : Copy with Move Table&lt;br /&gt;
* 1111 : Copy from backing store&lt;br /&gt;
&lt;br /&gt;
The one simple command in this table is &amp;quot;Skip single output&amp;quot; - it moves the output pointer 4 bytes ahead not changing the output bytes.&lt;br /&gt;
&lt;br /&gt;
===== Nibble buffer =====&lt;br /&gt;
The nibble buffer is loaded when a value is attempted to be read but the table is empty. This differs from the bit buffer which is eagerly loaded. After loading a byte, the low nibble is returned first, and the second time it&#039;s called the high nibble is returned.&lt;br /&gt;
&lt;br /&gt;
===== Backing store =====&lt;br /&gt;
The backing store holds up to 256 entries of 4 bytes each. The table starts empty, and entries are placed from the start with an automatically increasing storage ID - the first one goes in slot 0, the second in slot 1 and so on. They are copied from the backing store a full entry at a time.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy and store&amp;quot; command takes 4 bytes from the input stream and copies them into the next entry in the backing store, and also copies them to the output buffer.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy from backing store&amp;quot; command takes a single byte from the input stream, and copies that entry from the backing store into the output buffer.&lt;br /&gt;
&lt;br /&gt;
===== Copy from back =====&lt;br /&gt;
Most of the game&#039;s graphics refer to output previously generated. It can refer back to the previous line written or to the earlier bits in this line. The copy from back command takes a nibble of data from the nibble buffer to find out what operation to do. All three of these use the same offset lookup table: { -1, -2, -4, -8, 1, 0 }. It splits the values into three regions:&lt;br /&gt;
&lt;br /&gt;
* Below 4: It copies a single entry from the output buffer to the output buffer. It gets the offset from the offset lookup table.&lt;br /&gt;
* Between 4 and 9: It loads a nibble to find out how many entries to copy. It will copy the loaded nibble count plus two, and it uses the offset table as the previous (with the original value minus 4). If the offset resolves to 0, it effectively just skips this many entries in the output buffer.&lt;br /&gt;
* 10 and above: It sets the number of entries to copy to the remaining entries in the line. It also uses the offset to find where to copy from, and again if the offset is 0 it just skips to the end.&lt;br /&gt;
&lt;br /&gt;
===== Copy Skip =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads yet another nibble, and ... ??&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies a single value from bp-1A ?&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it skips ahead a byte in the output.&lt;br /&gt;
&lt;br /&gt;
===== Copy Move =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to copy, increased by 17. The top two bits (shifted right by 6) are used as an index into the offset table mentioned above to find the offset from where to copy.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies multiple values from bp-1A ?&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it copies the equivalent byte from the previous output word.&lt;br /&gt;
&lt;br /&gt;
===== Converting the output data from planar =====&lt;br /&gt;
Each &amp;quot;entry&amp;quot; of 4 bytes covers 8 pixels, where each of the bytes contains a single bit for every pixel. As example, let&#039;s take 00 01 03 07 as example inputs:&lt;br /&gt;
&lt;br /&gt;
* 0000 0111 (byte 4)  &lt;br /&gt;
* 0000 0011 (byte 3)  &lt;br /&gt;
* 0000 0001 (byte 2)  &lt;br /&gt;
* 0000 0000 (byte 1)  &lt;br /&gt;
* ----------  &lt;br /&gt;
* 0000 08CE&lt;br /&gt;
&lt;br /&gt;
[[DecodingExample]]&lt;br /&gt;
&lt;br /&gt;
=== EMI.VOL ===&lt;br /&gt;
&lt;br /&gt;
EMI.VOL contains the music for the game, it has 41 chunks of data. The first chunk is exactly 4096 bytes and contains the instruments.&lt;br /&gt;
&lt;br /&gt;
==== Instrument Bank ====&lt;br /&gt;
There are 128 instruments in the chunk and each instrument is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
* Bytes 0 - 7 of each instrument look like FM parameters. {{TODO|Figure out which parameter does what}}&lt;br /&gt;
* Bytes 8 - 9 contain low numbers numbers from 0 - 3. {{TODO|Figure out if these are modulator and carrier wave parameters}}&lt;br /&gt;
* Bytes 10 - 11 contain numbers between 0 and 16. {{TODO|Figure out what these parameters mean}}&lt;br /&gt;
* Bytes 12 - 15 are all zeroes.&lt;br /&gt;
* Byte 16 increments from  0 - 31, after that it decrements from 255 to 160. Changing this seems to change the instrument type. It looks like the first 32 instruments are percussion.&lt;br /&gt;
* Byte 17 contains a number from 0 - 255. {{TODO|Figure out what this byte does.}}&lt;br /&gt;
* Bytes 18 - 23 contain zeroes.&lt;br /&gt;
* Byte 24 - 31 contains a lot of data, but changing this to all zeroes seemingly does not change the music in-game.&lt;br /&gt;
&lt;br /&gt;
The 40 remaining chunks all have the EM header.&lt;br /&gt;
&lt;br /&gt;
==== EM Entry ====&lt;br /&gt;
* 00 - 03 : signature 45 4D 00 06&lt;br /&gt;
* 04 - 05 : Unknown, most of the times 00 00, but values such as 00 03 are also present.{{TODO|Version?}}&lt;br /&gt;
* 06 - 07 : [[UINT16LE]], Start index of title, most of the times 1C 00&lt;br /&gt;
* 08 - 09 : [[UINT16LE]], Offset in the EM chunk where the actual data starts&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], Always the same as the previous [[UINT16LE]]. (Pointing to data offset)&lt;br /&gt;
* 0C - 0D : [[UINT16LE]], The size of the EM chunk&lt;br /&gt;
* 0E - 0F : Unknown, could be initial tempo or volume or something similar. {{TODO|Figure out what this is}}&lt;br /&gt;
&lt;br /&gt;
After this 6 [[UINT16LE]] follow, that indicate the offset in the chunk where data is found for each channel.&lt;br /&gt;
&lt;br /&gt;
6 channels are supported and if there is no data for the channel, the value is 0.&lt;br /&gt;
&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], Index of track 1 in chunk, usually the same as the [[UINT16LE]] from 08-09 and 0A-0B.&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], Index of track 2 in chunk&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], Index of track 3 in chunk&lt;br /&gt;
* 16 - 17 : [[UINT16LE]], Index of track 4 in chunk&lt;br /&gt;
* 18 - 19 : [[UINT16LE]], Index of track 5 in chunk&lt;br /&gt;
* 1A - 1B : [[UINT16LE]], Index of track 6 in chunk&lt;br /&gt;
* 1C : Start of title, if there is no title, the value at this location is FF, otherwise it&#039;s FE. &lt;br /&gt;
&lt;br /&gt;
If there is a title, a zero-terminated string follows, it contains japanese characters and at the end a date when it was converted.&lt;br /&gt;
Finally, it ends with FF.&lt;br /&gt;
&lt;br /&gt;
==== Pattern data ====&lt;br /&gt;
{{TODO|Highly experimental reverse-engineering, https://github.com/BlackStar-EoP/cobra-mission-writer/tree/master/emidump is an attempt to convert these to S3M}}&lt;br /&gt;
&lt;br /&gt;
So far, it seems the pattern data has&lt;br /&gt;
* 2 byte control commands&lt;br /&gt;
* 1 byte control commands&lt;br /&gt;
* 1 byte speed commands&lt;br /&gt;
* note commands&lt;br /&gt;
{{TODO|Check if there are more types, such as 3 or 3 byte commands}}&lt;br /&gt;
&lt;br /&gt;
===== 2 byte control commands =====&lt;br /&gt;
* 0xE4: Unknown&lt;br /&gt;
* 0xE7: Unknown&lt;br /&gt;
* 0xE8: Unknown&lt;br /&gt;
* 0xFB: Unknown&lt;br /&gt;
* 0xFD: Select instrument, byte after this indicates the index of the instrument from the instrument bank.&lt;br /&gt;
* 0xF7: Unknown&lt;br /&gt;
* 0xFA: Unknown&lt;br /&gt;
* 0xFC: Unknown&lt;br /&gt;
&lt;br /&gt;
===== 1 byte control commands ===== &lt;br /&gt;
* 0xCD: Unknown&lt;br /&gt;
* 0xCF: Unknown&lt;br /&gt;
* 0xDC: Unknown&lt;br /&gt;
* 0xDD: Unknown&lt;br /&gt;
* 0xCE: Unknown&lt;br /&gt;
* 0xF8: {{TODO|Loop command?}}&lt;br /&gt;
&lt;br /&gt;
===== 1 byte speed commands =====&lt;br /&gt;
These commands look like a delay command of some sort&lt;br /&gt;
{{TODO|It seems these commands can do more than just have a delay for a note, looks like they can delay for a couple of notes and then return to another speed.}}&lt;br /&gt;
* 0x81: row delay = 2&lt;br /&gt;
* 0x82: row delay = 4&lt;br /&gt;
* 0x83: row delay = 8&lt;br /&gt;
* 0x84: row delay = 16&lt;br /&gt;
* 0x85: row delay = 32&lt;br /&gt;
* 0x86: row delay = 64&lt;br /&gt;
* 0x89: row delay = 12&lt;br /&gt;
* 0x90: row delay = 6&lt;br /&gt;
* 0x8B: row delay = 48&lt;br /&gt;
* 0x8E: row delay = 3&lt;br /&gt;
&lt;br /&gt;
===== 1 byte note commands =====&lt;br /&gt;
The note commands range from 0x00 to 0x7F, where 0x00 is a C, 0x01 is a C-# and so on.&lt;br /&gt;
It seems that 0x00 is used as a dummy note, it does not get played, but increases the delay.&lt;br /&gt;
&lt;br /&gt;
=== MCG.VOL ===&lt;br /&gt;
&lt;br /&gt;
MCG.VOL contains the tilesets for the game. It contains 14 chunks of tile data.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Chunk nr!!Tileset&lt;br /&gt;
|-&lt;br /&gt;
|0||Character sprites&lt;br /&gt;
|-&lt;br /&gt;
|1||Weapon sprites&lt;br /&gt;
|-&lt;br /&gt;
|2||CASTLE tileset&lt;br /&gt;
|-&lt;br /&gt;
|3||AREA1 tileset&lt;br /&gt;
|-&lt;br /&gt;
|4||AREA2 tileset&lt;br /&gt;
|-&lt;br /&gt;
|5||AREA3 tileset&lt;br /&gt;
|-&lt;br /&gt;
|6||AREA4 tileset&lt;br /&gt;
|-&lt;br /&gt;
|7||AREA5 tileset&lt;br /&gt;
|-&lt;br /&gt;
|8||HOUSE tileset&lt;br /&gt;
|-&lt;br /&gt;
|9||BAR tileset&lt;br /&gt;
|-&lt;br /&gt;
|10||CORP tileset&lt;br /&gt;
|-&lt;br /&gt;
|11||BRICK tileset&lt;br /&gt;
|-&lt;br /&gt;
|12||LAB tileset&lt;br /&gt;
|-&lt;br /&gt;
|13||SEASIDE tileset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The header for this file is 64 bytes and contains the offsets for each tileset.&lt;br /&gt;
The tilesets consist of a number of tiles, all are 32x32 pixels, each pixel stored as a byte, making each sprite 1024 bytes.&lt;br /&gt;
&lt;br /&gt;
The palette for the tilesets is found inside each entry inside MED.VOL.&lt;br /&gt;
The colors are stored as an array[16] of [[UINT16LE]].&lt;br /&gt;
For example white is stored as F0FF, this will be read as 0x0FFF, and here the components are 0GRB.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
byte r = (value &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
byte g = value &amp;gt;&amp;gt; 8;&lt;br /&gt;
byte b = value &amp;amp; 0x0F;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will result in values from 0 to 15. Getting the actual color requires 2 shifts, one left of 4 and added to that one right of 2.&lt;br /&gt;
&lt;br /&gt;
Reading all palette entries would look something like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Color parse_color(uint16_t col)&lt;br /&gt;
{&lt;br /&gt;
	byte r = (col &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
	byte g = col &amp;gt;&amp;gt; 8;&lt;br /&gt;
	byte b = col &amp;amp; 0x0F;&lt;br /&gt;
	return Color((r &amp;lt;&amp;lt; 4) + (r &amp;gt;&amp;gt; 2), (g &amp;lt;&amp;lt; 4) + (g &amp;gt;&amp;gt; 2), (b &amp;lt;&amp;lt; 4) + (b &amp;gt;&amp;gt; 2));&lt;br /&gt;
}&lt;br /&gt;
void parse_palette()&lt;br /&gt;
{&lt;br /&gt;
	int pal = 0;&lt;br /&gt;
	for (int i = 32; i &amp;lt; 64; i += 2)&lt;br /&gt;
	{&lt;br /&gt;
		uint16_t color = (m_data[i + 1] &amp;lt;&amp;lt; 8) | m_data[i];&lt;br /&gt;
		m_palette[pal++] = parse_color(color);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MED.VOL ===&lt;br /&gt;
MED.VOL contains all the levels for the game. It contains 54 chunks of map data.&lt;br /&gt;
&lt;br /&gt;
==== MD Entry ====&lt;br /&gt;
Each MD entry inside MED.VOL consists of 5 blocks. The header (96 bytes), a block of unknown data (variable size), the tiledata for all the floors(dependent on size and number of floors), the triggers for all floors (same as the floor sizes, but with most entries 0) and a footer of 256 bytes.&lt;br /&gt;
===== MD Header =====&lt;br /&gt;
* 0 - 6 : signature 4D 44 03 30 02 02 14&lt;br /&gt;
* 7 - 9 : Unknown, most of the times 77 60 00, but values 9F 60 00, FF 60 00 and 8B 60 00 are also found in a few maps&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], the offset inside this MD chunk where the actual map data starts&lt;br /&gt;
* 0C - 0F : [[UINT32LE]], the size of this MD chunk&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], the width (in tiles) of this map&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], the height (in tiles) of this map&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], the number of floors in this map&lt;br /&gt;
* 16 - 1F : Character array, refers to the used tileset (values can be CASTLE, AREA1, AREA2 etc. See MCG.VOL), rest zeroes&lt;br /&gt;
* 20 - 3F : Palette data, 16 colors, each color stored as [[UINT16LE]], colors are stored as 4 bit nibbles.&lt;br /&gt;
* 40 - 5F : Character array, contains 2 names for the map, or for HOUSE types, the area that is referred. A long and a short version seperated by a pipe character.&lt;br /&gt;
&lt;br /&gt;
===== Unknown data block =====&lt;br /&gt;
Unknown data block, usually ranging from 0060 to 0420. The data inside looks the same for all the MD chunks. It looks like a lot of 16 bit integers.&lt;br /&gt;
&lt;br /&gt;
===== Tile data block =====&lt;br /&gt;
The size of the block is width * height * number of floors.&lt;br /&gt;
Each byte corresponds to the tile number in the used tileset.&lt;br /&gt;
The floors are stored sequentially.&lt;br /&gt;
&lt;br /&gt;
===== Triggers block =====&lt;br /&gt;
The same layout as the tile data block, but now most bytes are 00 and the bytes that are not are triggers such as item pickups, stairs, doors etc. &lt;br /&gt;
Unknown what the numbers mean, but exits are usually 0x20, item pickups range in 0x40 and character sprites are usually 0xC0 and higher.&lt;br /&gt;
&lt;br /&gt;
===== Footer =====&lt;br /&gt;
At the end of each MD chunk there are 256 bytes, unknown what the data represents, but it looks like it is related to the trigger block.&lt;br /&gt;
&lt;br /&gt;
=== PCM1.VOL - PCM6.VOL ===&lt;br /&gt;
These files contain PCM data in the form of the [[VOC_Format|Creative Voice Format]]&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
This file format was reverse-engineered by [[User:BlackStar|BlackStar]]. If you find this information helpful in a project you&#039;re working on, please give credit where credit is due.  (A link back to this wiki would be nice too!)&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11024</id>
		<title>MegaTech VOL Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=11024"/>
		<updated>2023-05-08T18:34:10Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = Unlimited&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = No&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Cobra Mission}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;MegaTech VOL Format&#039;&#039;&#039; is an archive used by [[Cobra Mission]] to store all the game data.  The following .VOL files are included with the game:&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
There is no header.  The format is simply a list of offsets, repeated until the file data begins:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Data type !! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[UINT32LE]] || offset || Offset of this file, relative to start of archive file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Usually the above structure is repeated until it is 256 bytes long (with unused offsets as zero), but it can be smaller (&amp;lt;tt&amp;gt;pcm6.vol&amp;lt;/tt&amp;gt; has a 64 byte header).&lt;br /&gt;
&lt;br /&gt;
The last entry in the list is the file size, followed by zero offsets as needed to pad the list to the required length.&lt;br /&gt;
&lt;br /&gt;
{{TODO|Will the game accept files that lack this padding?}}&lt;br /&gt;
&lt;br /&gt;
== Instances ==&lt;br /&gt;
&lt;br /&gt;
=== Graphics VOL files ===&lt;br /&gt;
* CUT1.VOL&lt;br /&gt;
* CUT2.VOL&lt;br /&gt;
* CUT3.VOL&lt;br /&gt;
* CUTA.VOL&lt;br /&gt;
* ENM.VOL&lt;br /&gt;
* ENMA.VOL&lt;br /&gt;
* MAP.VOL&lt;br /&gt;
* OPENING.VOL&lt;br /&gt;
* PIC1.VOL&lt;br /&gt;
* PIC2.VOL&lt;br /&gt;
* PIC3.VOL&lt;br /&gt;
* PICA.VOL&lt;br /&gt;
&lt;br /&gt;
The listed VOL files contain the graphics for the game.&lt;br /&gt;
* OPENING.VOL contains the graphics for the intro sequence&lt;br /&gt;
* MAP.VOL contains the graphics for the inventory map items.&lt;br /&gt;
{{TODO|Below are assumptions on the other files}}&lt;br /&gt;
* CUT1 - CUTA : Cutscenes&lt;br /&gt;
* ENM - ENMA : Enemy graphics&lt;br /&gt;
* PIC1 - PICA : Inventory items (magazines and photos)&lt;br /&gt;
&lt;br /&gt;
These VOL files contain graphics chunks with the following structure&lt;br /&gt;
&lt;br /&gt;
==== GC Entry ====&lt;br /&gt;
* 00 - 01 : [[UINT16LE]] signature 47 43 &amp;quot;GC&amp;quot;&lt;br /&gt;
* 02 - 03 : [[UINT16LE]] Version 02.00&lt;br /&gt;
* 04 - 05 : [[UINT16LE]] Flag that indicates whether a palette is present.&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Points to the location of the sub-chunk table.&lt;br /&gt;
* 08 - 0B : [[UINT32LE]] Number of sub-chunks in the entry. Very often only 1, but sometimes more.&lt;br /&gt;
* 0C - 0D : [[UINT16LE]] Size of the chunk.&lt;br /&gt;
* 0E      : [[UINT8]] Padding (always 0)&lt;br /&gt;
* 0F      : [[UINT8]] Checksum; add up all the bytes from 00 to 0E and place the 2&#039;s complement of that sum here. To check, add all bytes from 00 to 0F and the result of that should be 0.&lt;br /&gt;
&lt;br /&gt;
If the palette bit is set in the header, a palette will follow. &lt;br /&gt;
* 10 - 2F : The colors are stored as an array[16] of [[UINT16LE]]. See MED.VOL for example code on how to read the palette.&lt;br /&gt;
&lt;br /&gt;
After the palette there&#039;s a subchunk table with N+1 values, where N is the number of subchunks. Each chunk runs from offset[X] to offset[X+1]. For a single chunk file, this has two values.&lt;br /&gt;
* (10 or 30) - xx : Offset pointers in the chunk stored as [[UINT32LE]]. The amount is indicated by the number of sub-chunks, plus one.&lt;br /&gt;
&lt;br /&gt;
===== GC data chunks =====&lt;br /&gt;
The GC data chunks have their own 10-byte header. Preliminary documentation below (not validated yet!):&lt;br /&gt;
* 00 : [[UINT8]] Always 0xA4&lt;br /&gt;
* 01 : [[UINT8]] Probably a checksum.&lt;br /&gt;
* 02 : [[UINT8]] X offset to display at&lt;br /&gt;
* 03 : [[UINT8]] Y offset to display at&lt;br /&gt;
* 04 : [[UINT8]] Width of contained image&lt;br /&gt;
* 05 : [[UINT8]] Height of contained image&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Subchunk size.&lt;br /&gt;
* 08 - 09 : [[UINT16LE]] Always 0?&lt;br /&gt;
&lt;br /&gt;
In the game the art looks like it contains a lot of dithering and the graphics chunks look like they are storing this in a clever way.&lt;br /&gt;
&lt;br /&gt;
The data is stored compressed in a style that looks like LZ77 (implicit reference table building) mixed with LZ78 (explicit table building) and Huffman coding. It is a very messy format; it is very easy to get a detail in the implementation wrong.&lt;br /&gt;
&lt;br /&gt;
For the decoder we will need two intermediate buffers for decoding, one called the &amp;quot;bit buffer&amp;quot; of 16 bits, and one called the &amp;quot;nibble buffer&amp;quot; of two 4-bit nibbles. We also need a third 1024-byte buffer to hold up to 256 4-byte samples, to be referenced.&lt;br /&gt;
&lt;br /&gt;
To start, the decoder loads the bit buffer with 16 bits. Every time the last bit is removed from the bit buffer, it loads the next two bytes in the input stream as a 16-bit big endian number into the bit buffer. Bits are removed from the high end one at a time, and are removed until a Huffman code is matched.&lt;br /&gt;
&lt;br /&gt;
The game uses the following Huffman table:&lt;br /&gt;
&lt;br /&gt;
===== Huffman table =====&lt;br /&gt;
* 00 : Copy from back&lt;br /&gt;
* 01 : Copy with Skip Table&lt;br /&gt;
* 10 : Skip single output&lt;br /&gt;
* 110 : Copy and store&lt;br /&gt;
* 1110 : Copy with Move Table&lt;br /&gt;
* 1111 : Copy from backing store&lt;br /&gt;
&lt;br /&gt;
The one simple command in this table is &amp;quot;Skip single output&amp;quot; - it moves the output pointer 4 bytes ahead not changing the output bytes.&lt;br /&gt;
&lt;br /&gt;
===== Nibble buffer =====&lt;br /&gt;
The nibble buffer is loaded when a value is attempted to be read but the table is empty. This differs from the bit buffer which is eagerly loaded. After loading a byte, the low nibble is returned first, and the second time it&#039;s called the high nibble is returned.&lt;br /&gt;
&lt;br /&gt;
===== Backing store =====&lt;br /&gt;
The backing store holds up to 256 entries of 4 bytes each. The table starts empty, and entries are placed from the start with an automatically increasing storage ID - the first one goes in slot 0, the second in slot 1 and so on. They are copied from the backing store a full entry at a time.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy and store&amp;quot; command takes 4 bytes from the input stream and copies them into the next entry in the backing store, and also copies them to the output buffer.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Copy from backing store&amp;quot; command takes a single byte from the input stream, and copies that entry from the backing store into the output buffer.&lt;br /&gt;
&lt;br /&gt;
===== Copy from back =====&lt;br /&gt;
Most of the game&#039;s graphics refer to output previously generated. It can refer back to the previous line written or to the earlier bits in this line. The copy from back command takes a nibble of data from the nibble buffer to find out what operation to do. All three of these use the same offset lookup table: { -1, -2, -4, -8, 1, 0 }. It splits the values into three regions:&lt;br /&gt;
&lt;br /&gt;
* Below 4: It copies a single entry from the output buffer to the output buffer. It gets the offset from the offset lookup table.&lt;br /&gt;
* Between 4 and 9: It loads a nibble to find out how many entries to copy. It will copy the loaded nibble count plus two, and it uses the offset table as the previous (with the original value minus 4). If the offset resolves to 0, it effectively just skips this many entries in the output buffer.&lt;br /&gt;
* 10 and above: It sets the number of entries to copy to the remaining entries in the line. It also uses the offset to find where to copy from, and again if the offset is 0 it just skips to the end.&lt;br /&gt;
&lt;br /&gt;
===== Copy Skip =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads yet another nibble, and ... ??&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies a single value from bp-1A ?&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it skips ahead a byte in the output.&lt;br /&gt;
&lt;br /&gt;
===== Copy Move =====&lt;br /&gt;
&lt;br /&gt;
This command loads an additional nibble of data V to determine what exactly to do.&lt;br /&gt;
&lt;br /&gt;
If V is 0, it reads a whole byte of input X. It uses the bottom 6 bits to determine how many entries to copy, increased by 17. The top two bits (shifted right by 6) are used as an index into the offset table mentioned above to find the offset from where to copy.&lt;br /&gt;
&lt;br /&gt;
If V is 15, it copies multiple values from bp-1A ?&lt;br /&gt;
&lt;br /&gt;
For other values of V, it treats it as a bitfield starting from the right. For each set bit, it copies a byte from the input to the output, and for each clear bit it copies the equivalent byte from the previous output word.&lt;br /&gt;
&lt;br /&gt;
===== Converting the output data from planar =====&lt;br /&gt;
Each &amp;quot;entry&amp;quot; of 4 bytes covers 8 pixels, where each of the bytes contains a single bit for every pixel. As example, let&#039;s take 00 01 03 07 as example inputs:&lt;br /&gt;
&lt;br /&gt;
* 0000 0111 (byte 4)  &lt;br /&gt;
* 0000 0011 (byte 3)  &lt;br /&gt;
* 0000 0001 (byte 2)  &lt;br /&gt;
* 0000 0000 (byte 1)  &lt;br /&gt;
* ----------  &lt;br /&gt;
* 0000 08CE&lt;br /&gt;
&lt;br /&gt;
=== EMI.VOL ===&lt;br /&gt;
&lt;br /&gt;
EMI.VOL contains the music for the game, it has 41 chunks of data. The first chunk is exactly 4096 bytes and contains the instruments.&lt;br /&gt;
&lt;br /&gt;
==== Instrument Bank ====&lt;br /&gt;
There are 128 instruments in the chunk and each instrument is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
* Bytes 0 - 7 of each instrument look like FM parameters. {{TODO|Figure out which parameter does what}}&lt;br /&gt;
* Bytes 8 - 9 contain low numbers numbers from 0 - 3. {{TODO|Figure out if these are modulator and carrier wave parameters}}&lt;br /&gt;
* Bytes 10 - 11 contain numbers between 0 and 16. {{TODO|Figure out what these parameters mean}}&lt;br /&gt;
* Bytes 12 - 15 are all zeroes.&lt;br /&gt;
* Byte 16 increments from  0 - 31, after that it decrements from 255 to 160. Changing this seems to change the instrument type. It looks like the first 32 instruments are percussion.&lt;br /&gt;
* Byte 17 contains a number from 0 - 255. {{TODO|Figure out what this byte does.}}&lt;br /&gt;
* Bytes 18 - 23 contain zeroes.&lt;br /&gt;
* Byte 24 - 31 contains a lot of data, but changing this to all zeroes seemingly does not change the music in-game.&lt;br /&gt;
&lt;br /&gt;
The 40 remaining chunks all have the EM header.&lt;br /&gt;
&lt;br /&gt;
==== EM Entry ====&lt;br /&gt;
* 00 - 03 : signature 45 4D 00 06&lt;br /&gt;
* 04 - 05 : Unknown, most of the times 00 00, but values such as 00 03 are also present.{{TODO|Version?}}&lt;br /&gt;
* 06 - 07 : [[UINT16LE]], Start index of title, most of the times 1C 00&lt;br /&gt;
* 08 - 09 : [[UINT16LE]], Offset in the EM chunk where the actual data starts&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], Always the same as the previous [[UINT16LE]]. (Pointing to data offset)&lt;br /&gt;
* 0C - 0D : [[UINT16LE]], The size of the EM chunk&lt;br /&gt;
* 0E - 0F : Unknown, could be initial tempo or volume or something similar. {{TODO|Figure out what this is}}&lt;br /&gt;
&lt;br /&gt;
After this 6 [[UINT16LE]] follow, that indicate the offset in the chunk where data is found for each channel.&lt;br /&gt;
&lt;br /&gt;
6 channels are supported and if there is no data for the channel, the value is 0.&lt;br /&gt;
&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], Index of track 1 in chunk, usually the same as the [[UINT16LE]] from 08-09 and 0A-0B.&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], Index of track 2 in chunk&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], Index of track 3 in chunk&lt;br /&gt;
* 16 - 17 : [[UINT16LE]], Index of track 4 in chunk&lt;br /&gt;
* 18 - 19 : [[UINT16LE]], Index of track 5 in chunk&lt;br /&gt;
* 1A - 1B : [[UINT16LE]], Index of track 6 in chunk&lt;br /&gt;
* 1C : Start of title, if there is no title, the value at this location is FF, otherwise it&#039;s FE. &lt;br /&gt;
&lt;br /&gt;
If there is a title, a zero-terminated string follows, it contains japanese characters and at the end a date when it was converted.&lt;br /&gt;
Finally, it ends with FF.&lt;br /&gt;
&lt;br /&gt;
==== Pattern data ====&lt;br /&gt;
{{TODO|Highly experimental reverse-engineering, https://github.com/BlackStar-EoP/cobra-mission-writer/tree/master/emidump is an attempt to convert these to S3M}}&lt;br /&gt;
&lt;br /&gt;
So far, it seems the pattern data has&lt;br /&gt;
* 2 byte control commands&lt;br /&gt;
* 1 byte control commands&lt;br /&gt;
* 1 byte speed commands&lt;br /&gt;
* note commands&lt;br /&gt;
{{TODO|Check if there are more types, such as 3 or 3 byte commands}}&lt;br /&gt;
&lt;br /&gt;
===== 2 byte control commands =====&lt;br /&gt;
* 0xE4: Unknown&lt;br /&gt;
* 0xE7: Unknown&lt;br /&gt;
* 0xE8: Unknown&lt;br /&gt;
* 0xFB: Unknown&lt;br /&gt;
* 0xFD: Select instrument, byte after this indicates the index of the instrument from the instrument bank.&lt;br /&gt;
* 0xF7: Unknown&lt;br /&gt;
* 0xFA: Unknown&lt;br /&gt;
* 0xFC: Unknown&lt;br /&gt;
&lt;br /&gt;
===== 1 byte control commands ===== &lt;br /&gt;
* 0xCD: Unknown&lt;br /&gt;
* 0xCF: Unknown&lt;br /&gt;
* 0xDC: Unknown&lt;br /&gt;
* 0xDD: Unknown&lt;br /&gt;
* 0xCE: Unknown&lt;br /&gt;
* 0xF8: {{TODO|Loop command?}}&lt;br /&gt;
&lt;br /&gt;
===== 1 byte speed commands =====&lt;br /&gt;
These commands look like a delay command of some sort&lt;br /&gt;
{{TODO|It seems these commands can do more than just have a delay for a note, looks like they can delay for a couple of notes and then return to another speed.}}&lt;br /&gt;
* 0x81: row delay = 2&lt;br /&gt;
* 0x82: row delay = 4&lt;br /&gt;
* 0x83: row delay = 8&lt;br /&gt;
* 0x84: row delay = 16&lt;br /&gt;
* 0x85: row delay = 32&lt;br /&gt;
* 0x86: row delay = 64&lt;br /&gt;
* 0x89: row delay = 12&lt;br /&gt;
* 0x90: row delay = 6&lt;br /&gt;
* 0x8B: row delay = 48&lt;br /&gt;
* 0x8E: row delay = 3&lt;br /&gt;
&lt;br /&gt;
===== 1 byte note commands =====&lt;br /&gt;
The note commands range from 0x00 to 0x7F, where 0x00 is a C, 0x01 is a C-# and so on.&lt;br /&gt;
It seems that 0x00 is used as a dummy note, it does not get played, but increases the delay.&lt;br /&gt;
&lt;br /&gt;
=== MCG.VOL ===&lt;br /&gt;
&lt;br /&gt;
MCG.VOL contains the tilesets for the game. It contains 14 chunks of tile data.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Chunk nr!!Tileset&lt;br /&gt;
|-&lt;br /&gt;
|0||Character sprites&lt;br /&gt;
|-&lt;br /&gt;
|1||Weapon sprites&lt;br /&gt;
|-&lt;br /&gt;
|2||CASTLE tileset&lt;br /&gt;
|-&lt;br /&gt;
|3||AREA1 tileset&lt;br /&gt;
|-&lt;br /&gt;
|4||AREA2 tileset&lt;br /&gt;
|-&lt;br /&gt;
|5||AREA3 tileset&lt;br /&gt;
|-&lt;br /&gt;
|6||AREA4 tileset&lt;br /&gt;
|-&lt;br /&gt;
|7||AREA5 tileset&lt;br /&gt;
|-&lt;br /&gt;
|8||HOUSE tileset&lt;br /&gt;
|-&lt;br /&gt;
|9||BAR tileset&lt;br /&gt;
|-&lt;br /&gt;
|10||CORP tileset&lt;br /&gt;
|-&lt;br /&gt;
|11||BRICK tileset&lt;br /&gt;
|-&lt;br /&gt;
|12||LAB tileset&lt;br /&gt;
|-&lt;br /&gt;
|13||SEASIDE tileset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The header for this file is 64 bytes and contains the offsets for each tileset.&lt;br /&gt;
The tilesets consist of a number of tiles, all are 32x32 pixels, each pixel stored as a byte, making each sprite 1024 bytes.&lt;br /&gt;
&lt;br /&gt;
The palette for the tilesets is found inside each entry inside MED.VOL.&lt;br /&gt;
The colors are stored as an array[16] of [[UINT16LE]].&lt;br /&gt;
For example white is stored as F0FF, this will be read as 0x0FFF, and here the components are 0GRB.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
byte r = (value &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
byte g = value &amp;gt;&amp;gt; 8;&lt;br /&gt;
byte b = value &amp;amp; 0x0F;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will result in values from 0 to 15. Getting the actual color requires 2 shifts, one left of 4 and added to that one right of 2.&lt;br /&gt;
&lt;br /&gt;
Reading all palette entries would look something like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Color parse_color(uint16_t col)&lt;br /&gt;
{&lt;br /&gt;
	byte r = (col &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
	byte g = col &amp;gt;&amp;gt; 8;&lt;br /&gt;
	byte b = col &amp;amp; 0x0F;&lt;br /&gt;
	return Color((r &amp;lt;&amp;lt; 4) + (r &amp;gt;&amp;gt; 2), (g &amp;lt;&amp;lt; 4) + (g &amp;gt;&amp;gt; 2), (b &amp;lt;&amp;lt; 4) + (b &amp;gt;&amp;gt; 2));&lt;br /&gt;
}&lt;br /&gt;
void parse_palette()&lt;br /&gt;
{&lt;br /&gt;
	int pal = 0;&lt;br /&gt;
	for (int i = 32; i &amp;lt; 64; i += 2)&lt;br /&gt;
	{&lt;br /&gt;
		uint16_t color = (m_data[i + 1] &amp;lt;&amp;lt; 8) | m_data[i];&lt;br /&gt;
		m_palette[pal++] = parse_color(color);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MED.VOL ===&lt;br /&gt;
MED.VOL contains all the levels for the game. It contains 54 chunks of map data.&lt;br /&gt;
&lt;br /&gt;
==== MD Entry ====&lt;br /&gt;
Each MD entry inside MED.VOL consists of 5 blocks. The header (96 bytes), a block of unknown data (variable size), the tiledata for all the floors(dependent on size and number of floors), the triggers for all floors (same as the floor sizes, but with most entries 0) and a footer of 256 bytes.&lt;br /&gt;
===== MD Header =====&lt;br /&gt;
* 0 - 6 : signature 4D 44 03 30 02 02 14&lt;br /&gt;
* 7 - 9 : Unknown, most of the times 77 60 00, but values 9F 60 00, FF 60 00 and 8B 60 00 are also found in a few maps&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], the offset inside this MD chunk where the actual map data starts&lt;br /&gt;
* 0C - 0F : [[UINT32LE]], the size of this MD chunk&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], the width (in tiles) of this map&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], the height (in tiles) of this map&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], the number of floors in this map&lt;br /&gt;
* 16 - 1F : Character array, refers to the used tileset (values can be CASTLE, AREA1, AREA2 etc. See MCG.VOL), rest zeroes&lt;br /&gt;
* 20 - 3F : Palette data, 16 colors, each color stored as [[UINT16LE]], colors are stored as 4 bit nibbles.&lt;br /&gt;
* 40 - 5F : Character array, contains 2 names for the map, or for HOUSE types, the area that is referred. A long and a short version seperated by a pipe character.&lt;br /&gt;
&lt;br /&gt;
===== Unknown data block =====&lt;br /&gt;
Unknown data block, usually ranging from 0060 to 0420. The data inside looks the same for all the MD chunks. It looks like a lot of 16 bit integers.&lt;br /&gt;
&lt;br /&gt;
===== Tile data block =====&lt;br /&gt;
The size of the block is width * height * number of floors.&lt;br /&gt;
Each byte corresponds to the tile number in the used tileset.&lt;br /&gt;
The floors are stored sequentially.&lt;br /&gt;
&lt;br /&gt;
===== Triggers block =====&lt;br /&gt;
The same layout as the tile data block, but now most bytes are 00 and the bytes that are not are triggers such as item pickups, stairs, doors etc. &lt;br /&gt;
Unknown what the numbers mean, but exits are usually 0x20, item pickups range in 0x40 and character sprites are usually 0xC0 and higher.&lt;br /&gt;
&lt;br /&gt;
===== Footer =====&lt;br /&gt;
At the end of each MD chunk there are 256 bytes, unknown what the data represents, but it looks like it is related to the trigger block.&lt;br /&gt;
&lt;br /&gt;
=== PCM1.VOL - PCM6.VOL ===&lt;br /&gt;
These files contain PCM data in the form of the [[VOC_Format|Creative Voice Format]]&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
This file format was reverse-engineered by [[User:BlackStar|BlackStar]]. If you find this information helpful in a project you&#039;re working on, please give credit where credit is due.  (A link back to this wiki would be nice too!)&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
	<entry>
		<id>https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=8269</id>
		<title>MegaTech VOL Format</title>
		<link rel="alternate" type="text/html" href="https://moddingwiki.shikadi.net/w/index.php?title=MegaTech_VOL_Format&amp;diff=8269"/>
		<updated>2018-11-19T13:08:28Z</updated>

		<summary type="html">&lt;p&gt;Dascandy: Updated GC header &amp;amp; added GC data header info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Archive Infobox&lt;br /&gt;
 | MaxFiles = Unlimited&lt;br /&gt;
 | FAT = Beginning&lt;br /&gt;
 | Names = No&lt;br /&gt;
 | Metadata = None&lt;br /&gt;
 | Subdirectories = N&lt;br /&gt;
 | Compressed = N&lt;br /&gt;
 | Encrypted = N&lt;br /&gt;
 | Hidden = N&lt;br /&gt;
 | Games = &lt;br /&gt;
   {{Game|Cobra Mission}}&lt;br /&gt;
}}&lt;br /&gt;
The &#039;&#039;&#039;MegaTech VOL Format&#039;&#039;&#039; is an archive used by [[Cobra Mission]] to store all the game data.  The following .VOL files are included with the game:&lt;br /&gt;
&lt;br /&gt;
== File format ==&lt;br /&gt;
&lt;br /&gt;
There is no header.  The format is simply a list of offsets, repeated until the file data begins:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Data type !! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[UINT32LE]] || offset || Offset of this file, relative to start of archive file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Usually the above structure is repeated until it is 256 bytes long (with unused offsets as zero), but it can be smaller (&amp;lt;tt&amp;gt;pcm6.vol&amp;lt;/tt&amp;gt; has a 64 byte header).&lt;br /&gt;
&lt;br /&gt;
The last entry in the list is the file size, followed by zero offsets as needed to pad the list to the required length.&lt;br /&gt;
&lt;br /&gt;
{{TODO|Will the game accept files that lack this padding?}}&lt;br /&gt;
&lt;br /&gt;
== Instances ==&lt;br /&gt;
&lt;br /&gt;
=== Graphics VOL files ===&lt;br /&gt;
* CUT1.VOL&lt;br /&gt;
* CUT2.VOL&lt;br /&gt;
* CUT3.VOL&lt;br /&gt;
* CUTA.VOL&lt;br /&gt;
* ENM.VOL&lt;br /&gt;
* ENMA.VOL&lt;br /&gt;
* MAP.VOL&lt;br /&gt;
* OPENING.VOL&lt;br /&gt;
* PIC1.VOL&lt;br /&gt;
* PIC2.VOL&lt;br /&gt;
* PIC3.VOL&lt;br /&gt;
* PICA.VOL&lt;br /&gt;
&lt;br /&gt;
The listed VOL files contain the graphics for the game.&lt;br /&gt;
* OPENING.VOL contains the graphics for the intro sequence&lt;br /&gt;
* MAP.VOL contains the graphics for the inventory map items.&lt;br /&gt;
{{TODO|Below are assumptions on the other files}}&lt;br /&gt;
* CUT1 - CUTA : Cutscenes&lt;br /&gt;
* ENM - ENMA : Enemy graphics&lt;br /&gt;
* PIC1 - PICA : Inventory items (magazines and photos)&lt;br /&gt;
&lt;br /&gt;
These VOL files contain graphics chunks with the following structure&lt;br /&gt;
&lt;br /&gt;
==== GC Entry ====&lt;br /&gt;
* 00 - 01 : [[UINT16LE]] signature 47 43 &amp;quot;GC&amp;quot;&lt;br /&gt;
* 02 - 03 : [[UINT16LE]] Version 02.00&lt;br /&gt;
* 04 - 05 : [[UINT16LE]] Flag that indicates whether a palette is present.&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Points to the location of the sub-chunk table.&lt;br /&gt;
* 08 - 0B : [[UINT32LE]] Number of sub-chunks in the entry. Very often only 1, but sometimes more.&lt;br /&gt;
* 0C - 0D : [[UINT16LE]] Size of the chunk.&lt;br /&gt;
* 0E      : [[UINT8]] Padding (always 0)&lt;br /&gt;
* 0F      : [[UINT8]] Checksum; add up all the bytes from 00 to 0E and place the 2&#039;s complement of that sum here. To check, add all bytes from 00 to 0F and the result of that should be 0.&lt;br /&gt;
&lt;br /&gt;
If the palette bit is set in the header, a palette will follow. &lt;br /&gt;
* 10 - 2F : The colors are stored as an array[16] of [[UINT16LE]]. See MED.VOL for example code on how to read the palette.&lt;br /&gt;
&lt;br /&gt;
After the palette there&#039;s a subchunk table with N+1 values, where N is the number of subchunks. Each chunk runs from offset[X] to offset[X+1]. For a single chunk file, this has two values.&lt;br /&gt;
* (10 or 30) - xx : Offset pointers in the chunk stored as [[UINT32LE]]. The amount is indicated by the number of sub-chunks, plus one.&lt;br /&gt;
&lt;br /&gt;
===== GC data chunks =====&lt;br /&gt;
The GC data chunks have their own 10-byte header. Preliminary documentation below (not validated yet!):&lt;br /&gt;
* 00 : [[UINT8]] Always 0xA4&lt;br /&gt;
* 01 : [[UINT8]] Probably a checksum.&lt;br /&gt;
* 02 : [[UINT8]] X offset to display at&lt;br /&gt;
* 03 : [[UINT8]] Y offset to display at&lt;br /&gt;
* 04 : [[UINT8]] Width of contained image&lt;br /&gt;
* 05 : [[UINT8]] Height of contained image&lt;br /&gt;
* 06 - 07 : [[UINT16LE]] Subchunk size.&lt;br /&gt;
* 08 - 09 : [[UINT16LE]] Always 0?&lt;br /&gt;
&lt;br /&gt;
In the game the art looks like it contains a lot of dithering and the graphics chunks look like they are storing this in a clever way.&lt;br /&gt;
&lt;br /&gt;
The data format is not clear, but tinkering with values has given some information on how the pixel data is stored.&lt;br /&gt;
&lt;br /&gt;
It seems that pixel data is stored as rows of 8 pixels, and somehow the format gives the following information to these rows:&lt;br /&gt;
* Palette values for each pixel in the row&lt;br /&gt;
* Dithering pattern for the row&lt;br /&gt;
* Possibly locations where these rows should be placed&lt;br /&gt;
&lt;br /&gt;
Tinkering with entry number 3 inside PIC3.VOL gave some information on how this format is working. (This is the second Girl&#039;s Photo in inventory)&lt;br /&gt;
&lt;br /&gt;
Shortly after the header the following pattern is found 01 01 01 01. Changing this to FF FF FF FF will make an 8 pixel white line appear in multiple parts of the image.&lt;br /&gt;
&lt;br /&gt;
Originally the pixel data is 7 black pixels and then one white. The palette has entry 0 = black, entry 15 is white and entry 14 is yellow&lt;br /&gt;
&lt;br /&gt;
changing it to 00 01 01 01 changes the rightmost white pixel to yellow.&lt;br /&gt;
&lt;br /&gt;
These blocks work in the following way:&lt;br /&gt;
&lt;br /&gt;
* 00000001&lt;br /&gt;
* 00000001&lt;br /&gt;
* 00000001&lt;br /&gt;
* 00000001&lt;br /&gt;
Makes the rightmost pixel white and the others black&lt;br /&gt;
&lt;br /&gt;
* 00000000&lt;br /&gt;
* 00000001&lt;br /&gt;
* 00000001&lt;br /&gt;
* 00000001&lt;br /&gt;
Makes the rightmost pixel yellow and the others black.&lt;br /&gt;
&lt;br /&gt;
The 4 byte row contains palette entries for each pixel, each bit represents one pixel, and the bit being on and off determines the final palette entry from 0 - 15.&lt;br /&gt;
&lt;br /&gt;
=== EMI.VOL ===&lt;br /&gt;
&lt;br /&gt;
EMI.VOL contains the music for the game, it has 41 chunks of data. The first chunk is exactly 4096 bytes and contains the instruments.&lt;br /&gt;
&lt;br /&gt;
==== Instrument Bank ====&lt;br /&gt;
There are 128 instruments in the chunk and each instrument is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
* Bytes 0 - 7 of each instrument look like FM parameters. {{TODO|Figure out which parameter does what}}&lt;br /&gt;
* Bytes 8 - 9 contain low numbers numbers from 0 - 3. {{TODO|Figure out if these are modulator and carrier wave parameters}}&lt;br /&gt;
* Bytes 10 - 11 contain numbers between 0 and 16. {{TODO|Figure out what these parameters mean}}&lt;br /&gt;
* Bytes 12 - 15 are all zeroes.&lt;br /&gt;
* Byte 16 increments from  0 - 31, after that it decrements from 255 to 160. Changing this seems to change the instrument type. It looks like the first 32 instruments are percussion.&lt;br /&gt;
* Byte 17 contains a number from 0 - 255. {{TODO|Figure out what this byte does.}}&lt;br /&gt;
* Bytes 18 - 23 contain zeroes.&lt;br /&gt;
* Byte 24 - 31 contains a lot of data, but changing this to all zeroes seemingly does not change the music in-game.&lt;br /&gt;
&lt;br /&gt;
The 40 remaining chunks all have the EM header.&lt;br /&gt;
&lt;br /&gt;
==== EM Entry ====&lt;br /&gt;
* 00 - 03 : signature 45 4D 00 06&lt;br /&gt;
* 04 - 05 : Unknown, most of the times 00 00, but values such as 00 03 are also present.{{TODO|Version?}}&lt;br /&gt;
* 06 - 07 : [[UINT16LE]], Start index of title, most of the times 1C 00&lt;br /&gt;
* 08 - 09 : [[UINT16LE]], Offset in the EM chunk where the actual data starts&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], Always the same as the previous [[UINT16LE]]. (Pointing to data offset)&lt;br /&gt;
* 0C - 0D : [[UINT16LE]], The size of the EM chunk&lt;br /&gt;
* 0E - 0F : Unknown, could be initial tempo or volume or something similar. {{TODO|Figure out what this is}}&lt;br /&gt;
&lt;br /&gt;
After this 6 [[UINT16LE]] follow, that indicate the offset in the chunk where data is found for each channel.&lt;br /&gt;
&lt;br /&gt;
6 channels are supported and if there is no data for the channel, the value is 0.&lt;br /&gt;
&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], Index of track 1 in chunk, usually the same as the [[UINT16LE]] from 08-09 and 0A-0B.&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], Index of track 2 in chunk&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], Index of track 3 in chunk&lt;br /&gt;
* 16 - 17 : [[UINT16LE]], Index of track 4 in chunk&lt;br /&gt;
* 18 - 19 : [[UINT16LE]], Index of track 5 in chunk&lt;br /&gt;
* 1A - 1B : [[UINT16LE]], Index of track 6 in chunk&lt;br /&gt;
* 1C : Start of title, if there is no title, the value at this location is FF, otherwise it&#039;s FE. &lt;br /&gt;
&lt;br /&gt;
If there is a title, a zero-terminated string follows, it contains japanese characters and at the end a date when it was converted.&lt;br /&gt;
Finally, it ends with FF.&lt;br /&gt;
&lt;br /&gt;
==== Pattern data ====&lt;br /&gt;
{{TODO|Highly experimental reverse-engineering, https://github.com/BlackStar-EoP/cobra-mission-writer/tree/master/emidump is an attempt to convert these to S3M}}&lt;br /&gt;
&lt;br /&gt;
So far, it seems the pattern data has&lt;br /&gt;
* 2 byte control commands&lt;br /&gt;
* 1 byte control commands&lt;br /&gt;
* 1 byte speed commands&lt;br /&gt;
* note commands&lt;br /&gt;
{{TODO|Check if there are more types, such as 3 or 3 byte commands}}&lt;br /&gt;
&lt;br /&gt;
===== 2 byte control commands =====&lt;br /&gt;
* 0xE4: Unknown&lt;br /&gt;
* 0xE7: Unknown&lt;br /&gt;
* 0xE8: Unknown&lt;br /&gt;
* 0xFB: Unknown&lt;br /&gt;
* 0xFD: Select instrument, byte after this indicates the index of the instrument from the instrument bank.&lt;br /&gt;
* 0xF7: Unknown&lt;br /&gt;
* 0xFA: Unknown&lt;br /&gt;
* 0xFC: Unknown&lt;br /&gt;
&lt;br /&gt;
===== 1 byte control commands ===== &lt;br /&gt;
* 0xCD: Unknown&lt;br /&gt;
* 0xCF: Unknown&lt;br /&gt;
* 0xDC: Unknown&lt;br /&gt;
* 0xDD: Unknown&lt;br /&gt;
* 0xCE: Unknown&lt;br /&gt;
* 0xF8: {{TODO|Loop command?}}&lt;br /&gt;
&lt;br /&gt;
===== 1 byte speed commands =====&lt;br /&gt;
These commands look like a delay command of some sort&lt;br /&gt;
{{TODO|It seems these commands can do more than just have a delay for a note, looks like they can delay for a couple of notes and then return to another speed.}}&lt;br /&gt;
* 0x81: row delay = 2&lt;br /&gt;
* 0x82: row delay = 4&lt;br /&gt;
* 0x83: row delay = 8&lt;br /&gt;
* 0x84: row delay = 16&lt;br /&gt;
* 0x85: row delay = 32&lt;br /&gt;
* 0x86: row delay = 64&lt;br /&gt;
* 0x89: row delay = 12&lt;br /&gt;
* 0x90: row delay = 6&lt;br /&gt;
* 0x8B: row delay = 48&lt;br /&gt;
* 0x8E: row delay = 3&lt;br /&gt;
&lt;br /&gt;
===== 1 byte note commands =====&lt;br /&gt;
The note commands range from 0x00 to 0x7F, where 0x00 is a C, 0x01 is a C-# and so on.&lt;br /&gt;
It seems that 0x00 is used as a dummy note, it does not get played, but increases the delay.&lt;br /&gt;
&lt;br /&gt;
=== MCG.VOL ===&lt;br /&gt;
&lt;br /&gt;
MCG.VOL contains the tilesets for the game. It contains 14 chunks of tile data.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Chunk nr!!Tileset&lt;br /&gt;
|-&lt;br /&gt;
|0||Character sprites&lt;br /&gt;
|-&lt;br /&gt;
|1||Weapon sprites&lt;br /&gt;
|-&lt;br /&gt;
|2||CASTLE tileset&lt;br /&gt;
|-&lt;br /&gt;
|3||AREA1 tileset&lt;br /&gt;
|-&lt;br /&gt;
|4||AREA2 tileset&lt;br /&gt;
|-&lt;br /&gt;
|5||AREA3 tileset&lt;br /&gt;
|-&lt;br /&gt;
|6||AREA4 tileset&lt;br /&gt;
|-&lt;br /&gt;
|7||AREA5 tileset&lt;br /&gt;
|-&lt;br /&gt;
|8||HOUSE tileset&lt;br /&gt;
|-&lt;br /&gt;
|9||BAR tileset&lt;br /&gt;
|-&lt;br /&gt;
|10||CORP tileset&lt;br /&gt;
|-&lt;br /&gt;
|11||BRICK tileset&lt;br /&gt;
|-&lt;br /&gt;
|12||LAB tileset&lt;br /&gt;
|-&lt;br /&gt;
|13||SEASIDE tileset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The header for this file is 64 bytes and contains the offsets for each tileset.&lt;br /&gt;
The tilesets consist of a number of tiles, all are 32x32 pixels, each pixel stored as a byte, making each sprite 1024 bytes.&lt;br /&gt;
&lt;br /&gt;
The palette for the tilesets is found inside each entry inside MED.VOL.&lt;br /&gt;
The colors are stored as an array[16] of [[UINT16LE]].&lt;br /&gt;
For example white is stored as F0FF, this will be read as 0x0FFF, and here the components are 0GRB.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
byte r = (value &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
byte g = value &amp;gt;&amp;gt; 8;&lt;br /&gt;
byte b = value &amp;amp; 0x0F;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This will result in values from 0 to 15. Getting the actual color requires 2 shifts, one left of 4 and added to that one right of 2.&lt;br /&gt;
&lt;br /&gt;
Reading all palette entries would look something like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Color parse_color(uint16_t col)&lt;br /&gt;
{&lt;br /&gt;
	byte r = (col &amp;gt;&amp;gt; 4) &amp;amp; 0x0F;&lt;br /&gt;
	byte g = col &amp;gt;&amp;gt; 8;&lt;br /&gt;
	byte b = col &amp;amp; 0x0F;&lt;br /&gt;
	return Color((r &amp;lt;&amp;lt; 4) + (r &amp;gt;&amp;gt; 2), (g &amp;lt;&amp;lt; 4) + (g &amp;gt;&amp;gt; 2), (b &amp;lt;&amp;lt; 4) + (b &amp;gt;&amp;gt; 2));&lt;br /&gt;
}&lt;br /&gt;
void parse_palette()&lt;br /&gt;
{&lt;br /&gt;
	int pal = 0;&lt;br /&gt;
	for (int i = 32; i &amp;lt; 64; i += 2)&lt;br /&gt;
	{&lt;br /&gt;
		uint16_t color = (m_data[i + 1] &amp;lt;&amp;lt; 8) | m_data[i];&lt;br /&gt;
		m_palette[pal++] = parse_color(color);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MED.VOL ===&lt;br /&gt;
MED.VOL contains all the levels for the game. It contains 54 chunks of map data.&lt;br /&gt;
&lt;br /&gt;
==== MD Entry ====&lt;br /&gt;
Each MD entry inside MED.VOL consists of 5 blocks. The header (96 bytes), a block of unknown data (variable size), the tiledata for all the floors(dependent on size and number of floors), the triggers for all floors (same as the floor sizes, but with most entries 0) and a footer of 256 bytes.&lt;br /&gt;
===== MD Header =====&lt;br /&gt;
* 0 - 6 : signature 4D 44 03 30 02 02 14&lt;br /&gt;
* 7 - 9 : Unknown, most of the times 77 60 00, but values 9F 60 00, FF 60 00 and 8B 60 00 are also found in a few maps&lt;br /&gt;
* 0A - 0B : [[UINT16LE]], the offset inside this MD chunk where the actual map data starts&lt;br /&gt;
* 0C - 0F : [[UINT32LE]], the size of this MD chunk&lt;br /&gt;
* 10 - 11 : [[UINT16LE]], the width (in tiles) of this map&lt;br /&gt;
* 12 - 13 : [[UINT16LE]], the height (in tiles) of this map&lt;br /&gt;
* 14 - 15 : [[UINT16LE]], the number of floors in this map&lt;br /&gt;
* 16 - 1F : Character array, refers to the used tileset (values can be CASTLE, AREA1, AREA2 etc. See MCG.VOL), rest zeroes&lt;br /&gt;
* 20 - 3F : Palette data, 16 colors, each color stored as [[UINT16LE]], colors are stored as 4 bit nibbles.&lt;br /&gt;
* 40 - 5F : Character array, contains 2 names for the map, or for HOUSE types, the area that is referred. A long and a short version seperated by a pipe character.&lt;br /&gt;
&lt;br /&gt;
===== Unknown data block =====&lt;br /&gt;
Unknown data block, usually ranging from 0060 to 0420. The data inside looks the same for all the MD chunks. It looks like a lot of 16 bit integers.&lt;br /&gt;
&lt;br /&gt;
===== Tile data block =====&lt;br /&gt;
The size of the block is width * height * number of floors.&lt;br /&gt;
Each byte corresponds to the tile number in the used tileset.&lt;br /&gt;
The floors are stored sequentially.&lt;br /&gt;
&lt;br /&gt;
===== Triggers block =====&lt;br /&gt;
The same layout as the tile data block, but now most bytes are 00 and the bytes that are not are triggers such as item pickups, stairs, doors etc. &lt;br /&gt;
Unknown what the numbers mean, but exits are usually 0x20, item pickups range in 0x40 and character sprites are usually 0xC0 and higher.&lt;br /&gt;
&lt;br /&gt;
===== Footer =====&lt;br /&gt;
At the end of each MD chunk there are 256 bytes, unknown what the data represents, but it looks like it is related to the trigger block.&lt;br /&gt;
&lt;br /&gt;
=== PCM1.VOL - PCM6.VOL ===&lt;br /&gt;
These files contain PCM data in the form of the [[VOC_Format|Creative Voice Format]]&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
This file format was reverse-engineered by [[User:BlackStar|BlackStar]]. If you find this information helpful in a project you&#039;re working on, please give credit where credit is due.  (A link back to this wiki would be nice too!)&lt;/div&gt;</summary>
		<author><name>Dascandy</name></author>
	</entry>
</feed>