private void PreviewProps(int n) { PCCObject.ExportEntry ent = pcc.Exports[n]; List<PropertyReader.Property> props = PropertyReader.getPropList(pcc, ent.Data); rtb1.Visible = true; string s = ""; s += "ObjectName : " + ent.ObjectName + "\n"; s += "Class : " + ent.ClassName + "\n"; s += "Data size : 0x" + ent.DataSize.ToString("X8") + "\n"; s += "Data offset : 0x" + ent.DataOffset.ToString("X8") + "\n\nProperties: \n"; foreach (PropertyReader.Property p in props) s += PropertyReader.PropertyToText(p, pcc) + "\n"; if (ent.ClassName == "Texture2D" || ent.ClassName == "LightMapTexture2D" || ent.ClassName == "TextureFlipBook") { s += "\nImage Info: \n"; try { Texture2D tex2D = new Texture2D(pcc, n); for (int i = 0; i < tex2D.imgList.Count; i++) { s += i + ": Location: " + tex2D.imgList[i].storageType + ", Storage: " + tex2D.imgList[i].storageType.ToString() + ", ImgSize: " + tex2D.imgList[i].imgSize.ToString() + "\n"; s += "Offset = " + tex2D.imgList[i].offset + ", CprSize = " + tex2D.imgList[i].cprSize + ", UncSize = " + tex2D.imgList[i].uncSize + "\n"; } } catch { } } rtb1.Text = s; //Status.Text = ent.ClassName + " Offset: " + ent.DataOffset + " - " + (ent.DataOffset + ent.DataSize); }
public void CopyImgList(Texture2D inTex, PCCObject pcc, bool norender = false) { List<ImageInfo> tempList = new List<ImageInfo>(); MemoryStream tempData = new MemoryStream(); SaltLZOHelper lzo = new SaltLZOHelper(); numMipMaps = inTex.numMipMaps; // forced norenderfix // norender = true; int type = -1; if (!norender) { if (imgList.Exists(img => img.storageType == storage.arcCpr) && imgList.Count > 1) type = 1; else if (imgList.Exists(img => img.storageType == storage.pccCpr)) type = 2; else if (imgList.Exists(img => img.storageType == storage.pccSto) || imgList.Count == 1) type = 3; } else type = 3; switch (type) { case 1: for (int i = 0; i < inTex.imgList.Count; i++) { try { ImageInfo newImg = new ImageInfo(); ImageInfo replaceImg = inTex.imgList[i]; Texture2D.storage replaceType = imgList.Find(img => img.imgSize == replaceImg.imgSize).storageType; int j = 0; while (replaceType == storage.empty) { j++; replaceType = imgList[imgList.FindIndex(img => img.imgSize == replaceImg.imgSize) + j].storageType; } if (replaceType == storage.arcCpr || !imgList.Exists(img => img.imgSize == replaceImg.imgSize)) { newImg.storageType = storage.arcCpr; newImg.uncSize = replaceImg.uncSize; newImg.cprSize = replaceImg.cprSize; newImg.imgSize = replaceImg.imgSize; newImg.offset = (int)(replaceImg.offset + inTex.pccOffset + inTex.dataOffset); } else { newImg.storageType = storage.pccSto; newImg.uncSize = replaceImg.uncSize; newImg.cprSize = replaceImg.uncSize; newImg.imgSize = replaceImg.imgSize; newImg.offset = (int)(tempData.Position); using (MemoryStream tempStream = new MemoryStream(inTex.imageData)) { tempData.WriteBytes(lzo.DecompressTex(tempStream, replaceImg.offset, replaceImg.uncSize, replaceImg.cprSize)); } } tempList.Add(newImg); } catch { ImageInfo replaceImg = inTex.imgList[i]; if (!imgList.Exists(img => img.imgSize == replaceImg.imgSize)) throw new Exception("An error occurred during imglist copying and no suitable replacement was found"); ImageInfo newImg = imgList.Find(img => img.imgSize == replaceImg.imgSize); if (newImg.storageType != storage.pccCpr && newImg.storageType != storage.pccSto) throw new Exception("An error occurred during imglist copying and no suitable replacement was found"); int temppos = newImg.offset; newImg.offset = (int)tempData.Position; tempData.Write(imageData, temppos, newImg.cprSize); tempList.Add(newImg); } } break; case 2: for (int i = 0; i < inTex.imgList.Count; i++) { ImageInfo newImg = new ImageInfo(); ImageInfo replaceImg = inTex.imgList[i]; newImg.storageType = storage.pccCpr; newImg.uncSize = replaceImg.uncSize; newImg.cprSize = replaceImg.cprSize; newImg.imgSize = replaceImg.imgSize; newImg.offset = (int)(tempData.Position); byte[] buffer = new byte[newImg.cprSize]; Buffer.BlockCopy(inTex.imageData, replaceImg.offset, buffer, 0, buffer.Length); tempData.WriteBytes(buffer); tempList.Add(newImg); } break; case 3: for (int i = 0; i < inTex.imgList.Count; i++) { ImageInfo newImg = new ImageInfo(); ImageInfo replaceImg = inTex.imgList[i]; newImg.storageType = storage.pccSto; newImg.uncSize = replaceImg.uncSize; newImg.cprSize = replaceImg.uncSize; newImg.imgSize = replaceImg.imgSize; newImg.offset = (int)(tempData.Position); if (replaceImg.storageType == storage.pccCpr) { using (MemoryStream tempStream = new MemoryStream(inTex.imageData)) { tempData.WriteBytes(lzo.DecompressTex(tempStream, replaceImg.offset, replaceImg.uncSize, replaceImg.cprSize)); } } else if (replaceImg.storageType == storage.pccSto) { byte[] buffer = new byte[newImg.cprSize]; Buffer.BlockCopy(inTex.imageData, replaceImg.offset, buffer, 0, buffer.Length); tempData.WriteBytes(buffer); } else throw new NotImplementedException("Copying from non package stored texture no available"); tempList.Add(newImg); } break; default: throw new NotImplementedException(); } for (int i = 0; i < tempList.Count; i++) { ImageInfo tempinfo = tempList[i]; if (inTex.imgList[i].storageType == storage.empty) tempinfo.storageType = storage.empty; tempList[i] = tempinfo; } imgList = tempList; imageData = tempData.ToArray(); tempData.Close(); byte[] buff; //Copy properties using (MemoryStream tempMem = new MemoryStream()) { tempMem.WriteBytes(headerData); for (int i = 0; i < inTex.properties.Count; i++) { SaltPropertyReader.Property prop = inTex.properties.ElementAt(i).Value; if (prop.Name == "UnpackMin") { for (int j = 0; j < inTex.UnpackNum; j++) { tempMem.WriteValueS64(pcc.AddName(prop.Name)); tempMem.WriteValueS64(pcc.AddName(prop.TypeVal.ToString())); tempMem.WriteValueS32(prop.Size); tempMem.WriteValueS32(j); tempMem.WriteValueF32(prop.Value.FloatValue, Endian.Little); } continue; } tempMem.WriteValueS64(pcc.AddName(prop.Name)); if (prop.Name == "None") { for (int j = 0; j < 12; j++) tempMem.WriteByte(0); } else { tempMem.WriteValueS64(pcc.AddName(prop.TypeVal.ToString())); tempMem.WriteValueS64(prop.Size); switch (prop.TypeVal) { case SaltPropertyReader.Type.IntProperty: tempMem.WriteValueS32(prop.Value.IntValue); break; case SaltPropertyReader.Type.BoolProperty: tempMem.Seek(-4, SeekOrigin.Current); tempMem.WriteValueS32(prop.Value.IntValue); tempMem.Seek(4, SeekOrigin.Current); break; case SaltPropertyReader.Type.NameProperty: tempMem.WriteValueS64(pcc.AddName(prop.Value.StringValue)); break; case SaltPropertyReader.Type.StrProperty: tempMem.WriteValueS32(prop.Value.StringValue.Length + 1); foreach (char c in prop.Value.StringValue) tempMem.WriteByte((byte)c); tempMem.WriteByte(0); break; case SaltPropertyReader.Type.StructProperty: tempMem.WriteValueS64(pcc.AddName(prop.Value.StringValue)); foreach (SaltPropertyReader.PropertyValue value in prop.Value.Array) tempMem.WriteValueS32(value.IntValue); break; case SaltPropertyReader.Type.ByteProperty: tempMem.WriteValueS32(pcc.AddName(prop.Value.StringValue)); tempMem.WriteValueS32(prop.Value.IntValue); break; case SaltPropertyReader.Type.FloatProperty: tempMem.WriteValueF32(prop.Value.FloatValue, Endian.Little); break; default: throw new FormatException("unknown property"); } } } buff = tempMem.ToArray(); } int propertiesOffset = SaltPropertyReader.detectStart(pcc, buff); headerData = new byte[propertiesOffset]; Buffer.BlockCopy(buff, 0, headerData, 0, propertiesOffset); properties = new Dictionary<string, SaltPropertyReader.Property>(); List<SaltPropertyReader.Property> tempProperties = SaltPropertyReader.getPropList(pcc, buff); UnpackNum = 0; for (int i = 0; i < tempProperties.Count; i++) { SaltPropertyReader.Property property = tempProperties[i]; if (property.Name == "UnpackMin") UnpackNum++; if (!properties.ContainsKey(property.Name)) properties.Add(property.Name, property); switch (property.Name) { case "Format": texFormat = property.Value.StringValue; break; case "LODGroup": LODGroup = property.Value.StringValue; break; case "CompressionSettings": Compression = property.Value.StringValue; break; case "None": dataOffset = (uint)(property.offsetval + property.Size); break; } } // if "None" property isn't found throws an exception if (dataOffset == 0) throw new Exception("\"None\" property not found"); }
public byte[] DumpImage(ImageSize imgSize) { byte[] imgBuffer = null; ImageInfo imgInfo; if (imgList.Exists(img => (img.imgSize == imgSize && img.cprSize != -1))) imgInfo = imgList.Find(img => img.imgSize == imgSize); else //throw new FileNotFoundException("Image with resolution " + imgSize + " not found"); return null; switch (imgInfo.storageType) { case storage.pccSto: imgBuffer = new byte[imgInfo.uncSize]; Buffer.BlockCopy(imageData, imgInfo.offset, imgBuffer, 0, imgInfo.uncSize); break; case storage.arcCpr: case storage.arcUnc: string archivePath = FindFile(); if (String.IsNullOrEmpty(archivePath)) throw new FileNotFoundException(); PCCObject temp = new PCCObject(archivePath); for (int i = 0; i < temp.ExportCount; i++) { if (String.Compare(texName, temp.Exports[i].ObjectName, true) == 0 && (temp.Exports[i].ClassName == "Texture2D"))// || temp.Exports[i].ClassName == "TextureFlipBook")) { Texture2D temptex = new Texture2D(temp, i); /*if (imgSize.width > dims) { dims = (int) imgSize.width;*/ byte[] temp1 = temptex.DumpImage(imgSize); if (temp1 != null) imgBuffer = temp1; //} } } break; case storage.pccCpr: using (MemoryStream ms = new MemoryStream(imageData)) { SaltLZOHelper lzohelp = new SaltLZOHelper(); imgBuffer = lzohelp.DecompressTex(ms, imgInfo.offset, imgInfo.uncSize, imgInfo.cprSize); } break; default: throw new FormatException("Unsupported texture storage type"); imgBuffer = null; break; } return imgBuffer; }
public void extractImage(ImageInfo imgInfo, string archiveDir = null, string fileName = null) { ImageFile imgFile; if (fileName == null) fileName = texName + "_" + imgInfo.imgSize + getFileFormat(); byte[] imgBuffer = null; switch (imgInfo.storageType) { case storage.pccSto: imgBuffer = new byte[imgInfo.uncSize]; Buffer.BlockCopy(imageData, imgInfo.offset, imgBuffer, 0, imgInfo.uncSize); break; case storage.arcCpr: case storage.arcUnc: string archivePath = FindFile(); if (String.IsNullOrEmpty(archivePath)) throw new FileNotFoundException(); PCCObject temp = new PCCObject(archivePath); for (int i = 0; i < temp.ExportCount; i++) { if (String.Compare(texName, temp.Exports[i].ObjectName, true) == 0 && temp.Exports[i].ClassName == "Texture2D") { Texture2D temptex = new Texture2D(temp, i); temptex.extractImage(imgInfo.imgSize.ToString(), temp, null, fileName); } } break; case storage.pccCpr: using (MemoryStream ms = new MemoryStream(imageData)) { SaltLZOHelper lzohelp = new SaltLZOHelper(); imgBuffer = lzohelp.DecompressTex(ms, imgInfo.offset, imgInfo.uncSize, imgInfo.cprSize); } break; default: throw new FormatException("Unsupported texture storage type"); } if (imgInfo.storageType == storage.pccSto || imgInfo.storageType == storage.pccCpr) { if (getFileFormat() == ".dds") imgFile = new DDS(fileName, imgInfo.imgSize, texFormat, imgBuffer); else imgFile = new TGA(fileName, imgInfo.imgSize, texFormat, imgBuffer); byte[] saveImg = imgFile.ToArray(); using (FileStream outputImg = new FileStream(imgFile.fileName, FileMode.Create, FileAccess.Write)) outputImg.Write(saveImg, 0, saveImg.Length); } }
/// <summary> /// This function will first guess and then do a thorough search to find the original location of the texture /// </summary> private string FindFile() { if (!String.IsNullOrEmpty(oriPackage)) return oriPackage; // KFreon: All files should have been added elsewhere rather than searched for here if (allFiles == null) { allFiles = new List<string>(); //List<string> allFiles = Directory.GetFiles(ME1Directory.cookedPath, "*.u", SearchOption.AllDirectories).ToList(); allFiles.AddRange(Directory.GetFiles(ME1Directory.cookedPath, "*.upk", SearchOption.AllDirectories)); allFiles.AddRange(Directory.GetFiles(ME1Directory.cookedPath, "*.upk", SearchOption.AllDirectories)); allFiles.AddRange(Directory.GetFiles(ME1Directory.cookedPath, "*.sfm", SearchOption.AllDirectories)); //List<string> allFiles = Directory.GetFiles(ME1Directory.DLCPath, "*.u", SearchOption.AllDirectories).ToList(); allFiles.AddRange(Directory.GetFiles(ME1Directory.DLCPath, "*.u", SearchOption.AllDirectories)); allFiles.AddRange(Directory.GetFiles(ME1Directory.DLCPath, "*.upk", SearchOption.AllDirectories)); allFiles.AddRange(Directory.GetFiles(ME1Directory.DLCPath, "*.sfm", SearchOption.AllDirectories)); } string package = FullPackage.Split('.')[0]; for (int i = 0; i < allFiles.Count; i++) { string tempFile = allFiles[i].Split('\\')[allFiles[i].Split('\\').Length - 1]; tempFile = tempFile.Split('.')[0]; if (String.Compare(package, tempFile, true) == 0) return allFiles[i]; } if (DialogResult.No == MessageBox.Show("Package guessing failed. Would you like to do the thorough check? (LONG)", "Continue?", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) return null; for (int i = 0; i < allFiles.Count; i++) { PCCObject temp = new PCCObject(allFiles[i]); for (int j = 0; j < temp.ExportCount; j++) { PCCObject.ExportEntry exp = temp.Exports[j]; if (String.Compare(texName, exp.ObjectName, true) == 0 && exp.ClassName == "Texture2D") { Texture2D temptex = new Texture2D(temp, j); if (temptex.imgList[0].storageType == storage.pccCpr || temptex.imgList[0].storageType == storage.pccSto) { return allFiles[i]; } } } } return null; }