-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
65 lines (49 loc) · 1.54 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System.Text;
var filename = args.FirstOrDefault();
if (string.IsNullOrEmpty(filename))
{
throw new ArgumentNullException(nameof(filename));
}
var file = File.OpenRead(filename);
var reader = new BinaryReader(file);
// check file magic
if (reader.ReadUInt32() != 22038099 /* SFP<1> */)
{
throw new ArgumentException("File is not a game.pack: Invalid magic");
}
var numFiles = reader.ReadUInt32();
// check file length
if (reader.ReadUInt32() != file.Length)
{
throw new ArgumentException("File is not a valid game.pack: Invalid length");
}
for (var i = 0; i < numFiles; i++)
{
// skip past sf::BasicString members, not needed
file.Position += 8;
var name = GetString(reader.ReadBytes(112));
var size = reader.ReadUInt32();
var offset = reader.ReadUInt32();
Console.WriteLine($"Name = {name}, Size = {size}, Offset = {offset}");
// extract file
ExtractFile(name, offset, size);
}
// null terminates the array and returns it as string
// could be left out if we read size from sf::BasicString
string GetString(byte[] str)
{
return Encoding.ASCII.GetString(
str.Take(Array.FindIndex(str, x => x == 0)).ToArray());
}
void ExtractFile(string name, uint offset, uint size)
{
// save the current position
var current = file.Position;
file.Position = offset;
var data = reader.ReadBytes((int)size);
var path = Path.Join("export", name);
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllBytes(path, data);
// restore cursor
file.Position = current;
}