Skip to content

Commit 873714c

Browse files
committedJan 16, 2016
* Hacky fix for non-standard version 4 ark files (Classic Rock Track Pack).
* Refactor to use IFile all around. * Allow opening archives within archives
1 parent ac81a03 commit 873714c

20 files changed

+547
-278
lines changed
 

‎ArchiveExplorer/ArchiveExplorer.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,14 @@ public ArchiveExplorer()
4242
pm = PackageManager.GetInstance();
4343
pm.Spinner = this.spinnerLabel;
4444
pm.StatusLabel = this.toolStripStatusLabel1;
45+
pm.Loader = LoadFile;
4546
pm.SetReady();
4647
string[] args = Environment.GetCommandLineArgs();
4748
if (args.Length > 1)
4849
{
4950
if(File.Exists(args[1]))
5051
{
51-
LoadFile(args[1]);
52+
LoadFile(Util.LocalFile(args[1]));
5253
}
5354
}
5455
}
@@ -57,7 +58,7 @@ public ArchiveExplorer()
5758
/// Deal with a new file.
5859
/// </summary>
5960
/// <param name="file"></param>
60-
private async void LoadFile(string file)
61+
private async void LoadFile(IFile file)
6162
{
6263
var newPage = new TabPage();
6364
newPage.Text = "Loading...";
@@ -97,7 +98,7 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e)
9798
of.Filter += "All Files (*.*)|*.*|" + PackageReader.SupportedFormats;
9899
if (of.ShowDialog() == DialogResult.OK)
99100
{
100-
LoadFile(of.FileName);
101+
LoadFile(Util.LocalFile(of.FileName));
101102
}
102103
}
103104

‎ArchiveExplorer/PackageManager.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using GameArchives;
2+
using System;
23
using System.Collections.Generic;
34
using System.Linq;
45
using System.Text;
@@ -20,6 +21,8 @@ public static PackageManager GetInstance()
2021

2122
public bool Ready { get; private set; }
2223

24+
public Action<IFile> Loader { get; set; }
25+
2326
private System.Windows.Forms.ToolStripStatusLabel statusLabel;
2427
private System.Windows.Forms.ToolStripStatusLabel spinner;
2528
private PackageManager()
@@ -53,5 +56,10 @@ public void SetBusyState(string busyState)
5356
if (statusLabel != null)
5457
statusLabel.Text = busyState;
5558
}
59+
60+
public void LoadFile(IFile f, AbstractPackage owner = null)
61+
{
62+
Loader(f);
63+
}
5664
}
5765
}

‎ArchiveExplorer/PackageView.Designer.cs

+29-19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ArchiveExplorer/PackageView.cs

+16
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ private void fileView_DoubleClick(object sender, EventArgs e)
183183
{
184184
SetCurrentDir(fileView.SelectedItems[0].Tag as IDirectory);
185185
}
186+
else if (fileView.SelectedItems[0].Tag is IFile)
187+
{
188+
pm.LoadFile(fileView.SelectedItems[0].Tag as IFile, currentPackage);
189+
}
186190
}
187191
}
188192

@@ -215,5 +219,17 @@ private async void extractItemsToolStripMenuItem_Click(object sender, EventArgs
215219
}
216220
}
217221

222+
private void openSelectedArchiveToolStripMenuItem_Click(object sender, EventArgs e)
223+
{
224+
if(fileView.SelectedItems.Count != 1)
225+
{
226+
MessageBox.Show("Please select just one archive to open.");
227+
return;
228+
}
229+
if(fileView.SelectedItems[0].Tag is IFile)
230+
{
231+
pm.LoadFile(fileView.SelectedItems[0].Tag as IFile, currentPackage);
232+
}
233+
}
218234
}
219235
}

‎ArchiveExplorer/PackageView.resx

