diff --git a/CreateXDF.sln b/CreateXDF.sln
new file mode 100644
index 0000000..b5ad37b
--- /dev/null
+++ b/CreateXDF.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateXDF", "CreateXDF\CreateXDF.csproj", "{00C12FC7-49DD-4291-8757-D6CD349641B8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {00C12FC7-49DD-4291-8757-D6CD349641B8}.Debug|x86.ActiveCfg = Debug|x86
+ {00C12FC7-49DD-4291-8757-D6CD349641B8}.Debug|x86.Build.0 = Debug|x86
+ {00C12FC7-49DD-4291-8757-D6CD349641B8}.Release|x86.ActiveCfg = Release|x86
+ {00C12FC7-49DD-4291-8757-D6CD349641B8}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+EndGlobal
diff --git a/CreateXDF/CreateXDF.csproj b/CreateXDF/CreateXDF.csproj
new file mode 100644
index 0000000..067e945
--- /dev/null
+++ b/CreateXDF/CreateXDF.csproj
@@ -0,0 +1,39 @@
+
+
+
+ Debug
+ x86
+ {00C12FC7-49DD-4291-8757-D6CD349641B8}
+ Exe
+ CreateXDF
+ CreateXDF
+ v4.6.1
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ true
+ x86
+
+
+ true
+ bin\Release
+ prompt
+ 4
+ true
+ x86
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CreateXDF/Program.cs b/CreateXDF/Program.cs
new file mode 100644
index 0000000..1d62c82
--- /dev/null
+++ b/CreateXDF/Program.cs
@@ -0,0 +1,275 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace CreateXDF
+{
+ class MainClass
+ {
+ static readonly byte[] bpb = { 0xEB, 0x4F, 0x90, 0x49, 0x42, 0x4D, 0x20, 0x32, 0x30, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x33, 0xDB, 0x8E, 0xD3, 0xBC, 0xFF, 0x7B, 0xFB, 0xBA,
+ 0xC0, 0xFA, 0x29, 0xC0, 0x8E, 0xD0, 0xBC, 0x00, 0x7C, 0xFB, 0x0E, 0x1F, 0xBE, 0x40, 0x7D, 0x8A,
+ 0x04, 0x08, 0xC0, 0x74, 0x0D, 0x56, 0x1E, 0xB4, 0x0E, 0xB7, 0x00, 0xCD, 0x10, 0x1F, 0x5E, 0x46,
+ 0xEB, 0xED, 0xB4, 0x00, 0xCD, 0x16, 0xCD, 0x19, 0xB9, 0x0B, 0x00, 0xF3, 0x00, 0x29, 0x0D, 0xB6,
+ 0x58, 0x44, 0x46, 0x20, 0x76, 0x31, 0x2E, 0x31, 0x61, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39,
+ 0x39, 0x33, 0x2C, 0x20, 0x31, 0x39, 0x39, 0x34, 0x20, 0x2D, 0x2D, 0x20, 0x42, 0x61, 0x63, 0x6B,
+ 0x75, 0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x2C,
+ 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x2C, 0x20, 0x54, 0x61, 0x6D, 0x70, 0x61, 0x20, 0x46, 0x4C, 0x0A,
+ 0x20, 0x50, 0x61, 0x74, 0x65, 0x6E, 0x74, 0x28, 0x73, 0x29, 0x20, 0x50, 0x65, 0x6E, 0x64, 0x69,
+ 0x6E, 0x67, 0x20, 0x2D, 0x2D, 0x20, 0x49, 0x6E, 0x76, 0x65, 0x6E, 0x74, 0x6F, 0x72, 0x3A, 0x20,
+ 0x52, 0x6F, 0x67, 0x65, 0x72, 0x20, 0x44, 0x2E, 0x20, 0x49, 0x76, 0x65, 0x79, 0x0A, 0x41, 0x6C,
+ 0x6C, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x64, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x77, 0x69, 0x64, 0x65, 0x0A, 0x44, 0x75, 0x70, 0x6C,
+ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x70, 0x72, 0x6F, 0x68, 0x69, 0x62, 0x69, 0x74,
+ 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6F, 0x75, 0x74, 0x20, 0x70, 0x65, 0x72, 0x6D, 0x69,
+ 0x73, 0x73, 0x69, 0x6F, 0x6E, 0x0A, 0x0A, 0xC0, 0x6E, 0xEF, 0xDD, 0x5F, 0xA5, 0xDA, 0xB1, 0xF7,
+ 0x4F, 0x53, 0x2F, 0x32, 0x20, 0x21, 0x21, 0x20, 0x53, 0x59, 0x53, 0x30, 0x31, 0x34, 0x37, 0x35,
+ 0x0D, 0x0A, 0x4F, 0x53, 0x2F, 0x32, 0x20, 0x21, 0x21, 0x20, 0x53, 0x59, 0x53, 0x30, 0x32, 0x30,
+ 0x32, 0x37, 0x0D, 0x0A, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x74, 0x65, 0x6E,
+ 0x74, 0x28, 0x73, 0x29, 0x20, 0x50, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x0D, 0x0A, 0x0D, 0x0A,
+ 0x4E, 0x6F, 0x6E, 0x2D, 0x42, 0x6F, 0x6F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x58, 0x44, 0x46,
+ 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x0D, 0x0A, 0x49, 0x6E, 0x73, 0x65,
+ 0x72, 0x74, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x20, 0x61,
+ 0x6E, 0x64, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79,
+ 0x0D, 0x0A, 0x00, 0x53, 0x2F, 0x32, 0x20, 0x21, 0x21, 0x20, 0x53, 0x59, 0x53, 0x30, 0x32, 0x30,
+ 0x32, 0x37, 0x0D, 0x0A, 0x00, 0x4F, 0x53, 0x32, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x20, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA };
+
+ static readonly byte[] fatid = { 0xF9, 0xFF, 0xFF };
+
+ const ushort fatSectors = 11;
+
+ const ushort rootEntries = 224;
+
+ const byte formatByte = 0xF6;
+
+ public static void Main(string[] args)
+ {
+ string volname = "NEW XDF IMG";
+ ushort sectors = 0;
+ byte mediaDescriptor = 0xF0;
+ ushort spt = 0;
+ byte unk_sector_num = 0x0B;
+ DateTime creation = DateTime.Now;
+
+ if((args.Length != 2 && args.Length != 3) || (args[0] != "-3" && args[0] != "-5"))
+ {
+ Console.WriteLine("CreateXDF - Creates an empty XDF disk image usable by XDFCOPY or emulators.");
+ Console.WriteLine("Usage:");
+ Console.WriteLine();
+ Console.WriteLine("CreateXDF -3/-5 image.xdf ");
+ Console.WriteLine("\t-3 creates a 3.5\" XDF disk image");
+ Console.WriteLine("\t-5 creates a 5.25\" XDF disk image");
+ return;
+ }
+
+ if (args.Length == 3)
+ volname = args[2];
+
+ if (args[0] == "-3")
+ {
+ spt = 23;
+ mediaDescriptor = 0xF0;
+ unk_sector_num = 0x0B;
+ }
+ else if (args[0] == "-5")
+ {
+ spt = 19;
+ mediaDescriptor = 0xF9;
+ unk_sector_num = 0x09;
+ }
+ sectors = (ushort)(80 * 2 * spt);
+
+ FileStream fs = new FileStream(args[1], FileMode.CreateNew, FileAccess.ReadWrite);
+
+ byte[] fat = new byte[fatSectors * 512];
+ Array.Copy(fatid, 0, fat, 0, 3);
+
+ byte[] rootDir = new byte[rootEntries * 32];
+
+ Random rand = new Random();
+ byte[] serial = new byte[4];
+ rand.NextBytes(serial);
+
+ byte[] tmp;
+ fs.Write(bpb, 0, 512);
+ fs.Seek(0, SeekOrigin.Begin);
+
+ // This is intentionally done step by step :p
+
+ // Skip jump
+ fs.Seek(3, SeekOrigin.Current);
+ // Skip OEM name
+ fs.Seek(8, SeekOrigin.Current);
+ // Bytes per sector
+ tmp = BitConverter.GetBytes((ushort)512);
+ fs.Write(tmp, 0, 2);
+ // Sectors per cluster
+ fs.WriteByte(1);
+ // Reserved sectors between BPB and FAT
+ tmp = BitConverter.GetBytes((ushort)1);
+ fs.Write(tmp, 0, 2);
+ // Number of FATs
+ fs.WriteByte(2);
+ // Entries in root directory
+ tmp = BitConverter.GetBytes(rootEntries);
+ fs.Write(tmp, 0, 2);
+ // Sectors in volume
+ tmp = BitConverter.GetBytes(sectors);
+ fs.Write(tmp, 0, 2);
+ // Media descriptor
+ fs.WriteByte(mediaDescriptor);
+ // Sectors per FAT
+ tmp = BitConverter.GetBytes(fatSectors);
+ fs.Write(tmp, 0, 2);
+ // Sectors per track
+ tmp = BitConverter.GetBytes(spt);
+ fs.Write(tmp, 0, 2);
+ // Heads
+ tmp = BitConverter.GetBytes((ushort)2);
+ fs.Write(tmp, 0, 2);
+ // Hidden sectors before BPB
+ tmp = BitConverter.GetBytes((uint)0);
+ fs.Write(tmp, 0, 4);
+ // Sectors in volume if > 65535
+ tmp = BitConverter.GetBytes((uint)0);
+ fs.Write(tmp, 0, 4);
+ // Drive numer
+ fs.WriteByte(0);
+ // Volume flags
+ fs.WriteByte(0);
+ // EBPB signature
+ fs.WriteByte(0x29);
+ // Serial number
+ fs.Write(serial, 0, 4);
+ // Volume label
+ tmp = Encoding.ASCII.GetBytes(volname.ToUpper());
+ fs.Write(tmp, 0, tmp.Length >= 11 ? 11 : tmp.Length);
+
+ // Write FATs
+ fs.Seek(512, SeekOrigin.Begin);
+ fs.Write(fat, 0, fat.Length);
+ fs.Write(fat, 0, fat.Length);
+
+ // Create directory entry
+ ushort ctime = 0, cdate = 0;
+ cdate += (ushort)(((creation.Year - 1980) << 9) & 0xFE00);
+ cdate += (ushort)((creation.Month << 5) & 0x1E0);
+ cdate += (ushort)creation.Day;
+ ctime += (ushort)((creation.Hour << 11) & 0xF800);
+ ctime += (ushort)((creation.Minute << 5) & 0x7E0);
+ ctime += (ushort)(creation.Second / 2);
+ byte[] cdate_b = BitConverter.GetBytes(cdate);
+ byte[] ctime_b = BitConverter.GetBytes(ctime);
+
+ // Volume label
+ for (int i = 0; i < 11; i++)
+ rootDir[i] = 0x20;
+ tmp = Encoding.ASCII.GetBytes(volname.ToUpper());
+ Array.Copy(tmp, 0, rootDir, 0, tmp.Length >= 11 ? 11 : tmp.Length);
+ // Attributes
+ rootDir[11] = 8;
+ // Case information
+ rootDir[12] = 0;
+ // Creation time milliseconds. This is DR-DOS so don't use.
+ rootDir[13] = 0;
+ // Creation time
+ Array.Copy(ctime_b, 0, rootDir, 14, 2);
+ // Creation date
+ Array.Copy(cdate_b, 0, rootDir, 16, 2);
+ // Last access date. From Windows 95 so don't use.
+ rootDir[18] = 0;
+ rootDir[19] = 0;
+ // Extended attributes handler
+ rootDir[20] = 0;
+ rootDir[21] = 0;
+ // Last written time
+ Array.Copy(ctime_b, 0, rootDir, 22, 2);
+ // Last written date
+ Array.Copy(cdate_b, 0, rootDir, 24, 2);
+ // Starting cluster
+ rootDir[26] = 0;
+ rootDir[27] = 0;
+ // Size
+ rootDir[28] = 0;
+ rootDir[29] = 0;
+ rootDir[30] = 0;
+ rootDir[31] = 0;
+
+ fs.Write(rootDir, 0, rootDir.Length);
+
+ ushort remainingSectors = (ushort)(sectors - (fatSectors * 2 + rootDir.Length / 512 + 1));
+ tmp = new byte[512];
+ for (int i = 0; i < 512; i++)
+ tmp[i] = formatByte;
+ for (ushort i = 0; i < remainingSectors; i++)
+ fs.Write(tmp, 0, 512);
+
+ // Write checksum
+ byte[] checksum = BitConverter.GetBytes(xdfcopy_verify_checksum(fs, unk_sector_num));
+ fs.Seek(0x13C, SeekOrigin.Begin);
+ fs.Write(checksum, 0, 4);
+
+ fs.Close();
+ }
+
+ // XDFCOPY algorithm from OBattler's xdfsum.c
+
+ static void xdfcopy_read_file(FileStream fs, uint start, uint len, ref byte[] buf)
+ {
+ fs.Seek(start << 9, SeekOrigin.Begin);
+ buf = new byte[len << 9];
+ fs.Read(buf, 0, buf.Length);
+ }
+
+ static uint xdfcopy_checksum(ref byte[] buf, ushort len)
+ {
+ ushort loc2 = 0;
+ ushort checksum = 0xABDC;
+ ushort i = 0;
+
+ for (i = 0; i < len; i++)
+ {
+ loc2 = buf[(buf[i] * 0x13) % len];
+ checksum += (ushort)((loc2 >> 5) + ((loc2 & 0x1F) << 4));
+ }
+
+ return checksum;
+ }
+
+ static uint xdfcopy_verify_checksum(FileStream fs, uint unk_sector_num)
+ {
+ ushort dx;
+ short i;
+ uint checksum;
+ byte[] buf = null;
+ byte[] pbuf = new byte[512];
+
+ fs.Seek(0x80, SeekOrigin.Begin);
+ fs.Read(pbuf, 0, 0xB6);
+ pbuf[0xB6] = 0;
+ fs.Seek(0, SeekOrigin.Begin);
+
+ checksum = 0x12345678;
+ xdfcopy_read_file(fs, 1, 5, ref buf); // sub_72 probably just reads Y sectors from sector X onwards in the image
+ checksum = (checksum << 1) + xdfcopy_checksum(ref buf, 0x0A00);
+ xdfcopy_read_file(fs, (unk_sector_num << 1) + 1, 5, ref buf); // from sector 25 onwards for 3.5" 2HD
+ checksum = (checksum << 1) + xdfcopy_checksum(ref buf, 0x0A00);
+ xdfcopy_read_file(fs, (unk_sector_num << 1) + 6, 5, ref buf); // from sector 30 onwards for 3.5" 2HD
+ checksum = (checksum << 1) + xdfcopy_checksum(ref buf, 0x0A00);
+
+ for (i = 0; i < 0xB6; i++)
+ {
+ dx = (ushort)(((unk_sector_num << 1) + 0x15) + pbuf[i] + (checksum & 0x7ff));
+ xdfcopy_read_file(fs, dx, 1, ref buf);
+ checksum = (checksum << 1) + xdfcopy_checksum(ref buf, 0x0200);
+ }
+
+ return checksum;
+ }
+ }
+}
diff --git a/CreateXDF/Properties/AssemblyInfo.cs b/CreateXDF/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b07c683
--- /dev/null
+++ b/CreateXDF/Properties/AssemblyInfo.cs
@@ -0,0 +1,26 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("CreateXDF")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Claunia.com")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Copyright © Claunia.com")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]