public unsafe Frame <ImageSource>[] GetAnimation(int body, int action, int direction, int hue, bool preserveHue)
        {
            if (preserveHue)
            {
                Translate(ref body);
            }
            else
            {
                Translate(ref body, ref hue);
            }

            int           fileType  = _bodyConverter.Convert(ref body);
            FileIndexBase fileIndex = _fileIndices[fileType - 1];

            int index;

            switch (fileType)
            {
            default:
            {
                if (body < 200)
                {
                    index = body * 110;
                }
                else if (body < 400)
                {
                    index = 22000 + ((body - 200) * 65);
                }
                else
                {
                    index = 35000 + ((body - 400) * 175);
                }

                break;
            }

            case 2:
            {
                if (body < 200)
                {
                    index = body * 110;
                }
                else
                {
                    index = 22000 + ((body - 200) * 65);
                }

                break;
            }

            case 3:
            {
                if (body < 300)
                {
                    index = body * 65;
                }
                else if (body < 400)
                {
                    index = 33000 + ((body - 300) * 110);
                }
                else
                {
                    index = 35000 + ((body - 400) * 175);
                }

                break;
            }

            case 4:
            {
                if (body < 200)
                {
                    index = body * 110;
                }
                else if (body < 400)
                {
                    index = 22000 + ((body - 200) * 65);
                }
                else
                {
                    index = 35000 + ((body - 400) * 175);
                }

                break;
            }

            case 5:
            {
                if (body < 200 && body != 34)     // looks strange, though it works.
                {
                    index = body * 110;
                }
                else
                {
                    index = 35000 + ((body - 400) * 65);
                }

                break;
            }
            }

            if ((index + (action * 5)) > int.MaxValue)
            {
                throw new ArithmeticException();
            }

            index += action * 5;

            if (direction <= 4)
            {
                index += direction;
            }
            else
            {
                index += direction - (direction - 4) * 2;
            }

            int    length, extra;
            Stream stream = fileIndex.Seek(index, out length, out extra);

            if (stream == null)
            {
                return(null);
            }

            bool flip = (direction > 4);

            BinaryReader bin = new BinaryReader(stream);

            ushort[] palette = new ushort[0x100];

            for (int i = 0; i < 0x100; ++i)
            {
                palette[i] = (ushort)(bin.ReadUInt16() ^ 0x8000);
            }

            int start      = (int)bin.BaseStream.Position;
            int frameCount = bin.ReadInt32();

            int[] lookups = new int[frameCount];

            for (int i = 0; i < frameCount; ++i)
            {
                lookups[i] = start + bin.ReadInt32();
            }

            bool onlyHueGrayPixels = ((hue & 0x8000) == 0);

            hue = (hue & 0x3FFF) - 1;

            Hue hueObject = null;

            if (hue >= 0 && hue < _hues.Table.Length)
            {
                hueObject = _hues.Table[hue];
            }

            Frame <ImageSource>[] frames = new Frame <ImageSource> [frameCount];

            for (int i = 0; i < frameCount; ++i)
            {
                bin.BaseStream.Seek(lookups[i], SeekOrigin.Begin);

                int xCenter = bin.ReadInt16();
                int yCenter = bin.ReadInt16();

                int width  = bin.ReadUInt16();
                int height = bin.ReadUInt16();

                WriteableBitmap bmp = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgr555, null);
                bmp.Lock();

                ushort *line  = (ushort *)bmp.BackBuffer;
                int     delta = bmp.BackBufferStride >> 1;

                int header;

                int xBase = xCenter - 0x200;
                int yBase = (yCenter + height) - 0x200;

                if (!flip)
                {
                    line += xBase;
                    line += (yBase * delta);

                    while ((header = bin.ReadInt32()) != 0x7FFF7FFF)
                    {
                        header ^= DoubleXor;

                        ushort *cur = line + ((((header >> 12) & 0x3FF) * delta) + ((header >> 22) & 0x3FF));
                        ushort *end = cur + (header & 0xFFF);

                        while (cur < end)
                        {
                            *cur++ = palette[bin.ReadByte()];
                        }
                    }
                }
                else
                {
                    line -= xBase - width + 1;
                    line += (yBase * delta);

                    while ((header = bin.ReadInt32()) != 0x7FFF7FFF)
                    {
                        header ^= DoubleXor;

                        ushort *cur = line + ((((header >> 12) & 0x3FF) * delta) - ((header >> 22) & 0x3FF));
                        ushort *end = cur - (header & 0xFFF);

                        while (cur > end)
                        {
                            *cur-- = palette[bin.ReadByte()];
                        }
                    }

                    xCenter = width - xCenter;
                }

                bmp.AddDirtyRect(new Int32Rect(0, 0, width, height));
                bmp.Unlock();

                if (hueObject != null)
                {
                    ApplyHue(bmp, hueObject, onlyHueGrayPixels);
                }

                frames[i] = new Frame <ImageSource>(xCenter, yCenter, bmp);
            }

            return(frames);
        }
