示例#1
0
文件: Mobd.cs 项目: jkalmar/OpenKrush
        public Mobd(SegmentStream stream)
        {
            // This is damn ugly, but it seems MOBD uses offsets from lvl start.
            var fileOffset      = (uint)stream.BaseOffset;
            var firstFrameStart = stream.Length;

            var animationOffsets     = new List <uint>();
            var rotationalAnimations = new List <MobdAnimation>();
            var simpleAnimations     = new List <MobdAnimation>();

            while (stream.Position < firstFrameStart)
            {
                var value = stream.ReadInt32();

                if (value == 0 || (value - fileOffset < stream.Position && value >= fileOffset))
                {
                    stream.Position -= 4;
                    break;
                }

                animationOffsets.Add((uint)(stream.Position - 4));

                while (true)
                {
                    value = stream.ReadInt32();

                    if (value == -1 || value == 0)
                    {
                        break;
                    }

                    firstFrameStart = Math.Min(firstFrameStart, value - fileOffset);
                }
            }

            while (stream.Position < firstFrameStart)
            {
                var value = stream.ReadUInt32();

                if (value == 0)
                {
                    continue;
                }

                animationOffsets.Remove(value - fileOffset);
                var returnPosition = stream.Position;
                stream.Position = value - fileOffset;
                rotationalAnimations.Add(new MobdAnimation(stream));
                stream.Position = returnPosition;
            }

            foreach (var animationOffset in animationOffsets)
            {
                stream.Position = animationOffset;
                simpleAnimations.Add(new MobdAnimation(stream));
            }

            RotationalAnimations = rotationalAnimations.ToArray();
            SimpleAnimations     = simpleAnimations.ToArray();
        }
示例#2
0
        public override bool TryParseSprite(Stream s, string filename, out ISpriteFrame[] frames, out TypeDictionary metadata)
        {
            metadata = null;

            if (!IsDdf(s))
            {
                frames = null;
                return(false);
            }

            var aniStream = s as DdfPackageLoader.AniSegmentStream;

            aniStream.Position = aniStream.AniPosition;
            frames             = new ISpriteFrame[aniStream.ReadUInt32()];

            for (var i = 0; i < frames.Length; i++)
            {
                var metaName = aniStream.ReadASCII(32).Replace("\0", string.Empty);

                aniStream.Position += 4 * 2;
                var numScripts = aniStream.ReadUInt32();
                aniStream.Position += 32 * numScripts;
                var returnPosition = aniStream.Position;

                long metaPosition;
                if (aniStream.MetaIndex.TryGetValue(metaName, out metaPosition))
                {
                    var metaStream = new SegmentStream(aniStream, 0, aniStream.Length);
                    metaStream.Position = metaPosition;

                    var ddfName = metaStream.ReadASCII(32).Replace("\0", string.Empty);
                    metaStream.Position += 4 * 3;
                    var offset = new float2(metaStream.ReadInt32(), metaStream.ReadInt32());

                    long ddfPosition;
                    if (aniStream.DdfIndex.TryGetValue(ddfName, out ddfPosition))
                    {
                        var ddfStream = aniStream.DdfStream;
                        ddfStream.Position = ddfPosition;
                        frames[i]          = new DdfSpriteFrame(ddfStream, offset);
                    }
                }

                aniStream.Position = returnPosition;
            }

            return(true);
        }
示例#3
0
        public MobdAnimation(SegmentStream stream)
        {
            // OpenRA needs the same amount of frames per facing, filling up missing frames:
            var missingFrameWorkaround = 0;

            // Beetle => 10,10,10,8,10,10,10,10,10,10,10,10,10,10,10,10
            missingFrameWorkaround += stream.BaseStream.Position == 174278 ? 2 : 0;

            // Flame => 9,9,9,9,8,8,9,9,9,9,9,9,9,9,9,9
            missingFrameWorkaround += stream.BaseStream.Position == 2010426 || stream.BaseStream.Position == 2010466 ? 1 : 0;

            // Gort => 10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
            missingFrameWorkaround += stream.BaseStream.Position == 2094122 ? 1 : 0;

            // TODO add gen2 ones here! (Worm projectile, ...)

            // TODO this is likely the animation speed.
            //      Pattern is 0x00aabbcc
            //      0x00000010
            //      0x00aaaa2a
            //      flipping the bytes to 0xccbbaa00 makes more sence:
            //      0x10000000
            //      0x2aaaaa00
            //      Notes:
            //      0x10000000 is the most common value
            //      cc is never 00
            //      aa and bb often consist of the same value: 0000 1111 8888 aaaa ...
            /*Unk1 =*/ stream.ReadUInt32();

            var frames = new List <MobdFrame>();

            while (true)
            {
                var value = stream.ReadInt32();

                if (value == 0 || value == -1)
                {
                    break;                     // TODO 0 might mean "repeat", -1 might mean "do not repeat"
                }
                var returnPosition = stream.Position;
                stream.Position = value - stream.BaseOffset;
                var frame = new MobdFrame(stream);
                frames.Add(frame);

                if (missingFrameWorkaround-- > 0)
                {
                    frames.Add(frame);
                }

                stream.Position = returnPosition;
            }

            Frames = frames.ToArray();
        }
