예제 #1
0
        public void Deserialize(Stream input)
        {
            var version = input.ReadValueU16();

            if (version < 2 || version > 5)
            {
                throw new FormatException("unsupported cfs version");
            }

            var header = new Sprite.Header();

            if (version >= 5)
            {
                header = input.ReadStructure <Sprite.Header>();
            }
            else if (version >= 4)
            {
                var oldHeader = input.ReadStructure <Sprite.OldHeader4>();
                header.FrameCount       = oldHeader.FrameCount;
                header.AnimationTime    = oldHeader.AnimationTime;
                header.Width            = oldHeader.Width;
                header.Height           = oldHeader.Height;
                header.RowCount         = oldHeader.RowCount;
                header.ColumnCount      = oldHeader.ColumnCount;
                header.ShadowCount      = oldHeader.ShadowCount;
                header.LightCount       = oldHeader.LightCount;
                header.UserDataSize     = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex    = oldHeader.MaxSolidIndex;
                header.DataSize         = oldHeader.DataSize;
                header.Category         = oldHeader.Category;
                header.BlitMode         = oldHeader.BlitMode;
                header.RowMeaning       = oldHeader.RowMeaning;
                header.YSortAdjust      = oldHeader.YSortAdjust;
                header.SortTransform    = oldHeader.SortTransform;
                header.UserPaletteStart = oldHeader.UserPaletteStart;
                header.UserPalette      = oldHeader.UserPalette;
                header.Description      = oldHeader.Description;
            }
            else if (version >= 3)
            {
                var oldHeader = input.ReadStructure <Sprite.OldHeader3>();
                header.FrameCount       = oldHeader.FrameCount;
                header.AnimationTime    = oldHeader.AnimationTime;
                header.Width            = oldHeader.Width;
                header.Height           = oldHeader.Height;
                header.RowCount         = oldHeader.RowCount;
                header.ColumnCount      = oldHeader.ColumnCount;
                header.ShadowCount      = oldHeader.ShadowCount;
                header.LightCount       = oldHeader.LightCount;
                header.UserDataSize     = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex    = oldHeader.MaxSolidIndex;
                header.DataSize         = oldHeader.DataSize;
                header.Category         = oldHeader.Category;
                header.BlitMode         = oldHeader.BlitMode;
                header.RowMeaning       = oldHeader.RowMeaning;
                header.YSortAdjust      = oldHeader.YSortAdjust;
                header.SortTransform    = oldHeader.SortTransform;
                header.UserPaletteStart = oldHeader.UserPaletteStart;
                header.UserPalette      = oldHeader.UserPalette;
            }
            else if (version >= 1)
            {
                var oldHeader = input.ReadStructure <Sprite.OldHeader2>();
                header.FrameCount       = oldHeader.FrameCount;
                header.AnimationTime    = oldHeader.AnimationTime;
                header.Width            = oldHeader.Width;
                header.Height           = oldHeader.Height;
                header.RowCount         = oldHeader.RowCount;
                header.ColumnCount      = oldHeader.ColumnCount;
                header.ShadowCount      = oldHeader.ShadowCount;
                header.LightCount       = oldHeader.LightCount;
                header.UserDataSize     = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex    = oldHeader.MaxSolidIndex;
                header.DataSize         = oldHeader.DataSize;
            }

            if (header.LightCount != 0 &&
                header.LightCount != 32)
            {
                throw new FormatException();
            }

            if (header.ShadowCount != 0 &&
                header.ShadowCount != 8)
            {
                throw new FormatException();
            }

            this.AnimationTime    = header.AnimationTime;
            this.Width            = header.Width;
            this.Height           = header.Height;
            this.RowCount         = header.RowCount;
            this.ColumnCount      = header.ColumnCount;
            this.ShadowCount      = header.ShadowCount;
            this.LightCount       = header.LightCount;
            this.MaxSolidIndex    = header.MaxSolidIndex;
            this.CompressionFlags = header.CompressionFlags;
            this.Category         = header.Category;
            this.Description      = header.Description;

            for (int i = 0; i < this.Palette.Length; i++)
            {
                this.Palette[i] = input.ReadValueU32();
            }

            this.UserData = new byte[header.UserDataSize];
            if (input.Read(this.UserData, 0, this.UserData.Length) != this.UserData.Length)
            {
                throw new FormatException();
            }

            var infos = new Sprite.FrameInfo[header.FrameCount];

            for (int i = 0; i < infos.Length; i++)
            {
                infos[i] = input.ReadStructure <Sprite.FrameInfo>();
            }

            var compressionFlags = (uint)header.CompressionFlags;

            if ((compressionFlags & ~0x1FFu) != 0)
            {
                throw new FormatException("unknown compression flags");
            }

            if (header.Unknown20 != 0 &&
                header.Unknown20 != 3)
            {
                // WHAT DOES THIS VALUE MEAN AUGH
                throw new NotSupportedException();
            }

            if ((header.CompressionFlags &
                 Sprite.CompressionFlags.NoCompression) != 0)
            {
                if ((header.CompressionFlags &
                     ~(Sprite.CompressionFlags.NoPixels | Sprite.CompressionFlags.NoCompression)) != 0)
                {
                    throw new FormatException("other compression flags set with NoCompression flag");
                }
            }

            using (var data = input.ReadToMemoryStream(header.DataSize))
            {
                this.Frames = new Sprite.Frame[header.FrameCount];
                for (int i = 0; i < header.FrameCount; i++)
                {
                    var info = infos[i];
                    data.Seek(info.Offset, SeekOrigin.Begin);

                    var frame = this.Frames[i] = new Sprite.Frame();

                    frame.X      = info.X;
                    frame.Y      = info.Y;
                    frame.Width  = Math.Abs(info.Width);
                    frame.Height = Math.Abs(info.Height);
                    frame.Pixels = new byte[frame.Width * frame.Height];

                    if ((header.CompressionFlags &
                         Sprite.CompressionFlags.NoCompression) != 0)
                    {
                        // uncompressed data
                        data.Read(frame.Pixels, 0, frame.Pixels.Length);
                    }
                    else
                    {
                        // compressed data

                        var lengths = new int[frame.Height];
                        var max     = 0;
                        for (int y = 0; y < frame.Height; y++)
                        {
                            int length = data.ReadValueU8();
                            if (length == 0xFF)
                            {
                                length = data.ReadValueU16();
                            }
                            lengths[y] = length;
                            max        = Math.Max(max, length);
                        }

                        var scanline = new byte[max];
                        for (int y = 0, offset = 0; y < frame.Height; y++, offset = y * frame.Width)
                        {
                            var length = lengths[y];
                            if (data.Read(scanline, 0, length) != length)
                            {
                                throw new FormatException();
                            }

                            for (int x = 0; x < length;)
                            {
                                offset += (scanline[x] >> 4) & 0xF; // transparent
                                var literalCount = scanline[x] & 0xF;
                                if (literalCount > 0)
                                {
                                    Array.Copy(scanline, x + 1, frame.Pixels, offset, literalCount);
                                }
                                offset += literalCount;
                                x      += 1 + literalCount;
                            }
                        }
                    }

                    // flip horizontal
                    if (info.Width < 0)
                    {
                        for (int y = 0, offset = 0; y < frame.Height; y++, offset += frame.Width)
                        {
                            Array.Reverse(frame.Pixels, offset, frame.Width);
                        }
                    }

                    // flip vertical
                    if (info.Height < 0)
                    {
                        var scanline = new byte[frame.Height];

                        for (int x = 0; x < frame.Width; x++)
                        {
                            for (int y = 0, offset = x; y < frame.Height; y++, offset += frame.Width)
                            {
                                scanline[y] = frame.Pixels[offset];
                            }

                            for (int y = 0, offset = x; y < frame.Height; y++, offset += frame.Width)
                            {
                                frame.Pixels[offset] = scanline[frame.Height - 1 - y];
                            }
                        }
                    }
                }
            }
        }
