private static Type getType(IPCCObject pcc, int type) { switch (pcc.GetName(type)) { case "None": return(Type.None); case "StructProperty": return(Type.StructProperty); case "IntProperty": return(Type.IntProperty); case "FloatProperty": return(Type.FloatProperty); case "ObjectProperty": return(Type.ObjectProperty); case "NameProperty": return(Type.NameProperty); case "BoolProperty": return(Type.BoolProperty); case "ByteProperty": return(Type.ByteProperty); case "ArrayProperty": return(Type.ArrayProperty); case "DelegateProperty": return(Type.DelegateProperty); case "StrProperty": return(Type.StrProperty); case "StringRefProperty": return(Type.StringRefProperty); default: return(Type.Unknown); } }
public static List <Property> getPropList(IPCCObject pcc, byte[] raw) { //Application.DoEvents(); int start = detectStart(pcc, raw); return(ReadProp(pcc, raw, start)); }
private static PropertyValue ReadValue(IPCCObject pcc, byte[] raw, int start, int type) { PropertyValue v = new PropertyValue(); switch (pcc.Names[type]) { case "IntProperty": case "FloatProperty": case "ObjectProperty": case "StringRefProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 4; break; case "NameProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 8; break; case "BoolProperty": if (start < raw.Length) { v.IntValue = raw[start]; } v.len = 1; break; } return(v); }
public static CustomProperty PropertyToGrid(Property p, IPCCObject pcc) { string cat = p.TypeVal.ToString(); CustomProperty pg; switch (p.TypeVal) { case Type.BoolProperty: pg = new CustomProperty(p.Name, cat, (p.Value.IntValue == 1), typeof(bool), false, true); break; case Type.FloatProperty: byte[] buff = BitConverter.GetBytes(p.Value.IntValue); float f = BitConverter.ToSingle(buff, 0); pg = new CustomProperty(p.Name, cat, f, typeof(float), false, true); break; case Type.ByteProperty: case Type.NameProperty: NameProp pp = new NameProp(); pp.name = pcc.GetName(p.Value.IntValue); pp.nameindex = p.Value.IntValue; pg = new CustomProperty(p.Name, cat, pp, typeof(NameProp), false, true); break; case Type.ObjectProperty: ObjectProp ppo = new ObjectProp(); ppo.name = pcc.getObjectName(p.Value.IntValue); //ppo.name = pcc.GetName(pcc.Exports[p.Value.IntValue].name); ppo.nameindex = p.Value.IntValue; pg = new CustomProperty(p.Name, cat, ppo, typeof(ObjectProp), false, true); break; case Type.StructProperty: StructProp ppp = new StructProp(); ppp.name = pcc.GetName(p.Value.IntValue); ppp.nameindex = p.Value.IntValue; byte[] buf = new byte[p.Value.Array.Count()]; for (int i = 0; i < p.Value.Array.Count(); i++) { buf[i] = (byte)p.Value.Array[i].IntValue; } List <int> buf2 = new List <int>(); for (int i = 0; i < p.Value.Array.Count() / 4; i++) { buf2.Add(BitConverter.ToInt32(buf, i * 4)); } ppp.data = buf2.ToArray(); pg = new CustomProperty(p.Name, cat, ppp, typeof(StructProp), false, true); break; default: pg = new CustomProperty(p.Name, cat, p.Value.IntValue, typeof(int), false, true); break; } return(pg); }
public static string PropertyToText(Property p, IPCCObject pcc) { string s = ""; s = "Name: " + p.Name; s += ", Type: " + TypeToString((int)p.TypeVal); s += ", Size: " + p.Size + ","; int MEtype = Methods.GetMEType(); switch (p.TypeVal) { case Type.StructProperty: s += " \"" + pcc.GetName(p.Value.IntValue) + "\" with " + p.Size + " bytes"; break; case Type.IntProperty: case Type.ObjectProperty: case Type.StringRefProperty: s += " Value: " + p.Value.IntValue.ToString(); break; case Type.BoolProperty: s += " Value: " + (p.raw[24] == 1); break; case Type.FloatProperty: s += " Value: " + p.Value.FloatValue; break; case Type.NameProperty: s += " " + p.Value.StringValue; break; case Type.ByteProperty: s += " Value: \"" + p.Value.StringValue + "\", with int: " + p.Value.IntValue; break; case Type.ArrayProperty: s += " bytes"; //Value: " + p.Value.Array.Count.ToString() + " Elements"; break; case Type.StrProperty: if (p.Value.StringValue.Length == 0) { break; } s += " Value: " + p.Value.StringValue; break; } return(s); }
/// <summary> /// Searches for PCC by name in a certain game specified by PathInclDLC. Can also use expID to narrow search if required. Return name of PCC, empty if not found. /// </summary> /// <param name="pccname">Name of PCC to search for.</param> /// <param name="PathInclDLC">Path encasing BIOGame and DLC. i.e. Parent folder containing folders BIOGame and DLC.</param> /// <param name="expID">ExpID of an object inside the desired PCC.</param> /// <returns>Name of PCC if found, else empty string.</returns> /*public static string SearchForPCC(string pccname, string PathInclDLC, int expID, string objectName, bool isTexture, int whichgame) * { * // KFreon: Lowercase PCC name * string name = Path.GetFileName(pccname).ToLowerInvariant(); * List<string> searchResults = new List<string>(); * * // KFreon: Create lists of valid files if necessary * lock (ValidFiles) * if (!ValidFiles.ContainsKey(PathInclDLC.ToLowerInvariant())) * { * List<string> temp = Directory.EnumerateFiles(PathInclDLC, "*", SearchOption.AllDirectories).Where(pcc => pcc.EndsWith(".pcc", true, null) || pcc.EndsWith(".u", true, null) || pcc.EndsWith(".sfm", true, null) || pcc.EndsWith(".upk", true, null)).ToList(); * ValidFiles.Add(PathInclDLC.ToLowerInvariant(), temp); * } * * // KFreon: Attempt to find PCC * searchResults.AddRange(ValidFiles[PathInclDLC.ToLowerInvariant()].Where(pcc => pcc.ToLowerInvariant().Contains(name))); * * string retval = ""; * * // KFreon: Do special stuff if multiple files found * if (searchResults.Count > 1) * { * // KFreon: If expID given, use it to try to discern correct pcc * if (expID != -1) * { * List<string> temp = new List<string>(); * foreach (string file in searchResults) * { * // KFreon: Only work on stuff if file is correct given the provided information * if (CheckSearchedTexture(file, expID, objectName, whichgame)) * { * temp.Add(file); * * // KFreon: See if DLC is relevent * string dlcname = KFreonLib.Misc.Methods.GetDLCNameFromPath(pccname); * if (dlcname != "") * { * temp.Clear(); * temp.Add(file); * break; * } * } * } * if (temp.Count == 1) * retval = temp[0]; * else if (temp.Count > 1) * { * // KFreon: If still multiple files found, break things. * using (SelectionForm sf = new SelectionForm(temp, "LET ME KNOW ABOUT THIS PLEASE!!", "Oh dang. More work for me.", false)) * sf.Show(); * * retval = String.Join("#", temp.ToArray()); * DebugOutput.PrintLn("Multiple pccs found for: " + pccname); * foreach (string item in temp) * DebugOutput.PrintLn(item); * DebugOutput.PrintLn(); * } * } * } * else if (searchResults.Count == 1) * { * if (isTexture && CheckSearchedTexture(searchResults[0], expID, objectName, whichgame) || !isTexture) * retval = searchResults[0]; * } * * return retval; * }*/ private static bool CheckSearchedTexture(string file, int expID, string objectName, int whichgame) { DebugOutput.PrintLn("Checking texture"); // KFreon: Test if this files' expID is the one we want IPCCObject pcc = Creation.CreatePCCObject(file, whichgame); // KFreon: First check if there's enough expID's in current file, then if we're looking at a texture in current file if (pcc.Exports.Count >= expID && pcc.Exports[expID].ValidTextureClass()) { bool nametest = (objectName == null ? true : pcc.Exports[expID].ObjectName.ToLowerInvariant().Contains(objectName.ToLowerInvariant())); return(nametest); } return(false); }
public void LoadPcc(IPCCObject pcc, string path) { switch (pcc.GameVersion) { case 1: pcc = new ME1PCCObject(path); break; case 2: pcc = new ME2PCCObject(path); break; case 3: pcc = new ME3PCCObject(path); break; } }
public static int detectStart(IPCCObject pcc, byte[] raw, long flags) { if ((flags & (long)UnrealFlags.EObjectFlags.HasStack) != 0) { return(30); } int result = 8; int test1 = BitConverter.ToInt32(raw, 4); int test2 = BitConverter.ToInt32(raw, 8); if (pcc.isName(test1) && test2 == 0) { result = 4; } if (pcc.isName(test1) && pcc.isName(test2) && test2 != 0) { result = 8; } return(result); }
private static PropertyValue ReadValue(IPCCObject pcc, byte[] raw, int start, int type) { PropertyValue v = new PropertyValue(); switch (pcc.GetName(type)) { case "IntProperty": case "FloatProperty": case "ObjectProperty": case "StringRefProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 4; break; case "NameProperty": v.IntValue = BitConverter.ToInt32(raw, start); var nameRef = new NameReference(); nameRef.index = v.IntValue; nameRef.count = BitConverter.ToInt32(raw, start + 4); nameRef.Name = pcc.getNameEntry(nameRef.index); if (nameRef.count > 0) { nameRef.Name += "_" + (nameRef.count - 1); } v.NameValue = nameRef; v.len = 8; break; case "BoolProperty": if (start < raw.Length) { v.IntValue = raw[start]; } v.len = 1; break; } return(v); }
public static int detectStart(IPCCObject pcc, byte[] raw) { int result = 8; int test1 = BitConverter.ToInt32(raw, 4); if (test1 < 0) { result = 30; } else { int test2 = BitConverter.ToInt32(raw, 8); if (pcc.isName(test1) && test2 == 0) { result = 4; } if (pcc.isName(test1) && pcc.isName(test2) && test2 != 0) { result = 8; } } return(result); }
/// <summary> /// Constructor for tree texture object. /// </summary> /// <param name="temppcc">PCC to get info from.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pathBIOGame">BIOGame path to game targeted.</param> /// <param name="ExecPath">Path to ME3Explorer \exec\ folder.</param> /// <param name="allfiles">List of all PCC's containing texture.</param> /// <param name="Success">OUT: True if sucessfully created.</param> public TreeTexInfo(IPCCObject temppcc, int ExpID, int WhichGame, string pathBIOGame, string ExecPath, out bool Success) { Success = false; CRC32 crcgen = new CRC32(); string ArcPath = pathBIOGame; ITexture2D temptex2D = null; if (temppcc.Exports[ExpID].ValidTextureClass()) { try { temptex2D = temppcc.CreateTexture2D(ExpID, pathBIOGame); } catch (Exception e) { Console.WriteLine(e); return; } // KFreon: If no images, ignore if (temptex2D.imgList.Count == 0) { return; } string texname = temptex2D.texName; IImageInfo tempImg = temptex2D.GenerateImageInfo(); uint hash = 0; /*if (WhichGame != 1 && temptex2D.arcName != "None") * ValidFirstPCC = true;*/ // KFreon: Add pcc name to list in tex2D if necessary /*if (temptex2D.allFiles == null || temptex2D.allFiles.Count == 0) * { * temptex2D.allFiles = new List<string>(); * temptex2D.allFiles.Add(temppcc.pccFileName); * } * else if (!temptex2D.allFiles.Contains(temppcc.pccFileName)) * temptex2D.allFiles.Add(temppcc.pccFileName);*/ // KFreon: Get texture hash if (tempImg.CompareStorage("pccSto")) { if (temptex2D.texFormat != "PF_NormalMap_HQ") { hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, ArcPath)); } else { hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, pathBIOGame), 0, tempImg.uncSize / 2); } } else { byte[] buffer = temptex2D.DumpImg(tempImg.imgSize, ArcPath); if (buffer == null) { hash = 0; } else { if (temptex2D.texFormat != "PF_NormalMap_HQ") { hash = ~crcgen.BlockChecksum(buffer); } else { hash = ~crcgen.BlockChecksum(buffer, 0, tempImg.uncSize / 2); } } } // KFreon: Get image thumbnail string thumbnailPath = ExecPath + "placeholder.ico"; string tempthumbpath = ExecPath + "ThumbnailCaches\\" + "ME" + WhichGame + "ThumbnailCache\\" + texname + "_" + hash + ".jpg"; bool exists = File.Exists(tempthumbpath); if (!exists) { try { using (MemoryStream ms = new MemoryStream(temptex2D.GetImageData())) if (ImageEngine.GenerateThumbnailToFile(ms, tempthumbpath, 128)) { thumbnailPath = tempthumbpath; } } catch { } // KFreon: Don't really care about failures } // KFreon: Initialise things ValidFirstPCC = WhichGame == 2 && (!String.IsNullOrEmpty(temptex2D.arcName) && temptex2D.arcName != "None"); InfoInitialise(temptex2D, ExpID, hash, WhichGame, temppcc, tempImg.offset, thumbnailPath, pathBIOGame); Success = true; } }
/// <summary> /// Common initialiser used by both TexInfo derivations. /// </summary> /// <param name="tex2D">Texture2D to get info from, e.g. Format, mips.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="hash">Hash of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pcc">PCC to get info from, e.g. PackageName</param> /// <param name="tfcoffset">Offset of image data in TFC.</param> /// <param name="thumbpath">Path to thumbnail image.</param> private void InfoInitialise(ITexture2D tex2D, int ExpID, uint hash, int WhichGame, IPCCObject pcc, int tfcoffset, string thumbpath, string pathBIOGame) { List <string> files = new List <string>(); files.Add(pcc.pccFileName); List <int> expids = new List <int>(); expids.Add(ExpID); InfoInitialise(files, expids, hash, tex2D.imgList.Count, new List <ITexture2D>(), WhichGame, pathBIOGame); FullPackage = pcc.Exports[ExpID].PackageFullName; TexName = tex2D.texName; tfcOffset = tfcoffset; Format = tex2D.texFormat; ThumbnailPath = thumbpath; // KFreon: ME2 only? if (pcc.Exports[ExpID].PackageFullName == "Base Package") { FullPackage = Path.GetFileNameWithoutExtension(pcc.pccFileName).ToUpperInvariant(); } else { FullPackage = pcc.Exports[ExpID].PackageFullName.ToUpperInvariant(); } }
/// <summary> /// Constructor for tree texture objects. /// </summary> /// <param name="tex2D">Texture2D to get data from.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="hash">Hash of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pcc">PCC to get info from.</param> /// <param name="tfcoffset">Offset of texture data in TFC.</param> /// <param name="thumbpath">Path to thumbnail.</param> public TreeTexInfo(ITexture2D tex2D, int ExpID, uint hash, int WhichGame, IPCCObject pcc, int tfcoffset, string thumbpath, string pathBIOGame) { InfoInitialise(tex2D, ExpID, hash, WhichGame, pcc, tfcoffset, thumbpath, pathBIOGame); }
private static PropertyValue ReadValue(IPCCObject pcc, byte[] raw, int start, int type) { PropertyValue v = new PropertyValue(); switch (pcc.Names[type]) { case "IntProperty": case "FloatProperty": case "ObjectProperty": case "StringRefProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 4; break; case "NameProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 8; break; case "BoolProperty": if (start < raw.Length) v.IntValue = raw[start]; v.len = 1; break; } return v; }
public static List<Property> ReadProp(IPCCObject pcc, byte[] raw, int start) { Property p; PropertyValue v; int sname; List<Property> result = new List<Property>(); int pos = start; if (raw.Length - pos < 8) return result; int name = (int)BitConverter.ToInt64(raw, pos); if (!pcc.isName(name)) return result; string t = pcc.Names[name]; if (pcc.Names[name] == "None") { p = new Property(); p.Name = name; p.TypeVal = Type.None; p.i = 0; p.offsetval = pos; p.Size = 8; p.Value = new PropertyValue(); p.raw = BitConverter.GetBytes((Int64)name); p.offend = pos + 8; result.Add(p); return result; } int type = (int)BitConverter.ToInt64(raw, pos + 8); int size = BitConverter.ToInt32(raw, pos + 16); int idx = BitConverter.ToInt32(raw, pos + 20); if (!pcc.isName(type) || size < 0 || size >= raw.Length) return result; string tp = pcc.Names[type]; switch (tp) { case "DelegateProperty": p = new Property(); p.Name = name; p.TypeVal = Type.DelegateProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = BitConverter.ToInt32(raw, pos + 28); v.len = size; v.Array = new List<PropertyValue>(); pos += 24; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "ArrayProperty": int count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.ArrayProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = size - 4; count = v.len;//TODO can be other objects too v.Array = new List<PropertyValue>(); pos += 28; for (int i = 0; i < count; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "StrProperty": count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.StrProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = count; pos += 28; string s = ""; for (int i = 0; i < count; i++) s += (char)raw[pos++]; v.StringValue = s; p.Value = v; break; case "StructProperty": sname = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.StructProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = sname; v.len = size; v.Array = new List<PropertyValue>(); pos += 32; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "ByteProperty": p = new Property(); p.Name = name; p.TypeVal = Type.ByteProperty; p.i = idx; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = raw[pos + 24]; v.len = size; pos += 24 + size; p.Value = v; break; case "BoolProperty": p = new Property(); p.Name = name; p.TypeVal = Type.BoolProperty; p.i = idx; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = raw[pos + 24]; v.len = 4; pos += 28; p.Value = v; break; default: p = new Property(); p.Name = name; p.TypeVal = getType(pcc, type); p.i = 0; p.offsetval = pos + 24; p.Value = ReadValue(pcc, raw, pos + 24, type); pos += p.Value.len + 24; break; } p.raw = new byte[pos - start]; p.offend = pos; if (pos < raw.Length) for (int i = 0; i < pos - start; i++) p.raw[i] = raw[start + i]; result.Add(p); if (pos != start) result.AddRange(ReadProp(pcc, raw, pos)); return result; }
public static string PropertyToText(Property p, IPCCObject pcc) { string s = ""; s = "Name: " + pcc.Names[p.Name]; s += " Type: " + TypeToString((int)p.TypeVal); s += " Size: " + p.Value.len.ToString(); int MEtype = Methods.GetMEType(); switch (p.TypeVal) { case Type.StructProperty: s += " \"" + pcc.GetName(p.Value.IntValue) + "\" with " + p.Value.Array.Count.ToString() + " bytes"; break; case Type.IntProperty: case Type.BoolProperty: case Type.StringRefProperty: s += " Value: " + p.Value.IntValue.ToString(); break; case Type.ObjectProperty: if (MEtype == 2) s += " Value: " + p.Value.IntValue.ToString(); else { s += " Value: " + p.Value.IntValue.ToString() + " "; int v = p.Value.IntValue; if (v == 0) s += "None"; else s += pcc.GetClass(v); } break; case Type.FloatProperty: byte[] buff = BitConverter.GetBytes(p.Value.IntValue); float f = BitConverter.ToSingle(buff, 0); s += " Value: " + f.ToString(); break; case Type.NameProperty: s += " " + pcc.Names[p.Value.IntValue]; break; case Type.ByteProperty: s += " Value: \"" + p.Value.StringValue + "\" with \"" + pcc.GetName(p.Value.IntValue) + "\""; break; case Type.ArrayProperty: s += " bytes"; //Value: " + p.Value.Array.Count.ToString() + " Elements"; break; case Type.StrProperty: if (p.Value.StringValue.Length == 0) break; s += " Value: " + p.Value.StringValue.Substring(0, p.Value.StringValue.Length - 1); break; } return s; }
public static int detectStart(IPCCObject pcc, byte[] raw) { int result = 8; int test1 = BitConverter.ToInt32(raw, 4); if (test1 < 0) result = 30; else { int test2 = BitConverter.ToInt32(raw, 8); if (pcc.isName(test1) && test2 == 0) result = 4; if (pcc.isName(test1) && pcc.isName(test2) && test2 != 0) result = 8; } return result; }
public void CopyImgList(ITexture2D tex2D, IPCCObject PCC) { throw new NotImplementedException(); }
public static List <Property> ReadProp(IPCCObject pcc, byte[] raw, int start) { Property p; PropertyValue v; int sname; List <Property> result = new List <Property>(); int pos = start; if (raw.Length - pos < 8) { return(result); } int name = (int)BitConverter.ToInt64(raw, pos); if (!pcc.isName(name)) { return(result); } int MEtype = Methods.GetMEType(); string t = pcc.GetName(name); bool test = t == "None"; if (MEtype == 3) { t = pcc.Names[name]; test = pcc.Names[name] == "None"; } else if (MEtype != 1 && MEtype != 2) { DebugOutput.PrintLn("Failed to get ME Game Type."); return(new List <Property>()); } if (test) { p = new Property(); p.Name = t; p.TypeVal = Type.None; p.i = 0; p.offsetval = pos; p.Size = (MEtype == 3) ? 8 : 20; p.Value = new PropertyValue(); p.raw = BitConverter.GetBytes((Int64)name); p.offend = pos + ((MEtype == 3) ? 8 : 20); result.Add(p); return(result); } int type = (int)BitConverter.ToInt64(raw, pos + 8); int size = BitConverter.ToInt32(raw, pos + 16); int idx = BitConverter.ToInt32(raw, pos + 20); //Unused if (!pcc.isName(type) || size < 0 || size >= raw.Length) { return(result); } string tp = (MEtype == 3) ? pcc.Names[type] : pcc.GetName(type); switch (tp) { case "BoolProperty": p = new Property(); p.TypeVal = Type.BoolProperty; p.Name = t; p.Size = size; v = new PropertyValue(); if (MEtype == 3) { p.offsetval = pos + 24; pos += 25; byte temp = raw[p.offsetval]; v.IntValue = (int)temp; v.Boolereno = temp == 1; } else { p.i = 0; v.IntValue = BitConverter.ToInt32(raw, pos + ((MEtype == 2) ? 24 : 16)); //Guess. I haven't seen a true boolproperty yet pos += 28; } p.Value = v; break; case "NameProperty": p = new Property(); p.TypeVal = Type.NameProperty; p.Name = t; p.Size = size; v = new PropertyValue(); if (MEtype == 3) { pos += 24; v.IntValue = BitConverter.ToInt32(raw, pos); v.StringValue = pcc.GetName(v.IntValue); // Heff: Temporary modification to handle name refs properly, until we can rewrite the whole property system accross all tools var nameRef = new NameReference(); nameRef.index = v.IntValue; nameRef.count = BitConverter.ToInt32(raw, pos + 4); nameRef.Name = pcc.getNameEntry(nameRef.index); if (nameRef.count > 0) { nameRef.Name += "_" + (nameRef.count - 1); } v.NameValue = nameRef; pos += size; } else { //pos += 32; //int tempInt = BitConverter.ToInt32(raw, pos + 24); p.i = 0; v.IntValue = BitConverter.ToInt32(raw, pos + 24); v.StringValue = pcc.GetName(v.IntValue); // Heff: Temporary modification to handle name refs properly, until we can rewrite the whole property system accross all tools var nameRef = new NameReference(); nameRef.index = v.IntValue; nameRef.count = BitConverter.ToInt32(raw, pos + 4); nameRef.Name = pcc.getNameEntry(nameRef.index); if (nameRef.count > 0) { nameRef.Name += "_" + (nameRef.count - 1); } v.NameValue = nameRef; pos += 32; } p.Value = v; break; case "IntProperty": p = new Property(); p.TypeVal = Type.IntProperty; v = new PropertyValue(); p.Name = t; p.Size = size; if (MEtype == 3) { pos += 24; v.IntValue = (int)BitConverter.ToInt64(raw, pos); pos += size; } else { v.IntValue = BitConverter.ToInt32(raw, pos + 24); p.i = 0; p.offsetval = pos + 24; pos += 28; } p.Value = v; break; case "DelegateProperty": p = new Property(); p.Name = t; p.TypeVal = Type.DelegateProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = BitConverter.ToInt32(raw, pos + 28); v.len = size; v.Array = new List <PropertyValue>(); if (MEtype != 3) { p.Size = size; } pos += 24; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) { v2.IntValue = raw[pos]; } v.Array.Add(v2); pos++; } p.Value = v; break; case "ArrayProperty": int count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = t; if (MEtype != 3) { p.Size = size; } p.TypeVal = Type.ArrayProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = size - 4; count = v.len;//TODO can be other objects too v.Array = new List <PropertyValue>(); pos += 28; for (int i = 0; i < count; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) { v2.IntValue = raw[pos]; } v.Array.Add(v2); pos++; } p.Value = v; break; case "StrProperty": if (MEtype == 2) { count = (int)BitConverter.ToInt32(raw, pos + 24); } else { count = (int)BitConverter.ToInt64(raw, pos + 24); } p = new Property(); p.Name = t; if (MEtype != 3) { p.Size = size; } p.TypeVal = Type.StrProperty; p.i = 0; p.offsetval = pos + 24; if (MEtype == 3) { count *= -1; } v = new PropertyValue(); v.IntValue = type; v.len = count; pos += 28; string s = ""; for (int i = 0; i < ((MEtype == 3) ? count : count - 1); i++) { s += (char)raw[pos]; if (MEtype == 3) { pos += 2; } else { pos++; } } if (MEtype != 3) { pos++; } v.StringValue = s; p.Value = v; break; case "StructProperty": sname = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = t; p.Size = size; p.TypeVal = Type.StructProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = sname; v.len = size; v.Array = new List <PropertyValue>(); if (MEtype == 3) { v.StringValue = pcc.Names[sname]; } else if (MEtype == 3) { v.StringValue = pcc.GetName(sname); } pos += 32; for (int i = 0; i < size; i += ((MEtype == 3) ? 1 : 4)) { PropertyValue v2 = new PropertyValue(); //if (pos < raw.Length) // v2.IntValue = raw[pos]; //v.Array.Add(v2); //pos++; if (pos < raw.Length) { v2.IntValue = (MEtype == 3) ? raw[pos] : BitConverter.ToInt32(raw, pos); } v.Array.Add(v2); pos += (MEtype == 3) ? 1 : 4; } p.Value = v; break; case "ByteProperty": if (MEtype == 3) { sname = (int)BitConverter.ToInt64(raw, pos + 24); } else { sname = BitConverter.ToInt32(raw, pos + 24); } p = new Property(); p.Name = t; p.Size = size; p.TypeVal = Type.ByteProperty; p.i = 0; p.offsetval = pos + 32; v = new PropertyValue(); v.StringValue = (MEtype == 3) ? pcc.getNameEntry(sname) : pcc.GetName(sname); v.len = size; if (MEtype == 3) { pos += 32; v.IntValue = BitConverter.ToInt32(raw, pos); v.String2 = pcc.Names[v.IntValue]; // Heff: Temporary modification to handle name refs properly, until we can rewrite the whole property system accross all tools // This is stupid for enum properties, but as the enum itself will probably never be a name with index it works.. var nameRef = new NameReference(); nameRef.index = v.IntValue; nameRef.count = BitConverter.ToInt32(raw, pos + 4); nameRef.Name = pcc.getNameEntry(nameRef.index); if (nameRef.count > 0) { nameRef.Name += "_" + (nameRef.count - 1); } v.NameValue = nameRef; pos += size; } else { v.IntValue = BitConverter.ToInt32(raw, pos + 28); if (MEtype == 2) { v.String2 = pcc.GetName(v.IntValue); } pos += 32; } //v.IntValue = (int)BitConverter.ToInt64(raw, pos); //pos += size; p.Value = v; break; case "FloatProperty": if (MEtype == 1) { sname = (int)BitConverter.ToInt64(raw, pos + 24); } else if (MEtype == 2) { sname = BitConverter.ToInt32(raw, pos + 24); } p = new Property(); p.Name = t; p.Size = size; p.TypeVal = Type.FloatProperty; p.i = 0; p.offsetval = (MEtype != 3) ? pos + 24 : 24; v = new PropertyValue(); v.FloatValue = BitConverter.ToSingle(raw, pos + 24); v.len = size; pos += 28; p.Value = v; break; default: p = new Property(); p.Name = t; p.TypeVal = getType(pcc, type); p.i = 0; if (MEtype != 3) { p.Size = size; } p.offsetval = pos + 24; p.Value = ReadValue(pcc, raw, pos + 24, type); pos += p.Value.len + 24; break; } p.raw = new byte[pos - start]; p.offend = pos; if (pos < raw.Length) { for (int i = 0; i < pos - start; i++) { p.raw[i] = raw[start + i]; } } result.Add(p); if (pos != start) { result.AddRange(ReadProp(pcc, raw, pos)); } return(result); }
/// <summary> /// Constructor for tree texture object. /// </summary> /// <param name="temppcc">PCC to get info from.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pathBIOGame">BIOGame path to game targeted.</param> /// <param name="ExecPath">Path to ME3Explorer \exec\ folder.</param> /// <param name="allfiles">List of all PCC's containing texture.</param> /// <param name="Success">OUT: True if sucessfully created.</param> public TreeTexInfo(IPCCObject temppcc, int ExpID, int WhichGame, string pathBIOGame, string ExecPath, out bool Success) { Success = false; CRC32 crcgen = new CRC32(); string ArcPath = pathBIOGame; ITexture2D temptex2D = null; if (temppcc.Exports[ExpID].ValidTextureClass()) { try { temptex2D = temppcc.CreateTexture2D(ExpID, pathBIOGame); } catch (Exception e) { Console.WriteLine(e); return; } // KFreon: If no images, ignore if (temptex2D.imgList.Count == 0) return; string texname = temptex2D.texName; IImageInfo tempImg = temptex2D.GenerateImageInfo(); uint hash = 0; /*if (WhichGame != 1 && temptex2D.arcName != "None") ValidFirstPCC = true;*/ // KFreon: Add pcc name to list in tex2D if necessary /*if (temptex2D.allFiles == null || temptex2D.allFiles.Count == 0) { temptex2D.allFiles = new List<string>(); temptex2D.allFiles.Add(temppcc.pccFileName); } else if (!temptex2D.allFiles.Contains(temppcc.pccFileName)) temptex2D.allFiles.Add(temppcc.pccFileName);*/ // KFreon: Get texture hash if (tempImg.CompareStorage("pccSto")) { if (temptex2D.texFormat != "PF_NormalMap_HQ") hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, ArcPath)); else hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, pathBIOGame), 0, tempImg.uncSize / 2); } else { byte[] buffer = temptex2D.DumpImg(tempImg.imgSize, ArcPath); if (buffer == null) hash = 0; else { if (temptex2D.texFormat != "PF_NormalMap_HQ") hash = ~crcgen.BlockChecksum(buffer); else hash = ~crcgen.BlockChecksum(buffer, 0, tempImg.uncSize / 2); } } // KFreon: Get image thumbnail string thumbnailPath = ExecPath + "placeholder.ico"; string tempthumbpath = ExecPath + "ThumbnailCaches\\" + "ME" + WhichGame + "ThumbnailCache\\" + texname + "_" + hash + ".jpg"; bool exists = File.Exists(tempthumbpath); if (!exists) try { using (MemoryStream ms = new MemoryStream(temptex2D.GetImageData())) if (ImageEngine.GenerateThumbnailToFile(ms, tempthumbpath, 128)) thumbnailPath = tempthumbpath; } catch { } // KFreon: Don't really care about failures // KFreon: Initialise things ValidFirstPCC = WhichGame == 2 && (!String.IsNullOrEmpty(temptex2D.arcName) && temptex2D.arcName != "None"); InfoInitialise(temptex2D, ExpID, hash, WhichGame, temppcc, tempImg.offset, thumbnailPath, pathBIOGame); Success = true; } }
/// <summary> /// Create a Texture2D from things. /// </summary> /// <param name="filename">Filename to load Texture2D from.</param> /// <param name="expID">ExpID of texture in question.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pathBIOGame">Path to BIOGame.</param> /// <param name="hash">Hash of texture.</param> /// <returns>Texture2D object</returns> public static ITexture2D CreateTexture2D(string filename, int expID, int WhichGame, string pathBIOGame, uint hash = 0) { IPCCObject pcc = PCCObjects.Creation.CreatePCCObject(filename, WhichGame); return(pcc.CreateTexture2D(expID, pathBIOGame, hash)); }
public MemoryStream DecompressPCC(Stream raw, IPCCObject pcc) { raw.Seek(pcc.header.Length, SeekOrigin.Begin); int pos = 4; pcc.NumChunks = raw.ReadValueS32(); List <Chunk> Chunks = new List <Chunk>(); //DebugOutput.PrintLn("Reading chunk headers..."); for (int i = 0; i < pcc.NumChunks; i++) { Chunk c = new Chunk(); c.uncompressedOffset = raw.ReadValueS32(); c.uncompressedSize = raw.ReadValueS32(); c.compressedOffset = raw.ReadValueS32(); c.compressedSize = raw.ReadValueS32(); c.Compressed = new byte[c.compressedSize]; c.Uncompressed = new byte[c.uncompressedSize]; //DebugOutput.PrintLn("Chunk " + i + ", compressed size = " + c.compressedSize + ", uncompressed size = " + c.uncompressedSize); //DebugOutput.PrintLn("Compressed offset = " + c.compressedOffset + ", uncompressed offset = " + c.uncompressedOffset); Chunks.Add(c); } //DebugOutput.PrintLn("\tRead Chunks..."); int count = 0; for (int i = 0; i < Chunks.Count; i++) { Chunk c = Chunks[i]; raw.Seek(c.compressedOffset, SeekOrigin.Begin); c.Compressed = raw.ReadBytes(c.compressedSize); ChunkHeader h = new ChunkHeader(); h.magic = BitConverter.ToInt32(c.Compressed, 0); if (h.magic != -1641380927) { throw new FormatException("Chunk magic number incorrect"); } h.blocksize = BitConverter.ToInt32(c.Compressed, 4); h.compressedsize = BitConverter.ToInt32(c.Compressed, 8); h.uncompressedsize = BitConverter.ToInt32(c.Compressed, 12); //DebugOutput.PrintLn("Chunkheader read: Magic = " + h.magic + ", Blocksize = " + h.blocksize + ", Compressed Size = " + h.compressedsize + ", Uncompressed size = " + h.uncompressedsize); pos = 16; int blockCount = (h.uncompressedsize % h.blocksize == 0) ? h.uncompressedsize / h.blocksize : h.uncompressedsize / h.blocksize + 1; List <Block> BlockList = new List <Block>(); //DebugOutput.PrintLn("\t\t" + count + " Read Blockheaders..."); for (int j = 0; j < blockCount; j++) { Block b = new Block(); b.compressedsize = BitConverter.ToInt32(c.Compressed, pos); b.uncompressedsize = BitConverter.ToInt32(c.Compressed, pos + 4); //DebugOutput.PrintLn("Block " + j + ", compressed size = " + b.compressedsize + ", uncompressed size = " + b.uncompressedsize); pos += 8; BlockList.Add(b); } int outpos = 0; //DebugOutput.PrintLn("\t\t" + count + " Read and decompress Blocks..."); foreach (Block b in BlockList) { byte[] datain = new byte[b.compressedsize]; byte[] dataout = new byte[b.uncompressedsize]; for (int j = 0; j < b.compressedsize; j++) { datain[j] = c.Compressed[pos + j]; } pos += b.compressedsize; try { LZO1X.Decompress(datain, dataout); } catch (DllNotFoundException ex) { var mbResult = MessageBox.Show("Decompression failed! This may be the fault of a missing 2010 VC++ redistributable. Would you like to install this now?\n(make sure to restart ME3Explorer after installation.)", "", MessageBoxButton.YesNo, MessageBoxImage.Exclamation); if (mbResult == MessageBoxResult.Yes) { Process.Start("https://www.microsoft.com/en-us/download/details.aspx?id=5555"); } throw new Exception("LZO decompression failed!", ex); } for (int j = 0; j < b.uncompressedsize; j++) { c.Uncompressed[outpos + j] = dataout[j]; } outpos += b.uncompressedsize; } c.header = h; c.blocks = BlockList; count++; Chunks[i] = c; } MemoryStream result = new MemoryStream(); foreach (Chunk c in Chunks) { result.Seek(c.uncompressedOffset, SeekOrigin.Begin); result.WriteBytes(c.Uncompressed); } return(result); }
public static List<Property> ReadProp(IPCCObject pcc, byte[] raw, int start) { Property p; PropertyValue v; int sname; List<Property> result = new List<Property>(); int pos = start; if (raw.Length - pos < 8) return result; int name = (int)BitConverter.ToInt64(raw, pos); if (!pcc.isName(name)) return result; int MEtype = Methods.GetMEType(); string t = pcc.GetName(name); bool test = t == "None"; if (MEtype == 3) { t = pcc.Names[name]; test = pcc.Names[name] == "None"; } else if (MEtype != 1 && MEtype != 2) { DebugOutput.PrintLn("Failed to get ME Game Type."); return new List<Property>(); } if (test) { p = new Property(); p.Name = t; p.TypeVal = Type.None; p.i = 0; p.offsetval = pos; p.Size = (MEtype == 3) ? 8 : 20; p.Value = new PropertyValue(); p.raw = BitConverter.GetBytes((Int64)name); p.offend = pos + ((MEtype == 3) ? 8 : 20); result.Add(p); return result; } int type = (int)BitConverter.ToInt64(raw, pos + 8); int size = BitConverter.ToInt32(raw, pos + 16); int idx = BitConverter.ToInt32(raw, pos + 20); //Unused if (!pcc.isName(type) || size < 0 || size >= raw.Length) return result; string tp = (MEtype == 3) ? pcc.Names[type] : pcc.GetName(type); switch (tp) { case "BoolProperty": p = new Property(); p.TypeVal = Type.BoolProperty; p.Name = t; p.Size = size; v = new PropertyValue(); if (MEtype == 3) { p.offsetval = pos + 24; pos += 25; byte temp = raw[p.offsetval]; v.IntValue = (int)temp; v.Boolereno = temp == 1; } else { p.i = 0; v.IntValue = BitConverter.ToInt32(raw, pos + ((MEtype == 2) ? 24 : 16)); //Guess. I haven't seen a true boolproperty yet pos += 28; } p.Value = v; break; case "NameProperty": p = new Property(); p.TypeVal = Type.NameProperty; p.Name = t; p.Size = size; v = new PropertyValue(); if (MEtype == 3) { pos += 24; v.IntValue = (int)BitConverter.ToInt64(raw, pos); v.StringValue = pcc.Names[v.IntValue]; pos += size; } else { //pos += 32; //int tempInt = BitConverter.ToInt32(raw, pos + 24); p.i = 0; v.StringValue = pcc.GetName(BitConverter.ToInt32(raw, pos + 24)); pos += 32; } p.Value = v; break; case "IntProperty": p = new Property(); p.TypeVal = Type.IntProperty; v = new PropertyValue(); p.Name = t; p.Size = size; if (MEtype == 3) { pos += 24; v.IntValue = (int)BitConverter.ToInt64(raw, pos); pos += size; } else { v.IntValue = BitConverter.ToInt32(raw, pos + 24); p.i = 0; p.offsetval = pos + 24; pos += 28; } p.Value = v; break; case "DelegateProperty": p = new Property(); p.Name = t; p.TypeVal = Type.DelegateProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = BitConverter.ToInt32(raw, pos + 28); v.len = size; v.Array = new List<PropertyValue>(); if (MEtype != 3) p.Size = size; pos += 24; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "ArrayProperty": int count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = t; if (MEtype != 3) p.Size = size; p.TypeVal = Type.ArrayProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = size - 4; count = v.len;//TODO can be other objects too v.Array = new List<PropertyValue>(); pos += 28; for (int i = 0; i < count; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "StrProperty": if (MEtype == 2) count = (int)BitConverter.ToInt32(raw, pos + 24); else count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = t; if (MEtype != 3) p.Size = size; p.TypeVal = Type.StrProperty; p.i = 0; p.offsetval = pos + 24; if (MEtype == 3) count *= -1; v = new PropertyValue(); v.IntValue = type; v.len = count; pos += 28; string s = ""; for (int i = 0; i < ((MEtype == 3) ? count : count - 1); i++) { s += (char)raw[pos]; if (MEtype == 3) pos += 2; else pos++; } if (MEtype != 3) pos++; v.StringValue = s; p.Value = v; break; case "StructProperty": sname = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = t; p.Size = size; p.TypeVal = Type.StructProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = sname; v.len = size; v.Array = new List<PropertyValue>(); if (MEtype == 3) v.StringValue = pcc.Names[sname]; else if (MEtype == 3) v.StringValue = pcc.GetName(sname); pos += 32; for (int i = 0; i < size; i += ((MEtype == 3) ? 1 : 4)) { PropertyValue v2 = new PropertyValue(); //if (pos < raw.Length) // v2.IntValue = raw[pos]; //v.Array.Add(v2); //pos++; if (pos < raw.Length) v2.IntValue = (MEtype == 3) ? raw[pos] : BitConverter.ToInt32(raw, pos); v.Array.Add(v2); pos += (MEtype == 3) ? 1 : 4; } p.Value = v; break; case "ByteProperty": if (MEtype == 3) sname = (int)BitConverter.ToInt64(raw, pos + 24); else sname = BitConverter.ToInt32(raw, pos + 24); p = new Property(); p.Name = t; p.Size = size; p.TypeVal = Type.ByteProperty; p.i = 0; p.offsetval = pos + 32; v = new PropertyValue(); v.StringValue = (MEtype == 3) ? pcc.getNameEntry(sname) : pcc.GetName(sname); v.len = size; if (MEtype == 3) { pos += 32; v.IntValue = BitConverter.ToInt32(raw, pos); v.String2 = pcc.Names[v.IntValue]; pos += size; } else { v.IntValue = BitConverter.ToInt32(raw, pos + 28); if (MEtype == 2) v.String2 = pcc.GetName(v.IntValue); pos += 32; } //v.IntValue = (int)BitConverter.ToInt64(raw, pos); //pos += size; p.Value = v; break; case "FloatProperty": if (MEtype == 1) sname = (int)BitConverter.ToInt64(raw, pos + 24); else if (MEtype == 2) sname = BitConverter.ToInt32(raw, pos + 24); p = new Property(); p.Name = t; p.Size = size; p.TypeVal = Type.FloatProperty; p.i = 0; p.offsetval = (MEtype != 3) ? pos + 24 : 24; v = new PropertyValue(); v.FloatValue = BitConverter.ToSingle(raw, pos + 24); v.len = size; pos += 28; p.Value = v; break; default: p = new Property(); p.Name = t; p.TypeVal = getType(pcc, type); p.i = 0; if (MEtype != 3) p.Size = size; p.offsetval = pos + 24; p.Value = ReadValue(pcc, raw, pos + 24, type); pos += p.Value.len + 24; break; } p.raw = new byte[pos - start]; p.offend = pos; if (pos < raw.Length) for (int i = 0; i < pos - start; i++) p.raw[i] = raw[start + i]; result.Add(p); if (pos != start) result.AddRange(ReadProp(pcc, raw, pos)); return result; }
public static string PropertyToText(Property p, IPCCObject pcc) { string s = ""; s = "Name: " + pcc.Names[p.Name]; s += " Type: " + TypeToString((int)p.TypeVal); s += " Size: " + p.Value.len.ToString(); int MEtype = Methods.GetMEType(); switch (p.TypeVal) { case Type.StructProperty: s += " \"" + pcc.GetName(p.Value.IntValue) + "\" with " + p.Value.Array.Count.ToString() + " bytes"; break; case Type.IntProperty: case Type.BoolProperty: case Type.StringRefProperty: s += " Value: " + p.Value.IntValue.ToString(); break; case Type.ObjectProperty: if (MEtype == 2) { s += " Value: " + p.Value.IntValue.ToString(); } else { s += " Value: " + p.Value.IntValue.ToString() + " "; int v = p.Value.IntValue; if (v == 0) { s += "None"; } else { s += pcc.GetClass(v); } } break; case Type.FloatProperty: byte[] buff = BitConverter.GetBytes(p.Value.IntValue); float f = BitConverter.ToSingle(buff, 0); s += " Value: " + f.ToString(); break; case Type.NameProperty: s += " " + pcc.Names[p.Value.IntValue]; break; case Type.ByteProperty: s += " Value: \"" + p.Value.StringValue + "\" with \"" + pcc.GetName(p.Value.IntValue) + "\""; break; case Type.ArrayProperty: s += " bytes"; //Value: " + p.Value.Array.Count.ToString() + " Elements"; break; case Type.StrProperty: if (p.Value.StringValue.Length == 0) { break; } s += " Value: " + p.Value.StringValue.Substring(0, p.Value.StringValue.Length - 1); break; } return(s); }
public static List<Property> getPropList(IPCCObject pcc, byte[] raw) { //Application.DoEvents(); int start = detectStart(pcc, raw); return ReadProp(pcc, raw, start); }
/// <summary> /// Gets details, like pcc's and expID's, from current script and sets local properties. /// Properties: /// ExpID's, PCC's, Texname, WhichGame, JobType. /// </summary> public bool GetJobDetails(bool update, out bool versionConflict, int version) { JobType = DetectJobType(); versionConflict = false; DebugOutput.PrintLn(String.Format("Job: {0} type: {1}", Name, JobType)); bool isTexture = JobType == "TEXTURE" ? true : false; ExpIDs = ModMaker.GetExpIDsFromScript(Script, isTexture); //Heff: adjust script paths for legacy ME3 DLC mods that references un-extracted DLC's FixLegacyDLCPaths(); PCCs = ModMaker.GetPCCsFromScript(Script, isTexture); Texname = ModMaker.GetObjectNameFromScript(Script, isTexture); WhichGame = version == -1 ? ModMaker.GetGameVersionFromScript(Script, isTexture) : version; DebugOutput.PrintLn(String.Format("Job: {0} Detected game version: {1} Detected texname: {2}", Name, WhichGame, Texname)); // KFreon: Extra stuff to guess various things - NEW rev696 - from the WPF builds. Maybe unstable. #region Extra stuff from WPF // KFreon: Guess game version if required if (WhichGame == -1 && update) { DebugOutput.PrintLn("Attempting to guess game version..."); /*int index = PCCs[0].IndexOf("Mass Effect"); * char c = PCCs[0][index + 1];*/ DebugOutput.PrintLn("Found num PCCS: " + PCCs.Count); WhichGame = GuessGame(PCCs); if (WhichGame == -2) { versionConflict = true; return(false); } } if (WhichGame == -1) { DebugOutput.PrintLn("ERROR: No game found matching the mod files!\n" + "Make sure that you have the proper game installed, and that the toolset has the correct path!\n" + "If the mod targets DLC files, make sure that you have extracted all relevant DLC's."); MessageBox.Show("No game found matching the mod files!\n" + "Make sure that you have the proper game installed, and that the toolset has the correct path!\n" + "If the mod targets DLC files, make sure that you have extracted all relevant DLC's.", "Error!"); return(false); } else { DebugOutput.PrintLn("Guessed gameversion: " + WhichGame); } // KFreon: Get ExpID's if required if (ExpIDs.Count == 0 && update) { DebugOutput.PrintLn("Unable to find ExpID's in script. Attempting to find them manually. Game: " + WhichGame); string biogame = MEDirectories.MEDirectories.GetDefaultBIOGame(WhichGame); List <string> gameFiles = MEDirectories.MEDirectories.EnumerateGameFiles(WhichGame, biogame); foreach (string pcc in PCCs) { //DebugOutput.PrintLn("Searching: " + pcc); int index = -1; if ((index = gameFiles.FindIndex(t => t.ToLower().Contains(pcc.ToLower()))) >= 0) { IPCCObject pccObject = PCCObjects.Creation.CreatePCCObject(gameFiles[index], WhichGame); int count = 0; foreach (IExportEntry export in pccObject.Exports) { //DebugOutput.PrintLn("Searching export: " + export.ObjectName); if (export.ObjectName.Contains(Texname)) { ExpIDs.Add(count); } count++; } } } DebugOutput.PrintLn("Finished searching. Found: " + ExpIDs.Count + " matches."); } #endregion Extra Stuff from WPF OrigExpIDs = new List <int>(ExpIDs); OrigPCCs = new List <string>(PCCs); OriginalScript = Script; return(true); }
public static CustomProperty PropertyToGrid(Property p, IPCCObject pcc) { string cat = p.TypeVal.ToString(); CustomProperty pg; switch (p.TypeVal) { case Type.BoolProperty: pg = new CustomProperty(pcc.Names[p.Name], cat, (p.Value.IntValue == 1), typeof(bool), false, true); break; case Type.FloatProperty: byte[] buff = BitConverter.GetBytes(p.Value.IntValue); float f = BitConverter.ToSingle(buff, 0); pg = new CustomProperty(pcc.Names[p.Name], cat, f, typeof(float), false, true); break; case Type.ByteProperty: case Type.NameProperty: NameProp pp = new NameProp(); pp.name = pcc.GetName(p.Value.IntValue); pp.nameindex = p.Value.IntValue; pg = new CustomProperty(pcc.Names[p.Name], cat, pp, typeof(NameProp), false, true); break; case Type.ObjectProperty: ObjectProp ppo = new ObjectProp(); ppo.name = pcc.getObjectName(p.Value.IntValue); ppo.nameindex = p.Value.IntValue; pg = new CustomProperty(pcc.Names[p.Name], cat, ppo, typeof(ObjectProp), false, true); break; case Type.StructProperty: StructProp ppp = new StructProp(); ppp.name = pcc.GetName(p.Value.IntValue); ppp.nameindex = p.Value.IntValue; byte[] buf = new byte[p.Value.Array.Count()]; for (int i = 0; i < p.Value.Array.Count(); i++) buf[i] = (byte)p.Value.Array[i].IntValue; List<int> buf2 = new List<int>(); for (int i = 0; i < p.Value.Array.Count() / 4; i++) buf2.Add(BitConverter.ToInt32(buf, i * 4)); ppp.data = buf2.ToArray(); pg = new CustomProperty(pcc.Names[p.Name], cat, ppp, typeof(StructProp), false, true); break; default: pg = new CustomProperty(pcc.Names[p.Name], cat, p.Value.IntValue, typeof(int), false, true); break; } return pg; }
public MemoryStream DecompressPCC(Stream raw, IPCCObject pcc) { raw.Seek(pcc.header.Length, SeekOrigin.Begin); int pos = 4; pcc.NumChunks = raw.ReadValueS32(); List <Chunk> Chunks = new List <Chunk>(); //DebugOutput.PrintLn("Reading chunk headers..."); for (int i = 0; i < pcc.NumChunks; i++) { Chunk c = new Chunk(); c.uncompressedOffset = raw.ReadValueS32(); c.uncompressedSize = raw.ReadValueS32(); c.compressedOffset = raw.ReadValueS32(); c.compressedSize = raw.ReadValueS32(); c.Compressed = new byte[c.compressedSize]; c.Uncompressed = new byte[c.uncompressedSize]; //DebugOutput.PrintLn("Chunk " + i + ", compressed size = " + c.compressedSize + ", uncompressed size = " + c.uncompressedSize); //DebugOutput.PrintLn("Compressed offset = " + c.compressedOffset + ", uncompressed offset = " + c.uncompressedOffset); Chunks.Add(c); } //DebugOutput.PrintLn("\tRead Chunks..."); int count = 0; for (int i = 0; i < Chunks.Count; i++) { Chunk c = Chunks[i]; raw.Seek(c.compressedOffset, SeekOrigin.Begin); c.Compressed = raw.ReadBytes(c.compressedSize); ChunkHeader h = new ChunkHeader(); h.magic = BitConverter.ToInt32(c.Compressed, 0); if (h.magic != -1641380927) { throw new FormatException("Chunk magic number incorrect"); } h.blocksize = BitConverter.ToInt32(c.Compressed, 4); h.compressedsize = BitConverter.ToInt32(c.Compressed, 8); h.uncompressedsize = BitConverter.ToInt32(c.Compressed, 12); //DebugOutput.PrintLn("Chunkheader read: Magic = " + h.magic + ", Blocksize = " + h.blocksize + ", Compressed Size = " + h.compressedsize + ", Uncompressed size = " + h.uncompressedsize); pos = 16; int blockCount = (h.uncompressedsize % h.blocksize == 0) ? h.uncompressedsize / h.blocksize : h.uncompressedsize / h.blocksize + 1; List <Block> BlockList = new List <Block>(); //DebugOutput.PrintLn("\t\t" + count + " Read Blockheaders..."); for (int j = 0; j < blockCount; j++) { Block b = new Block(); b.compressedsize = BitConverter.ToInt32(c.Compressed, pos); b.uncompressedsize = BitConverter.ToInt32(c.Compressed, pos + 4); //DebugOutput.PrintLn("Block " + j + ", compressed size = " + b.compressedsize + ", uncompressed size = " + b.uncompressedsize); pos += 8; BlockList.Add(b); } int outpos = 0; //DebugOutput.PrintLn("\t\t" + count + " Read and decompress Blocks..."); foreach (Block b in BlockList) { byte[] datain = new byte[b.compressedsize]; byte[] dataout = new byte[b.uncompressedsize]; for (int j = 0; j < b.compressedsize; j++) { datain[j] = c.Compressed[pos + j]; } pos += b.compressedsize; if (LZO2.Decompress(datain, (uint)datain.Length, dataout) != b.uncompressedsize) { throw new Exception("LZO decompression failed!"); } for (int j = 0; j < b.uncompressedsize; j++) { c.Uncompressed[outpos + j] = dataout[j]; } outpos += b.uncompressedsize; } c.header = h; c.blocks = BlockList; count++; Chunks[i] = c; } MemoryStream result = new MemoryStream(); foreach (Chunk c in Chunks) { result.Seek(c.uncompressedOffset, SeekOrigin.Begin); result.WriteBytes(c.Uncompressed); } return(result); }
private static Type getType(IPCCObject pcc, int type) { switch (pcc.GetName(type)) { case "None": return Type.None; case "StructProperty": return Type.StructProperty; case "IntProperty": return Type.IntProperty; case "FloatProperty": return Type.FloatProperty; case "ObjectProperty": return Type.ObjectProperty; case "NameProperty": return Type.NameProperty; case "BoolProperty": return Type.BoolProperty; case "ByteProperty": return Type.ByteProperty; case "ArrayProperty": return Type.ArrayProperty; case "DelegateProperty": return Type.DelegateProperty; case "StrProperty": return Type.StrProperty; case "StringRefProperty": return Type.StringRefProperty; default: return Type.Unknown; } }
public byte[] ToArray(uint pccExportDataOffset, IPCCObject pcc) { return ToArray(pccExportDataOffset, (ME3PCCObject)pcc); }
/// <summary> /// Common initialiser used by both TexInfo derivations. /// </summary> /// <param name="tex2D">Texture2D to get info from, e.g. Format, mips.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="hash">Hash of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pcc">PCC to get info from, e.g. PackageName</param> /// <param name="tfcoffset">Offset of image data in TFC.</param> /// <param name="thumbpath">Path to thumbnail image.</param> private void InfoInitialise(ITexture2D tex2D, int ExpID, uint hash, int WhichGame, IPCCObject pcc, int tfcoffset, string thumbpath, string pathBIOGame) { List<string> files = new List<string>(); files.Add(pcc.pccFileName); List<int> expids = new List<int>(); expids.Add(ExpID); InfoInitialise(files, expids, hash, tex2D.imgList.Where(t => t.offset != -1).Count(), new List<ITexture2D>(), WhichGame, pathBIOGame); FullPackage = pcc.Exports[ExpID].PackageFullName; TexName = tex2D.texName; tfcOffset = tfcoffset; Format = tex2D.texFormat; ThumbnailPath = thumbpath; // KFreon: ME2 only? if (pcc.Exports[ExpID].PackageFullName == "Base Package") FullPackage = Path.GetFileNameWithoutExtension(pcc.pccFileName).ToUpperInvariant(); else FullPackage = pcc.Exports[ExpID].PackageFullName.ToUpperInvariant(); }
/// <summary> /// Constructor for tree texture object. /// </summary> /// <param name="temppcc">PCC to get info from.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pathBIOGame">BIOGame path to game targeted.</param> /// <param name="ExecPath">Path to ME3Explorer \exec\ folder.</param> /// <param name="allfiles">List of all PCC's containing texture.</param> /// <param name="Success">OUT: True if sucessfully created.</param> public TreeTexInfo(IPCCObject temppcc, int ExpID, int WhichGame, string pathBIOGame, string ExecPath, out bool Success) { Success = false; CRC32 crcgen = new CRC32(); string ArcPath = pathBIOGame; ITexture2D temptex2D = null; if (temppcc.Exports[ExpID].ValidTextureClass()) { try { temptex2D = temppcc.CreateTexture2D(ExpID, pathBIOGame); } catch (Exception e) { Console.WriteLine(e); return; } // KFreon: If no images, ignore if (temptex2D.imgList.Count == 0) { return; } string texname = temptex2D.texName; IImageInfo tempImg = temptex2D.GenerateImageInfo(); uint hash = 0; // KFreon: Get texture hash if (tempImg.CompareStorage("pccSto")) { if (temptex2D.texFormat != ImageEngineFormat.DDS_ATI2_3Dc) { hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, ArcPath)); } else { hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, pathBIOGame), 0, tempImg.uncSize / 2); } } else { byte[] buffer = temptex2D.DumpImg(tempImg.imgSize, ArcPath); if (buffer == null) { hash = 0; } else { if (temptex2D.texFormat != ImageEngineFormat.DDS_ATI2_3Dc) { hash = ~crcgen.BlockChecksum(buffer); } else { hash = ~crcgen.BlockChecksum(buffer, 0, tempImg.uncSize / 2); } } } // KFreon: Get image thumbnail string thumbnailPath = ExecPath + "placeholder.ico"; string tempthumbpath = ExecPath + "ThumbnailCaches\\" + "ME" + WhichGame + "ThumbnailCache\\" + texname + "_" + hash + ".jpg"; bool exists = File.Exists(tempthumbpath); if (!exists) { try { using (MemoryStream ms = new MemoryStream(temptex2D.GetImageData())) { var tex = temptex2D.imgList.Where(t => t.offset != -1).First(); int max = (int)(tex.imgSize.height > tex.imgSize.width ? tex.imgSize.height : tex.imgSize.width); double divisor = max > 128 ? max / 128.0 : 1; int newWidth = (int)(tex.imgSize.width / divisor); int newHeight = (int)(tex.imgSize.height / divisor); string temp = KFreonLib.Textures.Creation.GenerateThumbnail(ms, tempthumbpath, newWidth, newHeight); if (temp != null) { thumbnailPath = temp; } } } catch { } // KFreon: Don't really care about failures } // KFreon: Initialise things ValidFirstPCC = WhichGame == 2 && (!String.IsNullOrEmpty(temptex2D.arcName) && temptex2D.arcName != "None"); InfoInitialise(temptex2D, ExpID, hash, WhichGame, temppcc, tempImg.offset, thumbnailPath, pathBIOGame); Success = true; } }
/// <summary> /// Constructor for tree texture object. /// </summary> /// <param name="temppcc">PCC to get info from.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pathBIOGame">BIOGame path to game targeted.</param> /// <param name="ExecPath">Path to ME3Explorer \exec\ folder.</param> /// <param name="allfiles">List of all PCC's containing texture.</param> /// <param name="Success">OUT: True if sucessfully created.</param> public TreeTexInfo(IPCCObject temppcc, int ExpID, int WhichGame, string pathBIOGame, string ExecPath, out bool Success) { Success = false; CRC32 crcgen = new CRC32(); string ArcPath = pathBIOGame; ITexture2D temptex2D = null; if (temppcc.Exports[ExpID].ValidTextureClass()) { try { temptex2D = temppcc.CreateTexture2D(ExpID, pathBIOGame); } catch (Exception e) { Console.WriteLine(e); return; } // KFreon: If no images, ignore if (temptex2D.imgList.Count == 0) return; string texname = temptex2D.texName; IImageInfo tempImg = temptex2D.GenerateImageInfo(); uint hash = 0; // KFreon: Get texture hash if (tempImg.CompareStorage("pccSto")) { if (temptex2D.texFormat != ImageEngineFormat.DDS_ATI2_3Dc) hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, ArcPath)); else hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, pathBIOGame), 0, tempImg.uncSize / 2); } else { byte[] buffer = temptex2D.DumpImg(tempImg.imgSize, ArcPath); if (buffer == null) hash = 0; else { if (temptex2D.texFormat != ImageEngineFormat.DDS_ATI2_3Dc) hash = ~crcgen.BlockChecksum(buffer); else hash = ~crcgen.BlockChecksum(buffer, 0, tempImg.uncSize / 2); } } // KFreon: Get image thumbnail string thumbnailPath = ExecPath + "placeholder.ico"; string tempthumbpath = ExecPath + "ThumbnailCaches\\" + "ME" + WhichGame + "ThumbnailCache\\" + texname + "_" + hash + ".jpg"; bool exists = File.Exists(tempthumbpath); if (!exists) try { using (MemoryStream ms = new MemoryStream(temptex2D.GetImageData())) { var tex = temptex2D.imgList.Where(t => t.offset != -1).First(); int max = (int)(tex.imgSize.height > tex.imgSize.width ? tex.imgSize.height : tex.imgSize.width); double divisor = max > 128 ? max / 128.0 : 1; int newWidth = (int)(tex.imgSize.width / divisor); int newHeight = (int)(tex.imgSize.height / divisor); string temp = KFreonLib.Textures.Creation.GenerateThumbnail(ms, tempthumbpath, newWidth, newHeight); if (temp != null) thumbnailPath = temp; } } catch { } // KFreon: Don't really care about failures // KFreon: Initialise things ValidFirstPCC = WhichGame == 2 && (!String.IsNullOrEmpty(temptex2D.arcName) && temptex2D.arcName != "None"); InfoInitialise(temptex2D, ExpID, hash, WhichGame, temppcc, tempImg.offset, thumbnailPath, pathBIOGame); Success = true; } }
public static int detectStart(IPCCObject pcc, byte[] raw, long flags) { if ((flags & (long)UnrealFlags.EObjectFlags.HasStack) != 0) { return 30; } int result = 8; int test1 = BitConverter.ToInt32(raw, 4); int test2 = BitConverter.ToInt32(raw, 8); if (pcc.isName(test1) && test2 == 0) result = 4; if (pcc.isName(test1) && pcc.isName(test2) && test2 != 0) result = 8; return result; }
public static string PropertyToText(Property p, IPCCObject pcc) { string s = ""; s = "Name: " + p.Name; s += ", Type: " + TypeToString((int)p.TypeVal); s += ", Size: " + p.Size + ","; int MEtype = Methods.GetMEType(); switch (p.TypeVal) { case Type.StructProperty: s += " \"" + pcc.GetName(p.Value.IntValue) + "\" with " + p.Size + " bytes"; break; case Type.IntProperty: case Type.ObjectProperty: case Type.StringRefProperty: s += " Value: " + p.Value.IntValue.ToString(); break; case Type.BoolProperty: s += " Value: " + (p.raw[24] == 1); break; case Type.FloatProperty: s += " Value: " + p.Value.FloatValue; break; case Type.NameProperty: s += " " + p.Value.StringValue; break; case Type.ByteProperty: s += " Value: \"" + p.Value.StringValue + "\", with int: " + p.Value.IntValue; break; case Type.ArrayProperty: s += " bytes"; //Value: " + p.Value.Array.Count.ToString() + " Elements"; break; case Type.StrProperty: if (p.Value.StringValue.Length == 0) break; s += " Value: " + p.Value.StringValue; break; } return s; }
public byte[] ToArray(uint pccExportDataOffset, IPCCObject pcc) { return(ToArray(pccExportDataOffset)); }
public static List <Property> ReadProp(IPCCObject pcc, byte[] raw, int start) { Property p; PropertyValue v; int sname; List <Property> result = new List <Property>(); int pos = start; if (raw.Length - pos < 8) { return(result); } int name = (int)BitConverter.ToInt64(raw, pos); if (!pcc.isName(name)) { return(result); } string t = pcc.Names[name]; if (pcc.Names[name] == "None") { p = new Property(); p.Name = name; p.TypeVal = Type.None; p.i = 0; p.offsetval = pos; p.Size = 8; p.Value = new PropertyValue(); p.raw = BitConverter.GetBytes((Int64)name); p.offend = pos + 8; result.Add(p); return(result); } int type = (int)BitConverter.ToInt64(raw, pos + 8); int size = BitConverter.ToInt32(raw, pos + 16); int idx = BitConverter.ToInt32(raw, pos + 20); if (!pcc.isName(type) || size < 0 || size >= raw.Length) { return(result); } string tp = pcc.Names[type]; switch (tp) { case "DelegateProperty": p = new Property(); p.Name = name; p.TypeVal = Type.DelegateProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = BitConverter.ToInt32(raw, pos + 28); v.len = size; v.Array = new List <PropertyValue>(); pos += 24; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) { v2.IntValue = raw[pos]; } v.Array.Add(v2); pos++; } p.Value = v; break; case "ArrayProperty": int count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.ArrayProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = size - 4; count = v.len;//TODO can be other objects too v.Array = new List <PropertyValue>(); pos += 28; for (int i = 0; i < count; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) { v2.IntValue = raw[pos]; } v.Array.Add(v2); pos++; } p.Value = v; break; case "StrProperty": count = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.StrProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = count; pos += 28; string s = ""; for (int i = 0; i < count; i++) { s += (char)raw[pos++]; } v.StringValue = s; p.Value = v; break; case "StructProperty": sname = (int)BitConverter.ToInt64(raw, pos + 24); p = new Property(); p.Name = name; p.TypeVal = Type.StructProperty; p.i = 0; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = sname; v.len = size; v.Array = new List <PropertyValue>(); pos += 32; for (int i = 0; i < size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) { v2.IntValue = raw[pos]; } v.Array.Add(v2); pos++; } p.Value = v; break; case "ByteProperty": p = new Property(); p.Name = name; p.TypeVal = Type.ByteProperty; p.i = idx; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = raw[pos + 24]; v.len = size; pos += 24 + size; p.Value = v; break; case "BoolProperty": p = new Property(); p.Name = name; p.TypeVal = Type.BoolProperty; p.i = idx; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = raw[pos + 24]; v.len = 4; pos += 28; p.Value = v; break; default: p = new Property(); p.Name = name; p.TypeVal = getType(pcc, type); p.i = 0; p.offsetval = pos + 24; p.Value = ReadValue(pcc, raw, pos + 24, type); pos += p.Value.len + 24; break; } p.raw = new byte[pos - start]; p.offend = pos; if (pos < raw.Length) { for (int i = 0; i < pos - start; i++) { p.raw[i] = raw[start + i]; } } result.Add(p); if (pos != start) { result.AddRange(ReadProp(pcc, raw, pos)); } return(result); }
public MemoryStream DecompressPCC(Stream raw, IPCCObject pcc) { raw.Seek(pcc.header.Length, SeekOrigin.Begin); int pos = 4; pcc.NumChunks = raw.ReadValueS32(); List<Chunk> Chunks = new List<Chunk>(); //DebugOutput.PrintLn("Reading chunk headers..."); for (int i = 0; i < pcc.NumChunks; i++) { Chunk c = new Chunk(); c.uncompressedOffset = raw.ReadValueS32(); c.uncompressedSize = raw.ReadValueS32(); c.compressedOffset = raw.ReadValueS32(); c.compressedSize = raw.ReadValueS32(); c.Compressed = new byte[c.compressedSize]; c.Uncompressed = new byte[c.uncompressedSize]; //DebugOutput.PrintLn("Chunk " + i + ", compressed size = " + c.compressedSize + ", uncompressed size = " + c.uncompressedSize); //DebugOutput.PrintLn("Compressed offset = " + c.compressedOffset + ", uncompressed offset = " + c.uncompressedOffset); Chunks.Add(c); } //DebugOutput.PrintLn("\tRead Chunks..."); int count = 0; for (int i = 0; i < Chunks.Count; i++) { Chunk c = Chunks[i]; raw.Seek(c.compressedOffset, SeekOrigin.Begin); c.Compressed = raw.ReadBytes(c.compressedSize); ChunkHeader h = new ChunkHeader(); h.magic = BitConverter.ToInt32(c.Compressed, 0); if (h.magic != -1641380927) throw new FormatException("Chunk magic number incorrect"); h.blocksize = BitConverter.ToInt32(c.Compressed, 4); h.compressedsize = BitConverter.ToInt32(c.Compressed, 8); h.uncompressedsize = BitConverter.ToInt32(c.Compressed, 12); //DebugOutput.PrintLn("Chunkheader read: Magic = " + h.magic + ", Blocksize = " + h.blocksize + ", Compressed Size = " + h.compressedsize + ", Uncompressed size = " + h.uncompressedsize); pos = 16; int blockCount = (h.uncompressedsize % h.blocksize == 0) ? h.uncompressedsize / h.blocksize : h.uncompressedsize / h.blocksize + 1; List<Block> BlockList = new List<Block>(); //DebugOutput.PrintLn("\t\t" + count + " Read Blockheaders..."); for (int j = 0; j < blockCount; j++) { Block b = new Block(); b.compressedsize = BitConverter.ToInt32(c.Compressed, pos); b.uncompressedsize = BitConverter.ToInt32(c.Compressed, pos + 4); //DebugOutput.PrintLn("Block " + j + ", compressed size = " + b.compressedsize + ", uncompressed size = " + b.uncompressedsize); pos += 8; BlockList.Add(b); } int outpos = 0; //DebugOutput.PrintLn("\t\t" + count + " Read and decompress Blocks..."); foreach (Block b in BlockList) { byte[] datain = new byte[b.compressedsize]; byte[] dataout = new byte[b.uncompressedsize]; for (int j = 0; j < b.compressedsize; j++) datain[j] = c.Compressed[pos + j]; pos += b.compressedsize; try { LZO1X.Decompress(datain, dataout); } catch { throw new Exception("LZO decompression failed!"); } for (int j = 0; j < b.uncompressedsize; j++) c.Uncompressed[outpos + j] = dataout[j]; outpos += b.uncompressedsize; } c.header = h; c.blocks = BlockList; count++; Chunks[i] = c; } MemoryStream result = new MemoryStream(); foreach (Chunk c in Chunks) { result.Seek(c.uncompressedOffset, SeekOrigin.Begin); result.WriteBytes(c.Uncompressed); } return result; }
public void CopyImgList(ITexture2D tex2D, IPCCObject PCC) { CopyImgList((ME3SaltTexture2D)tex2D, (ME3PCCObject)PCC); }
private static PropertyValue ReadValue(IPCCObject pcc, byte[] raw, int start, int type) { PropertyValue v = new PropertyValue(); switch (pcc.GetName(type)) { case "IntProperty": case "FloatProperty": case "ObjectProperty": case "StringRefProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 4; break; case "NameProperty": v.IntValue = BitConverter.ToInt32(raw, start); var nameRef = new NameReference(); nameRef.index = v.IntValue; nameRef.count = BitConverter.ToInt32(raw, start + 4); nameRef.Name = pcc.getNameEntry(nameRef.index); if (nameRef.count > 0) nameRef.Name += "_" + (nameRef.count - 1); v.NameValue = nameRef; v.len = 8; break; case "BoolProperty": if (start < raw.Length) v.IntValue = raw[start]; v.len = 1; break; } return v; }