Example #1
0
        /// <summary>
        /// Parse the VDX to locate individual chunks
        /// </summary>
        private void parseVDX(GJD.RLData? rlData)
        {
            long stop;
            // Final stream position
            if (rlData.HasValue)
            {
                stop = rlData.Value.offset + rlData.Value.length;
            }
            else
            {
                stop = file.BaseStream.Length;
            }
            VDXHeader header = new VDXHeader();
            VDXChunkHeader chunk = new VDXChunkHeader();

            // Initialise queue's
            audioOffsets = new Queue<long>();
            videoOffsets = new Queue<long>();

            // Read VDX header
            header.ID = file.ReadUInt16();
            if (header.ID != 0x9267)
                throw new Exception("Invalid VDX header");

            header.Unknown1 = file.ReadByte();
            header.Unknown2 = file.ReadByte();
            header.Unknown3 = file.ReadByte();
            header.Unknown4 = file.ReadByte();
            header.FPS = file.ReadUInt16();

            //fps = (byte)header.FPS;
            try
            {
                while (file.BaseStream.Position < stop)
                {
                    // Read VDX chunk header
                    chunk = readChunkHeader();

                    // Add offsets where appropriate
                    switch (chunk.BlockType)
                    {
                        case VDXBlockType.Video:
                            videoFrames++;
                            goto case VDXBlockType.Zero;
                        case VDXBlockType.Zero:
                            videoMaster.Enqueue(file.BaseStream.Position - VDXChunkHeader.size);
                            break;
                        case VDXBlockType.Sound:
                            audioOffsets.Enqueue(file.BaseStream.Position - VDXChunkHeader.size);
                            break;
                        case VDXBlockType.Image:
                            imageOffset = file.BaseStream.Position - VDXChunkHeader.size;
                            break;
                    }

                    // Seek to next chunk
                    file.BaseStream.Seek(chunk.DataSize, System.IO.SeekOrigin.Current);
                }
            } catch {
                audio = null;
                videoFrames = 1;

            }
        }
Example #2
0
        /* The LZSS algorithm - http://wiki.xentax.com/index.php/LZSS
         *
         *   Compression
         *       Set up parameters
         *           N           Circular buffer size
         *           F           Length window size
         *           Threshold   Minimum compression size (minimum length for a match)
         *           BufPos      Initial buffer position.  Generally N - F
         *           BufVoid     Initial fill byte.
         *
         *       To compress
         *           Try to find longest sequence that is also in buffer
         *               If length >= Threshold, save offset and length in output file.  record literal to buffer
         *               If no match, copy literal byte to output and repeat
         *
         *           To record if compression or literal copy made, set special flag byte,
         *
         *
         *   Decompression
         *       Done in reverse order.  Parameters need to be known.
         *       Pseudo:
         *
         *           while InputPos < InputSize do
         *           begin
         *
         *               FlagByte := Input[InputPos++]
         *               for i := 1 to 8 do
         *               begin
         *
         *                  if (FlagByte and 1) = 0 then
         *                  begin
         *
         *                       OfsLen := Input[InputPos] + Input[InputPos + 1] shl 8
         *                       InputPos += 2
         *                       if OfsLen = 0 then
         *                           Exit;
         *
         *                       Length := OfsLen and LengthMask + Threshold
         *                       Offset := (BufPos - (OfsLen shr LengthBits)) and (N - 1)
         *                       copy Length bytes from Buffer[Offset] onwards
         *                       while increasing BufPos
         *
         *                   end
         *                   else
         *                   begin
         *
         *                       copy 1 byte from Input[InputPos]
         *                       InputPos += 1
         *
         *                  end
         *                  FlagByte := FlagByte shr 1
         *
         *               end
         *           end
         *
         *       Length bits descibes number of bits to find F.  Above assumes length of buffer reference
         *           in lower bit of the word.  lenght mask = (1 << lenbits) - 1
         *
         *       also assumed buffer offset relative to current write position.  if absolute, BufPos subtraction unneeded
         *
         *       Buffer is circular.  wrap offset.
         *
         *       mirror output writes to history buffer
         *
         *       in most cases, data from history buffer will be byte-wise.
         */
        private void decompress(System.IO.BinaryReader inStream, ref VDXChunkHeader header, out System.IO.MemoryStream stream)
        {
            stream = new System.IO.MemoryStream();

            uint i, j, N, F, initwrite;
            byte flagbyte, tempa;
            uint offsetlen, length, offset, bufpos;
            byte[] hisbuff;

            N = (uint)(1 << (16 - header.LengthBits));  // History buffer size
            hisbuff = new byte[N];              // History buffer
            F = (uint)(1 << header.LengthBits);         // Window size
            initwrite = N - F;                  // Initial history write pos
            bufpos = 0;

            for (i = 0; i < N; i++)
                hisbuff[i] = 0;                 // Init history buffer

            long final = header.DataSize + inStream.BaseStream.Position;
            while (inStream.BaseStream.Position < final)
            {
                flagbyte = inStream.ReadByte();
                for (i = 1; i <= 8; i++)
                {
                    if (inStream.BaseStream.Position < final)
                    {
                        if ((flagbyte & 1) == 0)
                        {
                            offsetlen = inStream.ReadUInt16();
                            if (offsetlen == 0)
                                break;

                            length = (offsetlen & header.LengthMask) + 3;
                            offset = (bufpos - (offsetlen >> header.LengthBits)) & (N - 1);
                            for (j = 0; j < length; j++)
                            {
                                tempa = hisbuff[(offset + j) & (N - 1)];
                                stream.WriteByte(tempa);
                                hisbuff[bufpos] = tempa;
                                bufpos = (bufpos + 1) & (N - 1);
                            }
                        }
                        else
                        {
                            tempa = inStream.ReadByte();
                            stream.WriteByte(tempa);
                            hisbuff[bufpos] = tempa;
                            bufpos = (bufpos + 1) & (N - 1);
                        }
                        flagbyte = (byte)(flagbyte >> 1);
                    }
                }
            }
        }
Example #3
0
        /// <summary>
        /// Read in the header for the current chunk
        /// </summary>
        /// <returns>Chunk header structure</returns>
        private VDXChunkHeader readChunkHeader()
        {
            VDXChunkHeader chunk = new VDXChunkHeader();

            chunk.BlockType = (VDXBlockType)file.ReadByte();
            chunk.PlayCmd = (VDXChunkPlayCmd)file.ReadByte();
            chunk.DataSize = file.ReadInt32();
            chunk.LengthMask = file.ReadByte();
            chunk.LengthBits = file.ReadByte();

            return chunk;
        }