private void Run(Utility utility, string[] args) { const string prtFilename = "op2_art.prt"; // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData = utility.ModData; using (var stream = Game.ModData.DefaultFileSystem.Open(prtFilename)) { framePalettes = LoadPalettes(stream); prtFile = LoadGroups(stream, out var palettes); } WriteSequences(); Console.WriteLine($"Wrote sequences file: {OutputFilename}"); WriteActors(); Console.WriteLine($"Wrote rules file: {RulesOutputFilename}"); Console.WriteLine($"Wrote rules example file: {RulesExampleOutputFilename}"); }
PrtFile LoadImageHeader(Stream s, out Dictionary <int, uint[]> palettes) { var spriteCount = s.ReadUInt32(); var h = new PrtFile() { ImageCount = (int)spriteCount, ImageHeader = new Op2Image[spriteCount] }; palettes = new Dictionary <int, uint[]>(); var rawFrames = h.ImageHeader; for (var f = 0; f < rawFrames.Length; f++) { var paddedWidth = s.ReadUInt32(); var dataOffset = s.ReadUInt32(); var height = s.ReadUInt32(); var width = s.ReadUInt32(); var type = s.ReadUInt16(); var palette = s.ReadUInt16(); palettes.Add(f, framePalettes[palette]); var img = new Op2Image { PaddedWidth = paddedWidth, DataOffset = dataOffset, Height = height, Width = width, ImageType = type, Palette = palette, }; h.ImageHeader[f] = img; } h.AllGroupCount = s.ReadInt32(); h.AllFrameCount = s.ReadInt32(); h.AllPicCount = s.ReadInt32(); h.AllExtInfoCount = s.ReadInt32(); return(h); }
public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { var start = s.Position; var signature = s.ReadASCII(2); if (signature != "BM") { s.Position = start; metadata = null; frames = null; return(false); } var size = s.ReadUInt32(); var reserved1 = s.ReadUInt16(); var reserved2 = s.ReadUInt16(); var dataStart = s.ReadUInt32(); var prt = Game.ModData.DefaultFileSystem.Open("op2_art.prt"); framePalettes = LoadPalettes(prt); prtFile = LoadImageHeader(prt, out var palettes); var frameList = new List <ISpriteFrame>(); // Populate art data const byte shadowTileIndex = 1; var imgIndex = 0; foreach (var img in prtFile.ImageHeader) { var isShadow = img.ImageType == 4 || img.ImageType == 5; var dataSize = new Size((int)img.PaddedWidth, (int)img.Height); var frameSize = new Size((int)img.Width, (int)img.Height); s.Seek(dataStart + img.DataOffset, SeekOrigin.Begin); byte[] data; var numBytes = (int)(img.PaddedWidth * img.Height); if (isShadow) { var newSize = (int)(img.PaddedWidth * img.Height); var rowSize = (int)Math.Pow(2, Math.Ceiling(Math.Log(img.Width) / Math.Log(2))); var hasExtraRow = rowSize == (int)img.PaddedWidth; var tempData = s.ReadBytes(numBytes); var bits = new BitArray(tempData); var processedData = new byte[newSize * 8]; var paddedWidth = img.Width; const int bitsInAByte = 8; var numRows = (int)img.Height * 2; // TODO: This is a hack. Not sure why we need to double this if (hasExtraRow) { numRows *= 2; } // HACK: HACK HACK HACK // Obviously our rowSize calculation is borked, so correct some things here if (rowSize < 32) { rowSize = 32; } if (img.ImageType == 5) { if (rowSize == 128) { rowSize = 96; } else if (rowSize == 256) { rowSize = 128; } } for (var y = 0; y < numRows; y++) { for (var x = 0; x < img.Width; x++) { var i = (int)((y * paddedWidth) + x); var reversedBitIndex = 7 - (i % bitsInAByte); var byteFloor = i - (i % bitsInAByte); var lookupIndex = byteFloor + reversedBitIndex; processedData[i] = (byte)(bits[lookupIndex] ? shadowTileIndex : 0); } } var paddedDiff = (int)(img.PaddedWidth - img.Width); var newData = new List <byte>(); for (var i = 0; i < img.Height; i++) { var startIndex = i * rowSize; var firstX = processedData.Skip(startIndex).Take((int)img.Width).ToArray(); newData.AddRange(firstX); newData.AddRange(Enumerable.Repeat <byte>(0, paddedDiff)); // if (imgIndex == 1758) // { // var ss = imgIndex; // } } if (img.PaddedWidth * img.Height > newData.Count) { throw new ArgumentException("Image size did not match number of bytes."); } data = newData.ToArray(); } else { data = s.ReadBytes(numBytes); } img.SpriteFrame = new BitmapSpriteFrame { Size = dataSize, FrameSize = frameSize, Data = data, Type = SpriteFrameType.Indexed, }; frameList.Add(img.SpriteFrame); imgIndex++; } metadata = new TypeDictionary { new EmbeddedSpritePalette(framePalettes: palettes) }; frames = frameList.ToArray(); return(true); }
private bool IsPrt(Stream s) { var start = s.Position; var h = new PrtFile() { ID = s.ReadASCII(4), PalCount = s.ReadInt32(), }; if (h.ID != "CPAL") { s.Position = start; return(false); } h.PalData = new Ppal[h.PalCount]; // Parse palettes for (var i = 0; i < h.PalCount; i++) { var ppal = new Ppal { ID = s.ReadASCII(4), Size = s.ReadInt32(), HeadID = s.ReadASCII(4), BytesPerEntry = s.ReadInt32(), Unknown = s.ReadInt32(), DataID = s.ReadASCII(4), PalSize = s.ReadInt32() }; if (ppal.ID != "PPAL" || ppal.HeadID != "head" || ppal.DataID != "data") { s.Position = start; return(false); } var numPaletteEntries = ppal.PalSize / ppal.BytesPerEntry; ppal.PaletteData = new RgbQuad[numPaletteEntries]; // Populate palette for (var j = 0; j < numPaletteEntries; j++) { var rgba = new RgbQuad { Red = s.ReadByte(), Green = s.ReadByte(), Blue = s.ReadByte(), Reserved = s.ReadByte(), }; ppal.PaletteData[j] = rgba; } h.PalData[i] = ppal; } h.ImageCount = s.ReadInt32(); h.ImageHeader = new Op2Image[h.ImageCount]; for (var i = 0; i < h.ImageCount; i++) { var img = new Op2Image { SizeScanline = s.ReadInt32(), }; img.ImgData = s.ReadBytes(img.SizeScanline); img.SizeX = s.ReadInt32(); img.SizeY = s.ReadInt32(); img.Unknown = s.ReadInt16(); img.Palette = s.ReadInt16(); h.ImageHeader[i] = img; } h.AllGroupCount = s.ReadInt32(); h.AllFrameCount = s.ReadInt32(); h.AllPicCount = s.ReadInt32(); h.AllExtInfoCount = s.ReadInt32(); h.Groups = new ImageGroup[h.AllGroupCount]; for (var i = 0; i < h.AllGroupCount; i++) { var img = new ImageGroup { Unknown1 = s.ReadInt32(), SelLeft = s.ReadInt32(), SelTop = s.ReadInt32(), SelRight = s.ReadInt32(), SelBottom = s.ReadInt32(), CenterX = s.ReadInt32(), CenterY = s.ReadInt32(), Unknown8 = s.ReadInt32(), FrameCount = s.ReadInt32() }; img.Frames = new Op2Frame[img.FrameCount]; for (var j = 0; j < img.FrameCount; j++) { var frame = new Op2Frame { PicCount = s.ReadUInt8(), Unknown = s.ReadUInt8(), }; frame.ExtUnknown1 = new BytePair[frame.PicCount >> 7]; for (var k = 0; k < frame.PicCount >> 7; k++) { var bp = new BytePair { Byte1 = s.ReadUInt8(), Byte2 = s.ReadUInt8(), }; frame.ExtUnknown1[k] = bp; } frame.ExtUnknown2 = new BytePair[frame.Unknown >> 7]; for (var k = 0; k < frame.Unknown >> 7; k++) { var bp = new BytePair { Byte1 = s.ReadUInt8(), Byte2 = s.ReadUInt8(), }; frame.ExtUnknown2[k] = bp; } frame.Pictures = new Op2Picture[frame.PicCount & 0x7F]; for (var k = 0; k < frame.Pictures.Length; k++) { var pic = new Op2Picture { ImgNumber = s.ReadInt16(), Reserved = s.ReadUInt8(), PicOrder = s.ReadUInt8(), PosX = s.ReadInt16(), PosY = s.ReadInt16() }; frame.Pictures[k] = pic; } img.Frames[j] = frame; } img.GroupExtCount = s.ReadInt32(); img.Extended = new GroupExt[img.GroupExtCount]; for (var j = 0; j < img.GroupExtCount; j++) { var ext = new GroupExt { Unknown1 = s.ReadInt32(), Unknown2 = s.ReadInt32(), Unknown3 = s.ReadInt32(), Unknown4 = s.ReadInt32(), }; img.Extended[j] = ext; } h.Groups[i] = img; } file = h; return(true); }
public Op2SpriteFrame(Stream s, PrtFile head, Op2SpriteFrameInfo info) { /* * Type = SpriteFrameType.Indexed; * var picindex = info.A * sph.Nrots + info.R; * var readInt = new Func<int, int>((off) => * { * s.Position = off; * return s.ReadInt32(); * }); * * var picnr = readInt(HeaderSize + picindex * 4); * if (picnr >= sph.Npics) * throw new Exception("Pic number was greater or equal to number of pics."); * * var picoff = readInt(sph.OffPicoffs + 8 * picnr); * var nextpicoff = readInt(sph.OffPicoffs + 8 * (picnr + 1)); * var start = s.Position; * s.Position = sph.OffBits + picoff; * var tempData = s.ReadBytes(nextpicoff - picoff); * Data = new byte[(sph.Szx + 2) * sph.Szy]; * * var pixindex = new Func<int, int, int>((x, y) => * { * int vr = (y * sph.Szx) + x; * return vr; * }); * * var curr = 0; * for (var l = 0; l < sph.Szy; ++l) * { * int step = 0, currx = 0, cnt, i; * while (currx < sph.Szx) * { * cnt = tempData[curr++]; * if ((step & 1) != 0) * cnt &= 0x7f; * if ((step & 1) != 0) * { * if (!sph.IsShadow) * { * for (i = 0; i < cnt; ++i, ++curr) * { * int newIndex = pixindex(currx + i, l); * Data[newIndex] = tempData[curr]; * } * } * else * { * for (i = 0; i < cnt; ++i) * { * int newIndex = pixindex(currx + i, l); * Data[newIndex] = 47; * } * } * } * * currx += cnt; ++step; * } * * if (currx != sph.Szx) * throw new Exception("Current x was not equal to the line size."); * } * * Offset = new float2(0, 0); * FrameSize = new Size(sph.Szx, sph.Szy); * Size = FrameSize; * * s.Position = start; */ }
private static void Convert(string f) { string magic; using (FileStream fs = File.Open(f, FileMode.Open, FileAccess.Read, FileShare.Read)) { BrgBinaryReader reader = new BrgBinaryReader(EndianBitConverter.Little, fs); magic = reader.ReadString(4); } if (f.EndsWith("anim.txt")) { AnimFile.ConvertToXml(File.Open(f, FileMode.Open, FileAccess.Read, FileShare.Read), File.Open(f + ".xml", FileMode.Create, FileAccess.Write, FileShare.Read)); Console.WriteLine("Success! Anim converted."); } else if (f.EndsWith(".prt")) { PrtFile file = new PrtFile(File.Open(f, FileMode.Open, FileAccess.Read, FileShare.Read)); file.SerializeAsXml(File.Open(f + ".xml", FileMode.Create, FileAccess.Write, FileShare.Read)); Console.WriteLine("Success! Prt converted."); } else if (magic == "MTRL") { MtrlFile file = new MtrlFile(); file.Read(File.Open(f, FileMode.Open, FileAccess.Read, FileShare.Read)); file.SerializeAsXml(File.Open(f + ".xml", FileMode.Create, FileAccess.Write, FileShare.Read)); Console.WriteLine("Success! Mtrl converted."); } else if (magic == "BANG") { string brgMtrlOutputPath = Path.Combine(Path.GetDirectoryName(f), "materials"); if (!Directory.Exists(brgMtrlOutputPath)) { Directory.CreateDirectory(brgMtrlOutputPath); } BrgFile file = new BrgFile(File.Open(f, FileMode.Open, FileAccess.Read, FileShare.Read)); for (int i = 0; i < file.Materials.Count; ++i) { MtrlFile mtrl = new MtrlFile(file.Materials[i]); mtrl.Write(File.Open(Path.Combine(brgMtrlOutputPath, Path.GetFileNameWithoutExtension(f) + "_" + i + ".mtrl"), FileMode.Create, FileAccess.Write, FileShare.Read)); } Console.WriteLine("Success! Mtrl files created."); } else { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(f); if (xmlDoc.DocumentElement.Name == "AnimFile") { AnimFile.ConvertToAnim(File.Open(f, FileMode.Open, FileAccess.Read, FileShare.Read), File.Open(f + ".txt", FileMode.Create, FileAccess.Write, FileShare.Read)); Console.WriteLine("Success! Anim converted."); } else if (xmlDoc.DocumentElement.Name == "ParticleFile") { PrtFile file = PrtFile.DeserializeAsXml(File.Open(f, FileMode.Open, FileAccess.Read, FileShare.Read)); file.Write(File.Open(f + ".prt", FileMode.Create, FileAccess.Write, FileShare.Read)); Console.WriteLine("Success! Prt converted."); } else { MtrlFile file = MtrlFile.DeserializeAsXml(File.Open(f, FileMode.Open, FileAccess.Read, FileShare.Read)); file.Write(File.Open(f + ".mtrl", FileMode.Create, FileAccess.Write, FileShare.Read)); Console.WriteLine("Success! Mtrl converted."); } } }