diff --git a/dat-extractor.sln b/dat-extractor.sln
new file mode 100644
index 0000000..5c844fe
--- /dev/null
+++ b/dat-extractor.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32328.378
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dat-extractor", "dat-extractor\dat-extractor.csproj", "{26EC68A5-551C-4024-83A1-A8B6D5F97371}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {26EC68A5-551C-4024-83A1-A8B6D5F97371}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {26EC68A5-551C-4024-83A1-A8B6D5F97371}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {26EC68A5-551C-4024-83A1-A8B6D5F97371}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {26EC68A5-551C-4024-83A1-A8B6D5F97371}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {DD771827-A88F-416C-AA2E-15DC4EC607A8}
+ EndGlobalSection
+EndGlobal
diff --git a/dat-extractor/App.config b/dat-extractor/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/dat-extractor/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dat-extractor/DatFileEntry.cs b/dat-extractor/DatFileEntry.cs
new file mode 100644
index 0000000..fec2f8c
--- /dev/null
+++ b/dat-extractor/DatFileEntry.cs
@@ -0,0 +1,35 @@
+namespace dat_extractor
+{
+ public struct DatFileEntry
+ {
+ ///
+ /// Pointer offset in the .dat file where the data for the file starts.
+ ///
+ public uint FileOffset;
+
+ ///
+ /// Not sure, this value is always zero.
+ ///
+ public uint Unknown;
+
+ ///
+ /// How large the file data chunk is in the dat file.
+ ///
+ public uint FileDataSize;
+
+ ///
+ /// Pointer offset in the .dat file where the string for the file name starts.
+ ///
+ public uint FileNameOffset;
+
+ ///
+ /// The parsed string in the .dat file which is the file name
+ ///
+ public string FileName;
+
+ ///
+ /// The parsed byte array for the actual file data itself.
+ ///
+ public byte[] Data;
+ }
+}
diff --git a/dat-extractor/Program.cs b/dat-extractor/Program.cs
new file mode 100644
index 0000000..8e50e01
--- /dev/null
+++ b/dat-extractor/Program.cs
@@ -0,0 +1,166 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+
+namespace dat_extractor
+{
+ internal class Program
+ {
+ static void Main(string[] args)
+ {
+ //if there are not exactly 2 arguments, don't continue.
+ if(args.Length != 2)
+ {
+ Console.WriteLine("Incorrect amount of arguments!");
+ Utilities.PrintProgramUsage();
+ return;
+ }
+
+ //get both arguments
+ string inputPath = args[0];
+ string outputPath = args[1];
+
+ //validate the input path
+ if(!Directory.Exists(inputPath))
+ {
+ Console.WriteLine("Input directory does not exist!");
+ Utilities.PrintProgramUsage();
+ return;
+ }
+
+ //validate the output path
+ if (!Directory.Exists(outputPath))
+ {
+ Console.WriteLine("Output directory does not exist!");
+ Utilities.PrintProgramUsage();
+ return;
+ }
+
+ //declare and initalize a dynamic array of dat files in the input directory.
+ List datFiles = new List();
+
+ //get all the files in the input directory
+ string[] inputDirectoryFiles = Directory.GetFiles(inputPath);
+
+ //iterate through each file
+ foreach (string inputDirectoryFile in inputDirectoryFiles)
+ {
+ //if we find a file with a .dat extension
+ if (Path.GetExtension(inputDirectoryFile) == ".dat")
+ {
+ //add it to the list
+ Console.WriteLine("Found {0}", inputDirectoryFile);
+ datFiles.Add(inputDirectoryFile);
+ }
+ }
+
+ //let the user know what we found.
+ Console.WriteLine("Found {0} files, commencing extraction...", datFiles.Count);
+
+ //iterate through each dat file in the directory.
+ foreach(string datFile in datFiles)
+ {
+ Console.WriteLine("------------------------------------------------------");
+ Console.WriteLine("Extracting {0}", Path.GetFileName(datFile));
+ ExtractDatFile(datFile);
+ Console.WriteLine("Finished extracting {0}", Path.GetFileName(datFile));
+ Console.WriteLine("------------------------------------------------------");
+ }
+
+ Console.WriteLine("Finished, press a key to end.", datFiles.Count);
+ Console.ReadKey();
+ }
+
+ ///
+ /// Extracts a single .dat file, and creates a directory with the dat file name, and extracts the files into the directory.
+ ///
+ ///
+ private static void ExtractDatFile(string inputPath)
+ {
+ //construct the directory to which the extracted files in the .dat archive will be written to.
+ string inputFileName = Path.GetFileNameWithoutExtension(inputPath);
+ string inputDirectory = Path.GetDirectoryName(inputPath);
+ string extractedDirectory = inputDirectory + "/" + inputFileName;
+
+ //make sure it exists, otherwise create it.
+ if(Directory.Exists(extractedDirectory) == false)
+ Directory.CreateDirectory(extractedDirectory);
+
+ //open the .dat file, and we will read the binary file.
+ using(BinaryReader reader = new BinaryReader(File.OpenRead(inputPath)))
+ {
+ //parse the magic
+ string magic = Utilities.CombineChars(reader.ReadChars(4));
+ Console.WriteLine("Magic: {0}", magic);
+
+ //parse the total file size
+ uint fileSize = reader.ReadUInt32(); //total file size
+ Console.WriteLine("File Size: {0}", fileSize);
+
+ //parse the unknown value
+ uint unknown1 = reader.ReadUInt32(); //unknown1
+ Console.WriteLine("unknown1: {0}", unknown1);
+
+ //parse the amount of files listed in the dat archive
+ uint filecount = reader.ReadUInt32(); //filecount
+ Console.WriteLine("filecount: {0}", filecount);
+
+ //create an array with the amount of files in the dat archive.
+ DatFileEntry[] datFileEntries = new DatFileEntry[filecount];
+
+ //iterate through the dat file entry table.
+ for (int i = 0; i < filecount; i++)
+ {
+ //create our struct
+ datFileEntries[i] = new DatFileEntry();
+
+ //parse the file data offset in the dat file
+ Console.WriteLine("-------- Item {0} --------");
+ datFileEntries[i].FileOffset = reader.ReadUInt32();
+ Console.WriteLine("FileOffset: {0}", datFileEntries[i].FileOffset);
+
+ //parse the unknown value
+ datFileEntries[i].Unknown = reader.ReadUInt32();
+ Console.WriteLine("Unknown: {0}", datFileEntries[i].Unknown); //always 0
+
+ //parse the size of the file data
+ datFileEntries[i].FileDataSize = reader.ReadUInt32();
+ Console.WriteLine("FileDataSize: {0}", datFileEntries[i].FileDataSize);
+
+ //parse the file name offset in the dat file
+ datFileEntries[i].FileNameOffset = reader.ReadUInt32();
+ Console.WriteLine("FileNameOffset: {0}", datFileEntries[i].FileNameOffset);
+
+ Console.WriteLine("-------- Item End --------");
+ }
+
+ //table ends
+ //now we will iterate through the entires again, but with the offsets that we parsed.
+ //we will go through the file and set the pointer at the offsets to parse the needed data for the file.
+
+ //iterate once again through each of the file entires
+ for(int i = 0; i < datFileEntries.Length; i++)
+ {
+ //use the file name offset and seek to the position in the dat file where the file name string is located and parse it.
+ reader.BaseStream.Seek(datFileEntries[i].FileNameOffset, SeekOrigin.Begin);
+ datFileEntries[i].FileName = Utilities.ReadLengthPrefixedString(reader);
+ Console.WriteLine("[ENTRY {0}] File Name: {1}", i, datFileEntries[i].FileName);
+
+ //use the file data offset and seek to the position in the dat file where the file data is located and parse all of the bytes.
+ reader.BaseStream.Seek(datFileEntries[i].FileOffset, SeekOrigin.Begin);
+ datFileEntries[i].Data = reader.ReadBytes((int)datFileEntries[i].FileDataSize);
+ Console.WriteLine("[ENTRY {0}] Data Size: {1}", i, datFileEntries[i].Data.Length);
+
+ //construct the new file path and write the binary data for the file into the disk.
+ string newFilePath = string.Format("{0}/{1}", extractedDirectory, datFileEntries[i].FileName);
+ File.WriteAllBytes(newFilePath, datFileEntries[i].Data);
+ }
+
+ Console.WriteLine("left off at: {0}", reader.BaseStream.Position);
+ }
+ }
+ }
+}
diff --git a/dat-extractor/Properties/AssemblyInfo.cs b/dat-extractor/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7125e97
--- /dev/null
+++ b/dat-extractor/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("dat-extractor")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HP")]
+[assembly: AssemblyProduct("dat-extractor")]
+[assembly: AssemblyCopyright("Copyright © HP 2022")]
+[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("26ec68a5-551c-4024-83a1-a8b6d5f97371")]
+
+// 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/dat-extractor/Utilities.cs b/dat-extractor/Utilities.cs
new file mode 100644
index 0000000..d006093
--- /dev/null
+++ b/dat-extractor/Utilities.cs
@@ -0,0 +1,49 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace dat_extractor
+{
+ public static class Utilities
+ {
+ ///
+ /// Combines a char array into a single string.
+ ///
+ ///
+ ///
+ public static string CombineChars(char[] chars)
+ {
+ string result = "";
+
+ for (int i = 0; i < chars.Length; i++)
+ {
+ result += chars[i];
+ }
+
+ return result;
+ }
+
+ ///
+ /// Reads a string, which has in binary a uint32 serialized before the actual string itself to indicate length.
+ ///
+ ///
+ ///
+ public static string ReadLengthPrefixedString(BinaryReader reader)
+ {
+ //read the uint32 that is serialized right before the actual string, this is the length of the string.
+ uint length = reader.ReadUInt32();
+
+ //read each char and combine them into a single string.
+ return CombineChars(reader.ReadChars((int)length));
+ }
+
+ public static void PrintProgramUsage()
+ {
+ Console.WriteLine("Program Usage:");
+ Console.WriteLine("app.exe [input directory] [output directory]");
+ }
+ }
+}
diff --git a/dat-extractor/bin/Debug/dat-extractor.exe b/dat-extractor/bin/Debug/dat-extractor.exe
new file mode 100644
index 0000000..fda4f47
Binary files /dev/null and b/dat-extractor/bin/Debug/dat-extractor.exe differ
diff --git a/dat-extractor/bin/Debug/dat-extractor.exe.config b/dat-extractor/bin/Debug/dat-extractor.exe.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/dat-extractor/bin/Debug/dat-extractor.exe.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dat-extractor/bin/Debug/dat-extractor.pdb b/dat-extractor/bin/Debug/dat-extractor.pdb
new file mode 100644
index 0000000..c655384
Binary files /dev/null and b/dat-extractor/bin/Debug/dat-extractor.pdb differ
diff --git a/dat-extractor/dat-extractor.csproj b/dat-extractor/dat-extractor.csproj
new file mode 100644
index 0000000..b984d3d
--- /dev/null
+++ b/dat-extractor/dat-extractor.csproj
@@ -0,0 +1,55 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {26EC68A5-551C-4024-83A1-A8B6D5F97371}
+ Exe
+ dat_extractor
+ dat-extractor
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dat-extractor/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/dat-extractor/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs
new file mode 100644
index 0000000..3871b18
--- /dev/null
+++ b/dat-extractor/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs
@@ -0,0 +1,4 @@
+//
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
diff --git a/dat-extractor/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/dat-extractor/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
new file mode 100644
index 0000000..0898384
Binary files /dev/null and b/dat-extractor/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ
diff --git a/dat-extractor/obj/Debug/dat-extractor.csproj.AssemblyReference.cache b/dat-extractor/obj/Debug/dat-extractor.csproj.AssemblyReference.cache
new file mode 100644
index 0000000..ea321ff
Binary files /dev/null and b/dat-extractor/obj/Debug/dat-extractor.csproj.AssemblyReference.cache differ
diff --git a/dat-extractor/obj/Debug/dat-extractor.csproj.CoreCompileInputs.cache b/dat-extractor/obj/Debug/dat-extractor.csproj.CoreCompileInputs.cache
new file mode 100644
index 0000000..6d2c0b9
--- /dev/null
+++ b/dat-extractor/obj/Debug/dat-extractor.csproj.CoreCompileInputs.cache
@@ -0,0 +1 @@
+0c8e2c9e7669cfd45cf74f44a0fbb64fec83f5a6
diff --git a/dat-extractor/obj/Debug/dat-extractor.csproj.FileListAbsolute.txt b/dat-extractor/obj/Debug/dat-extractor.csproj.FileListAbsolute.txt
new file mode 100644
index 0000000..2503477
--- /dev/null
+++ b/dat-extractor/obj/Debug/dat-extractor.csproj.FileListAbsolute.txt
@@ -0,0 +1,15 @@
+F:\toradora-portable\dat-files\converter\dat-extractor\dat-extractor\bin\Debug\dat-extractor.exe.config
+F:\toradora-portable\dat-files\converter\dat-extractor\dat-extractor\bin\Debug\dat-extractor.exe
+F:\toradora-portable\dat-files\converter\dat-extractor\dat-extractor\bin\Debug\dat-extractor.pdb
+F:\toradora-portable\dat-files\converter\dat-extractor\dat-extractor\obj\Debug\dat-extractor.csproj.AssemblyReference.cache
+F:\toradora-portable\dat-files\converter\dat-extractor\dat-extractor\obj\Debug\dat-extractor.csproj.SuggestedBindingRedirects.cache
+F:\toradora-portable\dat-files\converter\dat-extractor\dat-extractor\obj\Debug\dat-extractor.csproj.CoreCompileInputs.cache
+F:\toradora-portable\dat-files\converter\dat-extractor\dat-extractor\obj\Debug\dat-extractor.exe
+F:\toradora-portable\dat-files\converter\dat-extractor\dat-extractor\obj\Debug\dat-extractor.pdb
+F:\toradora-portable\custom-tools\dat-extractor\dat-extractor\bin\Debug\dat-extractor.exe.config
+F:\toradora-portable\custom-tools\dat-extractor\dat-extractor\bin\Debug\dat-extractor.exe
+F:\toradora-portable\custom-tools\dat-extractor\dat-extractor\bin\Debug\dat-extractor.pdb
+F:\toradora-portable\custom-tools\dat-extractor\dat-extractor\obj\Debug\dat-extractor.csproj.AssemblyReference.cache
+F:\toradora-portable\custom-tools\dat-extractor\dat-extractor\obj\Debug\dat-extractor.csproj.CoreCompileInputs.cache
+F:\toradora-portable\custom-tools\dat-extractor\dat-extractor\obj\Debug\dat-extractor.exe
+F:\toradora-portable\custom-tools\dat-extractor\dat-extractor\obj\Debug\dat-extractor.pdb
diff --git a/dat-extractor/obj/Debug/dat-extractor.csproj.SuggestedBindingRedirects.cache b/dat-extractor/obj/Debug/dat-extractor.csproj.SuggestedBindingRedirects.cache
new file mode 100644
index 0000000..e69de29
diff --git a/dat-extractor/obj/Debug/dat-extractor.exe b/dat-extractor/obj/Debug/dat-extractor.exe
new file mode 100644
index 0000000..fda4f47
Binary files /dev/null and b/dat-extractor/obj/Debug/dat-extractor.exe differ
diff --git a/dat-extractor/obj/Debug/dat-extractor.pdb b/dat-extractor/obj/Debug/dat-extractor.pdb
new file mode 100644
index 0000000..c655384
Binary files /dev/null and b/dat-extractor/obj/Debug/dat-extractor.pdb differ