Ejemplo n.º 1
0
        public static IEnumerable <double> Pack(string infilePath, string outfilePath)
        {
            var file = new GamFile {
                Infile = File.ReadAllBytes(infilePath)
            };

            foreach (var i in Pack(file))
            {
                yield return(i);
            }
            File.WriteAllBytes(outfilePath, file.Outfile);
        }
Ejemplo n.º 2
0
        private static IEnumerable <double> Pack(GamFile file)
        {
            var stream = new MemoryStream();

            // Write GAM header and file size.
            var header = AsciiEncoding.GetBytes("GAM\0");

            stream.WriteAll(header);
            var size = file.Infile.Length;

            stream.WriteAll(LittleEndianBitConverter.GetBytes(size));

            // Loop over file and compress it.
            var read            = 0;
            var bitmask         = new List <int>();
            var bitmaskPosition = -1;

            while (read < size)
            {
                yield return((float)read / size * 100);

                if (bitmask.Count == 0)
                {
                    // Create 2-byte placeholder for bitmask, remember its position.
                    bitmaskPosition = (int)stream.Tell();
                    stream.WriteAll(0, 0);
                }


                // Find best position in buffer to copy from, if such position exists.
                var(bestPosition, bestLength) = Find(file.Infile, read);

                if (bestPosition != null)
                {
                    // Position found: write position and length to output.
                    var seek = (byte)(read - bestPosition.Value);
                    stream.WriteAll(seek, bestLength);
                    read += bestLength;
                    bitmask.Add(1);
                }
                else
                {
                    // Can't copy from buffer, copy one byte from input to output.
                    stream.WriteAll(file.Infile[read]);
                    read += 1;
                    bitmask.Add(0);
                }

                if (bitmask.Count == 16 || read >= size)
                {
                    // Bitmask is full: update placeholder for bitmask.
                    bitmask.Reverse();
                    var bitmaskShort = (short)bitmask.Aggregate((b, acc) => acc * 2 + b);
                    stream.Seek(bitmaskPosition, SeekOrigin.Begin);
                    stream.WriteAll(LittleEndianBitConverter.GetBytes(bitmaskShort));
                    stream.Seek(0, SeekOrigin.End);
                    bitmask.Clear();
                }
            }

            file.Outfile = stream.ToArray();
            stream.Close();
            yield return(100.0);
        }