using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
namespace CircuitBank2Patch
{
class Program
{
static void Main(string[] args)
{
string startPath ="";
string startfolderPath = "";
string startfileName = "";
string startfileExtension = "";
Console.OutputEncoding = System.Text.Encoding.GetEncoding(28591);
Console.Title = "Novation Circuit - Synth Bank Sysex Patch Dump";
string title = @"
_________ .__ .__ __
\_ ___ \|__|______ ____ __ __|__|/ |_
/ \ \/| \_ __ \_/ ___\| | \ \ __\
\ \___| || | \/\ \___| | / || |
\______ /__||__| \___ >____/|__||__|
\/ \/
--------------------------------------------
Novation Circuit Synth Bank SYSEX Patch Dump Utility v1.0
This program will dump all patches from a Cicruit Sysex (.syx) bank
to a subdirectory named BankName_Extracted located wherever your bank
file originates.
.----------------------------------------------------------------------.
| Notes: |
| This for Novation Circuit >>SYNTH bank .syx files ONLY<<. |
| The original bank file is NOT modified in any way. |
| If your bank contains patches with duplicate names, the file names |
| for those patches will have a number appended to the filename. |
| If the destination directory already contains patches, any new files |
| created will have a number appended to them. No files are deleted. |
`-----------------------------------------------------------------------'
Usage: Drag & Drop your Circuit Patch Bank .syx file onto this EXE.
----------------------------------------------------------------------
";
Console.WriteLine(title);
Console.WriteLine("Press any key to continue or press ESC to abort");
ConsoleKeyInfo info = Console.ReadKey();
if (info.Key == ConsoleKey.Escape)
{
Console.WriteLine("ESC pressed. Program Aborted, nothing will be processed.");
System.Threading.Thread.Sleep(5000);
System.Environment.Exit(0);
}
if (args.Length > 0 && File.Exists(args[0]))
{
startPath = args[0];
startfolderPath = Path.GetDirectoryName(startPath);
startfileName = Path.GetFileNameWithoutExtension(startPath);
startfileExtension = Path.GetExtension(startPath);
//Console.WriteLine("{0}, {1}, {2}, {3}", startfileName, startPath, startfileExtension, startfolderPath);
Console.WriteLine("\n" +
" Bank name: {0}\n" +
" Bank Directory: {1}\n" +
" Patches Destination Directory: {2}\n\n", startfileName, startfolderPath, startfolderPath + @"\" + startfileName + @"_Extracted\",
"-------------------------------------");
System.Threading.Thread.Sleep(5000);
}
if (args.Length <= 0)
{
Console.WriteLine("\nNo file detected: To use this program, Drag and Drop your Bank directly onto the exe. \n\n Exiting...");
System.Threading.Thread.Sleep(5000);
System.Environment.Exit(0);
}
string filePath = startfolderPath;
string outputPath = filePath + @"\" + startfileName + @"_Extracted\";
System.IO.Directory.CreateDirectory(outputPath);
FileStream filename;
filename = new FileStream(startPath, FileMode.Open);
var buffer = new byte[350];
//int bytesRead = 0; //replaced by _ discard
int filecount = 0;
int initialpatch = 0;
int renamecount = 1;
while ((_ = filename.Read(buffer, 0, buffer.Length)) > 0)
{
filecount++;
FileStream singlePatch;
singlePatch = new FileStream(outputPath + @"patch" + filecount + ".syx", FileMode.Append);
singlePatch.Write(buffer, 0, buffer.Length);
singlePatch.Close();
}
while (filecount > 0) //fix bytes for compatibility
{
FileStream renamePatch;
string fileforRename = outputPath + @"patch" + renamecount + ".syx";
renamePatch = new FileStream(fileforRename, FileMode.Open, FileAccess.ReadWrite);
renamePatch.Seek(0x07, SeekOrigin.Begin); //replace by 0x07 with value 0x00 for librarian compatibility ..in bank it increase by patch #
renamePatch.WriteByte(0x00);
renamePatch.Seek(0x06, SeekOrigin.Begin); //replace by 0x06 with value 0x00 for librarian compatibility ..in bank it increase by patch #
renamePatch.WriteByte(0x00);
renamePatch.Seek(0x09, SeekOrigin.Begin); //start byte location of patch name
var data = new byte[16]; //patch name can be up to 16 chars long
renamePatch.Read(data, 0, 16); //read all 16 bytes as new byte[]
string convertbytes = Encoding.UTF8.GetString(data, 0, data.Length).Trim(); //convert byte[] (data) containing patch name to string
string converted = convertbytes.Replace(" ", "_"); //replace whitespace with underscore for potential program, path, compatibility import issues
if (converted.Contains("Initial_Patch")) { converted += "_" + initialpatch; initialpatch++; } //handle initial patches seperately
//Console.WriteLine("{0}", converted.Trim());
renamePatch.Close();
//HAVE PATCH NAME NOW CHECK FOR FILE AND RENAME/MOVE TO PATCHNAME.SYX
//HANDLE OUTPUT HERE
//Console.WriteLine("{0}", GetUniqueFilePath(fullfilePath));
string fullfilePath = outputPath + converted.Trim() + ".syx";
string uniquePath = GetUniqueFilePath(fullfilePath);
File.Move(fileforRename, uniquePath); //output file with dupecheck and rename
string outFile = Path.GetFileNameWithoutExtension(uniquePath);
if (outFile.Contains(@"(")) { outFile = outFile + " - Possible Dupilcate"; }
Console.WriteLine(" Written: {0}", @".\" + startfileName + @"_Extracted\" + outFile );
System.Threading.Thread.Sleep(50);
renamecount++;
filecount--;
}
filename.Close();
Console.WriteLine("Dump completed. Press SPACE to open folder or any other key to Exit.");
ConsoleKeyInfo info2 = Console.ReadKey();
if (info2.Key == ConsoleKey.Spacebar)
{
Process.Start("explorer.exe", outputPath);
System.Environment.Exit(0);
}
}
public static string GetUniqueFilePath(string filePath)
{
if (File.Exists(filePath))
{
string folderPath = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileNameWithoutExtension(filePath);
string fileExtension = Path.GetExtension(filePath);
int number = 1;
Match regex = Regex.Match(fileName, @"^(.+) \((\d+)\)$");
if (regex.Success)
{
fileName = regex.Groups[1].Value;
number = int.Parse(regex.Groups[2].Value);
}
do
{
number++;
string newFileName = $"{fileName} ({number}){fileExtension}";
filePath = Path.Combine(folderPath, newFileName);
}
while (File.Exists(filePath));
}
return filePath;
}
}
}