Beispiel #2
0
        public unsafe Frame <Texture>[] GetAnimation(int body, int action, int direction, int hue, bool preserveHue)
        {
            if (preserveHue)
            {
                Translate(ref body);
            }
            else
            {
                Translate(ref body, ref hue);
            }

            var fileType  = _bodyConverter.Convert(ref body);
            var fileIndex = _fileIndices[fileType - 1];

            int index;

            switch (fileType)
            {
            default:
            {
                if (body < 200)
                {
                    index = body * 110;
                }
                else if (body < 400)
                {
                    index = 22000 + ((body - 200) * 65);
                }
                else
                {
                    index = 35000 + ((body - 400) * 175);
                }

                break;
            }

            case 2:
            {
                if (body < 200)
                {
                    index = body * 110;
                }
                else
                {
                    index = 22000 + ((body - 200) * 65);
                }

                break;
            }

            case 3:
            {
                if (body < 300)
                {
                    index = body * 65;
                }
                else if (body < 400)
                {
                    index = 33000 + ((body - 300) * 110);
                }
                else
                {
                    index = 35000 + ((body - 400) * 175);
                }

                break;
            }

            case 4:
            {
                if (body < 200)
                {
                    index = body * 110;
                }
                else if (body < 400)
                {
                    index = 22000 + ((body - 200) * 65);
                }
                else
                {
                    index = 35000 + ((body - 400) * 175);
                }

                break;
            }

            case 5:
            {
                if (body < 200 && body != 34)     // looks strange, though it works.
                {
                    index = body * 110;
                }
                else
                {
                    index = 35000 + ((body - 400) * 65);
                }

                break;
            }
            }

            index += action * 5;

            if (direction <= 4)
            {
                index += direction;
            }
            else
            {
                index += direction - (direction - 4) * 2;
            }

            int length, extra;

            using (var stream = fileIndex.Seek(index, out length, out extra))
            {
                if (stream == null)
                {
                    return(null);
                }

                var flip = (direction > 4);

                using (var bin = new BinaryReader(stream))
                {
                    var palette = new ushort[0x100];

                    for (var i = 0; i < 0x100; ++i)
                    {
                        palette[i] = (ushort)(bin.ReadUInt16() ^ 0x8000);
                    }

                    var startPosition = (int)bin.BaseStream.Position;
                    var frameCount    = bin.ReadInt32();

                    var lookups = new int[frameCount];

                    for (var i = 0; i < frameCount; ++i)
                    {
                        lookups[i] = startPosition + bin.ReadInt32();
                    }

                    var frames = new Frame <Texture> [frameCount];

                    for (var i = 0; i < frameCount; ++i)
                    {
                        bin.BaseStream.Seek(lookups[i], SeekOrigin.Begin);

                        int xCenter = bin.ReadInt16();
                        int yCenter = bin.ReadInt16();

                        int width  = bin.ReadUInt16();
                        int height = bin.ReadUInt16();

                        var texture = Texture.New2D(GraphicsDevice, width, height, PixelFormat.B5G5R5A1_UNorm);
                        var buffer  = new ushort[width * height];

                        fixed(ushort *start = buffer)
                        {
                            var ptr   = start;
                            var delta = texture.Width;

                            int header;

                            var xBase = xCenter - 0x200;
                            var yBase = (yCenter + height) - 0x200;

                            if (!flip)
                            {
                                ptr += xBase;
                                ptr += (yBase * delta);

                                while ((header = bin.ReadInt32()) != 0x7FFF7FFF)
                                {
                                    header ^= DoubleXor;

                                    var cur = ptr + ((((header >> 12) & 0x3FF) * delta) + ((header >> 22) & 0x3FF));
                                    var end = cur + (header & 0xFFF);

                                    while (cur < end)
                                    {
                                        *cur++ = palette[bin.ReadByte()];
                                    }
                                }
                            }
                            else
                            {
                                ptr -= xBase - width + 1;
                                ptr += (yBase * delta);

                                while ((header = bin.ReadInt32()) != 0x7FFF7FFF)
                                {
                                    header ^= DoubleXor;

                                    var cur = ptr + ((((header >> 12) & 0x3FF) * delta) - ((header >> 22) & 0x3FF));
                                    var end = cur - (header & 0xFFF);

                                    while (cur > end)
                                    {
                                        *cur-- = palette[bin.ReadByte()];
                                    }
                                }

                                xCenter = width - xCenter;
                            }
                        }

                        texture.SetData(buffer);

                        frames[i] = new Frame <Texture>(xCenter, yCenter, texture);
                    }

                    return(frames);
                }
            }
        }