private bool Analyze()
{
SetStatus("Analyzing...");
if (File.Exists(_basePath + @"\Resources\CodePatches.txt"))
{
// First we'll read the patches we are going to make
string[] actions = { "REMOVE", "PATCH", "TO", "IF", "ENDIF", "REMOVE_EN" };
string action = "";
bool doActions = true;
string bytesString = "";
string patchBytesString = "";
int removes = 0;
int successfulRemoves = 0;
int patches = 0;
int successfulPatches = 0;
// Load GCT into memory
byte[] gctBytes = File.ReadAllBytes(gctFile.Text);
foreach (string s in File.ReadLines(_basePath + @"\Resources\CodePatches.txt"))
{
string line = s.Trim().Substring(0, s.IndexOf('#') < 0 ? s.Length : s.IndexOf('#')); // Trim whitespace, ignore comments
if (actions.Contains(line))
{
// Handle one-liner statements. These don't affect action
if (line == "ENDIF")
{
doActions = true; // 'IF' statement is over, start doing actions again (if they were ever stopped)
continue;
}
else if (line == "REMOVE_EN" && doActions)
{
_remove_en = true;
continue;
}
action = line;
continue;
}
if (!doActions)
continue; // If we aren't doing actions just keep looping until the 'ENDIF'
// Handle multi-line statements
switch (action)
{
case "IF":
if (line == "") // Blank line means end of codes block, so we can handle the 'IF' statement now.
{
action = "";
if (bytesString.Length > 0)
{
byte[] bytes = Enumerable.Range(0, bytesString.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(bytesString.Substring(x, 2), 16)).ToArray();
if (SearchBytes(gctBytes, bytes) < 1)
doActions = false; // If code wasn't found, stop doing actions until the 'ENDIF' statement
}
bytesString = "";
}
else
bytesString += line.Replace(" ", "");
break;
case "REMOVE":
if (line == "")
{
action = "";
if (bytesString.Length > 0)
{
removes++;
byte[] bytes = Enumerable.Range(0, bytesString.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(bytesString.Substring(x, 2), 16)).ToArray();
int index = SearchBytes(gctBytes, bytes);
if (index >= 0)
{
IEnumerable<byte> before = gctBytes.Take(index);
IEnumerable<byte> after = gctBytes.Skip(index + bytes.Length);
gctBytes = before.Concat(after).ToArray();
successfulRemoves++;
}
bytesString = "";
}
}
else
bytesString += line.Replace(" ", "");
break;
case "PATCH":
if (line == "")
action = ""; // Patch is done after next 'TO'
else
patchBytesString += line.Replace(" ", "");
break;
case "TO":
if (line == "")
{
action = "";
if (bytesString.Length > 0 && patchBytesString.Length > 0)
{
patches++;
byte[] patchBytes = Enumerable.Range(0, patchBytesString.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(patchBytesString.Substring(x, 2), 16)).ToArray();
byte[] bytes = Enumerable.Range(0, bytesString.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(bytesString.Substring(x, 2), 16)).ToArray();
int index = SearchBytes(gctBytes, patchBytes);
if (index >= 0)
{
IEnumerable<byte> before = gctBytes.Take(index);
IEnumerable<byte> after = gctBytes.Skip(index + patchBytes.Length);
gctBytes = before.Concat(bytes.Concat(after)).ToArray();
successfulPatches++;
}
bytesString = "";
patchBytesString = "";
}
}
else
bytesString += line.Replace(" ", "");
break;
}
}
if (Environment.GetCommandLineArgs().Contains("--notify-gct-patch"))
MessageBox.Show("Removed codes: " + successfulRemoves + "/" + removes + "\nPatched Codes: " + successfulPatches + "/" + patches + "\nRemove '_en': " + _remove_en, "Notice", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
File.WriteAllBytes(_basePath + @"\Resources\temp.gct", gctBytes);
}
else
{
DialogResult result = MessageBox.Show("CodePatches.txt not found. Do you want to continue without GCT patching? The output ISO may not work without this.", "Notice", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.No)
buildWorker.CancelAsync();
}
if (buildWorker.CancellationPending)
return false;
return true;
}