private bool repackFile(TPF.Texture tpfEntry, string name, string baseDir, string subDir) { string inputPath = baseDir + "\\" + subDir + "\\" + name + ".dds"; //DBGTEX_DETAIL crashes this, what in the heck if (inputPath != null && File.Exists(inputPath) && name != "DBGTEX_DETAIL") { byte[] inputBytes = File.ReadAllBytes(inputPath); DXGIFormat originalFormat = DDSFile.Read(new MemoryStream(tpfEntry.Bytes)).Format; DXGIFormat newFormat = DDSFile.Read(new MemoryStream(inputBytes)).Format; if (originalFormat != DXGIFormat.Unknown && newFormat != DXGIFormat.Unknown && originalFormat != newFormat) { byte[] newBytes = convertFile(inputPath, originalFormat); if (newBytes != null) { inputBytes = newBytes; } } tpfEntry.Bytes = inputBytes; return(true); } else { return(false); } }
private void repackTPF(TPF tpf, string baseDir, string subDir) { // parts\HR_F_0010 and parts\HR_F_0010_M have duplicate filenames in the same tpf // thx QLOC List <string> names = new List <string>(); List <string> dupes = new List <string>(); foreach (TPF.Texture tpfEntry in tpf.Textures) { if (names.Contains(tpfEntry.Name)) { dupes.Add(tpfEntry.Name); } else { names.Add(tpfEntry.Name); } } for (int i = 0; i < tpf.Textures.Count; i++) { TPF.Texture tpfEntry = tpf.Textures[i]; string name = tpfEntry.Name; if (dupes.Contains(name)) { name += "_" + i; } repackFile(tpfEntry, name, baseDir, subDir); } }
public static bool IsTPFCube(TPF.Texture tex, TPF.TPFPlatform platform) { if (platform == TPF.TPFPlatform.PC) { DDS dds = new DDS(tex.Bytes); return((dds.dwCaps2 & DDS.DDSCAPS2.CUBEMAP) > 0); } return(tex.Type == TPF.TexType.Cubemap); }
public UnpackReportFile(TPF.Texture tex) { using (var ms = new MemoryStream(tex.Bytes)) using (var dds = DDSFile.Read(ms)) { Name = tex.Name; Format = dds?.Format ?? DXGIFormat.Unknown; Width = dds?.MipChains[0][0].Width ?? -1; Height = dds?.MipChains[0][0].Height ?? -1; } }
private void UnpackFile(TPF.Texture tpfEntry, string name, string baseDir, string subDir) { string subPath = subDir + "\\" + name + ".dds"; string ddsPath = baseDir + "\\" + subPath; if (!File.Exists(ddsPath)) { Directory.CreateDirectory(Path.GetDirectoryName(ddsPath)); File.WriteAllBytes(ddsPath, tpfEntry.Bytes); } }
private bool repackFile(TPF.Texture tpfEntry, string name, string baseDir, string subDir) { string inputPath = getSwappedPath(name, subDir, out bool dds); if (inputPath != null && File.Exists(inputPath)) { byte[] inputBytes = File.ReadAllBytes(inputPath); DXGIFormat originalFormat = DDSFile.Read(new MemoryStream(tpfEntry.Bytes)).Format; if (originalFormat == DXGIFormat.Unknown) { appendError("Error: {0}\r\n\u2514\u2500 Could not determine format of game file.", subDir + "\\" + name + ".dds"); } bool convert = !dds; if (dds) { DXGIFormat newFormat = DDSFile.Read(new MemoryStream(inputBytes)).Format; if (newFormat == DXGIFormat.Unknown) { appendError("Error: {0}\r\n\u2514\u2500 Could not determine format of override file.", inputPath); } if (originalFormat != DXGIFormat.Unknown && newFormat != DXGIFormat.Unknown && originalFormat != newFormat) { convert = true; } } if (convert) { byte[] newBytes = convertFile(inputPath, originalFormat); if (newBytes != null) { inputBytes = newBytes; } } tpfEntry.Bytes = inputBytes; lock (countLock) textureCount++; return(true); } else { return(false); } }
public static void Unpack(this TPF tpf, string sourceName, string targetDir, IProgress <float> progress) { #if !DEBUG if (tpf.Platform != TPF.TPFPlatform.PC) { throw new NotSupportedException("Yabber does not support console TPFs at the moment."); } #endif Directory.CreateDirectory(targetDir); var xws = new XmlWriterSettings(); xws.Indent = true; var xw = XmlWriter.Create($"{targetDir}\\_yabber-tpf.xml", xws); xw.WriteStartElement("tpf"); xw.WriteElementString("filename", sourceName); xw.WriteElementString("compression", tpf.Compression.ToString()); xw.WriteElementString("encoding", $"0x{tpf.Encoding:X2}"); xw.WriteElementString("flag2", $"0x{tpf.Flag2:X2}"); xw.WriteStartElement("textures"); for (int i = 0; i < tpf.Textures.Count; i++) { TPF.Texture texture = tpf.Textures[i]; xw.WriteStartElement("texture"); xw.WriteElementString("name", texture.Name + ".dds"); xw.WriteElementString("format", texture.Format.ToString()); xw.WriteElementString("flags1", $"0x{texture.Flags1:X2}"); if (texture.FloatStruct != null) { xw.WriteStartElement("FloatStruct"); xw.WriteAttributeString("Unk00", texture.FloatStruct.Unk00.ToString()); foreach (float value in texture.FloatStruct.Values) { xw.WriteElementString("Value", value.ToString()); } xw.WriteEndElement(); } xw.WriteEndElement(); File.WriteAllBytes($"{targetDir}\\{texture.Name}.dds", texture.Headerize()); progress.Report((float)i / tpf.Textures.Count); } xw.WriteEndElement(); xw.WriteEndElement(); xw.Close(); }
private bool processTPF(TPF tpf, string baseDir, string subDir) { // parts\HR_F_0010 and parts\HR_F_0010_M have duplicate filenames in the same tpf // thx QLOC List <string> names = new List <string>(); List <string> dupes = new List <string>(); foreach (TPF.Texture tpfEntry in tpf.Textures) { if (names.Contains(tpfEntry.Name)) { dupes.Add(tpfEntry.Name); } else { names.Add(tpfEntry.Name); } } bool edited = false; for (int i = 0; i < tpf.Textures.Count; i++) { if (stop) { return(false); } TPF.Texture tpfEntry = tpf.Textures[i]; string name = tpfEntry.Name; if (dupes.Contains(name)) { name += "_" + i; } if (repack) { edited |= repackFile(tpfEntry, name, baseDir, subDir); } else { unpackFile(tpfEntry, name, baseDir, subDir); } } return(edited); }
public static void Repack(string sourceDir, string targetDir) { TPF tpf = new TPF(); XmlDocument xml = new XmlDocument(); xml.Load($"{sourceDir}\\_yabber-tpf.xml"); string filename = xml.SelectSingleNode("tpf/filename").InnerText; Enum.TryParse(xml.SelectSingleNode("tpf/compression")?.InnerText ?? "None", out tpf.Compression); tpf.Encoding = Convert.ToByte(xml.SelectSingleNode("tpf/encoding").InnerText, 16); tpf.Flag2 = Convert.ToByte(xml.SelectSingleNode("tpf/flag2").InnerText, 16); foreach (XmlNode texNode in xml.SelectNodes("tpf/textures/texture")) { string name = Path.GetFileNameWithoutExtension(texNode.SelectSingleNode("name").InnerText); byte format = Convert.ToByte(texNode.SelectSingleNode("format").InnerText); byte flags1 = Convert.ToByte(texNode.SelectSingleNode("flags1").InnerText, 16); TPF.FloatStruct floatStruct = null; XmlNode floatsNode = texNode.SelectSingleNode("FloatStruct"); if (floatsNode != null) { floatStruct = new TPF.FloatStruct(); floatStruct.Unk00 = int.Parse(floatsNode.Attributes["Unk00"].InnerText); foreach (XmlNode valueNode in floatsNode.SelectNodes("Value")) { floatStruct.Values.Add(float.Parse(valueNode.InnerText)); } } byte[] bytes = File.ReadAllBytes($"{sourceDir}\\{name}.dds"); var texture = new TPF.Texture(name, format, flags1, bytes); texture.FloatStruct = floatStruct; tpf.Textures.Add(texture); } string outPath = $"{targetDir}\\{filename}"; YBUtil.Backup(outPath); tpf.Write(outPath); }
private void unpackFile(TPF.Texture tpfEntry, string name, string baseDir, string subDir) { string subPath = subDir + "\\" + name + ".dds"; string ddsPath = baseDir + "\\" + subPath; lock (writeLock) { if (!File.Exists(ddsPath)) { Directory.CreateDirectory(Path.GetDirectoryName(ddsPath)); File.WriteAllBytes(ddsPath, tpfEntry.Bytes); lock (countLock) textureCount++; } else { appendError("Error: {0}\r\n\u2514\u2500 Duplicate file found.", subPath); } } }
public unsafe void FillWithPS4TPF(GraphicsDevice d, CommandList cl, TPF.TPFPlatform platform, TPF.Texture tex, string name) { if (platform != TPF.TPFPlatform.PS4) { return; } uint width = (uint)tex.Header.Width; uint height = (uint)tex.Header.Height; uint mipCount = (uint)tex.Mipmaps; PixelFormat format; format = GetPixelFormatFromDXGI((DDS.DXGI_FORMAT)tex.Header.DXGIFormat); width = (uint)(Math.Ceiling(width / 4f) * 4f); height = (uint)(Math.Ceiling(height / 4f) * 4f); if (mipCount == 0) { mipCount = (uint)(1 + Math.Floor(Math.Log(Math.Max(width, height), 2))); } bool isCubemap = (tex.Type == TPF.TexType.Cubemap); var usage = (isCubemap) ? TextureUsage.Cubemap : 0; uint arrayCount = isCubemap ? 6u : 1; TextureDescription desc = new TextureDescription(); desc.Width = width; desc.Height = height; desc.MipLevels = mipCount; desc.SampleCount = TextureSampleCount.Count1; desc.ArrayLayers = arrayCount; desc.Depth = 1; desc.Type = TextureType.Texture2D; desc.Usage = TextureUsage.Staging; desc.Format = format; _staging = d.ResourceFactory.CreateTexture(desc); uint blockSize = (uint)GetBlockSize(tex.Format); uint paddedWidth = 0; uint paddedHeight = 0; uint paddedSize = 0; uint copyOffset = 0; for (int slice = 0; slice < arrayCount; slice++) { uint currentWidth = width; uint currentHeight = height; for (uint level = 0; level < mipCount; level++) { if (tex.Format == 105) { paddedWidth = currentWidth; paddedHeight = currentHeight; paddedSize = paddedWidth * paddedHeight * blockSize; } else { paddedWidth = (uint)(Math.Ceiling(currentWidth / 32f) * 32f); paddedHeight = (uint)(Math.Ceiling(currentHeight / 32f) * 32f); paddedSize = (uint)(Math.Ceiling(paddedWidth / 4f) * Math.Ceiling(paddedHeight / 4f) * blockSize); } var mipInfo = GetMipInfo(format, tex.Header.Width, tex.Header.Height, (int)level, false); MappedResource map = d.Map(_staging, MapMode.Write, (uint)slice * (uint)mipCount + level); //fixed (void* data = &tex.Bytes[copyOffset]) //{ //Unsafe.CopyBlock(map.Data.ToPointer(), data, (uint)paddedSize); DeswizzleDDSBytesPS4((int)currentWidth, (int)currentHeight, tex.Format, (int)blockSize, (int)paddedWidth, new Span <byte>(tex.Bytes, (int)copyOffset, (int)paddedSize), new Span <byte>(map.Data.ToPointer(), (int)mipInfo)); //} copyOffset += paddedSize; if (currentWidth > 1) { currentWidth /= 2; } if (currentHeight > 1) { currentHeight /= 2; } } } desc.Usage = TextureUsage.Sampled | usage; desc.ArrayLayers = 1; _texture = d.ResourceFactory.CreateTexture(desc); _texture.Name = name; cl.CopyTexture(_staging, _texture); Resident = true; _pool.DescriptorTableDirty = true; }
public unsafe void FillWithTPF(GraphicsDevice d, CommandList cl, TPF.TPFPlatform platform, TPF.Texture tex, string name) { DDS dds; var bytes = tex.Bytes; if (platform != TPF.TPFPlatform.PC) { bytes = tex.Headerize(); dds = new DDS(bytes); } else { dds = new DDS(tex.Bytes); } uint width = (uint)dds.dwWidth; uint height = (uint)dds.dwHeight; PixelFormat format; if (dds.header10 != null) { format = GetPixelFormatFromDXGI(dds.header10.dxgiFormat); } else { if (dds.ddspf.dwFlags == (DDS.DDPF.RGB | DDS.DDPF.ALPHAPIXELS) && dds.ddspf.dwRGBBitCount == 32) { format = PixelFormat.R8_G8_B8_A8_UNorm_SRgb; } else if (dds.ddspf.dwFlags == (DDS.DDPF.RGB) && dds.ddspf.dwRGBBitCount == 24) { format = PixelFormat.R8_G8_B8_A8_UNorm_SRgb; // 24-bit formats are annoying for now return; } else { format = GetPixelFormatFromFourCC(dds.ddspf.dwFourCC); } } if (!Utils.IsPowerTwo(width) || !Utils.IsPowerTwo(height)) { return; } width = IsCompressedFormat(format) ? (uint)((width + 3) & ~0x3) : width; height = IsCompressedFormat(format) ? (uint)((height + 3) & ~0x3) : height; bool isCubemap = false; if ((dds.dwCaps2 & DDS.DDSCAPS2.CUBEMAP) > 0) { isCubemap = true; } var usage = (isCubemap) ? TextureUsage.Cubemap : 0; uint arrayCount = isCubemap ? 6u : 1; TextureDescription desc = new TextureDescription(); desc.Width = width; desc.Height = height; desc.MipLevels = (uint)dds.dwMipMapCount; desc.SampleCount = TextureSampleCount.Count1; desc.ArrayLayers = arrayCount; desc.Depth = 1; desc.Type = TextureType.Texture2D; desc.Usage = TextureUsage.Staging; desc.Format = format; _staging = d.ResourceFactory.CreateTexture(desc); int paddedWidth = 0; int paddedHeight = 0; int paddedSize = 0; int copyOffset = dds.DataOffset; for (int slice = 0; slice < arrayCount; slice++) { for (uint level = 0; level < dds.dwMipMapCount; level++) { MappedResource map = d.Map(_staging, MapMode.Write, (uint)slice * (uint)dds.dwMipMapCount + level); var mipInfo = GetMipInfo(format, (int)dds.dwWidth, (int)dds.dwHeight, (int)level, false); //paddedSize = mipInfo.ByteCount; paddedSize = mipInfo; fixed(void *data = &bytes[copyOffset]) { Unsafe.CopyBlock(map.Data.ToPointer(), data, (uint)paddedSize); } copyOffset += paddedSize; } } desc.Usage = TextureUsage.Sampled | usage; desc.ArrayLayers = 1; _texture = d.ResourceFactory.CreateTexture(desc); _texture.Name = name; cl.CopyTexture(_staging, _texture); Resident = true; _pool.DescriptorTableDirty = true; }