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); }
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); } } }