more bug fixes, can recompress 3DNPCs and a bunch of other BSAs

This commit is contained in:
Timothy Baldridge 2019-07-29 15:24:05 -06:00
parent 8facc9a1f4
commit 39e1a20741
4 changed files with 97 additions and 7 deletions

View File

@ -45,6 +45,14 @@ namespace Compression.BSA.Test
w.Build("c:\\tmp\\built.bsa"); w.Build("c:\\tmp\\built.bsa");
Equal(a.Files.Count(), w.Files.Count());
Equal(a.Files.Select(f => f.Path).ToHashSet(), w.Files.Select(f => f.Path).ToHashSet());
foreach (var pair in Enumerable.Zip(a.Files, w.Files, (ai, bi) => (ai, bi)))
{
Equal(pair.ai.Path, pair.bi.Path);
}
} }
using (var b = new BSAReader("c:\\tmp\\built.bsa")) using (var b = new BSAReader("c:\\tmp\\built.bsa"))
@ -59,11 +67,11 @@ namespace Compression.BSA.Test
foreach (var pair in Enumerable.Zip(a.Files, b.Files, (ai, bi) => (ai, bi))) foreach (var pair in Enumerable.Zip(a.Files, b.Files, (ai, bi) => (ai, bi)))
{ {
idx ++; idx ++;
Console.WriteLine($" - {pair.ai.Path}"); //Console.WriteLine($" - {pair.ai.Path}");
Equal(pair.ai.Path, pair.bi.Path); Equal(pair.ai.Path, pair.bi.Path);
Equal(pair.ai.Compressed, pair.bi.Compressed); Equal(pair.ai.Compressed, pair.bi.Compressed);
Equal(pair.ai.Size, pair.bi.Size); Equal(pair.ai.Size, pair.bi.Size);
//Equal(pair.ai.GetData(), pair.bi.GetData()); Equal(pair.ai.GetData(), pair.bi.GetData());
} }
} }
@ -72,6 +80,19 @@ namespace Compression.BSA.Test
} }
} }
private static void Equal(HashSet<string> a, HashSet<string> b)
{
Equal(a.Count, b.Count);
foreach (var itm in a)
Equal(b.Contains(itm));
}
private static void Equal(bool v)
{
if (!v) throw new InvalidDataException("False");
}
public static void Equal(uint a, uint b) public static void Equal(uint a, uint b)
{ {

View File

@ -30,6 +30,14 @@ namespace Compression.BSA
_offset = 0x24; _offset = 0x24;
} }
public IEnumerable<FileEntry> Files
{
get
{
return _files;
}
}
public ArchiveFlags ArchiveFlags public ArchiveFlags ArchiveFlags
{ {
get get
@ -193,6 +201,7 @@ namespace Compression.BSA
public class FolderRecordBuilder public class FolderRecordBuilder
{ {
internal IEnumerable<FileEntry> _files; internal IEnumerable<FileEntry> _files;
private string _name;
internal BSABuilder _bsa; internal BSABuilder _bsa;
internal ulong _hash; internal ulong _hash;
internal uint _fileCount; internal uint _fileCount;
@ -200,6 +209,22 @@ namespace Compression.BSA
internal uint _recordSize; internal uint _recordSize;
internal ulong _offset; internal ulong _offset;
public ulong Hash
{
get
{
return _hash;
}
}
public string Name
{
get
{
return _name;
}
}
public ulong SelfSize public ulong SelfSize
{ {
get get
@ -230,8 +255,10 @@ namespace Compression.BSA
public FolderRecordBuilder(BSABuilder bsa, string folderName, IEnumerable<FileEntry> files) public FolderRecordBuilder(BSABuilder bsa, string folderName, IEnumerable<FileEntry> files)
{ {
_files = files.OrderBy(f => f._hash); _files = files.OrderBy(f => f._hash);
_name = folderName.ToLowerInvariant();
_bsa = bsa; _bsa = bsa;
_hash = folderName.GetBSAHash(); // Folders don't have extensions, so let's make sure we cut it out
_hash = _name.GetBSAHash("");
_fileCount = (uint)files.Count(); _fileCount = (uint)files.Count();
_nameBytes = folderName.ToBZString(); _nameBytes = folderName.ToBZString();
_recordSize = sizeof(ulong) + sizeof(uint) + sizeof(uint); _recordSize = sizeof(ulong) + sizeof(uint) + sizeof(uint);
@ -299,9 +326,11 @@ namespace Compression.BSA
if (_bsa.HeaderType == VersionType.SSE) if (_bsa.HeaderType == VersionType.SSE)
{ {
var r = new MemoryStream(); var r = new MemoryStream();
var w = LZ4Stream.Encode(r); using (var w = LZ4Stream.Encode(r))
(new MemoryStream(_rawData)).CopyTo(w); (new MemoryStream(_rawData)).CopyTo(w);
_rawData = r.ToArray(); _rawData = r.ToArray();
} }
} }
@ -336,6 +365,20 @@ namespace Compression.BSA
} }
} }
public ulong Hash { get
{
return _hash;
}
}
public FolderRecordBuilder Folder
{
get
{
return _folder;
}
}
internal void WriteFileRecord(BinaryWriter wtr) internal void WriteFileRecord(BinaryWriter wtr)
{ {

View File

@ -218,6 +218,13 @@ namespace Compression.BSA
} }
public string Name { get; private set; } public string Name { get; private set; }
public ulong Hash
{
get
{
return _nameHash;
}
}
internal void LoadFileRecordBlock(BSAReader bsa, BinaryReader src) internal void LoadFileRecordBlock(BSAReader bsa, BinaryReader src)
{ {
@ -293,7 +300,22 @@ namespace Compression.BSA
return _size; return _size;
} }
} }
public ulong Hash {
get
{
return _hash;
}
}
public FolderRecord Folder
{
get
{
return _folder;
}
}
public void CopyDataTo(Stream output) public void CopyDataTo(Stream output)
{ {
using (var in_file = File.OpenRead(_bsa._fileName)) using (var in_file = File.OpenRead(_bsa._fileName))
@ -314,6 +336,10 @@ namespace Compression.BSA
var original_size = rdr.ReadUInt32(); var original_size = rdr.ReadUInt32();
if (_bsa.HeaderType == VersionType.SSE) if (_bsa.HeaderType == VersionType.SSE)
{ {
var settings = new LZ4DecoderSettings()
{
ExtraMemory = 1024 * 1024 * 8
};
var r = LZ4Stream.Decode(rdr.BaseStream); var r = LZ4Stream.Decode(rdr.BaseStream);
r.CopyTo(output); r.CopyTo(output);
} }

View File

@ -80,7 +80,7 @@ namespace Compression.BSA
return GetBSAHash(Path.ChangeExtension(name, null), Path.GetExtension(name)); return GetBSAHash(Path.ChangeExtension(name, null), Path.GetExtension(name));
} }
private static ulong GetBSAHash(string name, string ext) public static ulong GetBSAHash(this string name, string ext)
{ {
name = name.ToLowerInvariant(); name = name.ToLowerInvariant();
ext = ext.ToLowerInvariant(); ext = ext.ToLowerInvariant();