From 57c2e75a592cc344d38508ec85a20c058a8d946a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 1 Dec 2013 14:35:13 +1300 Subject: [PATCH] Add a Pak parser for Dune II archives. --- CHANGELOG | 2 +- OpenRA.FileFormats/FileSystem/FileSystem.cs | 4 + OpenRA.FileFormats/Filesystem/Pak.cs | 97 ++++++++++++++++++++ OpenRA.FileFormats/OpenRA.FileFormats.csproj | 1 + 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 OpenRA.FileFormats/Filesystem/Pak.cs diff --git a/CHANGELOG b/CHANGELOG index 7d92929a72..7d6b8c7976 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -90,7 +90,7 @@ NEW: Overhauled sprite loading code. Improved error message when loading corrupted sprites. Rewritten shp(ts) parser makes more efficient use of texture space. - Added support for the dune 2 shp format. + Added support for the dune 2 shp and pak formats. Build system and packages: Added GeoIP to Makefile so it is installed properly. Added desktop shortcut creation support to the Makefile and Windows installer. diff --git a/OpenRA.FileFormats/FileSystem/FileSystem.cs b/OpenRA.FileFormats/FileSystem/FileSystem.cs index 84f3f4c654..c4dd0f8b13 100644 --- a/OpenRA.FileFormats/FileSystem/FileSystem.cs +++ b/OpenRA.FileFormats/FileSystem/FileSystem.cs @@ -57,6 +57,8 @@ namespace OpenRA.FileFormats throw new NotImplementedException("Creating .RS archives is unsupported"); else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase)) throw new NotImplementedException("Creating .Z archives is unsupported"); + else if (filename.EndsWith(".PAK", StringComparison.InvariantCultureIgnoreCase)) + throw new NotImplementedException("Creating .PAK archives is unsupported"); else return new Folder(filename, order, content); } @@ -77,6 +79,8 @@ namespace OpenRA.FileFormats return new D2kSoundResources(filename, order); else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase)) return new InstallShieldPackage(filename, order); + else if (filename.EndsWith(".PAK", StringComparison.InvariantCultureIgnoreCase)) + return new PakFile(filename, order); else return new Folder(filename, order); } diff --git a/OpenRA.FileFormats/Filesystem/Pak.cs b/OpenRA.FileFormats/Filesystem/Pak.cs new file mode 100644 index 0000000000..4247c37c35 --- /dev/null +++ b/OpenRA.FileFormats/Filesystem/Pak.cs @@ -0,0 +1,97 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.IO; + +namespace OpenRA.FileFormats +{ + struct Entry + { + public uint Offset; + public uint Length; + public string Filename; + } + + public class PakFile : IFolder + { + string filename; + int priority; + Dictionary index; + Stream stream; + + public PakFile(string filename, int priority) + { + this.filename = filename; + this.priority = priority; + index = new Dictionary(); + stream = FileSystem.Open(filename); + + index = new Dictionary(); + var offset = stream.ReadUInt32(); + while (offset != 0) + { + var file = stream.ReadASCIIZ(); + var next = stream.ReadUInt32(); + var length = (next == 0 ? (uint)stream.Length : next) - offset; + + // Ignore duplicate files + if (index.ContainsKey(file)) + continue; + + index.Add(file, new Entry { Offset = offset, Length = length, Filename = file }); + offset = next; + } + } + + public Stream GetContent(string filename) + { + Entry entry; + if (!index.TryGetValue(filename, out entry)) + return null; + + stream.Seek(entry.Offset, SeekOrigin.Begin); + var data = new byte[entry.Length]; + stream.Read(data, 0, (int)entry.Length); + return new MemoryStream(data); + } + + public IEnumerable ClassicHashes() + { + foreach (var filename in index.Keys) + yield return PackageEntry.HashFilename(filename, PackageHashType.Classic); + } + + public IEnumerable CrcHashes() + { + yield break; + } + + public IEnumerable AllFileNames() + { + foreach (var filename in index.Keys) + yield return filename; + } + + public bool Exists(string filename) + { + return index.ContainsKey(filename); + } + + public void Write(Dictionary contents) + { + throw new NotImplementedException("Cannot save Pak archives."); + } + + public int Priority { get { return 1000 + priority; } } + public string Name { get { return filename; } } + } +} diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index e867a1dc03..1f838e1a46 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -153,6 +153,7 @@ +