Quick fix for wii u bfres and fix TXTG 8x5 format
This commit is contained in:
parent
49074ab44a
commit
925830b8bb
@ -9,6 +9,7 @@ using System.Windows.Forms;
|
||||
using Syroot.NintenTools.NSW.Bfres;
|
||||
using Toolbox.Library;
|
||||
using Toolbox.Library.IO;
|
||||
using ZstdSharp;
|
||||
using ZstdSharp.Unsafe;
|
||||
|
||||
namespace FirstPlugin
|
||||
@ -19,15 +20,22 @@ namespace FirstPlugin
|
||||
|
||||
public List<TXTG> TextureList = new List<TXTG>();
|
||||
|
||||
public static bool IsMeshCodec(Stream stream)
|
||||
public static bool IsMeshCodecBfres(Stream stream)
|
||||
{
|
||||
using (var reader = new FileReader(stream, true))
|
||||
{
|
||||
reader.Seek(10, SeekOrigin.Begin);
|
||||
byte version = reader.ReadByte();
|
||||
if (version < 10)
|
||||
return false;
|
||||
|
||||
reader.Seek(238, SeekOrigin.Begin);
|
||||
byte flag = reader.ReadByte();
|
||||
byte flag2 = reader.ReadByte(); //flag custom set by bfres resave
|
||||
|
||||
reader.Position = 0;
|
||||
//Check if flag is external buffer .mc binary
|
||||
return flag == 11;
|
||||
return flag == 11 || flag2 == 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +65,97 @@ namespace FirstPlugin
|
||||
LoadExternalStrings();
|
||||
}
|
||||
|
||||
static void LoadExternalStrings()
|
||||
{
|
||||
if (ExternalStringBinary != null)
|
||||
return;
|
||||
|
||||
string path = Path.Combine(Runtime.TotkGamePath, "Shader", "ExternalBinaryString.bfres.mc");
|
||||
byte[] data = DecompressMeshCodec(path);
|
||||
//Load string table into memory
|
||||
//Strings are stored in a static list which will be used for opened bfres
|
||||
ExternalStringBinary = new ResFile(new MemoryStream(data));
|
||||
}
|
||||
|
||||
public static byte[] DecompressMeshCodec(string file)
|
||||
{
|
||||
using (var fs = File.OpenRead(file)) {
|
||||
return DecompressMeshCodec(fs);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] DecompressMeshCodec(Stream stream)
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
reader.ReadUInt32(); //Magic
|
||||
reader.ReadUInt32(); //Version 1.1.0.0
|
||||
var flags = reader.ReadInt32();
|
||||
var decompressed_size = (flags >> 5) << (flags & 0xf);
|
||||
|
||||
reader.BaseStream.Seek(0xC, SeekOrigin.Begin);
|
||||
byte[] src = reader.ReadBytes((int)reader.BaseStream.Length - 0xC);
|
||||
return Decompress(src, (uint)decompressed_size);
|
||||
}
|
||||
}
|
||||
|
||||
static unsafe byte[] Decompress(byte[] src, uint decompressed_size)
|
||||
{
|
||||
var dctx = Methods.ZSTD_createDCtx();
|
||||
Methods.ZSTD_DCtx_setFormat(dctx, ZSTD_format_e.ZSTD_f_zstd1_magicless);
|
||||
var uncompressed = new byte[decompressed_size];
|
||||
fixed (byte* srcPtr = src)
|
||||
fixed (byte* uncompressedPtr = uncompressed)
|
||||
{
|
||||
var decompressedLength = Methods.ZSTD_decompressDCtx(dctx, uncompressedPtr, (UIntPtr)uncompressed.Length, srcPtr, (UIntPtr)src.Length);
|
||||
|
||||
byte[] arr = new byte[(uint)decompressed_size];
|
||||
Marshal.Copy((IntPtr)uncompressedPtr, arr, 0, arr.Length);
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] CompressMeshCodec(Stream stream)
|
||||
{
|
||||
var src = stream.ToArray();
|
||||
|
||||
var mem = new MemoryStream();
|
||||
using (var writer = new BinaryWriter(mem))
|
||||
{
|
||||
writer.Write(1263551309); //MCPK
|
||||
//Version 1.1.0.0
|
||||
writer.Write((byte)1);
|
||||
writer.Write((byte)1);
|
||||
writer.Write((byte)0);
|
||||
writer.Write((byte)0);
|
||||
//Flags
|
||||
writer.Write(GetMeshCodecFlags((uint)src.Length));
|
||||
//ZSTD bfres with no magic
|
||||
writer.Write(CompressZSTD(src));
|
||||
}
|
||||
return mem.ToArray();
|
||||
}
|
||||
|
||||
static uint GetMeshCodecFlags(uint decompSize)
|
||||
{
|
||||
var aligned = (uint)(-decompSize % 0x1000 + 0x1000) % 0x1000;
|
||||
decompSize = decompSize + aligned;
|
||||
return ((decompSize >> (int)0xc) << 5) + 0xc;
|
||||
}
|
||||
|
||||
static byte[] CompressZSTD(byte[] src)
|
||||
{
|
||||
int level = 20;
|
||||
Compressor comp = new Compressor(level);
|
||||
comp.SetParameter(ZSTD_cParameter.ZSTD_c_contentSizeFlag, 0);
|
||||
comp.SetParameter(ZSTD_cParameter.ZSTD_c_checksumFlag, 0);
|
||||
comp.SetParameter(ZSTD_cParameter.ZSTD_c_dictIDFlag, 0);
|
||||
comp.SetParameter(ZSTD_cParameter.ZSTD_c_experimentalParam2, 1);
|
||||
|
||||
var compressed = comp.Wrap(src);
|
||||
return compressed.ToArray();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var tex in this.TextureList)
|
||||
@ -88,49 +187,5 @@ namespace FirstPlugin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadExternalStrings()
|
||||
{
|
||||
if (ExternalStringBinary != null)
|
||||
return;
|
||||
|
||||
string path = Path.Combine(Runtime.TotkGamePath, "Shader", "ExternalBinaryString.bfres.mc");
|
||||
byte[] data = DecompressMeshCodec(path);
|
||||
//Load string table into memory
|
||||
//Strings are stored in a static list which will be used for opened bfres
|
||||
ExternalStringBinary = new ResFile(new MemoryStream(data));
|
||||
}
|
||||
|
||||
static byte[] DecompressMeshCodec(string file)
|
||||
{
|
||||
using (var fs = File.OpenRead(file))
|
||||
using (var reader = new BinaryReader(fs))
|
||||
{
|
||||
reader.ReadUInt32(); //Magic
|
||||
reader.ReadUInt32(); //Version 1.1.0.0
|
||||
var flags = reader.ReadInt32();
|
||||
var decompressed_size = (flags >> 5) << (flags & 0xf);
|
||||
|
||||
reader.BaseStream.Seek(0xC, SeekOrigin.Begin);
|
||||
byte[] src = reader.ReadBytes((int)reader.BaseStream.Length - 0xC);
|
||||
return Decompress(src, (uint)decompressed_size);
|
||||
}
|
||||
}
|
||||
|
||||
static unsafe byte[] Decompress(byte[] src, uint decompressed_size)
|
||||
{
|
||||
var dctx = Methods.ZSTD_createDCtx();
|
||||
Methods.ZSTD_DCtx_setFormat(dctx, ZSTD_format_e.ZSTD_f_zstd1_magicless);
|
||||
var uncompressed = new byte[decompressed_size];
|
||||
fixed (byte* srcPtr = src)
|
||||
fixed (byte* uncompressedPtr = uncompressed)
|
||||
{
|
||||
var decompressedLength = Methods.ZSTD_decompressDCtx(dctx, uncompressedPtr, (UIntPtr)uncompressed.Length, srcPtr, (UIntPtr)src.Length);
|
||||
|
||||
byte[] arr = new byte[(uint)decompressed_size];
|
||||
Marshal.Copy((IntPtr)uncompressedPtr, arr, 0, arr.Length);
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,11 +213,14 @@ namespace FirstPlugin
|
||||
|
||||
//Dumb hack. Terrain is oddly 8x8 astc, but the format seems to be 0x101
|
||||
//Use some of the different texture settings, as they likely configure the astc blocks in some way
|
||||
if (this.HeaderInfo.TextureSetting2 == 32628)
|
||||
{
|
||||
this.Format = TEX_FORMAT.ASTC_8x5_UNORM;
|
||||
}
|
||||
if (this.HeaderInfo.TextureSetting2 == 32631)
|
||||
{
|
||||
this.Format = TEX_FORMAT.ASTC_8x8_UNORM;
|
||||
}
|
||||
|
||||
//Image data is properly loaded afterwards
|
||||
List<List<byte[]>> data = new List<List<byte[]>>();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user