public PCCObject(String path) { lzo = new SaltLZOHelper(); fullname = path; BitConverter.IsLittleEndian = true; DebugOutput.PrintLn("Load file : " + path); pccFileName = Path.GetFullPath(path); MemoryTributary tempStream = new MemoryTributary(); if (!File.Exists(pccFileName)) throw new FileNotFoundException("PCC file not found"); using (FileStream fs = new FileStream(pccFileName, FileMode.Open, FileAccess.Read)) { FileInfo tempInfo = new FileInfo(pccFileName); tempStream.WriteFromStream(fs, tempInfo.Length); if (tempStream.Length != tempInfo.Length) { throw new FileLoadException("File not fully read in. Try again later"); } } tempStream.Seek(12, SeekOrigin.Begin); int tempNameSize = tempStream.ReadValueS32(); tempStream.Seek(64 + tempNameSize, SeekOrigin.Begin); int tempGenerator = tempStream.ReadValueS32(); tempStream.Seek(36 + tempGenerator * 12, SeekOrigin.Current); int tempPos = (int)tempStream.Position; NumChunks = tempStream.ReadValueS32(); tempStream.Seek(0, SeekOrigin.Begin); header = tempStream.ReadBytes(tempPos); tempStream.Seek(0, SeekOrigin.Begin); if (magic != ZBlock.magic && magic.Swap() != ZBlock.magic) { DebugOutput.PrintLn("Magic number incorrect: " + magic); throw new FormatException("This is not a pcc file. The magic number is incorrect."); } if (bCompressed) { DebugOutput.PrintLn("File is compressed"); { listsStream = lzo.DecompressPCC(tempStream, this); //Correct the header bCompressed = false; listsStream.Seek(0, SeekOrigin.Begin); listsStream.WriteBytes(header); //Set numblocks to zero listsStream.WriteValueS32(0); //Write the magic number listsStream.WriteValueS32(1026281201); //Write 8 bytes of 0 listsStream.WriteValueS32(0); listsStream.WriteValueS32(0); } } else { DebugOutput.PrintLn("File already decompressed. Reading decompressed data."); listsStream = tempStream; } ReadNames(listsStream); ReadImports(listsStream); ReadExports(listsStream); LoadExports(); }
public void CopyImgList(Texture2D inTex, PCCObject pcc) { numMipMaps = inTex.numMipMaps; if (properties.ContainsKey("NeverStream") && properties["NeverStream"].Value.IntValue == 1) { imageData = null; GC.Collect(); // store images as pccSto format imgList = new List<ImageInfo>(); MemoryStream tempData = new MemoryStream(); 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.arcCpr) { string archivePath = inTex.FullArcPath; if (!File.Exists(archivePath)) throw new FileNotFoundException("Texture archive not found in " + archivePath); using (FileStream archiveStream = File.OpenRead(archivePath)) { archiveStream.Seek(replaceImg.offset, SeekOrigin.Begin); SaltLZOHelper lzohelp = new SaltLZOHelper(); tempData.WriteBytes(lzohelp.DecompressTex(archiveStream, 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"); imgList.Add(newImg); } for (int i = 0; i < imgList.Count; i++) { ImageInfo tempinfo = imgList[i]; if (inTex.imgList[i].storageType == storage.empty) tempinfo.storageType = storage.empty; imgList[i] = tempinfo; } imageData = tempData.ToArray(); tempData.Close(); tempData = null; GC.Collect(); } else { imageData = inTex.imageData; imgList = inTex.imgList; } // add properties "TextureFileCacheName" and "TFCFileGuid" if they are missing, if (!properties.ContainsKey("TextureFileCacheName") && inTex.properties.ContainsKey("TextureFileCacheName")) { SaltPropertyReader.Property none = properties["None"]; properties.Remove("None"); SaltPropertyReader.Property property = new SaltPropertyReader.Property(); property.TypeVal = SaltPropertyReader.Type.NameProperty; property.Name = "TextureFileCacheName"; property.Size = 8; SaltPropertyReader.PropertyValue value = new SaltPropertyReader.PropertyValue(); value.StringValue = "Textures"; property.Value = value; properties.Add("TextureFileCacheName", property); arcName = value.StringValue; if (!properties.ContainsKey("TFCFileGuid")) { SaltPropertyReader.Property guidprop = new SaltPropertyReader.Property(); guidprop.TypeVal = SaltPropertyReader.Type.StructProperty; guidprop.Name = "TFCFileGuid"; guidprop.Size = 16; SaltPropertyReader.PropertyValue guid = new SaltPropertyReader.PropertyValue(); guid.len = guidprop.Size; guid.StringValue = "Guid"; guid.IntValue = pcc.AddName(guid.StringValue); guid.Array = new List<SaltPropertyReader.PropertyValue>(); for (int i = 0; i < 4; i++) guid.Array.Add(new SaltPropertyReader.PropertyValue()); guidprop.Value = guid; properties.Add("TFCFileGuid", guidprop); } properties.Add("None", none); } // copy specific properties from inTex for (int i = 0; i < inTex.properties.Count; i++) { SaltPropertyReader.Property prop = inTex.properties.ElementAt(i).Value; switch (prop.Name) { case "TextureFileCacheName": arcName = prop.Value.StringValue; properties["TextureFileCacheName"].Value.StringValue = arcName; break; case "TFCFileGuid": SaltPropertyReader.Property GUIDProp = properties["TFCFileGuid"]; for (int l = 0; l < 4; l++) { SaltPropertyReader.PropertyValue tempVal = GUIDProp.Value.Array[l]; tempVal.IntValue = prop.Value.Array[l].IntValue; GUIDProp.Value.Array[l] = tempVal; } break; case "MipTailBaseIdx": properties["MipTailBaseIdx"].Value.IntValue = prop.Value.IntValue; break; case "SizeX": properties["SizeX"].Value.IntValue = prop.Value.IntValue; break; case "SizeY": properties["SizeY"].Value.IntValue = prop.Value.IntValue; break; } } }
public void DumpImageData(ImageInfo imgInfo, string archiveDir = null, string fileName = null) { if (fileName == null) { fileName = texName + "_" + imgInfo.imgSize + ".bin"; } byte[] imgBuffer; 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 = FullArcPath; if (String.IsNullOrEmpty(archivePath)) GetTexArchive(archiveDir); if (!File.Exists(archivePath)) { throw new FileNotFoundException("Texture archive not found in " + archivePath); } using (FileStream archiveStream = File.OpenRead(archivePath)) { //archiveStream.Seek(imgInfo.offset, SeekOrigin.Begin); if (imgInfo.storageType == storage.arcCpr) { SaltLZOHelper lzohelp = new SaltLZOHelper(); imgBuffer = lzohelp.DecompressTex(archiveStream, imgInfo.offset, imgInfo.uncSize, imgInfo.cprSize); } else { archiveStream.Seek(imgInfo.offset, SeekOrigin.Begin); imgBuffer = new byte[imgInfo.uncSize]; archiveStream.Read(imgBuffer, 0, imgBuffer.Length); } } break; default: throw new FormatException("Unsupported texture storage type"); } using (FileStream outputImg = new FileStream(fileName, FileMode.Create, FileAccess.Write)) outputImg.Write(imgBuffer, 0, imgBuffer.Length); }
public byte[] DumpImage(ImageSize imgSize, string archiveDir) { byte[] imgBuff = null; ImageInfo imgInfo; if (imgList.Exists(img => img.imgSize == imgSize)) imgInfo = imgList.Find(img => img.imgSize == imgSize); else throw new FileNotFoundException("Image with resolution " + imgSize + " not found"); switch (imgInfo.storageType) { case storage.pccSto: imgBuff = new byte[imgInfo.uncSize]; Buffer.BlockCopy(imageData, imgInfo.offset, imgBuff, 0, imgInfo.uncSize); break; case storage.arcCpr: case storage.arcUnc: string archivePath = FullArcPath; if (String.IsNullOrEmpty(archivePath)) archivePath = GetTexArchive(archiveDir); if (!File.Exists(archivePath)) throw new FileNotFoundException("Texture archive not found in " + archivePath); using (FileStream archiveStream = File.OpenRead(archivePath)) { if (imgInfo.storageType == storage.arcCpr) { SaltLZOHelper lzohelp = new SaltLZOHelper(); imgBuff = lzohelp.DecompressTex(archiveStream, imgInfo.offset, imgInfo.uncSize, imgInfo.cprSize); } else { archiveStream.Seek(imgInfo.offset, SeekOrigin.Begin); imgBuff = new byte[imgInfo.uncSize]; archiveStream.Read(imgBuff, 0, imgBuff.Length); } } break; default: throw new FormatException("Unsupported texture storage type"); } return imgBuff; }
public void replaceImage2(string strImgSize, string fileToReplace, string archiveDir) { ImageSize imgSize = ImageSize.stringToSize(strImgSize); if (!imgList.Exists(img => img.imgSize == imgSize)) throw new FileNotFoundException("Image with resolution " + imgSize + " isn't found"); int imageIdx = imgList.FindIndex(img => img.imgSize == imgSize); ImageInfo imgInfo = imgList[imageIdx]; if (!File.Exists(fileToReplace)) throw new FileNotFoundException("invalid file to replace: " + fileToReplace); // check if replacing image is supported ImageFile imgFile; string fileFormat = Path.GetExtension(fileToReplace); switch (fileFormat) { case ".dds": imgFile = new DDS(fileToReplace, null); break; case ".DDS": imgFile = new DDS(fileToReplace, null); break; default: throw new FormatException(fileFormat + " image extension not supported"); } if (texFormat == "PF_NormalMap_HQ") { if (imgFile.format != "ATI2") throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype()); } else if (String.Compare(texFormat, "PF_" + imgFile.format, true) != 0 && String.Compare(texFormat, imgFile.format, true) != 0) { throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype()); } byte[] imgBuffer; // if the image is empty then recover the archive compression from the image list if (imgInfo.storageType == storage.empty) { imgInfo.storageType = imgList.Find(img => img.storageType != storage.empty && img.storageType != storage.pccSto).storageType; imgInfo.uncSize = imgFile.resize().Length; imgInfo.cprSize = imgFile.resize().Length; } switch (imgInfo.storageType) { case storage.arcCpr: case storage.arcUnc: string archivePath = FullArcPath; if (String.IsNullOrEmpty(archivePath)) archivePath = GetTexArchive(archiveDir); if (!File.Exists(archivePath)) throw new FileNotFoundException("Texture archive not found in " + archivePath); imgBuffer = imgFile.imgData; if (imgBuffer.Length != imgInfo.uncSize) throw new FormatException("image sizes do not match, original is " + imgInfo.uncSize + ", new is " + imgBuffer.Length); if (arcName.Length <= CustCache.Length || arcName.Substring(0, CustCache.Length) != CustCache) // Check whether existing texture is in a custom cache { ChooseNewCache(archiveDir, imgBuffer.Length); archivePath = FullArcPath; } else { FileInfo arc = new FileInfo(archivePath); if (arc.Length + imgBuffer.Length >= 0x80000000) { ChooseNewCache(archiveDir, imgBuffer.Length); archivePath = FullArcPath; } } using (FileStream archiveStream = new FileStream(archivePath, FileMode.Append, FileAccess.Write)) { int newOffset = (int)archiveStream.Position; if (imgInfo.storageType == storage.arcCpr) { byte[] tempBuff; SaltLZOHelper lzohelper = new SaltLZOHelper(); tempBuff = lzohelper.CompressTex(imgBuffer); imgBuffer = new byte[tempBuff.Length]; Buffer.BlockCopy(tempBuff, 0, imgBuffer, 0, tempBuff.Length); imgInfo.cprSize = imgBuffer.Length; } archiveStream.Write(imgBuffer, 0, imgBuffer.Length); imgInfo.offset = newOffset; } break; case storage.pccSto: imgBuffer = imgFile.resize(); using (MemoryStream dataStream = new MemoryStream()) { dataStream.WriteBytes(imageData); if (imgBuffer.Length <= imgInfo.uncSize && imgInfo.offset > 0) dataStream.Seek(imgInfo.offset, SeekOrigin.Begin); else imgInfo.offset = (int)dataStream.Position; dataStream.WriteBytes(imgBuffer); imgInfo.cprSize = imgBuffer.Length; imgInfo.uncSize = imgBuffer.Length; imageData = dataStream.ToArray(); } break; } imgList[imageIdx] = imgInfo; }