+192-192
Large diffs are not rendered by default.
+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6+
<ProjectGuid>{4312AA1C-904E-4FCD-860A-AA888D5BE0CE}</ProjectGuid>
7+
<OutputType>Library</OutputType>
8+
<AppDesignerFolder>Properties</AppDesignerFolder>
9+
<RootNamespace>GameArchivesTests</RootNamespace>
10+
<AssemblyName>GameArchivesTests</AssemblyName>
11+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
12+
<FileAlignment>512</FileAlignment>
13+
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
14+
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
15+
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
16+
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
17+
<IsCodedUITest>False</IsCodedUITest>
18+
<TestProjectType>UnitTest</TestProjectType>
19+
</PropertyGroup>
20+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
21+
<DebugSymbols>true</DebugSymbols>
22+
<DebugType>full</DebugType>
23+
<Optimize>false</Optimize>
24+
<OutputPath>bin\Debug\</OutputPath>
25+
<DefineConstants>DEBUG;TRACE</DefineConstants>
26+
<ErrorReport>prompt</ErrorReport>
27+
<WarningLevel>4</WarningLevel>
28+
</PropertyGroup>
29+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
30+
<DebugType>pdbonly</DebugType>
31+
<Optimize>true</Optimize>
32+
<OutputPath>bin\Release\</OutputPath>
33+
<DefineConstants>TRACE</DefineConstants>
34+
<ErrorReport>prompt</ErrorReport>
35+
<WarningLevel>4</WarningLevel>
36+
</PropertyGroup>
37+
<ItemGroup>
38+
<Reference Include="System" />
39+
</ItemGroup>
40+
<Choose>
41+
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
42+
<ItemGroup>
43+
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
44+
</ItemGroup>
45+
</When>
46+
<Otherwise>
47+
<ItemGroup>
48+
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
49+
</ItemGroup>
50+
</Otherwise>
51+
</Choose>
52+
<ItemGroup>
53+
<Compile Include="Local\LocalDirectoryTests.cs" />
54+
<Compile Include="Properties\AssemblyInfo.cs" />
55+
</ItemGroup>
56+
<ItemGroup>
57+
<ProjectReference Include="..\Library\GameArchives.csproj">
58+
<Project>{906748F0-3A55-4B20-BCCB-9DC7187F1D5E}</Project>
59+
<Name>GameArchives</Name>
60+
</ProjectReference>
61+
</ItemGroup>
62+
<Choose>
63+
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
64+
<ItemGroup>
65+
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
66+
<Private>False</Private>
67+
</Reference>
68+
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
69+
<Private>False</Private>
70+
</Reference>
71+
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
72+
<Private>False</Private>
73+
</Reference>
74+
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
75+
<Private>False</Private>
76+
</Reference>
77+
</ItemGroup>
78+
</When>
79+
</Choose>
80+
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
81+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
82+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
83+
Other similar extension points exist, see Microsoft.Common.targets.
84+
<Target Name="BeforeBuild">
85+
</Target>
86+
<Target Name="AfterBuild">
87+
</Target>
88+
-->
89+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using GameArchives.Local;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace GameArchives.Local.Tests
10+
{
11+
[TestClass()]
12+
public class LocalDirectoryTests
13+
{
14+
[TestMethod()]
15+
public void GetDirectoryTest()
16+
{
17+
}
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("GameArchivesTests")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("GameArchivesTests")]
13+
[assembly: AssemblyCopyright("Copyright © 2016")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("4312aa1c-904e-4fcd-860a-aa888d5be0ce")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]

‎Library/Ark/ArkPackage.cs

+19-14
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ public static bool IsArk(Stream s)
118118
return version <= 6 && version >= 3;
119119
}
120120

121-
public static ArkPackage OpenFile(string filename)
121+
public static ArkPackage OpenFile(IFile f)
122122
{
123-
return new ArkPackage(filename);
123+
return new ArkPackage(f);
124124
}
125125

