mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
implement new BSA framework for old BSA routines
This commit is contained in:
parent
ce4a3e17dd
commit
88fa091d07
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -9,17 +10,24 @@ namespace Compression.BSA.Test
|
|||||||
{
|
{
|
||||||
internal class Program
|
internal class Program
|
||||||
{
|
{
|
||||||
private const string TestDir = @"D:\MO2 Instances\F4EE";
|
//private const string TestDirBSA = @"D:\MO2 Instances\F4EE";
|
||||||
|
//private const string TestDirBA2 = @"D:\MO2 Instances\F4EE";
|
||||||
|
private const string TestDir = @"D:\MO2 Instances";
|
||||||
//private const string TestDir = @"D:\Steam\steamapps\common\Fallout 4";
|
//private const string TestDir = @"D:\Steam\steamapps\common\Fallout 4";
|
||||||
private const string TempDir = @"c:\tmp\out\f4ee";
|
private const string TempDir = @"c:\tmp\out\f4ee";
|
||||||
|
private const string ArchiveTempDir = @"c:\tmp\out\archive";
|
||||||
|
|
||||||
|
//private const string Archive2Location = @"D:\Steam\steamapps\common\Fallout 4\Tools\Archive2\Archive2.exe";
|
||||||
|
|
||||||
private static void Main(string[] args)
|
private static void Main(string[] args)
|
||||||
{
|
{
|
||||||
foreach (var bsa in Directory.EnumerateFiles(TestDir, "*.ba2", SearchOption.AllDirectories).Skip(0))
|
foreach (var bsa in Directory.EnumerateFiles(TestDir, "*.ba2", SearchOption.AllDirectories)
|
||||||
|
.Concat(Directory.EnumerateFiles(TestDir, "*.bsa", SearchOption.AllDirectories)).Skip(200))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"From {bsa}");
|
Console.WriteLine($"From {bsa}");
|
||||||
Console.WriteLine("Cleaning Output Dir");
|
Console.WriteLine("Cleaning Output Dir");
|
||||||
if (Directory.Exists(TempDir)) Directory.Delete(TempDir, true);
|
if (Directory.Exists(TempDir)) Directory.Delete(TempDir, true);
|
||||||
|
if (Directory.Exists(ArchiveTempDir)) Directory.Delete(ArchiveTempDir, true);
|
||||||
Directory.CreateDirectory(TempDir);
|
Directory.CreateDirectory(TempDir);
|
||||||
|
|
||||||
Console.WriteLine($"Reading {bsa}");
|
Console.WriteLine($"Reading {bsa}");
|
||||||
@ -28,6 +36,7 @@ namespace Compression.BSA.Test
|
|||||||
Parallel.ForEach(a.Files, file =>
|
Parallel.ForEach(a.Files, file =>
|
||||||
{
|
{
|
||||||
var abs_name = Path.Combine(TempDir, file.Path);
|
var abs_name = Path.Combine(TempDir, file.Path);
|
||||||
|
ViaJson(file.State);
|
||||||
|
|
||||||
if (!Directory.Exists(Path.GetDirectoryName(abs_name)))
|
if (!Directory.Exists(Path.GetDirectoryName(abs_name)))
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(abs_name));
|
Directory.CreateDirectory(Path.GetDirectoryName(abs_name));
|
||||||
@ -43,6 +52,22 @@ namespace Compression.BSA.Test
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
Console.WriteLine("Extracting via Archive.exe");
|
||||||
|
if (bsa.ToLower().EndsWith(".ba2"))
|
||||||
|
{
|
||||||
|
var p = Process.Start(Archive2Location, $"\"{bsa}\" -e=\"{ArchiveTempDir}\"");
|
||||||
|
p.WaitForExit();
|
||||||
|
|
||||||
|
foreach (var file in a.Files)
|
||||||
|
{
|
||||||
|
var a_path = Path.Combine(TempDir, file.Path);
|
||||||
|
var b_path = Path.Combine(ArchiveTempDir, file.Path);
|
||||||
|
Equal(new FileInfo(a_path).Length, new FileInfo(b_path).Length);
|
||||||
|
Equal(File.ReadAllBytes(a_path), File.ReadAllBytes(b_path));
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine($"Building {bsa}");
|
Console.WriteLine($"Building {bsa}");
|
||||||
|
|
||||||
@ -59,9 +84,6 @@ namespace Compression.BSA.Test
|
|||||||
});
|
});
|
||||||
|
|
||||||
w.Build("c:\\tmp\\tmp.bsa");
|
w.Build("c:\\tmp\\tmp.bsa");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"Verifying {bsa}");
|
Console.WriteLine($"Verifying {bsa}");
|
||||||
@ -163,7 +185,7 @@ namespace Compression.BSA.Test
|
|||||||
|
|
||||||
for (var idx = 0; idx < a.Length; idx++)
|
for (var idx = 0; idx < a.Length; idx++)
|
||||||
if (a[idx] != b[idx])
|
if (a[idx] != b[idx])
|
||||||
throw new InvalidDataException($"Byte array contents not equal at {idx}");
|
throw new InvalidDataException($"Byte array contents not equal at {idx} - {a[idx]} vs {b[idx]}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -250,6 +250,7 @@ namespace Compression.BSA
|
|||||||
ddsHeader.dwWidth = _width;
|
ddsHeader.dwWidth = _width;
|
||||||
ddsHeader.dwMipMapCount = _numMips;
|
ddsHeader.dwMipMapCount = _numMips;
|
||||||
ddsHeader.PixelFormat.dwSize = ddsHeader.PixelFormat.GetSize();
|
ddsHeader.PixelFormat.dwSize = ddsHeader.PixelFormat.GetSize();
|
||||||
|
ddsHeader.dwDepth = 1;
|
||||||
ddsHeader.dwSurfaceFlags = DDS.DDS_SURFACE_FLAGS_TEXTURE | DDS.DDS_SURFACE_FLAGS_MIPMAP;
|
ddsHeader.dwSurfaceFlags = DDS.DDS_SURFACE_FLAGS_TEXTURE | DDS.DDS_SURFACE_FLAGS_MIPMAP;
|
||||||
|
|
||||||
switch ((DXGI_FORMAT)_format)
|
switch ((DXGI_FORMAT)_format)
|
||||||
@ -274,7 +275,7 @@ namespace Compression.BSA
|
|||||||
if (_bsa.UseATIFourCC)
|
if (_bsa.UseATIFourCC)
|
||||||
ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('A', 'T', 'I', '2'); // this is more correct but the only thing I have found that supports it is the nvidia photoshop plugin
|
ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('A', 'T', 'I', '2'); // this is more correct but the only thing I have found that supports it is the nvidia photoshop plugin
|
||||||
else
|
else
|
||||||
ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('D', 'X', 'T', '5');
|
ddsHeader.PixelFormat.dwFourCC = DDS.MAKEFOURCC('B', 'C', '5', 'U');
|
||||||
ddsHeader.dwPitchOrLinearSize = (uint)(_width * _height); // 8bpp
|
ddsHeader.dwPitchOrLinearSize = (uint)(_width * _height); // 8bpp
|
||||||
break;
|
break;
|
||||||
case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB:
|
case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||||
|
@ -11,7 +11,7 @@ using Path = Alphaleonis.Win32.Filesystem.Path;
|
|||||||
|
|
||||||
namespace Compression.BSA
|
namespace Compression.BSA
|
||||||
{
|
{
|
||||||
public class BSABuilder : IDisposable
|
public class BSABuilder : IDisposable, IBSABuilder
|
||||||
{
|
{
|
||||||
internal uint _archiveFlags;
|
internal uint _archiveFlags;
|
||||||
internal uint _fileCount;
|
internal uint _fileCount;
|
||||||
@ -32,6 +32,13 @@ namespace Compression.BSA
|
|||||||
_offset = 0x24;
|
_offset = 0x24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BSABuilder(BSAStateObject bsaStateObject) : this()
|
||||||
|
{
|
||||||
|
_version = bsaStateObject.Version;
|
||||||
|
_fileFlags = bsaStateObject.FileFlags;
|
||||||
|
_archiveFlags = bsaStateObject.ArchiveFlags;
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<FileEntry> Files => _files;
|
public IEnumerable<FileEntry> Files => _files;
|
||||||
|
|
||||||
public ArchiveFlags ArchiveFlags
|
public ArchiveFlags ArchiveFlags
|
||||||
@ -85,6 +92,18 @@ namespace Compression.BSA
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddFile(FileStateObject state, Stream src)
|
||||||
|
{
|
||||||
|
var ostate = (BSAFileStateObject) state;
|
||||||
|
|
||||||
|
var r = new FileEntry(this, ostate.Path, src, ostate.FlipCompression);
|
||||||
|
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
_files.Add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Build(string outputName)
|
public void Build(string outputName)
|
||||||
{
|
{
|
||||||
RegenFolderRecords();
|
RegenFolderRecords();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
|
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
|
||||||
using K4os.Compression.LZ4.Streams;
|
using K4os.Compression.LZ4.Streams;
|
||||||
using File = Alphaleonis.Win32.Filesystem.File;
|
using File = Alphaleonis.Win32.Filesystem.File;
|
||||||
@ -48,19 +49,19 @@ namespace Compression.BSA
|
|||||||
|
|
||||||
public class BSAReader : IDisposable, IBSAReader
|
public class BSAReader : IDisposable, IBSAReader
|
||||||
{
|
{
|
||||||
private uint _archiveFlags;
|
internal uint _archiveFlags;
|
||||||
private uint _fileCount;
|
internal uint _fileCount;
|
||||||
private uint _fileFlags;
|
internal uint _fileFlags;
|
||||||
internal string _fileName;
|
internal string _fileName;
|
||||||
private uint _folderCount;
|
internal uint _folderCount;
|
||||||
private uint _folderRecordOffset;
|
internal uint _folderRecordOffset;
|
||||||
private List<FolderRecord> _folders;
|
private List<FolderRecord> _folders;
|
||||||
private string _magic;
|
internal string _magic;
|
||||||
private readonly BinaryReader _rdr;
|
private readonly BinaryReader _rdr;
|
||||||
private readonly Stream _stream;
|
private readonly Stream _stream;
|
||||||
private uint _totalFileNameLength;
|
internal uint _totalFileNameLength;
|
||||||
private uint _totalFolderNameLength;
|
internal uint _totalFolderNameLength;
|
||||||
private uint _version;
|
internal uint _version;
|
||||||
|
|
||||||
public BSAReader(string filename) : this(File.OpenRead(filename))
|
public BSAReader(string filename) : this(File.OpenRead(filename))
|
||||||
{
|
{
|
||||||
@ -84,7 +85,7 @@ namespace Compression.BSA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArchiveStateObject State { get; }
|
public ArchiveStateObject State => new BSAStateObject(this);
|
||||||
|
|
||||||
public VersionType HeaderType => (VersionType) _version;
|
public VersionType HeaderType => (VersionType) _version;
|
||||||
|
|
||||||
@ -150,6 +151,29 @@ namespace Compression.BSA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class BSAStateObject : ArchiveStateObject
|
||||||
|
{
|
||||||
|
public BSAStateObject() { }
|
||||||
|
public BSAStateObject(BSAReader bsaReader)
|
||||||
|
{
|
||||||
|
Magic = bsaReader._magic;
|
||||||
|
Version = bsaReader._version;
|
||||||
|
ArchiveFlags = bsaReader._archiveFlags;
|
||||||
|
FileFlags = bsaReader._fileFlags;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IBSABuilder MakeBuilder()
|
||||||
|
{
|
||||||
|
return new BSABuilder(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Magic { get; set; }
|
||||||
|
public uint Version { get; set; }
|
||||||
|
public uint ArchiveFlags { get; set; }
|
||||||
|
public uint FileFlags { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class FolderRecord
|
public class FolderRecord
|
||||||
{
|
{
|
||||||
private readonly uint _fileCount;
|
private readonly uint _fileCount;
|
||||||
@ -181,7 +205,8 @@ namespace Compression.BSA
|
|||||||
if (bsa.HasFolderNames) Name = src.ReadStringLen(bsa.HeaderType);
|
if (bsa.HasFolderNames) Name = src.ReadStringLen(bsa.HeaderType);
|
||||||
|
|
||||||
_files = new List<FileRecord>();
|
_files = new List<FileRecord>();
|
||||||
for (var idx = 0; idx < _fileCount; idx += 1) _files.Add(new FileRecord(bsa, this, src));
|
for (var idx = 0; idx < _fileCount; idx += 1)
|
||||||
|
_files.Add(new FileRecord(bsa, this, src, idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,9 +221,11 @@ namespace Compression.BSA
|
|||||||
private readonly uint _onDiskSize;
|
private readonly uint _onDiskSize;
|
||||||
private readonly uint _originalSize;
|
private readonly uint _originalSize;
|
||||||
private readonly uint _size;
|
private readonly uint _size;
|
||||||
|
internal readonly int _index;
|
||||||
|
|
||||||
public FileRecord(BSAReader bsa, FolderRecord folderRecord, BinaryReader src)
|
public FileRecord(BSAReader bsa, FolderRecord folderRecord, BinaryReader src, int index)
|
||||||
{
|
{
|
||||||
|
_index = index;
|
||||||
_bsa = bsa;
|
_bsa = bsa;
|
||||||
Hash = src.ReadUInt64();
|
Hash = src.ReadUInt64();
|
||||||
var size = src.ReadUInt32();
|
var size = src.ReadUInt32();
|
||||||
@ -262,7 +289,7 @@ namespace Compression.BSA
|
|||||||
}
|
}
|
||||||
|
|
||||||
public uint Size => _dataSize;
|
public uint Size => _dataSize;
|
||||||
public FileStateObject State { get; }
|
public FileStateObject State => new BSAFileStateObject(this);
|
||||||
|
|
||||||
public ulong Hash { get; }
|
public ulong Hash { get; }
|
||||||
|
|
||||||
@ -314,4 +341,18 @@ namespace Compression.BSA
|
|||||||
return ms.ToArray();
|
return ms.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class BSAFileStateObject : FileStateObject
|
||||||
|
{
|
||||||
|
public BSAFileStateObject() { }
|
||||||
|
public BSAFileStateObject(FileRecord fileRecord)
|
||||||
|
{
|
||||||
|
FlipCompression = fileRecord.FlipCompression;
|
||||||
|
Path = fileRecord.Path;
|
||||||
|
Index = fileRecord._index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool FlipCompression { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user