a good dozen BA2s passed the full test suite

This commit is contained in:
Timothy Baldridge 2019-10-07 22:02:03 -06:00
parent 9f3ee6a5cc
commit ce4a3e17dd
4 changed files with 176 additions and 17 deletions

View File

@ -15,7 +15,7 @@ namespace Compression.BSA.Test
private static void Main(string[] args)
{
foreach (var bsa in Directory.EnumerateFiles(TestDir, "*.ba2", SearchOption.AllDirectories).Skip(0).Take(1))
foreach (var bsa in Directory.EnumerateFiles(TestDir, "*.ba2", SearchOption.AllDirectories).Skip(0))
{
Console.WriteLine($"From {bsa}");
Console.WriteLine("Cleaning Output Dir");

View File

@ -43,6 +43,10 @@ namespace Compression.BSA
var result = new BA2FileEntryBuilder((BA2FileEntryState)state, src);
lock(_entries) _entries.Add(result);
break;
case EntryType.DX10:
var resultdx10 = new BA2DX10FileEntryBuilder((BA2DX10EntryState)state, src);
lock(_entries) _entries.Add(resultdx10);
break;
}
}
@ -92,6 +96,92 @@ namespace Compression.BSA
}
}
public class BA2DX10FileEntryBuilder : IFileBuilder
{
private BA2DX10EntryState _state;
private List<ChunkBuilder> _chunks;
public BA2DX10FileEntryBuilder(BA2DX10EntryState state, Stream src)
{
_state = state;
_chunks = _state.Chunks.Select(ch => new ChunkBuilder(state, ch, src)).ToList();
}
public uint FileHash => _state.NameHash;
public uint DirHash => _state.DirHash;
public string FullName => _state.FullName;
public int Index => _state.Index;
public void WriteHeader(BinaryWriter bw)
{
bw.Write(_state.NameHash);
bw.Write(Encoding.ASCII.GetBytes(_state.Extension));
bw.Write(_state.DirHash);
bw.Write(_state.Unk8);
bw.Write((byte)_chunks.Count);
bw.Write(_state.ChunkHdrLen);
bw.Write(_state.Height);
bw.Write(_state.Width);
bw.Write(_state.NumMips);
bw.Write(_state.PixelFormat);
bw.Write(_state.Unk16);
foreach (var chunk in _chunks)
chunk.WriteHeader(bw);
}
public void WriteData(BinaryWriter wtr)
{
foreach (var chunk in _chunks)
chunk.WriteData(wtr);
}
}
public class ChunkBuilder
{
private ChunkState _chunk;
private byte[] _data;
private uint _packSize;
private long _offsetOffset;
public ChunkBuilder(BA2DX10EntryState state, ChunkState ch, Stream src)
{
_chunk = ch;
_data = new byte[_chunk.FullSz];
if (_chunk.Compressed)
{
using (var ms = new MemoryStream())
using (var ds = new DeflaterOutputStream(ms))
{
ds.Write(_data, 0, _data.Length);
}
_packSize = (uint)_data.Length;
}
}
public void WriteHeader(BinaryWriter bw)
{
_offsetOffset = bw.BaseStream.Position;
bw.Write((ulong)0);
bw.Write(_packSize);
bw.Write(_chunk.FullSz);
bw.Write(_chunk.StartMip);
bw.Write(_chunk.EndMip);
bw.Write(_chunk.Align);
}
public void WriteData(BinaryWriter bw)
{
var pos = bw.BaseStream.Position;
bw.BaseStream.Position = _offsetOffset;
bw.Write((ulong)pos);
bw.BaseStream.Position = pos;
bw.Write(_data);
}
}
public class BA2FileEntryBuilder : IFileBuilder
{
private byte[] _data;

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@ -10,6 +11,7 @@ using System.Threading.Tasks;
using Alphaleonis.Win32.Filesystem;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Zip.Compression;
using Microsoft.SqlServer.Server;
using File = Alphaleonis.Win32.Filesystem.File;
namespace Compression.BSA
@ -85,7 +87,7 @@ namespace Compression.BSA
files.Add(new BA2FileEntry(this, idx));
break;
case EntryType.DX10:
files.Add(new BA2DX10Entry(this));
files.Add(new BA2DX10Entry(this, idx));
break;
case EntryType.GNMF:
break;
@ -139,21 +141,22 @@ namespace Compression.BSA
public class BA2DX10Entry : IFileEntry
{
private uint _nameHash;
private string _extension;
private uint _dirHash;
private byte _unk8;
private byte _numChunks;
private ushort _chunkHdrLen;
private ushort _height;
private ushort _width;
private byte _numMips;
private byte _format;
private ushort _unk16;
private List<BA2TextureChunk> _chunks;
internal uint _nameHash;
internal string _extension;
internal uint _dirHash;
internal byte _unk8;
internal byte _numChunks;
internal ushort _chunkHdrLen;
internal ushort _height;
internal ushort _width;
internal byte _numMips;
internal byte _format;
internal ushort _unk16;
internal List<BA2TextureChunk> _chunks;
private BA2Reader _bsa;
internal int _index;
public BA2DX10Entry(BA2Reader ba2Reader)
public BA2DX10Entry(BA2Reader ba2Reader, int idx)
{
_bsa = ba2Reader;
var _rdr = ba2Reader._rdr;
@ -169,9 +172,10 @@ namespace Compression.BSA
_numMips = _rdr.ReadByte();
_format = _rdr.ReadByte();
_unk16 = _rdr.ReadUInt16();
_index = idx;
_chunks = Enumerable.Range(0, _numChunks)
.Select(idx => new BA2TextureChunk(_rdr))
.Select(_ => new BA2TextureChunk(_rdr))
.ToList();
}
@ -180,7 +184,7 @@ namespace Compression.BSA
public string Path => FullPath;
public uint Size => (uint)_chunks.Sum(f => f._fullSz) + HeaderSize + sizeof(uint);
public FileStateObject State { get; }
public FileStateObject State => new BA2DX10EntryState(this);
public uint HeaderSize
{
@ -344,6 +348,70 @@ namespace Compression.BSA
}
}
public class BA2DX10EntryState : FileStateObject
{
public BA2DX10EntryState() { }
public BA2DX10EntryState(BA2DX10Entry ba2Dx10Entry)
{
FullName = ba2Dx10Entry.FullPath;
NameHash = ba2Dx10Entry._nameHash;
Extension = ba2Dx10Entry._extension;
DirHash = ba2Dx10Entry._dirHash;
Unk8 = ba2Dx10Entry._unk8;
ChunkHdrLen = ba2Dx10Entry._chunkHdrLen;
Height = ba2Dx10Entry._height;
Width = ba2Dx10Entry._width;
NumMips = ba2Dx10Entry._numMips;
PixelFormat = ba2Dx10Entry._format;
Unk16 = ba2Dx10Entry._unk16;
Index = ba2Dx10Entry._index;
Chunks = ba2Dx10Entry._chunks.Select(ch => new ChunkState(ch)).ToList();
}
public string FullName { get; set; }
public List<ChunkState> Chunks { get; set; }
public ushort Unk16 { get; set; }
public byte PixelFormat { get; set; }
public byte NumMips { get; set; }
public ushort Width { get; set; }
public ushort Height { get; set; }
public ushort ChunkHdrLen { get; set; }
public byte Unk8 { get; set; }
public uint DirHash { get; set; }
public string Extension { get; set; }
public uint NameHash { get; set; }
}
public class ChunkState
{
public ChunkState() {}
public ChunkState(BA2TextureChunk ch)
{
FullSz = ch._fullSz;
StartMip = ch._startMip;
EndMip = ch._endMip;
Align = ch._align;
Compressed = ch._packSz != null;
}
public bool Compressed { get; set; }
public uint Align { get; set; }
public ushort EndMip { get; set; }
public ushort StartMip { get; set; }
public uint FullSz { get; set; }
}
public class BA2TextureChunk
{
internal ulong _offset;

View File

@ -74,6 +74,7 @@
<HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>