126126
public static ArkPackage FromStream(Stream fs)
@@ -133,10 +133,10 @@ public static ArkPackage FromStream(Stream fs)
133133
/// Note: will check for data files and throw exception if they're not found.
134134
/// </summary>
135135
/// <param name="pathToHdr">Full path to .hdr file</param>
136-
public ArkPackage(string pathToHdr)
136+
public ArkPackage(IFile hdrFile)
137137
{
138-
FileName = pathToHdr;
139-
using (var hdr = new FileStream(pathToHdr, FileMode.Open, FileAccess.Read))
138+
FileName = hdrFile.Name;
139+
using (var hdr = hdrFile.GetStream())
140140
{
141141
Stream actualHdr = hdr;
142142
uint version = hdr.ReadUInt32LE();
@@ -151,11 +151,11 @@ public ArkPackage(string pathToHdr)
151151
}
152152
version = actualHdr.ReadUInt32LE();
153153
}
154-
readHeader(actualHdr, pathToHdr, version);
154+
readHeader(actualHdr, hdrFile, version);
155155
}
156156
}
157157

158-
private void readHeader(Stream header, string headerPath, uint version)
158+
private void readHeader(Stream header, IFile hdrFile, uint version, bool brokenv5 = false)
159159
{
160160
if (version == 6) // Version 6 has some sort of hash/key at the beginning?
161161
{
@@ -174,6 +174,13 @@ private void readHeader(Stream header, string headerPath, uint version)
174174
{
175175
// All versions except 4 use 32-bit file sizes.
176176
arkFileSizes[i] = (version == 4 ? header.ReadInt64LE() : header.ReadInt32LE());
177+
if(version == 4 && arkFileSizes[i] > UInt32.MaxValue)
178+
{
179+
// RB TrackPack Classic has a broken v4, really a v5 mixed with v3
180+
header.Position = 4;
181+
readHeader(header, hdrFile, 5, true);
182+
return;
183+
}
177184
totalArkFileSizes += arkFileSizes[i];
178185
}
179186

@@ -188,9 +195,8 @@ private void readHeader(Stream header, string headerPath, uint version)
188195
contentFiles = new Stream[numArks];
189196
for (var i = 0; i < numArkPaths; i++)
190197
{
191-
string filePath = Path.Combine(Path.GetDirectoryName(headerPath),
192-
header.ReadLengthUTF8().Split('/').Last());
193-
contentFiles[i] = new FileStream(filePath, FileMode.Open, FileAccess.Read);
198+
IFile arkFile = hdrFile.Parent.GetFile(header.ReadLengthUTF8().Split('/').Last());
199+
contentFiles[i] = arkFile.GetStream();
194200
}
195201

196202
// Version 6: appears to checksums or something for each content file
@@ -205,9 +211,8 @@ private void readHeader(Stream header, string headerPath, uint version)
205211
contentFiles = new Stream[numArks];
206212
for (var i = 0; i < numArks2; i++)
207213
{
208-
string filePath = Path.Combine(Path.GetDirectoryName(headerPath),
209-
Path.GetFileNameWithoutExtension(headerPath)) + "_" + i + ".ark";
210-
contentFiles[i] = new FileStream(filePath, FileMode.Open, FileAccess.Read);
214+
IFile arkFile = hdrFile.Parent.GetFile(hdrFile.Name.Substring(0, hdrFile.Name.Length - 4) + "_" + i + ".ark");
215+
contentFiles[i] = arkFile.GetStream();
211216
}
212217
}
213218

@@ -258,7 +263,7 @@ private void readHeader(Stream header, string headerPath, uint version)
258263
for (var i = 0; i < numFiles; i++)
259264
{
260265
// Version 3 uses 32-bit file offsets
261-
long arkFileOffset = (version == 3 ? header.ReadUInt32LE() : header.ReadInt64LE());
266+
long arkFileOffset = (brokenv5 || version == 3 ? header.ReadUInt32LE() : header.ReadInt64LE());
262267
int filenameStringId = header.ReadInt32LE();
263268
uint dirStringId = header.ReadUInt32LE();
264269
uint size = header.ReadUInt32LE();

‎Library/Common/DefaultDirectory.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace GameArchives.Common
2424
/// <summary>
2525
/// A default implementation of a directory.
2626
/// Useful for archives where directories are implicit.
27+
/// Filenames are case-insensitive.
2728
/// </summary>
2829
public class DefaultDirectory : IDirectory
2930
{
@@ -39,7 +40,7 @@ public class DefaultDirectory : IDirectory
3940

4041
public bool TryGetDirectory(string name, out IDirectory dir)
4142
{
42-
return dirs.TryGetValue(name, out dir);
43+
return dirs.TryGetValue(name.ToLower(), out dir);
4344
}
4445

4546
public IDirectory GetDirectory(string name)
@@ -52,7 +53,7 @@ public IDirectory GetDirectory(string name)
5253

5354
public bool TryGetFile(string name, out IFile file)
5455
{
55-
return files.TryGetValue(name, out file);
56+
return files.TryGetValue(name.ToLower(), out file);
5657
}
5758

5859
public IFile GetFile(string name)
@@ -80,15 +81,15 @@ internal void AddFile(IFile f)
8081
{
8182
if (!files.ContainsKey(f.Name))
8283
{
83-
files.Add(f.Name, f);
84+
files.Add(f.Name.ToLower(), f);
8485
}
8586
}
8687

8788
internal void AddDir(IDirectory d)
8889
{
8990
if (!dirs.ContainsKey(d.Name))
9091
{
91-
dirs.Add(d.Name, d);
92+
dirs.Add(d.Name.ToLower(), d);
9293
}
9394
}
9495

‎Library/FSAR/FSARPackage.cs

+9-9
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ public static bool IsFSAR(Stream s)
3939
return s.ReadUInt32BE() == 0x46534152;
4040
}
4141

42-
public static FSARPackage FromFile(string fn)
42+
public static FSARPackage FromFile(IFile f)
4343
{
44-
return new FSARPackage(fn);
44+
return new FSARPackage(f);
4545
}
4646

4747
public override string FileName { get; }
@@ -54,14 +54,14 @@ public static FSARPackage FromFile(string fn)
5454
private FSARDirectory root;
5555

5656
/// <summary>
57-
/// Open the .far archive at the given path.
57+
/// Open the .far archive which is the given file.
5858
/// </summary>
5959
/// <param name="path"></param>
60-
public FSARPackage(string path)
60+
public FSARPackage(IFile f)
6161
{
62-
FileName = path;
62+
FileName = f.Name;
6363
root = new FSARDirectory(null, ROOT_DIR);
64-
filestream = new FileStream(path, FileMode.Open);
64+
filestream = f.GetStream();
6565
uint magic = filestream.ReadUInt32BE();
6666
if(magic == 0x46534743) // "FSGC"
6767
{
@@ -75,11 +75,11 @@ public FSARPackage(string path)
7575
uint file_base = filestream.ReadUInt32BE();
7676
uint num_files = filestream.ReadUInt32BE();
7777
filestream.Position = 0x20;
78-
for(int f = 0; f < num_files; f++)
78+
for(int i = 0; i < num_files; i++)
7979
{
80-
filestream.Position = 0x20 + 0x120 * f;
80+
filestream.Position = 0x20 + 0x120 * i;
8181
string fpath = filestream.ReadASCIINullTerminated();
82-
filestream.Position = 0x20 + 0x120 * f + 0x100;
82+
filestream.Position = 0x20 + 0x120 * i + 0x100;
8383
long size = filestream.ReadInt64BE();
8484
long zsize = filestream.ReadInt64BE();
8585
long offset = filestream.ReadInt64BE();

‎Library/FSGIMG/FSGIMGPackage.cs

+9-8
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ public static bool IsFSGIMG(string path)
3636
using (FileStream fs = File.OpenRead(path))
3737
return IsFSGIMG(fs);
3838
}
39-
public static FSGIMGPackage OpenFile(string path)
39+
public static FSGIMGPackage OpenFile(IFile f)
4040
{
41-
return new FSGIMGPackage(path);
41+
return new FSGIMGPackage(f);
4242
}
4343

4444
public override string FileName { get; }
@@ -58,17 +58,18 @@ class file_descriptor
5858
public long size;
5959
}
6060

61-
public FSGIMGPackage(string filename)
61+
public FSGIMGPackage(IFile f)
6262
{
63-
FileName = filename;
63+
FileName = f.Name;
6464
var parts = new List<Stream>(1);
65-
parts.Add(new FileStream(filename, FileMode.Open));
66-
if (filename.Split('.').Length > 2) // this is a .part* file
65+
parts.Add(f.GetStream());
66+
if (f.Name.Split('.').Length > 2) // this is a .part* file
6767
{
6868
int partNum = 1;
69-
while (File.Exists(filename.Substring(0, filename.Length - 1) + partNum))
69+
IFile tmp;
70+
while (f.Parent.TryGetFile(f.Name.Substring(0, f.Name.Length - 1) + partNum, out tmp))
7071
{
71-
var fs = new FileStream(filename.Substring(0, filename.Length - 1) + partNum, FileMode.Open);
72+
var fs = tmp.GetStream();
7273
parts.Add(fs);
7374
partNum++;
7475
}

‎Library/GameArchives.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
<Compile Include="Common\DefaultDirectory.cs" />
5252
<Compile Include="Common\MultiStream.cs" />
5353
<Compile Include="Common\OffsetStream.cs" />
54+
<Compile Include="Local\LocalDirectory.cs" />
55+
<Compile Include="Local\LocalFile.cs" />
5456
<Compile Include="PackageReader.cs" />
5557
<Compile Include="FSAR\FSARDirectory.cs" />
5658
<Compile Include="FSAR\FSARFile.cs" />

‎Library/Local/LocalDirectory.cs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using GameArchives.Common;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using System.IO;
8+
9+
namespace GameArchives.Local
10+
{
11+
/// <summary>
12+
/// Represents a directory in the local file system.
13+
/// </summary>
14+
public class LocalDirectory : DefaultDirectory
15+
{
16+
/// <summary>
17+
/// Make a shallow instance of the given local directory.
18+
/// </summary>
19+
/// <param name="path">Location of the directory.</param>
20+
internal LocalDirectory(string path) : base(null, new DirectoryInfo(path).Name)
21+
{
22+
if (File.Exists(path))
23+
{
24+
throw new ArgumentException("Given path must point to directory, not file.");
25+
}
26+
foreach(string f in Directory.EnumerateFiles(path))
27+
{
28+
AddFile(new LocalFile(this, f));
29+
}
30+
}
31+
}
32+
}

‎Library/Local/LocalFile.cs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace GameArchives.Local
9+
{
10+
/// <summary>
11+
/// Represents a file on the local filesystem.
12+
/// </summary>
13+
class LocalFile : IFile
14+
{
15+
public bool Compressed => false;
16+
public long CompressedSize => Size;
17+
public long Size { get; }
18+
public string Name { get; }
19+
public IDirectory Parent { get; }
20+
21+
private string path;
22+
23+
internal LocalFile(IDirectory parent, string path)
24+
{
25+
Parent = parent;
26+
this.path = path;
27+
Size = new FileInfo(path).Length;
28+
this.Name = Path.GetFileName(path);
29+
}
30+
31+
public byte[] GetBytes()
32+
{
33+
return File.ReadAllBytes(path);
34+
}
35+
public Stream GetStream()
36+
{
37+
return File.OpenRead(path);
38+
}
39+
}
40+
}

‎Library/PackageReader.cs

+10-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,17 @@ public class PackageReader
1717
/// <exception cref="NotSupportedException">Thrown when an unsupported file type is given.</exception>
1818
public static AbstractPackage ReadPackageFromFile(string file)
1919
{
20-
foreach(PackageType t in PackageType.Types)
20+
return ReadPackageFromFile(Util.LocalFile(file));
21+
}
22+
23+
public static AbstractPackage ReadPackageFromFile(IFile file)
24+
{
25+
foreach (PackageType t in PackageType.Types)
2126
{
22-
if(t.CheckPath(file))
27+
bool result;
28+
using (Stream tmp = file.GetStream())
29+
result = t.CheckStream(tmp);
30+
if (result)
2331
{
2432
return t.Load(file);
2533
}

‎Library/PackageTypes.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ class PackageType
3737
public Func<Stream, bool> CheckStream { get; }
3838

3939
/// <summary>
40-
/// Given a string which is the path to a valid package, opens it as this
40+
/// Given a file which is a valid package, opens it as this
4141
/// package type, returning the package instance.
4242
/// </summary>
43-
public Func<string, AbstractPackage> Load { get; }
43+
public Func<IFile, AbstractPackage> Load { get; }
4444

4545
PackageType(string name, string[] extensions,
46-
Func<string, bool> path, Func<Stream, bool> stream, Func<string, AbstractPackage> load)
46+
Func<string, bool> path, Func<Stream, bool> stream, Func<IFile, AbstractPackage> load)
4747
{
4848
Name = name;
4949
Extensions = extensions;

‎Library/STFS/STFSPackage.cs

+7-18
Original file line numberDiff line numberDiff line change
@@ -147,22 +147,9 @@ public static bool IsSTFS(Stream fs)
147147
public Image TitleThumbnail { get; }
148148

149149
/// <summary>
150-
/// The filename of this package, if it was opened from disk.
150+
/// The filename of this package.
151151
/// </summary>
152-
public override string FileName
153-
{
154-
get
155-
{
156-
if(stream is System.IO.FileStream)
157-
{
158-
return ((System.IO.FileStream)stream).Name;
159-
}
160-
else
161-
{
162-
return "AnonymousPackage";
163-
}
164-
}
165-
}
152+
public override string FileName { get; }
166153

167154
int BaseBlock => tableSizeShift == 0 ? 0xB << 12 : 0xA << 12;
168155

@@ -189,9 +176,9 @@ public override string FileName
189176
/// <param name="path">Path to the STFS file.</param>
190177
/// <returns>New STFS instance which refers to given file.</returns>
191178
/// <exception cref="System.IO.InvalidDataException">Thrown if file is not valid STFS package.</exception>
192-
public static STFSPackage OpenFile(string path)
179+
public static STFSPackage OpenFile(IFile f)
193180
{
194-
return new STFSPackage(System.IO.File.OpenRead(path));
181+
return new STFSPackage(f);
195182
}
196183

197184
/// <summary>
@@ -203,8 +190,10 @@ public static STFSPackage OpenFile(string path)
203190
Dispose();
204191
}
205192

206-
private STFSPackage(System.IO.Stream input)
193+
private STFSPackage(IFile f)
207194
{
195+
Stream input = f.GetStream();
196+
FileName = f.Name;
208197
if (!IsSTFS(input))
209198
{
210199
throw new System.IO.InvalidDataException("Given file is not a valid STFS archive.");

‎Library/Util.cs

+12
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ namespace GameArchives
2424
{
2525
public static class Util
2626
{
27+
/// <summary>
28+
/// Create an instance of an IFile from the given local path.
29+
/// </summary>
30+
/// <param name="file"></param>
31+
/// <returns></returns>
32+
public static IFile LocalFile(string file)
33+
{
34+
IDirectory d = new Local.LocalDirectory(Path.GetDirectoryName(file));
35+
IFile f = d.GetFile(Path.GetFileName(file));
36+
return f;
37+
}
38+
2739
public static T Last<T>(this T[] arr)
2840
{
2941
return arr[arr.Length - 1];

‎Library/XISO/XISOPackage.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ public static bool IsXISO(Stream s)
4545
return false;
4646
}
4747

48-
public static XISOPackage OpenFile(string filename)
48+
public static XISOPackage OpenFile(IFile f)
4949
{
50-
return new XISOPackage(filename);
50+
return new XISOPackage(f);
5151
}
5252

53-
private XISOPackage(string filename)
53+
private XISOPackage(IFile f)
5454
{
55-
this.filename = filename;
56-
stream = File.OpenRead(filename);
55+
this.filename = f.Name;
56+
stream = f.GetStream();
5757
if (!IsXISO(stream))
5858
{
5959
stream.Dispose();

0 commit comments

Comments
 (0)
Please sign in to comment.