libdgf/LibDgf/Aqualead/Archive/AlArchiveV2.cs
2021-02-16 01:04:29 -07:00

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);
}
}
}