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(); }
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; }