mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-15 02:26:44 -04:00
Added FSO.Files for use with the API server
Don't ask me. FreeSO is the prime example of dependency hell.
This commit is contained in:
parent
4b5e584eeb
commit
8fec258215
104 changed files with 14653 additions and 163 deletions
243
server/tso.files/FAR3/FAR3Archive.cs
Executable file
243
server/tso.files/FAR3/FAR3Archive.cs
Executable file
|
@ -0,0 +1,243 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Files.FAR3
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single FAR3 archive.
|
||||
/// </summary>
|
||||
public class FAR3Archive : IDisposable
|
||||
{
|
||||
private BinaryReader m_Reader;
|
||||
public static bool isReadingSomething = false;
|
||||
|
||||
private string m_ArchivePath;
|
||||
private Dictionary<string, Far3Entry> m_Entries = new Dictionary<string, Far3Entry>();
|
||||
private List<Far3Entry> m_EntriesList = new List<Far3Entry>();
|
||||
private Dictionary<uint, Far3Entry> m_EntryByID = new Dictionary<uint, Far3Entry>();
|
||||
private uint m_ManifestOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new FAR3Archive instance from a path.
|
||||
/// </summary>
|
||||
/// <param name="Path">The path to the archive.</param>
|
||||
public FAR3Archive(string Path)
|
||||
{
|
||||
m_ArchivePath = Path;
|
||||
|
||||
if (isReadingSomething == false)
|
||||
{
|
||||
isReadingSomething = true;
|
||||
|
||||
try
|
||||
{
|
||||
m_Reader = new BinaryReader(File.Open(Path, FileMode.Open, FileAccess.Read, FileShare.Read));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FAR3Exception("Could not open the specified archive - " + Path + "! (FAR3Archive())");
|
||||
}
|
||||
|
||||
string Header = Encoding.ASCII.GetString(m_Reader.ReadBytes(8));
|
||||
uint Version = m_Reader.ReadUInt32();
|
||||
|
||||
if ((Header != "FAR!byAZ") || (Version != 3))
|
||||
{
|
||||
throw new FAR3Exception("Archive wasn't a valid FAR V.3 archive! (FAR3Archive())");
|
||||
}
|
||||
|
||||
uint ManifestOffset = m_Reader.ReadUInt32();
|
||||
m_ManifestOffset = ManifestOffset;
|
||||
|
||||
m_Reader.BaseStream.Seek(ManifestOffset, SeekOrigin.Begin);
|
||||
|
||||
uint NumFiles = m_Reader.ReadUInt32();
|
||||
|
||||
for (int i = 0; i < NumFiles; i++)
|
||||
{
|
||||
Far3Entry Entry = new Far3Entry();
|
||||
Entry.DecompressedFileSize = m_Reader.ReadUInt32();
|
||||
byte dummy0 = m_Reader.ReadByte();
|
||||
byte dummy1 = m_Reader.ReadByte();
|
||||
byte dummy2 = m_Reader.ReadByte();
|
||||
Entry.CompressedFileSize = (uint)((dummy0 << 0) | (dummy1 << 8) | (dummy2) << 16);
|
||||
Entry.DataType = m_Reader.ReadByte();
|
||||
Entry.DataOffset = m_Reader.ReadUInt32();
|
||||
//Entry.HasFilename = m_Reader.ReadUInt16();
|
||||
Entry.IsCompressed = m_Reader.ReadByte();
|
||||
Entry.AccessNumber = m_Reader.ReadByte();
|
||||
Entry.FilenameLength = m_Reader.ReadUInt16();
|
||||
Entry.TypeID = m_Reader.ReadUInt32();
|
||||
Entry.FileID = m_Reader.ReadUInt32();
|
||||
Entry.Filename = Encoding.ASCII.GetString(m_Reader.ReadBytes(Entry.FilenameLength));
|
||||
|
||||
if (!m_Entries.ContainsKey(Entry.Filename))
|
||||
m_Entries.Add(Entry.Filename, Entry);
|
||||
m_EntriesList.Add(Entry);
|
||||
|
||||
m_EntryByID.Add(Entry.FileID, Entry); //isn't this a bad idea? i have a feeling this is a bad idea...
|
||||
}
|
||||
|
||||
//Keep the stream open, it helps peformance.
|
||||
//m_Reader.Close();
|
||||
isReadingSomething = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an entry's data from a Far3Entry instance.
|
||||
/// </summary>
|
||||
/// <param name="Entry">The Far3Entry instance.</param>
|
||||
/// <returns>The entry's data.</returns>
|
||||
public byte[] GetEntry(Far3Entry Entry)
|
||||
{
|
||||
lock (m_Reader)
|
||||
{
|
||||
m_Reader.BaseStream.Seek((long)Entry.DataOffset, SeekOrigin.Begin);
|
||||
|
||||
isReadingSomething = true;
|
||||
|
||||
if (Entry.IsCompressed == 0x01)
|
||||
{
|
||||
m_Reader.BaseStream.Seek(9, SeekOrigin.Current);
|
||||
uint Filesize = m_Reader.ReadUInt32();
|
||||
ushort CompressionID = m_Reader.ReadUInt16();
|
||||
|
||||
if (CompressionID == 0xFB10)
|
||||
{
|
||||
byte dummy0 = m_Reader.ReadByte();
|
||||
byte dummy1 = m_Reader.ReadByte();
|
||||
byte dummy2 = m_Reader.ReadByte();
|
||||
uint DecompressedSize = (uint)((dummy0 << 0x10) | (dummy1 << 0x08) | +dummy2);
|
||||
|
||||
Decompresser Dec = new Decompresser();
|
||||
Dec.CompressedSize = Filesize;
|
||||
Dec.DecompressedSize = DecompressedSize;
|
||||
|
||||
byte[] DecompressedData = Dec.Decompress(m_Reader.ReadBytes((int)Filesize));
|
||||
//m_Reader.Close();
|
||||
|
||||
isReadingSomething = false;
|
||||
|
||||
return DecompressedData;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Reader.BaseStream.Seek((m_Reader.BaseStream.Position - 15), SeekOrigin.Begin);
|
||||
|
||||
byte[] Data = m_Reader.ReadBytes((int)Entry.DecompressedFileSize);
|
||||
//m_Reader.Close();
|
||||
|
||||
isReadingSomething = false;
|
||||
|
||||
return Data;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] Data = m_Reader.ReadBytes((int)Entry.DecompressedFileSize);
|
||||
//m_Reader.Close();
|
||||
|
||||
isReadingSomething = false;
|
||||
|
||||
return Data;
|
||||
}
|
||||
}
|
||||
|
||||
throw new FAR3Exception("FAR3Entry didn't exist in archive - FAR3Archive.GetEntry()");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the entries of this FAR3Archive as byte arrays together with their corresponding FileIDs.
|
||||
/// </summary>
|
||||
/// <returns>A List of KeyValuePair instances.</returns>
|
||||
public List<KeyValuePair<uint, byte[]>> GetAllEntries()
|
||||
{
|
||||
List<KeyValuePair<uint, byte[]>> toReturn = new List<KeyValuePair<uint, byte[]>>();
|
||||
foreach (Far3Entry Entry in m_EntriesList)
|
||||
{
|
||||
toReturn.Add(new KeyValuePair<uint, byte[]>(Entry.FileID, GetEntry(Entry)));
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the entries of this FAR3Archive as FAR3Entry instances in a List.
|
||||
/// </summary>
|
||||
/// <returns>Returns the entries of this FAR3Archive as FAR3Entry instances in a List.</returns>
|
||||
public List<Far3Entry> GetAllFAR3Entries()
|
||||
{
|
||||
List<Far3Entry> Entries = new List<Far3Entry>();
|
||||
|
||||
foreach (KeyValuePair<string, Far3Entry> KVP in m_Entries)
|
||||
Entries.Add(KVP.Value);
|
||||
|
||||
return Entries;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an entry from a FileID.
|
||||
/// </summary>
|
||||
/// <param name="FileID">The entry's FileID.</param>
|
||||
/// <returns>The entry's data.</returns>
|
||||
public byte[] GetItemByID(uint FileID)
|
||||
{
|
||||
var item = m_EntryByID[FileID];
|
||||
if (item == null)
|
||||
{
|
||||
throw new FAR3Exception("Didn't find entry!");
|
||||
}
|
||||
return GetEntry(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an entry from its ID (TypeID + FileID).
|
||||
/// </summary>
|
||||
/// <param name="ID">The ID of the entry.</param>
|
||||
/// <returns>The entry's data.</returns>
|
||||
public byte[] GetItemByID(ulong ID)
|
||||
{
|
||||
byte[] Bytes = BitConverter.GetBytes(ID);
|
||||
uint FileID = BitConverter.ToUInt32(Bytes, 4);
|
||||
uint TypeID = BitConverter.ToUInt32(Bytes, 0);
|
||||
|
||||
var item = m_EntryByID[FileID];
|
||||
if (item == null || item.TypeID != TypeID)
|
||||
{
|
||||
throw new FAR3Exception("Didn't find entry!");
|
||||
}
|
||||
|
||||
return GetEntry(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an entry's data from a filename.
|
||||
/// </summary>
|
||||
/// <param name="Filename">The filename of the entry.</param>
|
||||
/// <returns>The entry's data.</returns>
|
||||
public byte[] this[string Filename]
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetEntry(m_Entries[Filename]);
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Disposes this FAR3Archive instance.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (m_Reader != null)
|
||||
{
|
||||
m_Reader.Close();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue