Skip to content

Commit b656171

Browse files
committed
Add SecuROM DFA
1 parent 2bf3d6f commit b656171

File tree

6 files changed

+243
-0
lines changed

6 files changed

+243
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Text;
4+
using SabreTools.IO.Extensions;
5+
using SabreTools.Matching;
6+
using SabreTools.Models.SecuROM;
7+
using static SabreTools.Models.SecuROM.Constants;
8+
9+
namespace SabreTools.Serialization.Deserializers
10+
{
11+
public class SecuROMDFA : BaseBinaryDeserializer<DFAFile>
12+
{
13+
/// <inheritdoc/>
14+
public override DFAFile? Deserialize(Stream? data)
15+
{
16+
// If the data is invalid
17+
if (data == null || !data.CanRead)
18+
return null;
19+
20+
try
21+
{
22+
// Create a new file to fill
23+
var dfa = new DFAFile();
24+
25+
#region Header
26+
27+
// Try to parse the header
28+
dfa.Signature = data.ReadBytes(8);
29+
if (!dfa.Signature.EqualsExactly(DFAMagicBytes))
30+
return null;
31+
32+
dfa.BlockOrHeaderSize = data.ReadUInt32();
33+
34+
#endregion
35+
36+
#region Entries
37+
38+
// If we have any entries
39+
List<DFAEntry> entries = [];
40+
41+
// Read entries while there is data
42+
while (data.Position < data.Length)
43+
{
44+
var entry = ParseDFAEntry(data);
45+
entries.Add(entry);
46+
}
47+
48+
// Set the entries list
49+
dfa.Entries = [.. entries];
50+
51+
#endregion
52+
53+
return dfa;
54+
}
55+
catch
56+
{
57+
// Ignore the actual error
58+
return null;
59+
}
60+
}
61+
62+
/// <summary>
63+
/// Parse a Stream into a DFAEntry
64+
/// </summary>
65+
/// <param name="data">Stream to parse</param>
66+
/// <returns>Filled DFAEntry on success, null on error</returns>
67+
public static DFAEntry ParseDFAEntry(Stream data)
68+
{
69+
var obj = new DFAEntry();
70+
71+
byte[] name = data.ReadBytes(4);
72+
obj.Name = Encoding.ASCII.GetString(name);
73+
obj.Length = data.ReadUInt32();
74+
if (obj.Length > 0)
75+
obj.Value = data.ReadBytes((int)obj.Length);
76+
77+
return obj;
78+
}
79+
}
80+
}

SabreTools.Serialization/Printer.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public static void PrintToConsole(this IWrapper wrapper)
6464
Wrapper.PlayJPlaylist item => item.PrettyPrint(),
6565
Wrapper.PortableExecutable item => item.PrettyPrint(),
6666
Wrapper.Quantum item => item.PrettyPrint(),
67+
Wrapper.SecuROMDFA item => item.PrettyPrint(),
6768
Wrapper.SGA item => item.PrettyPrint(),
6869
Wrapper.VBSP item => item.PrettyPrint(),
6970
Wrapper.VPK item => item.PrettyPrint(),
@@ -113,6 +114,7 @@ public static string ExportJSON(this IWrapper wrapper)
113114
Wrapper.PlayJPlaylist item => item.ExportJSON(),
114115
Wrapper.PortableExecutable item => item.ExportJSON(),
115116
Wrapper.Quantum item => item.ExportJSON(),
117+
Wrapper.SecuROMDFA item => item.ExportJSON(),
116118
Wrapper.SGA item => item.ExportJSON(),
117119
Wrapper.VBSP item => item.ExportJSON(),
118120
Wrapper.VPK item => item.ExportJSON(),
@@ -427,6 +429,16 @@ private static StringBuilder PrettyPrint(this Wrapper.Quantum item)
427429
return builder;
428430
}
429431

432+
/// <summary>
433+
/// Export the item information as pretty-printed text
434+
/// </summary>
435+
private static StringBuilder PrettyPrint(this Wrapper.SecuROMDFA item)
436+
{
437+
var builder = new StringBuilder();
438+
SecuROMDFA.Print(builder, item.Model);
439+
return builder;
440+
}
441+
430442
/// <summary>
431443
/// Export the item information as pretty-printed text
432444
/// </summary>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Text;
2+
using SabreTools.Models.SecuROM;
3+
using SabreTools.Serialization.Interfaces;
4+
5+
namespace SabreTools.Serialization.Printers
6+
{
7+
public class SecuROMDFA : IPrinter<DFAFile>
8+
{
9+
/// <inheritdoc/>
10+
public void PrintInformation(StringBuilder builder, DFAFile model)
11+
=> Print(builder, model);
12+
13+
public static void Print(StringBuilder builder, DFAFile dfaFile)
14+
{
15+
builder.AppendLine("SecuROM DFA File Information:");
16+
builder.AppendLine("-------------------------");
17+
builder.AppendLine(dfaFile.Signature, "Signature");
18+
builder.AppendLine(dfaFile.BlockOrHeaderSize, "Block or header size");
19+
builder.AppendLine();
20+
21+
22+
Print(builder, dfaFile.Entries);
23+
}
24+
25+
private static void Print(StringBuilder builder, DFAEntry[]? entries)
26+
{
27+
builder.AppendLine(" Entries Information:");
28+
builder.AppendLine(" -------------------------");
29+
if (entries == null || entries.Length == 0)
30+
{
31+
builder.AppendLine(" No entries");
32+
builder.AppendLine();
33+
return;
34+
}
35+
36+
for (int i = 0; i < entries.Length; i++)
37+
{
38+
var entry = entries[i];
39+
Print(builder, entry, i);
40+
}
41+
42+
builder.AppendLine();
43+
}
44+
45+
private static void Print(StringBuilder builder, DFAEntry? entry, int index)
46+
{
47+
builder.AppendLine($" Entry {index}");
48+
if (entry == null)
49+
{
50+
builder.AppendLine(" [NULL]");
51+
return;
52+
}
53+
54+
builder.AppendLine(entry.Name, " Name");
55+
builder.AppendLine(entry.Length, " Length");
56+
builder.AppendLine(entry.Value, " Value");
57+
}
58+
}
59+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System.IO;
2+
using SabreTools.Models.SecuROM;
3+
4+
namespace SabreTools.Serialization.Wrappers
5+
{
6+
public class SecuROMDFA : WrapperBase<DFAFile>
7+
{
8+
#region Descriptive Properties
9+
10+
/// <inheritdoc/>
11+
public override string DescriptionString => "SecuROM DFA File";
12+
13+
#endregion
14+
15+
#region Constructors
16+
17+
/// <inheritdoc/>
18+
public SecuROMDFA(DFAFile? model, byte[]? data, int offset)
19+
: base(model, data, offset)
20+
{
21+
// All logic is handled by the base class
22+
}
23+
24+
/// <inheritdoc/>
25+
public SecuROMDFA(DFAFile? model, Stream? data)
26+
: base(model, data)
27+
{
28+
// All logic is handled by the base class
29+
}
30+
31+
/// <summary>
32+
/// Create a SecuROM DFA file from a byte array and offset
33+
/// </summary>
34+
/// <param name="data">Byte array representing the archive</param>
35+
/// <param name="offset">Offset within the array to parse</param>
36+
/// <returns>A SecuROM DFA file wrapper on success, null on failure</returns>
37+
public static SecuROMDFA? Create(byte[]? data, int offset)
38+
{
39+
// If the data is invalid
40+
if (data == null || data.Length == 0)
41+
return null;
42+
43+
// If the offset is out of bounds
44+
if (offset < 0 || offset >= data.Length)
45+
return null;
46+
47+
// Create a memory stream and use that
48+
var dataStream = new MemoryStream(data, offset, data.Length - offset);
49+
return Create(dataStream);
50+
}
51+
52+
/// <summary>
53+
/// Create a SecuROM DFA file from a Stream
54+
/// </summary>
55+
/// <param name="data">Stream representing the archive</param>
56+
/// <returns>A SecuROM DFA file wrapper on success, null on failure</returns>
57+
public static SecuROMDFA? Create(Stream? data)
58+
{
59+
// If the data is invalid
60+
if (data == null || !data.CanRead)
61+
return null;
62+
63+
try
64+
{
65+
var file = Deserializers.SecuROMDFA.DeserializeStream(data);
66+
if (file == null)
67+
return null;
68+
69+
return new SecuROMDFA(file, data);
70+
}
71+
catch
72+
{
73+
return null;
74+
}
75+
}
76+
77+
#endregion
78+
}
79+
}

SabreTools.Serialization/Wrappers/WrapperFactory.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public static class WrapperFactory
4949
WrapperType.RAR => null,// TODO: Implement wrapper
5050
WrapperType.RealArcadeInstaller => null,// TODO: Implement wrapper
5151
WrapperType.RealArcadeMezzanine => null,// TODO: Implement wrapper
52+
WrapperType.SecuROMDFA => SecuROMDFA.Create(data),
5253
WrapperType.SevenZip => null,// TODO: Implement wrapper
5354
WrapperType.SFFS => null,// TODO: Implement wrapper
5455
WrapperType.SGA => SGA.Create(data),
@@ -616,6 +617,13 @@ public static WrapperType GetFileType(byte[]? magic, string? extension)
616617

617618
#endregion
618619

620+
#region SecuROM DFA
621+
622+
if (magic.StartsWith(Models.SecuROM.Constants.DFAMagicBytes))
623+
return WrapperType.SecuROMDFA;
624+
625+
#endregion
626+
619627
// TODO: Use constants from Models here
620628
#region SevenZip
621629

SabreTools.Serialization/Wrappers/WrapperType.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ public enum WrapperType
185185
/// <remarks>Currently has no IWrapper implementation</remarks>
186186
RealArcadeMezzanine,
187187

188+
/// <summary>
189+
/// SecuROM DFA File
190+
/// </summary>
191+
SecuROMDFA,
192+
188193
/// <summary>
189194
/// 7-zip archive
190195
/// </summary>

0 commit comments

Comments
 (0)