https://wiki.multimedia.cx/api.php?hidebots=1&hidepatrolled=1&hidemyself=1&days=30&limit=50&action=feedrecentchanges&feedformat=atomMultimediaWiki - Recent changes [en]2024-03-28T16:12:41ZTrack the most recent changes to the wiki in this feed.MediaWiki 1.39.5https://wiki.multimedia.cx/index.php?title=Talisman_ANI&diff=15765&oldid=0Talisman ANI2024-03-22T14:50:32Z<p>fill format description</p>
<p><b>New page</b></p><div>* Company: Software 2000<br />
* Extension: ani<br />
* Game: [https://www.mobygames.com/game/32166/talisman/ Talisman]<br />
<br />
This is a rather peculiar video game format that uses frame data compression in addition to the frame coding.<br />
<br />
The file consists of chunks of various types, each starting with 32-bit little-endian chunk type and 32-bit payload size (compressed payload will start with an additional 32-bit unpacked size).<br />
<br />
== Known chunks ==<br />
* <code>0x1234</code> -- ANI header, should be 20 bytes long (always unpacked);<br />
* <code>0x4321</code> -- sync chunk, should be 16 bytes long (always unpacked);<br />
* <code>0x1111</code> -- Huffman codebooks data, always unpacked;<br />
* <code>0x2001</code> -- intra frame;<br />
* <code>0x2110</code> -- inter frame;<br />
* <code>0x2332</code> -- seems to always contain 32-value equal to one (obviously unpacked), probably skip frame signal;<br />
* <code>0x2553</code> -- probably the same, not encountered in game files;<br />
* <code>0x3456</code> -- unknown, might be related to audio data;<br />
* <code>0x5544</code> -- palette (unpacked), always 768 bytes;<br />
* <code>0xABCD</code> -- acknowledged by the decoder as unpacked but not encountered in game files.<br />
<br />
=== Header chunk ===<br />
The header chunk should be the first in the file, occur only once. It contains the following information:<br />
* 32-bit image width<br />
* 32-bit image height<br />
* 32-bit value that is always zero<br />
* 32-bit value that is always 300000<br />
* 32-bit number of frames<br />
<br />
=== Sync chunk ===<br />
Sync chunks mark a sequence aka group of frames (an intra frame plus some inter frames).<br />
<br />
* 32-bit offset to the next sync chunk<br />
* 32-bit value that is always zero<br />
* 32-bit value that looks like some suggested buffer size<br />
* 32-bit number of video frames until next sync chunk<br />
<br />
=== Codebooks data chunk ===<br />
This chunk contains Huffman codebook definition.<br />
<br />
First there may be a sequence of <code>0xFF</code> bytes that should be ignored.<br />
<br />
The first byte with another value tells which Huffman tree should be used for the sequence.<br />
<br />
The following data contains symbol values for the Huffman trees. It starts with an opcode telling what to do with the entries: <code>0xFF</code> means skip definition set, <code>0x00..0x7F</code> mean the next byte is the number of new symbols and the following N bytes are new symbol values, other values mean previously decoded definition with number in the low seven bits should be re-used (skipped ones included but should not be re-used).<br />
<br />
See the next section on how that data is used.<br />
<br />
=== Chunks unpacking ===<br />
Chunks are packed using order-1 static Huffman codes with some predefined tables and per-sequence symbol values (defined in chunk <code>0x1111</code>). That means when the data is decoded, it reads the same code set but the symbol value depends on the definitions transmitted in the chunk so e.g. if symbol <code>011</code> meant 0 in one sequence, it may mean 4 in another.<br />
<br />
First symbol is transmitted as is, then actual Huffman bitstream follows (packed in 16-bit words, MSB first). The first byte is transmitted as is since the symbol table is defined for the previously decoded symbol and newly decoded value from the stream. Chunk <code>0x1111</code> stores those context-dependent symbol definitions for each previously decoded value and all possible input values (i.e. first set is used when previous symbol value is 0, next set is used when previous symbol value is 1 and so on).<br />
<br />
== Video decoding ==<br />
Video frames are split into 2x2 blocks and use motion value in byte form (low nibble - X offset, high nibble - Y offset) with nibble values being signed (e.g. nibble value <code>0x3</code> means offset 3 and nibble value <code>0xD</code> means offset -3).<br />
<br />
Frame data is split into two parts, namely the motion vectors data (and run values) and pixel values. 32-bit value at the beginning tells where the pixel data starts (motion data always starts at offset 4).<br />
<br />
Codes <code>0x00..0xF6</code> copy 2x2 block using the corresponding motion vector (<code>0x00</code> - do nothing, <code>0x3D</code> - copy with 3,-3 offset).<br />
<br />
Codes <code>0xF7..0xFA</code> read a motion vector byte and a pixel byte, copy block from the specified location and replace pixel 3..0 with the new pixel value.<br />
<br />
Codes <code>0xFB..0xFD</code> read a motion vector byte and copy the source block rotated by 90/180/270 degrees counter-clockwise correspondingly.<br />
<br />
Code <code>0xFE</code> reads a run value (that may be prefixed with several <code>0xFF</code> to add 255 to its value) from motion data section and skips the signalled number of blocks.<br />
<br />
Code <code>0xFF</code> reads four pixel values for the block.<br />
<br />
Inter frame seems to be the same but uses the intra frame as the reference.<br />
<br />
[[Category:Game Formats]]<br />
[[Category:Video Codecs]]</div>Kostyahttps://wiki.multimedia.cx/index.php?title=FVF&diff=15764&oldid=15729FVF2024-03-19T15:31:02Z<p><span dir="auto"><span class="autocomment">Video frame part: </span> clarify video coding a bit</span></p>
<table style="background-color: #fff; color: #202122;" data-mw="interface">
<col class="diff-marker" />
<col class="diff-content" />
<col class="diff-marker" />
<col class="diff-content" />
<tr class="diff-title" lang="en">
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Older revision</td>
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 08:31, 19 March 2024</td>
</tr><tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l54">Line 54:</td>
<td colspan="2" class="diff-lineno">Line 54:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><br/></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><br/></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>== Video frame part ==</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>== Video frame part ==</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div>Video frame part starts with 32-bit size and two 16-bit fields (one of those is used to signal palette change, another one is for motion vector table size). Compression method seems to work by painting tiles using colour combinations generated from the palette colours. Bitstream is little-endian, low three bits signal tile opcode and it's aligned to the byte boundary before each next opcode:</div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div>Video frame part starts with 32-bit size and two 16-bit fields (one of those is used to signal palette change, another one is for motion vector table size). Compression method seems to work by painting tiles using <ins style="font-weight: bold; text-decoration: none;">RGB555 </ins>colour combinations generated from the palette colours. Bitstream is little-endian, low three bits signal tile opcode and it's aligned to the byte boundary before each next opcode:</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div>* code 0 -- get 7-bit value, get 14-bit value, <del style="font-weight: bold; text-decoration: none;">paint </del>4x4 <del style="font-weight: bold; text-decoration: none;">tile using them</del>;</div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div>* code 0 -- get 7-bit value <ins style="font-weight: bold; text-decoration: none;">for palette LUT offset</ins>, get 14-bit value <ins style="font-weight: bold; text-decoration: none;">for source data offset</ins>, <ins style="font-weight: bold; text-decoration: none;">copy </ins>4x4 <ins style="font-weight: bold; text-decoration: none;">block from the source applying palette LUT</ins>;</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div>* code 1 -- the same as above but tile is <del style="font-weight: bold; text-decoration: none;">painted </del>flipped horizontally;</div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div>* code 1 -- the same as above but tile is flipped horizontally;</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>* code 2 -- same as code 0 but tile is flipped vertically;</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>* code 2 -- same as code 0 but tile is flipped vertically;</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>* code 3 -- same as above but tile is flipped horizontally as well;</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>* code 3 -- same as above but tile is flipped horizontally as well;</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l63">Line 63:</td>
<td colspan="2" class="diff-lineno">Line 63:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>* code 6 -- skip 5 bits (to byte align) and copy 16 bytes from the input to the tile data;</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>* code 6 -- skip 5 bits (to byte align) and copy 16 bytes from the input to the tile data;</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>* code 7 -- this is large tile mode, the next 4 bits signal the operation:</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>* code 7 -- this is large tile mode, the next 4 bits signal the operation:</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div>** case 0 -- skip 1 bit, get 7-bit index, get 1-bit flag, get 14-bit index, paint 8x8 tile;</div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div>** case 0 -- skip 1 bit, get 7-bit <ins style="font-weight: bold; text-decoration: none;">palette LUT </ins>index, get 1-bit flag, get 14-bit <ins style="font-weight: bold; text-decoration: none;">source offset </ins>index, paint 8x8 tile;</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>** cases 1-7 -- same but with various flipping modes;</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>** cases 1-7 -- same but with various flipping modes;</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>** cases 8-11, 13-14 -- should not be present;</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>** cases 8-11, 13-14 -- should not be present;</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div>** case 12 -- special 4x4 tile copy run with long values;</div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div>** case 12 -- special 4x4 tile copy run with long values <ins style="font-weight: bold; text-decoration: none;">(either 8-bit run value + 32 or 16-bit run value + 288 depending on flag)</ins>;</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>** case 14 -- raw 2x2 tile.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>** case 14 -- raw 2x2 tile.</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><br/></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><br/></td></tr>
</table>Kostyahttps://wiki.multimedia.cx/index.php?title=Intelligent_Games_MOV&diff=15763&oldid=0Intelligent Games MOV2024-03-14T16:21:24Z<p>document yet another game codec</p>
<p><b>New page</b></p><div>* Company: Intelligent Games Ltd.<br />
* Extension: MOV<br />
* Game used: [https://www.mobygames.com/game/1852/azraels-tear/ Azrael's Tear]<br />
<br />
This is a rather simple container for paletted video cutscenes.<br />
<br />
The file starts with the following header (all values are little-endian):<br />
4 bytes - always 90 EF 12 AB<br />
2 bytes - total number of frames in the file<br />
2 bytes - frames per second? (in reality it seems to be 10 instead of declared 12)<br />
2 bytes - video width<br />
2 bytes - video height<br />
18 bytes - seems to be random garbage<br />
<br />
Each frame starts with 16-byte header:<br />
4 bytes - always CF 01 99 EE<br />
2 bytes - frame type? (seems to be 3 for the first frame and 2 for the following ones)<br />
4 bytes - unpacked frame size<br />
4 bytes - packed frame size (or 0 for raw frames)<br />
2 bytes - padding?<br />
<br />
Frame consists of one or more chunks:<br />
4 bytes - always DC FE 23 01<br />
2 bytes - chunk type<br />
4 bytes - chunk size<br />
6 bytes - junk<br />
<br />
Chunk types:<br />
* 1 - raw frame data<br />
* 2 and 3 - empty/skip frame<br />
* 4 - VGA palette<br />
* 5 - inter frame<br />
* 6 - audio data (8-bit PCM, 22050Hz mono)<br />
<br />
=== Frame data unpacking ===<br />
Frame data may be compressed with Huffman codes. In that case it consists of four blocks: 32-bit unpacked data size (the same as in frame header), 32-bit Huffman tree root index, Huffman tree nodes (an array of 1024 16-bit numbers), packed data.<br />
<br />
Data decoding is trivial:<br />
* set <code>index</code> to the tree root index<br />
* while <code>index</code> &ge; 256<br />
** read bit (LSB first) from packed data part<br />
** <code>index = nodes[index * 2 + bit]</code><br />
* output <code>index</code><br />
<br />
=== Inter frame compression ===<br />
Inter frames are split in 4x4 blocks and may be coded using one of four modes and modes for four tiles are packed in one byte (LSB first) e.g. modes 0, 1, 2, 3 will be transmitted as <code>0xE4</code>.<br />
<br />
* mode 0 is long motion compensation. It requires two additional bytes, first one is X coordinate displacement plus 127 (i.e. value 0 mean -127 and value 255 means +128), second one is Y coordinate displacement plus 63 in low 7 bits and the top bit is used to signal data source (not set - copy data from the previous frame, set - copy data from the current frame).<br />
* mode 1 is a skip run. Next byte in the stream tells how many blocks need to be left unchanged from the previous frame (value 0 signals 256 blocks to copy).<br />
* mode 2 is short motion compensation. Next byte contains displacement for the previous frame. Top nibble - X coordinate plus 7, low nibble - Y coordinate plus 7.<br />
* mode 3 is for raw block. Following 16 bytes are the new block contents.<br />
<br />
[[Category:Game Formats]]<br />
[[Category:Video Codecs]]</div>Kostya