예제 #2
0
        public void Deserialize(Stream input)
        {
            var version = input.ReadValueU16();
            if (version < 2 || version > 5)
            {
                throw new FormatException("unsupported cfs version");
            }

            var header = new Sprite.Header();

            if (version >= 5)
            {
                header = input.ReadStructure<Sprite.Header>();
            }
            else if (version >= 4)
            {
                var oldHeader = input.ReadStructure<Sprite.OldHeader4>();
                header.FrameCount = oldHeader.FrameCount;
                header.AnimationTime = oldHeader.AnimationTime;
                header.Width = oldHeader.Width;
                header.Height = oldHeader.Height;
                header.RowCount = oldHeader.RowCount;
                header.ColumnCount = oldHeader.ColumnCount;
                header.ShadowCount = oldHeader.ShadowCount;
                header.LightCount = oldHeader.LightCount;
                header.UserDataSize = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex = oldHeader.MaxSolidIndex;
                header.DataSize = oldHeader.DataSize;
                header.Category = oldHeader.Category;
                header.BlitMode = oldHeader.BlitMode;
                header.RowMeaning = oldHeader.RowMeaning;
                header.YSortAdjust = oldHeader.YSortAdjust;
                header.SortTransform = oldHeader.SortTransform;
                header.UserPaletteStart = oldHeader.UserPaletteStart;
                header.UserPalette = oldHeader.UserPalette;
                header.Description = oldHeader.Description;
            }
            else if (version >= 3)
            {
                var oldHeader = input.ReadStructure<Sprite.OldHeader3>();
                header.FrameCount = oldHeader.FrameCount;
                header.AnimationTime = oldHeader.AnimationTime;
                header.Width = oldHeader.Width;
                header.Height = oldHeader.Height;
                header.RowCount = oldHeader.RowCount;
                header.ColumnCount = oldHeader.ColumnCount;
                header.ShadowCount = oldHeader.ShadowCount;
                header.LightCount = oldHeader.LightCount;
                header.UserDataSize = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex = oldHeader.MaxSolidIndex;
                header.DataSize = oldHeader.DataSize;
                header.Category = oldHeader.Category;
                header.BlitMode = oldHeader.BlitMode;
                header.RowMeaning = oldHeader.RowMeaning;
                header.YSortAdjust = oldHeader.YSortAdjust;
                header.SortTransform = oldHeader.SortTransform;
                header.UserPaletteStart = oldHeader.UserPaletteStart;
                header.UserPalette = oldHeader.UserPalette;
            }
            else if (version >= 1)
            {
                var oldHeader = input.ReadStructure<Sprite.OldHeader2>();
                header.FrameCount = oldHeader.FrameCount;
                header.AnimationTime = oldHeader.AnimationTime;
                header.Width = oldHeader.Width;
                header.Height = oldHeader.Height;
                header.RowCount = oldHeader.RowCount;
                header.ColumnCount = oldHeader.ColumnCount;
                header.ShadowCount = oldHeader.ShadowCount;
                header.LightCount = oldHeader.LightCount;
                header.UserDataSize = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex = oldHeader.MaxSolidIndex;
                header.DataSize = oldHeader.DataSize;
            }

            if (header.LightCount != 0 &&
                header.LightCount != 32)
            {
                throw new FormatException();
            }

            if (header.ShadowCount != 0 &&
                header.ShadowCount != 8)
            {
                throw new FormatException();
            }

            this.AnimationTime = header.AnimationTime;
            this.Width = header.Width;
            this.Height = header.Height;
            this.RowCount = header.RowCount;
            this.ColumnCount = header.ColumnCount;
            this.ShadowCount = header.ShadowCount;
            this.LightCount = header.LightCount;
            this.MaxSolidIndex = header.MaxSolidIndex;
            this.CompressionFlags = header.CompressionFlags;

            for (int i = 0; i < this.Palette.Length; i++)
            {
                this.Palette[i] = input.ReadValueU32();
            }

            this.UserData = new byte[header.UserDataSize];
            if (input.Read(this.UserData, 0, this.UserData.Length) != this.UserData.Length)
            {
                throw new FormatException();
            }

            var infos = new Sprite.FrameInfo[header.FrameCount];
            for (int i = 0; i < infos.Length; i++)
            {
                infos[i] = input.ReadStructure<Sprite.FrameInfo>();
            }

            var compressionFlags = (uint)header.CompressionFlags;
            if ((compressionFlags & ~0x1FFu) != 0)
            {
                throw new FormatException("unknown compression flags");
            }

            if (header.Unknown20 != 0 &&
                header.Unknown20 != 3)
            {
                // WHAT DOES THIS VALUE MEAN AUGH
                throw new NotSupportedException();
            }

            if ((header.CompressionFlags &
                 Sprite.CompressionFlags.NoCompression) != 0)
            {
                if ((header.CompressionFlags &
                     ~(Sprite.CompressionFlags.NoPixels | Sprite.CompressionFlags.NoCompression)) != 0)
                {
                    throw new FormatException("other compression flags set with NoCompression flag");
                }
            }

            using (var data = input.ReadToMemoryStream(header.DataSize))
            {
                this.Frames = new Sprite.Frame[header.FrameCount];
                for (int i = 0; i < header.FrameCount; i++)
                {
                    var info = infos[i];
                    data.Seek(info.Offset, SeekOrigin.Begin);

                    var frame = this.Frames[i] = new Sprite.Frame();

                    frame.X = info.X;
                    frame.Y = info.Y;
                    frame.Width = Math.Abs(info.Width);
                    frame.Height = Math.Abs(info.Height);
                    frame.Pixels = new byte[frame.Width * frame.Height];

                    if ((header.CompressionFlags &
                         Sprite.CompressionFlags.NoCompression) != 0)
                    {
                        // uncompressed data
                        data.Read(frame.Pixels, 0, frame.Pixels.Length);
                    }
                    else
                    {
                        // compressed data

                        var lengths = new int[frame.Height];
                        var max = 0;
                        for (int y = 0; y < frame.Height; y++)
                        {
                            int length = data.ReadValueU8();
                            if (length == 0xFF)
                            {
                                length = data.ReadValueU16();
                            }
                            lengths[y] = length;
                            max = Math.Max(max, length);
                        }

                        var scanline = new byte[max];
                        for (int y = 0, offset = 0; y < frame.Height; y++, offset = y * frame.Width)
                        {
                            var length = lengths[y];
                            if (data.Read(scanline, 0, length) != length)
                            {
                                throw new FormatException();
                            }

                            for (int x = 0; x < length;)
                            {
                                offset += (scanline[x] >> 4) & 0xF; // transparent
                                var literalCount = scanline[x] & 0xF;
                                if (literalCount > 0)
                                {
                                    Array.Copy(scanline, x + 1, frame.Pixels, offset, literalCount);
                                }
                                offset += literalCount;
                                x += 1 + literalCount;
                            }
                        }
                    }

                    // flip horizontal
                    if (info.Width < 0)
                    {
                        for (int y = 0, offset = 0; y < frame.Height; y++, offset += frame.Width)
                        {
                            Array.Reverse(frame.Pixels, offset, frame.Width);
                        }
                    }

                    // flip vertical
                    if (info.Height < 0)
                    {
                        var scanline = new byte[frame.Height];

                        for (int x = 0; x < frame.Width; x++)
                        {
                            for (int y = 0, offset = x; y < frame.Height; y++, offset += frame.Width)
                            {
                                scanline[y] = frame.Pixels[offset];
                            }

                            for (int y = 0, offset = x; y < frame.Height; y++, offset += frame.Width)
                            {
                                frame.Pixels[offset] = scanline[frame.Height - 1 - y];
                            }
                        }
                    }
                }
            }
        }