public byte[] ToArray(uint pccExportDataOffset, ME3PCCObject pcc) { using (MemoryStream tempStream = new MemoryStream()) { tempStream.WriteBytes(headerData); // Whilst testing get rid of this // Heff: Seems like the shadowmap was the best solution in most cases, // adding an exception for known problematic animated textures for now. // (See popup in tpftools) if (properties.ContainsKey("LODGroup")) properties["LODGroup"].Value.String2 = "TEXTUREGROUP_Shadowmap"; else { tempStream.WriteValueS64(pcc.addName2("LODGroup")); tempStream.WriteValueS64(pcc.addName2("ByteProperty")); tempStream.WriteValueS64(8); tempStream.WriteValueS64(pcc.addName2("TextureGroup")); tempStream.WriteValueS64(pcc.addName2("TEXTUREGROUP_Shadowmap")); } foreach (KeyValuePair<string, SaltPropertyReader.Property> kvp in properties) { SaltPropertyReader.Property prop = kvp.Value; if (prop.Name == "UnpackMin") { for (int i = 0; i < UnpackNum; i++) { tempStream.WriteValueS64(pcc.addName2(prop.Name)); tempStream.WriteValueS64(pcc.addName2(prop.TypeVal.ToString())); tempStream.WriteValueS32(prop.Size); tempStream.WriteValueS32(i); tempStream.WriteValueF32(prop.Value.FloatValue); } continue; } tempStream.WriteValueS64(pcc.addName2(prop.Name)); if (prop.Name == "None") continue; tempStream.WriteValueS64(pcc.addName2(prop.TypeVal.ToString())); tempStream.WriteValueS64(prop.Size); switch (prop.TypeVal) { case SaltPropertyReader.Type.FloatProperty: tempStream.WriteValueF32(prop.Value.FloatValue); break; case SaltPropertyReader.Type.IntProperty: tempStream.WriteValueS32(prop.Value.IntValue); break; case SaltPropertyReader.Type.NameProperty: tempStream.WriteValueS64(pcc.addName2(prop.Value.StringValue)); // Heff: Modified to handle name references. //var nameIndex = pcc.addName2(prop.Value.StringValue); //tempStream.WriteValueS32(nameIndex); //tempStream.WriteValueS32(prop.Value.NameValue.count); break; case SaltPropertyReader.Type.ByteProperty: tempStream.WriteValueS64(pcc.addName2(prop.Value.StringValue)); tempStream.WriteValueS64(pcc.addName2(prop.Value.String2)); // Heff: Modified to handle name references. //var valueIndex = pcc.addName2(prop.Value.String2); //tempStream.WriteValueS32(valueIndex); //tempStream.WriteValueS32(prop.Value.NameValue.count); //tempStream.WriteValueS32(pcc.addName2(prop.Value.String2)); //byte[] footer = new byte[4]; //Buffer.BlockCopy(prop.raw, prop.raw.Length - 4, footer, 0, 4); //tempStream.WriteBytes(footer); break; case SaltPropertyReader.Type.BoolProperty: tempStream.WriteValueBoolean(prop.Value.Boolereno); break; case SaltPropertyReader.Type.StructProperty: tempStream.WriteValueS64(pcc.addName2(prop.Value.StringValue)); for (int i = 0; i < prop.Size; i++) tempStream.WriteByte((byte)prop.Value.Array[i].IntValue); break; default: throw new NotImplementedException("Property type: " + prop.TypeVal + ", not yet implemented. TELL ME ABOUT THIS!"); } } //Remove empty textures List<ImageInfo> tempList = new List<ImageInfo>(); foreach (ImageInfo imgInfo in privateimgList) { if (imgInfo.storageType != storage.empty) tempList.Add(imgInfo); } privateimgList = tempList; numMipMaps = (uint)privateimgList.Count; tempStream.WriteValueU32(numMipMaps); foreach (ImageInfo imgInfo in privateimgList) { tempStream.WriteValueS32((int)imgInfo.storageType); tempStream.WriteValueS32(imgInfo.uncSize); tempStream.WriteValueS32(imgInfo.cprSize); if (imgInfo.storageType == storage.pccSto) { tempStream.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset)); tempStream.Write(imageData, imgInfo.offset, imgInfo.uncSize); } else tempStream.WriteValueS32(imgInfo.offset); tempStream.WriteValueU32(imgInfo.imgSize.width); tempStream.WriteValueU32(imgInfo.imgSize.height); } //// Texture2D footer, 24 bytes size - changed to 20 //tempStream.Write(imageData, imageData.Length - 20, 20); tempStream.WriteBytes(footerData); return tempStream.ToArray(); } #region Unused Code /* bool lodExists = false; foreach (KeyValuePair<string, PropertyReader.Property> kvp in properties) { PropertyReader.Property property = kvp.Value; if (kvp.Key == "LODGroup") { lodExists = true; break; } } MemoryStream buffer = new MemoryStream(); buffer.Write(headerData, 0, headerData.Length); if (lodExists) { // extracting values from LODGroup Property PropertyReader.Property LODGroup = properties["LODGroup"]; string textureGroupName = pcc.Names[LODGroup.Value.IntValue]; bool nameExists = false; string newTextureGroupName = "TEXTUREGROUP_Shadowmap"; if (String.Compare(newTextureGroupName, textureGroupName) != 0) { textureGroupName = newTextureGroupName; if (!pcc.Names.Exists(name => name == newTextureGroupName)) pcc.Names.Add(newTextureGroupName); using (MemoryStream rawStream = new MemoryStream(LODGroup.raw)) { rawStream.Seek(32, SeekOrigin.Begin); rawStream.WriteValueS32(pcc.Names.FindIndex(name => name == newTextureGroupName)); rawStream.WriteValueS32(0); properties["LODGroup"].raw = rawStream.ToArray(); } } else nameExists = true; //MemoryStream buffer = new MemoryStream(); //buffer.Write(headerData, 0, headerData.Length); foreach (KeyValuePair<string, PropertyReader.Property> kvp in properties) { PropertyReader.Property property = kvp.Value; if (kvp.Key == "LODBias") continue; if (kvp.Key == "InternalFormatLODBias") continue; if (kvp.Key == "LODGroup" && nameExists == false) { int name; if (!nameExists) name = pcc.Names.Count - 1; //Warranty Voiders Name redirect hack^^ else name = LODGroup.Value.IntValue; ME3_HR_Patch.Helper.BitConverter.IsLittleEndian = true; byte[] buff = ME3_HR_Patch.Helper.BitConverter.GetBytes(name); for (int i = 0; i < 4; i++) property.raw[i + 24] = buff[i]; } buffer.Write(property.raw, 0, property.raw.Length); if (kvp.Key == "UnpackMin") { buffer.Write(property.raw, 0, property.raw.Length); buffer.Write(property.raw, 0, property.raw.Length); } } } else { //MemoryStream buffer = new MemoryStream(); //buffer.Write(headerData, 0, headerData.Length); int lodID = pcc.findName("LODGroup"); if (lodID == -1) { pcc.addName("LODGroup"); lodID = pcc.Names.Count - 1; } buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes(lodID)); buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0)); lodID = pcc.findName("ByteProperty"); buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes(lodID)); buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0)); //Write an int buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)8)); buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0)); lodID = pcc.findName("TextureGroup"); if (lodID == -1) { pcc.addName("TextureGroup"); lodID = pcc.Names.Count - 1; } buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes(lodID)); buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0)); lodID = pcc.findName("TEXTUREGROUP_Shadowmap"); if (lodID == -1) { pcc.addName("TEXTUREGROUP_Shadowmap"); lodID = pcc.Names.Count - 1; } buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes(lodID)); buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0)); foreach (KeyValuePair<string, PropertyReader.Property> kvp in properties) { PropertyReader.Property property = kvp.Value; if (kvp.Key == "LODBias") continue; if (kvp.Key == "InternalFormatLODBias") continue; if (kvp.Key == "LODGroup") { int name = pcc.Names.Count - 1; //Warranty Voiders Name redirect hack^^ ME3_HR_Patch.Helper.BitConverter.IsLittleEndian = true; byte[] buff = ME3_HR_Patch.Helper.BitConverter.GetBytes(name); for (int i = 0; i < 4; i++) property.raw[i + 24] = buff[i]; } buffer.Write(property.raw, 0, property.raw.Length); if (kvp.Key == "UnpackMin") { buffer.Write(property.raw, 0, property.raw.Length); buffer.Write(property.raw, 0, property.raw.Length); } } } buffer.WriteValueU32(numMipMaps); foreach (ImageInfo imgInfo in imgList) { buffer.WriteValueS32((int)imgInfo.storageType); buffer.WriteValueS32(imgInfo.uncSize); buffer.WriteValueS32(imgInfo.cprSize); if (imgInfo.storageType == storage.pccSto) { buffer.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset)); buffer.Write(imageData, imgInfo.offset, imgInfo.uncSize); } else buffer.WriteValueS32(imgInfo.offset); buffer.WriteValueU32(imgInfo.imgSize.width); buffer.WriteValueU32(imgInfo.imgSize.height); } // Texture2D footer, 24 bytes size buffer.Write(imageData, imageData.Length - 24, 24); byte[] rawData = buffer.ToArray(); return rawData; */ #endregion }
public void CopyImgList(ME3SaltTexture2D inTex, ME3PCCObject pcc) { imageData = inTex.imageData; privateimgList = inTex.privateimgList; numMipMaps = inTex.numMipMaps; //Copy Properties byte[] buff; 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.addName2(prop.Name)); tempMem.WriteValueS64(pcc.addName2(prop.TypeVal.ToString())); tempMem.WriteValueS32(prop.Size); tempMem.WriteValueS32(j); tempMem.WriteValueF32(prop.Value.FloatValue); } continue; } tempMem.WriteValueS64(pcc.addName2(prop.Name)); if (prop.Name == "None") continue; tempMem.WriteValueS64(pcc.addName2(prop.TypeVal.ToString())); tempMem.WriteValueS64(prop.Size); switch (prop.TypeVal) { case SaltPropertyReader.Type.FloatProperty: tempMem.WriteValueF32(prop.Value.FloatValue); break; case SaltPropertyReader.Type.IntProperty: tempMem.WriteValueS32(prop.Value.IntValue); break; case SaltPropertyReader.Type.NameProperty: tempMem.WriteValueS64(pcc.addName2(prop.Value.StringValue)); // Heff: Modified to handle name references. //var index = pcc.addName2(prop.Value.StringValue); //tempMem.WriteValueS32(index); //tempMem.WriteValueS32(prop.Value.NameValue.count); break; case SaltPropertyReader.Type.ByteProperty: tempMem.WriteValueS64(pcc.addName2(prop.Value.StringValue)); tempMem.WriteValueS32(pcc.addName2(prop.Value.String2)); byte[] footer = new byte[4]; Buffer.BlockCopy(prop.raw, prop.raw.Length - 4, footer, 0, 4); tempMem.WriteBytes(footer); break; case SaltPropertyReader.Type.BoolProperty: tempMem.WriteValueBoolean(prop.Value.Boolereno); break; case SaltPropertyReader.Type.StructProperty: tempMem.WriteValueS64(pcc.addName2(prop.Value.StringValue)); for (int k = 0; k < prop.Size; k++) tempMem.WriteByte((byte)prop.Value.Array[k].IntValue); break; default: throw new NotImplementedException("Property type: " + prop.TypeVal + ", not yet implemented. TELL ME ABOUT THIS!"); } } buff = tempMem.ToArray(); } properties = new Dictionary<string, SaltPropertyReader.Property>(); List<SaltPropertyReader.Property> tempProperties = SaltPropertyReader.ReadProp(pcc, buff, headerData.Length); 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 = Textures.Methods.ParseFormat(pcc.Names[property.Value.IntValue].Substring(3)); break; case "TextureFileCacheName": arcName = property.Value.NameValue.Name; break; case "LODGroup": LODGroup = property.Value.NameValue.Name; 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[] ThisToArray(uint pccExportDataOffset, ME2PCCObject pcc) { MemoryStream buffer = new MemoryStream(); buffer.Write(headerData, 0, headerData.Length); if (properties.ContainsKey("LODGroup")) { properties["LODGroup"].Value.StringValue = "TEXTUREGROUP_LightAndShadowMap"; properties["LODGroup"].Value.String2 = pcc.Names[0]; } else { buffer.WriteValueS64(pcc.AddName("LODGroup")); buffer.WriteValueS64(pcc.AddName("ByteProperty")); buffer.WriteValueS64(8); buffer.WriteValueS64(pcc.AddName("TEXTUREGROUP_LightAndShadowMap")); } int count = 0; foreach (KeyValuePair<string, SaltPropertyReader.Property> kvp in properties) { SaltPropertyReader.Property prop = kvp.Value; if (prop.Name == "UnpackMin") { for (int j = 0; j < UnpackNum; j++) { buffer.WriteValueS64(pcc.AddName(prop.Name)); buffer.WriteValueS64(pcc.AddName(prop.TypeVal.ToString())); buffer.WriteValueS32(prop.Size); buffer.WriteValueS32(j); buffer.WriteValueF32(prop.Value.FloatValue, Endian.Little); } continue; } buffer.WriteValueS64(pcc.AddName(prop.Name)); if (prop.Name == "None") { for (int j = 0; j < 12; j++) buffer.WriteByte(0); } else { buffer.WriteValueS64(pcc.AddName(prop.TypeVal.ToString())); buffer.WriteValueS64(prop.Size); switch (prop.TypeVal) { case SaltPropertyReader.Type.IntProperty: buffer.WriteValueS32(prop.Value.IntValue); break; case SaltPropertyReader.Type.BoolProperty: buffer.WriteValueS32(prop.Value.IntValue); break; case SaltPropertyReader.Type.NameProperty: buffer.WriteValueS64(pcc.AddName(prop.Value.StringValue)); // Heff: Modified to handle name references. //var index = pcc.AddName(prop.Value.StringValue); //buffer.WriteValueS32(index); //buffer.WriteValueS32(prop.Value.NameValue.count); break; case SaltPropertyReader.Type.StrProperty: buffer.WriteValueS32(prop.Value.StringValue.Length + 1); foreach (char c in prop.Value.StringValue) buffer.WriteByte((byte)c); buffer.WriteByte(0); break; case SaltPropertyReader.Type.StructProperty: string strVal = prop.Value.StringValue; if (prop.Name.ToLowerInvariant().Contains("guid")) strVal = "Guid"; buffer.WriteValueS64(pcc.AddName(strVal)); foreach (SaltPropertyReader.PropertyValue value in prop.Value.Array) buffer.WriteValueS32(value.IntValue); break; case SaltPropertyReader.Type.ByteProperty: buffer.WriteValueS32(pcc.AddName(prop.Value.StringValue)); buffer.WriteValueS32(pcc.AddName(prop.Value.String2)); break; case SaltPropertyReader.Type.FloatProperty: buffer.WriteValueF32(prop.Value.FloatValue, Endian.Little); break; default: throw new FormatException("unknown property"); } } } buffer.WriteValueS32((int)buffer.Position + (int)pccExportDataOffset); //Remove empty textures List<ImageInfo> tempList = new List<ImageInfo>(); foreach (ImageInfo imgInfo in privateimgList) { if (imgInfo.storageType != storage.empty) tempList.Add(imgInfo); } privateimgList = tempList; numMipMaps = (uint)privateimgList.Count; buffer.WriteValueU32(numMipMaps); foreach (ImageInfo imgInfo in privateimgList) { buffer.WriteValueS32((int)imgInfo.storageType); buffer.WriteValueS32(imgInfo.uncSize); buffer.WriteValueS32(imgInfo.cprSize); if (imgInfo.storageType == storage.pccSto) { buffer.WriteValueS32((int)(buffer.Position + pccExportDataOffset)); buffer.Write(imageData, imgInfo.offset, imgInfo.uncSize); } else buffer.WriteValueS32(imgInfo.offset); if (imgInfo.imgSize.width < 4) buffer.WriteValueU32(4); else buffer.WriteValueU32(imgInfo.imgSize.width); if (imgInfo.imgSize.height < 4) buffer.WriteValueU32(4); else buffer.WriteValueU32(imgInfo.imgSize.height); } buffer.WriteBytes(footerData); return buffer.ToArray(); }
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[] ToArray(int pccExportDataOffset, PCCObject pcc) { MemoryStream buffer = new MemoryStream(); buffer.Write(headerData, 0, headerData.Length); if (properties.ContainsKey("LODGroup")) { properties["LODGroup"].Value.StringValue = "TEXTUREGROUP_LightAndShadowMap"; //properties["LODGroup"].Value.IntValue = 1025; } else { buffer.WriteValueS64(pcc.AddName("LODGroup")); buffer.WriteValueS64(pcc.AddName("ByteProperty")); buffer.WriteValueS64(8); buffer.WriteValueS32(pcc.AddName("TEXTUREGROUP_LightAndShadowMap")); buffer.WriteValueS32(1025); } foreach (KeyValuePair<string, SaltPropertyReader.Property> kvp in properties) { SaltPropertyReader.Property prop = kvp.Value; if (prop.Name == "UnpackMin") { for (int j = 0; j < UnpackNum; j++) { buffer.WriteValueS64(pcc.AddName(prop.Name)); buffer.WriteValueS64(pcc.AddName(prop.TypeVal.ToString())); buffer.WriteValueS32(prop.Size); buffer.WriteValueS32(j); buffer.WriteValueF32(prop.Value.FloatValue, Endian.Little); } continue; } buffer.WriteValueS64(pcc.AddName(prop.Name)); if (prop.Name == "None") { for (int j = 0; j < 12; j++) buffer.WriteByte(0); } else { buffer.WriteValueS64(pcc.AddName(prop.TypeVal.ToString())); buffer.WriteValueS64(prop.Size); switch (prop.TypeVal) { case SaltPropertyReader.Type.IntProperty: buffer.WriteValueS32(prop.Value.IntValue); break; case SaltPropertyReader.Type.BoolProperty: buffer.Seek(-4, SeekOrigin.Current); buffer.WriteValueS32(prop.Value.IntValue); buffer.Seek(4, SeekOrigin.Current); break; case SaltPropertyReader.Type.NameProperty: buffer.WriteValueS64(pcc.AddName(prop.Value.StringValue)); break; case SaltPropertyReader.Type.StrProperty: buffer.WriteValueS32(prop.Value.StringValue.Length + 1); foreach (char c in prop.Value.StringValue) buffer.WriteByte((byte)c); buffer.WriteByte(0); break; case SaltPropertyReader.Type.StructProperty: buffer.WriteValueS64(pcc.AddName(prop.Value.StringValue)); foreach (SaltPropertyReader.PropertyValue value in prop.Value.Array) buffer.WriteValueS32(value.IntValue); break; case SaltPropertyReader.Type.ByteProperty: buffer.WriteValueS32(pcc.AddName(prop.Value.StringValue)); buffer.WriteValueS32(prop.Value.IntValue); break; case SaltPropertyReader.Type.FloatProperty: buffer.WriteValueF32(prop.Value.FloatValue, Endian.Little); break; default: throw new FormatException("unknown property"); } } } buffer.WriteValueS32((int)(pccOffset + buffer.Position + 4)); //Remove empty textures List<ImageInfo> tempList = new List<ImageInfo>(); foreach (ImageInfo imgInfo in imgList) { if (imgInfo.storageType != storage.empty) tempList.Add(imgInfo); } imgList = tempList; numMipMaps = (uint)imgList.Count; buffer.WriteValueU32(numMipMaps); foreach (ImageInfo imgInfo in imgList) { buffer.WriteValueS32((int)imgInfo.storageType); buffer.WriteValueS32(imgInfo.uncSize); buffer.WriteValueS32(imgInfo.cprSize); if (imgInfo.storageType == storage.pccSto) { buffer.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset)); buffer.Write(imageData, imgInfo.offset, imgInfo.uncSize); } else if (imgInfo.storageType == storage.pccCpr) { buffer.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset)); buffer.Write(imageData, imgInfo.offset, imgInfo.cprSize); } else buffer.WriteValueS32(imgInfo.offset); if (imgInfo.imgSize.width < 4) buffer.WriteValueU32(4); else buffer.WriteValueU32(imgInfo.imgSize.width); if (imgInfo.imgSize.height < 4) buffer.WriteValueU32(4); else buffer.WriteValueU32(imgInfo.imgSize.height); } buffer.WriteBytes(footerData); return buffer.ToArray(); }
public static void WriteStructPropVector(this Stream stream, IMEPackage pcc, string propName, float x, float y, float z) { MemoryStream m = new MemoryStream(12); m.WriteValueF32(x); m.WriteValueF32(y); m.WriteValueF32(z); stream.WriteStructProperty(pcc, propName, "Vector", m.ToArray()); }