private CostumeAnimation LoadAnimation(ScummBinaryReader reader, string resourceId, int animationIndex, long startOffset, ushort[] animationOffsets, ushort[] limbOffsets, ushort animationCommandOffset, byte[] palette, Color[] roomPalette, bool containsRedirection, bool mirror) { if (animationOffsets[animationIndex] == 0) { return(null); } reader.BaseStream.Position = startOffset + animationOffsets[animationIndex]; var costumeAnimation = new CostumeAnimation(); costumeAnimation.IsMirrored = mirror; var currentFrameIndex = 0; var framesCount = 0; var startAnimationPosition = reader.BaseStream.Position; while (currentFrameIndex < framesCount || currentFrameIndex == 0) { var mask = reader.ReadUInt16(); var costumeFrame = new CostumeFrame(); var imageData = new LayeredImageData(); var i = 0; do { if ((mask & 0x8000) != 0) { var startAnimationCommandOffset = reader.ReadUInt16(); if (startAnimationCommandOffset != 0xFFFF) { var flags = reader.ReadByte(); var loop = flags & 0x8000; var endFrame = flags & 0x7F; if (currentFrameIndex == 0 && framesCount == 0) { framesCount = Math.Max(framesCount, endFrame) + 1; } var oldStreamPosition = reader.BaseStream.Position; reader.BaseStream.Position = startOffset + animationCommandOffset + startAnimationCommandOffset + Math.Min(currentFrameIndex, endFrame); var animationCommandValue = reader.ReadByte(); if (animationCommandValue == 0x71) { // TODO: Handle special commands (sounds, etc.) } else if (animationCommandValue == 0x7A) { // TODO: Implement start command } else if (animationCommandValue == 0x79) { // TODO: Implement stopped command } else { reader.BaseStream.Position = startOffset + limbOffsets[i] + animationCommandValue * 2; var pictOffset = reader.ReadUInt16(); reader.BaseStream.Position = startOffset + pictOffset; var width = reader.ReadUInt16(); var height = reader.ReadUInt16(); var relativeX = reader.ReadInt16(); var relativeY = reader.ReadInt16(); var movementX = reader.ReadInt16(); var movementY = reader.ReadInt16(); if (containsRedirection) { var redirectionLimb = reader.ReadByte(); var redirectionPict = reader.ReadByte(); } imageData.CreateLayer(width, height, new Vector2(relativeX, relativeY)); DecodeImageData(reader, imageData, width, height, palette, roomPalette); } reader.BaseStream.Position = oldStreamPosition; } } mask = (ushort)(mask << 1); i++; } while ((mask & 0xFFFF) != 0); costumeFrame.FrameType = CostumeFrameType.Frame; // TODO: Fill offset and movement vector var textureData = imageData.GetBytes(); costumeFrame.Data = new Microsoft.Xna.Framework.Graphics.Texture2D(this.graphicsDevice, imageData.Width, imageData.Height, false, Microsoft.Xna.Framework.Graphics.SurfaceFormat.Color); costumeFrame.Data.SetData(textureData); costumeAnimation.Frames.Add(costumeFrame); if (!Directory.Exists("DebugAnims\\" + resourceId)) { Directory.CreateDirectory("DebugAnims\\" + resourceId); } costumeFrame.Data.SaveAsPng(File.Create(string.Format("DebugAnims\\" + resourceId + "\\Anim{0}_{1}.png", animationIndex, currentFrameIndex)), costumeFrame.Data.Width, costumeFrame.Data.Height); reader.BaseStream.Position = startAnimationPosition; currentFrameIndex++; } return(costumeAnimation); }
private void DecodeImageData(ScummBinaryReader reader, LayeredImageData imageData, int width, int height, byte[] palette, Color[] roomPalette) { byte shift; byte mask; if (palette.Length == 16) { shift = 4; mask = 0xF; } else { shift = 3; mask = 0x7; } int x = 0; int y = 0; bool end = false; while (end == false) { var rep = reader.ReadByte(); var colorPaletteIndex = (byte)(rep >> shift); Color color = Color.Black; var roomColor = roomPalette[palette[colorPaletteIndex]]; color.R = roomColor.R; color.G = roomColor.G; color.B = roomColor.B; rep &= mask; if (rep == 0) { rep = reader.ReadByte(); } while (rep > 0) { if (colorPaletteIndex != 0) { imageData.SetPixel(x, y, color); } rep--; y++; if (y >= height) { y = 0; x++; if (x >= width) { end = true; } } } } }