diff --git a/.gitignore b/.gitignore
index c78880ca..a90c9a98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,9 @@
/Deheader/obj
/Deheader/obj/Debug
/Deheader/obj/Release
+/DiffDat/obj
+/DiffDat/obj/Debug
+/DiffDat/obj/Release
/SabreHelper/obj
/SabreHelper/obj/Debug
/SabreHelper/obj/Release
diff --git a/DiffDat/App.config b/DiffDat/App.config
new file mode 100644
index 00000000..88fa4027
--- /dev/null
+++ b/DiffDat/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DiffDat/DiffDat.cs b/DiffDat/DiffDat.cs
new file mode 100644
index 00000000..9e57aa0f
--- /dev/null
+++ b/DiffDat/DiffDat.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+using SabreTools.Helper;
+
+namespace SabreTools
+{
+ public class DiffDat
+ {
+ private static Logger logger;
+
+ public static void Main(string[] args)
+ {
+ Console.Clear();
+
+ // Credits take precidence over all
+ if ((new List(args)).Contains("--credits"))
+ {
+ Build.Credits();
+ return;
+ }
+
+ if (args.Length == 0)
+ {
+ Build.Help();
+ return;
+ }
+
+ logger = new Logger(false, "diffdat.log");
+ logger.Start();
+
+ // Output the title
+ Build.Start("DiffDat");
+
+ List inputs = new List();
+ bool tofile = false, help = false;
+ foreach (string arg in args)
+ {
+ switch (arg)
+ {
+ case "-h":
+ case "-?":
+ case "--help":
+ help = true;
+ break;
+ case "-l":
+ case "--log":
+ tofile = true;
+ break;
+ default:
+ // Add actual files to the list of inputs
+ if (File.Exists(arg.Replace("\"", "")))
+ {
+ inputs.Add(Path.GetFullPath(arg.Replace("\"", "")));
+ }
+ else if (Directory.Exists(arg.Replace("\"", "")))
+ {
+ foreach (string file in Directory.EnumerateFiles(arg, "*", SearchOption.AllDirectories))
+ {
+ inputs.Add(Path.GetFullPath(file));
+ }
+ }
+ break;
+ }
+ }
+
+ // Set the possibly new value for logger
+ logger.ToFile = tofile;
+
+ // Show help if explicitly asked for it or if not enough files are supplied
+ if (help || inputs.Count < 2)
+ {
+ Build.Help();
+ logger.Close();
+ return;
+ }
+
+ // Otherwise, read in the two files, diff them, and write the result to the file type that the first one is
+ List A = new List();
+ foreach (string input in inputs)
+ {
+ logger.Log("Merging in DAT: " + input);
+ List B = RomManipulation.Parse(input, 0, 0, logger);
+ A = RomManipulation.Diff(A, B);
+ }
+ Output.WriteToDat("diffdat", "diffdat", "", "", "DiffDat", "SabreTools", false, !RomManipulation.IsXmlDat(inputs[0]), "", A, logger);
+ }
+ }
+}
diff --git a/DiffDat/DiffDat.csproj b/DiffDat/DiffDat.csproj
new file mode 100644
index 00000000..8adb5e6f
--- /dev/null
+++ b/DiffDat/DiffDat.csproj
@@ -0,0 +1,66 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {785A4E9E-0DC1-4FAD-AA3A-57B5B122CD8E}
+ Exe
+ Properties
+ DiffDat
+ DiffDat
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ ..\..\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ ..\..\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {225a1afd-0890-44e8-b779-7502665c23a5}
+ SabreHelper
+
+
+
+
+
\ No newline at end of file
diff --git a/DiffDat/Properties/AssemblyInfo.cs b/DiffDat/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..d86f7c5c
--- /dev/null
+++ b/DiffDat/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DiffDat")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DiffDat")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("785a4e9e-0dc1-4fad-aa3a-57b5b122cd8e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/README.MD b/README.MD
index 6787d779..abcc7f13 100644
--- a/README.MD
+++ b/README.MD
@@ -77,7 +77,7 @@ CURRENTLY UNCODED - A program to merge an arbitrary number of DATs into a single
DiffDat
-CURRENTLY UNCODED - A program to create a DAT based on the differences between two input DATs. Optionally, if the output file exists, the information is appended. (This latter functionality may be wrapped into MergeDAT.)
+A program to create a DAT based on the differences between two or more input DATs.
Licensing
diff --git a/SabreHelper/Build.cs b/SabreHelper/Build.cs
index 77f8fd1a..e1084772 100644
--- a/SabreHelper/Build.cs
+++ b/SabreHelper/Build.cs
@@ -156,6 +156,15 @@ Options:
-l, --log Enable log to file
-sd, --superdat Enable SuperDAT creation");
break;
+ case "DiffDat":
+ Console.WriteLine(@"DiffDat - Get the difference between two or more DAT files
+-----------------------------------------
+Usage: DiffDat [options] [filename] [filename] ...
+
+Options:
+ -h, -?, --help Show this help dialog
+ -l, --log Enable log to file");
+ break;
default:
Console.Write("This is the default help output");
break;
diff --git a/SabreHelper/Output.cs b/SabreHelper/Output.cs
index 73a513b1..d0dca637 100644
--- a/SabreHelper/Output.cs
+++ b/SabreHelper/Output.cs
@@ -171,5 +171,70 @@ namespace SabreTools.Helper
return true;
}
+
+ ///
+ /// Convert a List of RomData objects to a List of tab-deliminated strings
+ ///
+ /// List of RomData objects representing the roms to be parsed
+ /// List of Strings representing the roms
+ public static List RomDataToString(List roms)
+ {
+ List outlist = new List();
+ foreach (RomData rom in roms)
+ {
+ outlist.Add(rom.Manufacturer + "\t" +
+ rom.System + "\t" +
+ rom.SystemID + "\t" +
+ rom.Source + "\t" +
+ rom.URL + "\t" +
+ rom.SourceID + "\t" +
+ rom.Game + "\t" +
+ rom.Name + "\t" +
+ rom.Type + "\t" +
+ rom.Size + "\t" +
+ rom.CRC + "\t" +
+ rom.MD5 + "\t" +
+ rom.SHA1);
+ }
+ return outlist;
+ }
+
+ ///
+ /// Convert a List of tab-deliminated strings objects to a List of RomData objects
+ ///
+ /// List of Strings representing the roms to be parsed
+ /// List of RomData objects representing the roms
+ public static List StringToRomData(List roms)
+ {
+ List outlist = new List();
+ foreach (String rom in roms)
+ {
+ string[] temp = rom.Split('\t');
+ try
+ {
+ outlist.Add(new RomData
+ {
+ Manufacturer = temp[0],
+ System = temp[1],
+ SystemID = Int32.Parse(temp[2]),
+ Source = temp[3],
+ URL = temp[4],
+ SourceID = Int32.Parse(temp[5]),
+ Game = temp[6],
+ Name = temp[7],
+ Type = temp[8],
+ Size = Int64.Parse(temp[9]),
+ CRC = temp[10],
+ MD5 = temp[11],
+ SHA1 = temp[12],
+ });
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.ToString());
+ }
+ }
+ return outlist;
+ }
}
}
diff --git a/SabreHelper/RomManipulation.cs b/SabreHelper/RomManipulation.cs
index 1afe6378..36475905 100644
--- a/SabreHelper/RomManipulation.cs
+++ b/SabreHelper/RomManipulation.cs
@@ -333,7 +333,10 @@ namespace SabreTools.Helper
/// Adapted from http://stackoverflow.com/questions/5620266/the-opposite-of-intersect
public static List Diff(List A, List B)
{
- return A.Except(B).Union(B.Except(A)).ToList();
+ List AString = Output.RomDataToString(A);
+ List BString = Output.RomDataToString(B);
+ List CString = AString.Except(BString).Union(BString.Except(AString)).ToList();
+ return Output.StringToRomData(CString);
}
}
}
diff --git a/SabreTools.sln b/SabreTools.sln
index 581310a4..7e909153 100644
--- a/SabreTools.sln
+++ b/SabreTools.sln
@@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreHelper", "SabreHelper\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DATFromDir", "DATFromDir\DATFromDir.csproj", "{382B75D3-079E-49D5-A830-54DD6EB5A02D}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiffDat", "DiffDat\DiffDat.csproj", "{785A4E9E-0DC1-4FAD-AA3A-57B5B122CD8E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -52,6 +54,10 @@ Global
{382B75D3-079E-49D5-A830-54DD6EB5A02D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{382B75D3-079E-49D5-A830-54DD6EB5A02D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{382B75D3-079E-49D5-A830-54DD6EB5A02D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {785A4E9E-0DC1-4FAD-AA3A-57B5B122CD8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {785A4E9E-0DC1-4FAD-AA3A-57B5B122CD8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {785A4E9E-0DC1-4FAD-AA3A-57B5B122CD8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {785A4E9E-0DC1-4FAD-AA3A-57B5B122CD8E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE