2021-09-27 12:42:46 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Wabbajack.Compression.BSA.Interfaces;
|
|
|
|
using Wabbajack.DTOs.BSA.ArchiveStates;
|
|
|
|
using Wabbajack.DTOs.Streams;
|
|
|
|
using Wabbajack.Paths;
|
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
namespace Wabbajack.Compression.BSA.TES3Archive;
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public class Reader : IReader
|
|
|
|
{
|
|
|
|
public static string TES3_MAGIC = Encoding.ASCII.GetString(new byte[] {0, 1, 0, 0});
|
|
|
|
internal long _dataOffset;
|
|
|
|
private uint _fileCount;
|
|
|
|
private TES3FileEntry[] _files;
|
|
|
|
private uint _hashTableOffset;
|
|
|
|
public IStreamFactory _streamFactory;
|
|
|
|
private uint _versionNumber;
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public IEnumerable<IFile> Files => _files;
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public IArchive State =>
|
|
|
|
new TES3State
|
2021-09-27 12:42:46 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
FileCount = _fileCount,
|
|
|
|
DataOffset = _dataOffset,
|
|
|
|
HashOffset = _hashTableOffset,
|
|
|
|
VersionNumber = _versionNumber
|
|
|
|
};
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public static async ValueTask<Reader> Load(IStreamFactory factory)
|
|
|
|
{
|
|
|
|
await using var fs = await factory.GetStream();
|
|
|
|
using var br = new BinaryReader(fs);
|
|
|
|
var rdr = new Reader
|
|
|
|
{
|
|
|
|
_streamFactory = factory,
|
|
|
|
_versionNumber = br.ReadUInt32(),
|
|
|
|
_hashTableOffset = br.ReadUInt32(),
|
|
|
|
_fileCount = br.ReadUInt32()
|
|
|
|
};
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
rdr._files = new TES3FileEntry[rdr._fileCount];
|
|
|
|
for (var i = 0; i < rdr._fileCount; i++)
|
|
|
|
{
|
|
|
|
var file = new TES3FileEntry
|
2021-09-27 12:42:46 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
Index = i,
|
|
|
|
Archive = rdr,
|
|
|
|
Size = br.ReadUInt32(),
|
|
|
|
Offset = br.ReadUInt32()
|
|
|
|
};
|
|
|
|
rdr._files[i] = file;
|
2021-09-27 12:42:46 +00:00
|
|
|
}
|
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
for (var i = 0; i < rdr._fileCount; i++) rdr._files[i].NameOffset = br.ReadUInt32();
|
|
|
|
|
|
|
|
var origPos = br.BaseStream.Position;
|
|
|
|
for (var i = 0; i < rdr._fileCount; i++)
|
2021-09-27 12:42:46 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
br.BaseStream.Position = origPos + rdr._files[i].NameOffset;
|
|
|
|
rdr._files[i].Path = br.ReadStringTerm(VersionType.TES3).ToRelativePath();
|
2021-09-27 12:42:46 +00:00
|
|
|
}
|
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
br.BaseStream.Position = rdr._hashTableOffset + 12;
|
|
|
|
for (var i = 0; i < rdr._fileCount; i++)
|
2021-09-27 12:42:46 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
rdr._files[i].Hash1 = br.ReadUInt32();
|
|
|
|
rdr._files[i].Hash2 = br.ReadUInt32();
|
2021-09-27 12:42:46 +00:00
|
|
|
}
|
2021-10-23 16:51:17 +00:00
|
|
|
|
|
|
|
rdr._dataOffset = br.BaseStream.Position;
|
|
|
|
return rdr;
|
|
|
|
}
|
|
|
|
|
2022-10-07 22:57:12 +00:00
|
|
|
public ValueTask DisposeAsync()
|
2021-10-23 16:51:17 +00:00
|
|
|
{
|
2022-10-07 22:57:12 +00:00
|
|
|
return ValueTask.CompletedTask;
|
2021-10-23 16:51:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void Dump(Action<string> print)
|
|
|
|
{
|
|
|
|
throw new NotImplementedException();
|
2021-09-27 12:42:46 +00:00
|
|
|
}
|
|
|
|
}
|