示例#4
0
        public Blit(SegmentStream stream)
        {
            // This is damn ugly, but it seems BLIT uses offsets from lvl start.
            var basePosition = (int)((SegmentStream)stream.BaseStream).BaseStream.Position - 8;

            Frames = new BlitFrame[stream.ReadInt32()];
            var frameOffsets = new int[Frames.Length];

            stream.ReadInt32();     // Unk
            var paletteOffset = stream.ReadInt32() - basePosition;
            var identifier    = new string(stream.ReadASCII(4).Reverse().ToArray());

            if (identifier != "BLT8")
            {
                throw new Exception("Unknwon blit type.");
            }
            for (var i = 0; i < Frames.Length; i++)
            {
                frameOffsets[i] = stream.ReadInt32() - basePosition;
            }

            stream.Position = paletteOffset;

            var palette = new byte[256 * 4];

            for (var i = 0; i < palette.Length;)
            {
                var color16 = stream.ReadUInt16();         // aRRRRRGGGGGBBBBB
                palette[i++] = (byte)(((color16 & 0x001f) << 3) & 0xff);
                palette[i++] = (byte)(((color16 & 0x03e0) >> 2) & 0xff);
                palette[i++] = (byte)(((color16 & 0x7c00) >> 7) & 0xff);
                palette[i++] = 0xff;
            }

            for (var i = 0; i < Frames.Length; i++)
            {
                stream.Position = frameOffsets[i];
                Frames[i]       = new BlitFrame(stream, palette);
            }
        }
示例#5
0
        public MobdAnimation(SegmentStream stream, Version version)
        {
            // This are actually broken / bugged files. As we can not fix the containers, we have them hardcoded here:
            var missingFrameWorkaround = 0;

            // Beetle => 10,10,10,8,10,10,10,10,10,10,10,10,10,10,10,10
            missingFrameWorkaround += stream.BaseStream.Position == 174278 ? 2 : 0;

            // Flame => 9,9,9,9,8,8,9,9,9,9,9,9,9,9,9,9
            missingFrameWorkaround += stream.BaseStream.Position == 2010426 || stream.BaseStream.Position == 2010466 ? 1 : 0;

            // Gort => 10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
            missingFrameWorkaround += stream.BaseStream.Position == 2094122 ? 1 : 0;

            // TODO add kknd2 bugged ones here! (Worm projectile, ...)

            /*Unk1 = */ stream.ReadUInt32();            // TODO this is likely the animation speed

            var frames = new List <MobdFrame>();

            while (true)
            {
                var value = stream.ReadInt32();

                if (value == 0 || value == -1)
                {
                    break;                     // TODO this is most likely repeat pattern. 1,2,3,1,2,3 or 1,2,3,2,1,2,3
                }
                var returnPosition = stream.Position;
                stream.Position = value - stream.BaseOffset;
                var frame = new MobdFrame(stream, version);
                frames.Add(frame);

                if (missingFrameWorkaround-- > 0)
                {
                    frames.Add(frame);
                }

                stream.Position = returnPosition;
            }

            Frames = frames.ToArray();

            if (version == Version.KKND2)
            {
                // KKnD 2 uses offsets only for frames they are used on instead of the whole animation.
                var points = new List <MobdPoint>();

                foreach (var frame in Frames)
                {
                    if (frame.Points == null)
                    {
                        continue;
                    }

                    foreach (var point in frame.Points)
                    {
                        if (point.Id == 0)
                        {
                            points.Add(new MobdPoint {
                                X = point.X, Y = point.Y, Z = point.Z, Id = points.Count
                            });
                        }
                    }
                }

                foreach (var frame in Frames)
                {
                    frame.Points = points.ToArray();
                }
            }
        }
