private MphdRecord ReadChunkMPHD(Stream stream, Chunk chunk) { MphdRecord mphdRecord = new MphdRecord(); stream.Position = chunk.FilePosition; mphdRecord.VersionHigh = ReadSignedByte(stream); mphdRecord.VersionLow = ReadSignedByte(stream); mphdRecord.LSB = ReadSignedByte(stream) != 0; mphdRecord.MapType = ReadSignedByte(stream); if (mphdRecord.MapType != 0) throw new Exception("Only MapType = 0 is supported"); mphdRecord.MapWidth = ReadShort(stream, mphdRecord.LSB); mphdRecord.MapHeight = ReadShort(stream, mphdRecord.LSB); mphdRecord.Reserved1 = ReadShort(stream, mphdRecord.LSB); mphdRecord.Reserved2 = ReadShort(stream, mphdRecord.LSB); mphdRecord.BlockWidth = ReadShort(stream, mphdRecord.LSB); mphdRecord.BlockHeight = ReadShort(stream, mphdRecord.LSB); mphdRecord.BlockDepth = ReadShort(stream, mphdRecord.LSB); mphdRecord.BlockStructSize = ReadShort(stream, mphdRecord.LSB); mphdRecord.NumBlockStruct = ReadShort(stream, mphdRecord.LSB); mphdRecord.NumBlockGfx = ReadShort(stream, mphdRecord.LSB); if (chunk.Length > 24) { mphdRecord.ColourKeyIndex = ReadUnsignedByte(stream); mphdRecord.ColourKeyRed = ReadUnsignedByte(stream); mphdRecord.ColourKeyGreen = ReadUnsignedByte(stream); mphdRecord.ColourKeyBlue = ReadUnsignedByte(stream); if (chunk.Length > 28) { mphdRecord.BlockGapX = ReadShort(stream, mphdRecord.LSB); mphdRecord.BlockGapY = ReadShort(stream, mphdRecord.LSB); mphdRecord.BlockStaggerX = ReadShort(stream, mphdRecord.LSB); mphdRecord.BlockStaggerY = ReadShort(stream, mphdRecord.LSB); if (chunk.Length > 36) { mphdRecord.ClickMask = ReadShort(stream, mphdRecord.LSB); mphdRecord.Pillars = ReadShort(stream, mphdRecord.LSB); } } } return mphdRecord; }
private short[] ReadChunkLayer(Stream stream, Chunk chunk, MphdRecord mphdRecord) { bool lsb = mphdRecord.LSB; short[] offsets = new short[chunk.Length / 2]; stream.Position = chunk.FilePosition; for (int index = 0; index < offsets.Length; index++) { short offset = ReadShort(stream, lsb); if (mphdRecord.VersionHigh < 1) { if (offset >= 0) offset /= mphdRecord.BlockStructSize; else offset /= AnimationRecord.SIZE; } offsets[index] = offset; } return offsets; }
private Image ReadChunkBGFX(Stream stream, Chunk chunk, MphdRecord mphdRecord, Color[] colourMap) { int tileCount = mphdRecord.NumBlockStruct; int imageWidth = mphdRecord.BlockWidth; int imageHeight = mphdRecord.BlockHeight * tileCount; byte[] imageData = new byte[chunk.Length]; stream.Position = chunk.FilePosition; stream.Read(imageData, 0, chunk.Length); bool applyColourKeying = false; if (mphdRecord.BlockDepth < 32) { applyColourKeying = MessageBox.Show( "Apply colour keying?", "Mappy BGFX Chunk", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes; } Bitmap imageSource = new Bitmap(imageWidth, imageHeight, PixelFormat.Format32bppArgb); int pixelIndex = 0; if (mphdRecord.BlockDepth == 8) { for (int pixelY = 0; pixelY < imageHeight; pixelY++) { for (int pixelX = 0; pixelX < imageWidth; pixelX++) { byte colourIndex = imageData[pixelIndex++]; if (!applyColourKeying || colourIndex != mphdRecord.ColourKeyIndex) imageSource.SetPixel(pixelX, pixelY, colourMap[colourIndex]); } } } else if (mphdRecord.BlockDepth == 15) { for (int pixelY = 0; pixelY < imageHeight; pixelY++) { for (int pixelX = 0; pixelX < imageWidth; pixelX++) { ushort colourValue = (ushort)(imageData[pixelIndex++] | (imageData[pixelIndex++] << 8)); byte alpha = 255; byte red = (byte)(colourValue & 31); byte green = (byte)((colourValue >> 5) & 31); byte blue = (byte)((colourValue >> 10) & 31); red *= 4; green *= 4; blue *= 4; if (applyColourKeying && red == mphdRecord.ColourKeyRed && green == mphdRecord.ColourKeyGreen && blue == mphdRecord.ColourKeyBlue) alpha = 0; Color colour = Color.FromArgb(alpha, red, green, blue); imageSource.SetPixel(pixelX, pixelY, colour); } } } else if (mphdRecord.BlockDepth == 16) { for (int pixelY = 0; pixelY < imageHeight; pixelY++) { for (int pixelX = 0; pixelX < imageWidth; pixelX++) { ushort colourValue = (ushort)(imageData[pixelIndex++] | (imageData[pixelIndex++] << 8)); byte alpha = 255; byte red = (byte)(colourValue & 31); byte green = (byte)((colourValue >> 5) & 63); byte blue = (byte)((colourValue >> 11) & 31); red *= 8; green *= 4; blue *= 8; if (applyColourKeying && red == mphdRecord.ColourKeyRed && green == mphdRecord.ColourKeyGreen && blue == mphdRecord.ColourKeyBlue) alpha = 0; Color colour = Color.FromArgb(alpha, red, green, blue); imageSource.SetPixel(pixelX, pixelY, colour); } } } else if (mphdRecord.BlockDepth == 24) { for (int pixelY = 0; pixelY < imageHeight; pixelY++) { for (int pixelX = 0; pixelX < imageWidth; pixelX++) { byte alpha = 255; byte red = imageData[pixelIndex++]; byte green = imageData[pixelIndex++]; byte blue = imageData[pixelIndex++]; if (applyColourKeying && red == mphdRecord.ColourKeyRed && green == mphdRecord.ColourKeyGreen && blue == mphdRecord.ColourKeyBlue) alpha = 0; Color colour = Color.FromArgb(alpha, red, green, blue); imageSource.SetPixel(pixelX, pixelY, colour); } } } else if (mphdRecord.BlockDepth == 32) { for (int pixelY = 0; pixelY < imageHeight; pixelY++) { for (int pixelX = 0; pixelX < imageWidth; pixelX++) { byte alpha = imageData[pixelIndex++]; byte red = imageData[pixelIndex++]; byte green = imageData[pixelIndex++]; byte blue = imageData[pixelIndex++]; Color colour = Color.FromArgb(alpha, red, green, blue); imageSource.SetPixel(pixelX, pixelY, colour); } } } return imageSource; }
private BlockRecord[] ReadChunkBKDT(Stream stream, Chunk chunk, MphdRecord mphdRecord) { BlockRecord[] blockRecords = new BlockRecord[mphdRecord.NumBlockStruct]; bool lsb = mphdRecord.LSB; for(int index = 0; index < mphdRecord.NumBlockStruct; index++) { stream.Position = chunk.FilePosition + mphdRecord.BlockStructSize * index; BlockRecord blockRecord = new BlockRecord(); blockRecord.BackgroundOffset = ReadSignedLong(stream, lsb); blockRecord.ForegroundOffset = ReadSignedLong(stream, lsb); blockRecord.BackgroundOffset2 = ReadSignedLong(stream, lsb); blockRecord.ForegroundOffset2 = ReadSignedLong(stream, lsb); blockRecord.User1 = ReadUnsignedLong(stream, lsb); blockRecord.User2 = ReadUnsignedLong(stream, lsb); blockRecord.User3 = ReadUnsignedShort(stream, lsb); blockRecord.User4 = ReadUnsignedShort(stream, lsb); blockRecord.User5 = ReadUnsignedByte(stream); blockRecord.User6 = ReadUnsignedByte(stream); blockRecord.User7 = ReadUnsignedByte(stream); blockRecord.Flags = ReadUnsignedByte(stream); blockRecords[index] = blockRecord; } return blockRecords; }
private AnimationRecord[] ReadChunkANDT(Stream stream, Chunk chunk, MphdRecord mphdRecord) { bool lsb = mphdRecord.LSB; // count structures backwards stream.Position = chunk.FilePosition + chunk.Length - AnimationRecord.SIZE; int animationCount = 0; while (ReadSignedByte(stream) != -1) { ++animationCount; stream.Position -= (AnimationRecord.SIZE + 1); } AnimationRecord[] animationRecords = new AnimationRecord[animationCount]; stream.Position = chunk.FilePosition + chunk.Length - AnimationRecord.SIZE; int animationIndex = 0; while (true) { long recordPosition = stream.Position; AnimationRecord animationRecord = new AnimationRecord(); animationRecord.Type = ReadSignedByte(stream); if (animationRecord.Type == -1) break; animationRecord.Delay = ReadSignedByte(stream); animationRecord.Counter = ReadSignedByte(stream); animationRecord.UserInfo = ReadSignedByte(stream); animationRecord.CurrentOffset = ReadSignedLong(stream, lsb); animationRecord.StartOffset = ReadSignedLong(stream, lsb); animationRecord.EndOffset = ReadSignedLong(stream, lsb); // offsets are negative offsets into a list of frame indices (32bit) at the beginning of the chunk int frameCount = (int)((animationRecord.EndOffset - animationRecord.StartOffset) / 4); // move (backwards) to frame indices at beginning of chunk animationRecord.Frames = new int[frameCount]; //stream.Position += animationRecord.StartOffset; stream.Position = chunk.FilePosition + chunk.Length + animationRecord.StartOffset; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { animationRecord.Frames[frameIndex] = (int)ReadSignedLong(stream, lsb); if (mphdRecord.VersionHigh < 1) animationRecord.Frames[frameIndex] /= mphdRecord.BlockStructSize; } animationRecords[animationIndex++] = animationRecord; stream.Position = recordPosition - AnimationRecord.SIZE; } stream.Position = chunk.FilePosition + chunk.Length; return animationRecords; }