108 lines
3.2 KiB
C#
108 lines
3.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
using GMWare.IO;
|
|
|
|
namespace LibDgf.Aqualead.Archive
|
|
{
|
|
public class AlArchiveV2 : IDisposable
|
|
{
|
|
AlAarHeaderV2 header;
|
|
List<AlAarEntryV2> entries;
|
|
Stream stream;
|
|
private bool disposedValue;
|
|
|
|
public AlArchiveV2(Stream stream)
|
|
{
|
|
this.stream = stream ?? throw new ArgumentNullException(nameof(stream));
|
|
Load();
|
|
}
|
|
|
|
public IList<AlAarEntryV2> Entries
|
|
{
|
|
get
|
|
{
|
|
CheckDisposed();
|
|
return new ReadOnlyCollection<AlAarEntryV2>(entries);
|
|
}
|
|
}
|
|
|
|
void Load()
|
|
{
|
|
BinaryReader br = new BinaryReader(stream);
|
|
if (new string(br.ReadChars(4)) != "ALAR")
|
|
throw new InvalidDataException("Not an AquaLead archive.");
|
|
if (br.ReadByte() != 2)
|
|
throw new NotSupportedException("Not version 2 archive.");
|
|
|
|
header = new AlAarHeaderV2();
|
|
header.Read(br);
|
|
|
|
entries = new List<AlAarEntryV2>();
|
|
for (int i = 0; i < header.Count; ++i)
|
|
{
|
|
var entry = new AlAarEntryV2();
|
|
entry.Read(br);
|
|
entries.Add(entry);
|
|
}
|
|
|
|
foreach (var entry in entries)
|
|
{
|
|
if ((entry.Flags & AlAarEntryFlags.IsUseName) != 0)
|
|
{
|
|
stream.Seek(entry.Offset - 0x22, SeekOrigin.Begin);
|
|
entry.Name = StringReadingHelper.ReadNullTerminatedStringFromFixedSizeBlock(br, 0x20, Encoding.UTF8);
|
|
}
|
|
|
|
if ((entry.Flags & ~AlAarEntryFlags.IsUseName) != 0)
|
|
{
|
|
Console.WriteLine($"Entry {entry.Name} has other flags set: {entry.Flags}");
|
|
//Debugger.Break();
|
|
}
|
|
}
|
|
}
|
|
|
|
public Stream GetFile(AlAarEntryV2 entry)
|
|
{
|
|
if (!entries.Contains(entry))
|
|
throw new ArgumentException("Entry not from this archive.", nameof(entry));
|
|
if (stream == null) throw new InvalidOperationException("Archive is not opened from existing.");
|
|
CheckDisposed();
|
|
|
|
stream.Seek(entry.Offset, SeekOrigin.Begin);
|
|
MemoryStream ms = new MemoryStream();
|
|
StreamUtils.StreamCopy(stream, ms, entry.Length);
|
|
ms.Seek(0, SeekOrigin.Begin);
|
|
return Utils.CheckDecompress(ms);
|
|
}
|
|
|
|
void CheckDisposed()
|
|
{
|
|
if (disposedValue) throw new ObjectDisposedException(GetType().FullName);
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!disposedValue)
|
|
{
|
|
if (disposing)
|
|
{
|
|
stream.Close();
|
|
}
|
|
|
|
entries = null;
|
|
disposedValue = true;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
Dispose(disposing: true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|
|
}
|