示例#6
0
文件: Mapd.cs 项目: jkalmar/OpenKrush
        public Mapd(SegmentStream stream)
        {
            // This is damn ugly, but it seems MAPD uses offsets from lvl start.
            var basePosition = ((SegmentStream)stream.BaseStream).BaseStream.Position - 8;

            var test = stream.ReadInt32();

            stream.Position += test * 4;
            var generation = stream.ReadInt32() == 256 ? Generation.Gen1 : Generation.Gen2;

            stream.Position -= (test + 2) * 4;

            if (generation == Generation.Gen2)
            {
                stream.ReadInt32(); // Unk
            }
            var layerOffsets = new int[stream.ReadInt32()];

            Layers = new MapdLayer[layerOffsets.Length];

            for (var i = 0; i < layerOffsets.Length; i++)
            {
                layerOffsets[i] = stream.ReadInt32();
            }

            var palette = new byte[stream.ReadInt32() * 4];

            if (generation == Generation.Gen2)
            {
                for (var i = 0; i < palette.Length;)
                {
                    var color16 = stream.ReadUInt16(); // aRRRRRGGGGGBBBBB
                    palette[i++] = (byte)(((color16 & 0x7c00) >> 7) & 0xff);
                    palette[i++] = (byte)(((color16 & 0x03e0) >> 2) & 0xff);
                    palette[i++] = (byte)(((color16 & 0x001f) << 3) & 0xff);
                    palette[i++] = 0xff;
                }
            }
            else
            {
                stream.Read(palette);

                for (var i = 0; i < palette.Length / 4; i++)
                {
                    palette[i * 4 + 3] = 0xff;
                }
            }

            for (var i = 0; i < Layers.Length; i++)
            {
                stream.Position = layerOffsets[i] - basePosition;

                var type = new string(stream.ReadASCII(4).Reverse().ToArray());

                if (type != "SCRL")
                {
                    throw new Exception("Unknown type.");
                }

                var tileWidth  = stream.ReadInt32();
                var tileHeight = stream.ReadInt32();
                var tilesX     = stream.ReadInt32();
                var tilesY     = stream.ReadInt32();

                if (generation == Generation.Gen2)
                {
                    stream.ReadInt32(); // Unk
                    stream.ReadInt32(); // Unk
                    stream.ReadInt32(); // Unk
                }

                var tilePixels = new Dictionary <int, byte[]>();
                var tiles      = new List <int>();

                for (var y = 0; y < tilesY; y++)
                {
                    for (var x = 0; x < tilesX; x++)
                    {
                        var tile = stream.ReadInt32();

                        if (generation == Generation.Gen2)
                        {
                            tile -= tile % 4;
                        }

                        tiles.Add(tile);

                        if (tile != 0 && !tilePixels.ContainsKey(tile))
                        {
                            tilePixels.Add(tile, new byte[tileWidth * tileHeight * 4]);
                        }
                    }
                }

                foreach (var(offset, pixels) in tilePixels)
                {
                    stream.Position = offset - basePosition;

                    if (generation == Generation.Gen1)
                    {
                        stream.ReadInt32(); // Unk
                    }
                    for (var y = 0; y < tileHeight; y++)
                    {
                        for (var x = 0; x < tileWidth; x++)
                        {
                            var index = stream.ReadByte();

                            if (index == 0 && i != 0)
                            {
                                continue;
                            }

                            Array.Copy(palette, index * 4, pixels, (y * tileWidth + x) * 4, 4);
                        }
                    }
                }

                var layer = new MapdLayer(tilesX * tileWidth, tilesY * tileHeight);
                Layers[i] = layer;

                for (var y = 0; y < tilesY; y++)
                {
                    for (var x = 0; x < tilesX; x++)
                    {
                        var tile = tiles[y * tilesX + x];

                        if (tile == 0)
                        {
                            continue;
                        }

                        var pixels = tilePixels[tile];
                        var offset = (y * tileHeight * tilesX + x) * tileWidth;

                        for (var row = 0; row < tileHeight; row++)
                        {
                            Array.Copy(pixels, row * tileWidth * 4, layer.Pixels, (offset + row * layer.Width) * 4, tileWidth * 4);
                        }
                    }
                }
            }
        }