public MobdImage(SegmentStream stream, uint flags, Version version) { bool flipped; Width = stream.ReadUInt32(); Height = stream.ReadUInt32(); Pixels = new byte[Width * Height]; if (version == Version.KKND1) { flipped = (flags & 0x1) == 1; var isCompressed = stream.ReadUInt8() == 2; if (isCompressed) { DecompressKknd1(stream); } else { stream.ReadBytes(Pixels, 0, Pixels.Length); } } else { flipped = ((flags >> 31) & 0x1) == 1; var isCompressed = ((flags >> 27) & 0x1) == 1; var has256Colors = ((flags >> 26) & 0x1) == 1; if (isCompressed) { DecompressKknd2(stream, has256Colors); } else { stream.ReadBytes(Pixels, 0, Pixels.Length); } } if (!flipped) { return; } for (var i = 0; i < Height; i++) { var row = new byte[Width]; Array.Copy(Pixels, i * Width, row, 0, Width); Array.Reverse(row); Array.Copy(row, 0, Pixels, i * Width, Width); } }
public byte[] ApplyFrame(byte[] oldFrame, uint[] palette, int2 size) { var newFrame = new byte[oldFrame.Length]; var offset = globalMotion.X + globalMotion.Y * size.X; int[] patterns = { 0x0660, 0xFF00, 0xCCCC, 0xF000, 0x8888, 0x000F, 0x1111, 0xFEC8, 0x8CEF, 0x137F, 0xF731, 0xC800, 0x008C, 0x0013, 0x3100, 0xCC00, 0x00CC, 0x0033, 0x3300, 0x0FF0, 0x6666, 0x00F0, 0x0F00, 0x2222, 0x4444, 0xF600, 0x8CC8, 0x006F, 0x1331, 0x318C, 0xC813, 0x33CC, 0x6600, 0x0CC0, 0x0066, 0x0330, 0xF900, 0xC88C, 0x009F, 0x3113, 0x6000, 0x0880, 0x0006, 0x0110, 0xCC88, 0xFC00, 0x00CF, 0x88CC, 0x003F, 0x1133, 0x3311, 0xF300, 0x6FF6, 0x0603, 0x08C6, 0x8C63, 0xC631, 0x6310, 0xC060, 0x0136, 0x136C, 0x36C8, 0x6C80, 0x324C }; if (colors != null) { colors.Position = 0; var firstIndex = colors.ReadUInt8(); var numColors = (colors.ReadUInt8() - 1) & 0xff; for (var i = 0; i <= numColors; i++) { palette[firstIndex + i] = (uint)((0xff << 24) | (colors.ReadUInt8() << 16) | (colors.ReadUInt8() << 8) | (colors.ReadUInt8() << 0)); } } video.Position = 0; for (var by = 0; by < size.Y / 4; by++) { for (var bx = 0; bx < size.X / 4;) { var blockTypes = video.ReadUInt8(); for (var i = 0; i < 4; i++, bx++) { var blockType = (blockTypes >> (6 - i * 2)) & 0x03; switch (blockType) { case 0: { for (var y = 0; y < 4; y++) { var dst = (by * 4 + y) * size.X + bx * 4; Array.Copy(oldFrame, dst + offset, newFrame, dst, 4); } break; } case 1: { var motion = video.ReadUInt8(); if (motion == 0) { for (var y = 0; y < 4; y++) { Array.Copy(video.ReadBytes(4), 0, newFrame, (by * 4 + y) * size.X + bx * 4, 4); } } else { var motionX = ((motion & 0xf) ^ 8) - 8; var motionY = ((motion >> 4) ^ 8) - 8; for (var y = 0; y < 4; y++) { var dst = (by * 4 + y) * size.X + bx * 4; Array.Copy(oldFrame, dst + offset + motionY * size.X + motionX, newFrame, dst, 4); } } break; } case 2: { var color = video.ReadUInt8(); for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { newFrame[(by * 4 + y) * size.X + bx * 4 + x] = color; } } break; } case 3: { var patternData = video.ReadUInt8(); var patternType = patternData >> 6; var pattern = patterns[patternData & 0x3f]; switch (patternType) { case 0: { var pixel0 = video.ReadUInt8(); var pixel1 = video.ReadUInt8(); for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { newFrame[(by * 4 + y) * size.X + bx * 4 + x] = ((pattern >> (y * 4 + x)) & 1) == 0 ? pixel0 : pixel1; } } break; } case 1: { var pixel = video.ReadUInt8(); for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { var dst = (by * 4 + y) * size.X + bx * 4 + x; if (((pattern >> (y * 4 + x)) & 1) == 0) { newFrame[dst] = oldFrame[dst + offset]; } else { newFrame[dst] = pixel; } } } break; } case 2: { var pixel = video.ReadUInt8(); for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { var dst = (by * 4 + y) * size.X + bx * 4 + x; if (((pattern >> (y * 4 + x)) & 1) == 1) { newFrame[dst] = oldFrame[dst + offset]; } else { newFrame[dst] = pixel; } } } break; } } break; } } } } } return(newFrame); }
public uint[,] ApplyFrame(uint[,] oldFrame, ref uint[] palette, ref string textData) { var width = oldFrame.GetLength(1); var height = oldFrame.GetLength(0); var newFrame = new uint[height, width]; // We use Buffer.BlockCopy as Array.Copy does not properly handle 2d array! var shift = (globalMotion.X + globalMotion.Y * width) * 4; if (shift >= 0) { Buffer.BlockCopy(oldFrame, shift, newFrame, 0, oldFrame.Length * 4 - shift); } else { Buffer.BlockCopy(oldFrame, 0, newFrame, -shift, oldFrame.Length * 4 + shift); } int[] patterns = { 0x0660, 0xFF00, 0xCCCC, 0xF000, 0x8888, 0x000F, 0x1111, 0xFEC8, 0x8CEF, 0x137F, 0xF731, 0xC800, 0x008C, 0x0013, 0x3100, 0xCC00, 0x00CC, 0x0033, 0x3300, 0x0FF0, 0x6666, 0x00F0, 0x0F00, 0x2222, 0x4444, 0xF600, 0x8CC8, 0x006F, 0x1331, 0x318C, 0xC813, 0x33CC, 0x6600, 0x0CC0, 0x0066, 0x0330, 0xF900, 0xC88C, 0x009F, 0x3113, 0x6000, 0x0880, 0x0006, 0x0110, 0xCC88, 0xFC00, 0x00CF, 0x88CC, 0x003F, 0x1133, 0x3311, 0xF300, 0x6FF6, 0x0603, 0x08C6, 0x8C63, 0xC631, 0x6310, 0xC060, 0x0136, 0x136C, 0x36C8, 0x6C80, 0x324C }; if (colors != null) { colors.Position = 0; var firstIndex = colors.ReadUInt8(); var numColors = (colors.ReadUInt8() - 1) & 0xff; for (var i = 0; i <= numColors; i++) { palette[firstIndex + i] = (uint)((0xff << 24) | (colors.ReadUInt8() << 16) | (colors.ReadUInt8() << 8) | (colors.ReadUInt8() << 0)); } } video.Position = 0; for (var by = 0; by < height / 4; by++) { for (var bx = 0; bx < width / 4;) { var blockTypes = video.ReadUInt8(); for (var i = 0; i < 4; i++, bx++) { var blockType = (blockTypes >> (6 - i * 2)) & 0x03; switch (blockType) { case 0: { break; } case 1: { var motion = video.ReadUInt8(); if (motion == 0) { for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { newFrame[by * 4 + y, bx * 4 + x] = palette[video.ReadByte()]; } } } else { var motionX = ((motion & 0xf) ^ 8) - 8; var motionY = ((motion >> 4) ^ 8) - 8; for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { newFrame[by * 4 + y, bx * 4 + x] = oldFrame[by * 4 + y + globalMotion.Y + motionY, bx * 4 + x + globalMotion.X + motionX]; } } } break; } case 2: { var color = palette[video.ReadUInt8()]; for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { newFrame[by * 4 + y, bx * 4 + x] = color; } } break; } case 3: { var patternData = video.ReadUInt8(); var patternType = patternData >> 6; var pattern = patterns[patternData & 0x3f]; switch (patternType) { case 0: { var pixel0 = palette[video.ReadUInt8()]; var pixel1 = palette[video.ReadUInt8()]; for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { newFrame[by * 4 + y, bx * 4 + x] = ((pattern >> (y * 4 + x)) & 1) == 0 ? pixel0 : pixel1; } } break; } case 1: { var pixel = palette[video.ReadUInt8()]; for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { if (((pattern >> (y * 4 + x)) & 1) == 1) { newFrame[by * 4 + y, bx * 4 + x] = pixel; } } } break; } case 2: { var pixel = palette[video.ReadUInt8()]; for (var y = 0; y < 4; y++) { for (var x = 0; x < 4; x++) { if (((pattern >> (y * 4 + x)) & 1) == 0) { newFrame[by * 4 + y, bx * 4 + x] = pixel; } } } break; } } break; } } } } } if (Text != null) { textData = Text; } return(newFrame); }