Queue Feature and Version 1.2.0 Beta

The new queue feature allows several corruptions to be performed in
sequence on the same file. This allows corruption of multiple byte
ranges, among other things.
This commit is contained in:
Ryan Sammon
2013-06-13 01:25:49 -04:00
parent b56daf84a4
commit 971f9b40ed
8 changed files with 1775 additions and 593 deletions
+535
View File
@@ -0,0 +1,535 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Vinesauce_ROM_Corruptor
{
static class Corruption
{
public enum ByteCorruptionOptions
{
AddXToByte,
ShiftRightXBytes,
ReplaceByteXwithY
}
static private List<byte> NESCPUJamProtection_Avoid = new List<byte>() { 0x48, 0x08, 0x68, 0x28, 0x78, 0x00, 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x92, 0xB2, 0xD2, 0xF2 };
static private List<byte> NESCPUJamProtection_Protect_1 = new List<byte>() { 0x48, 0x08, 0x68, 0x28, 0x78, 0x40, 0x60, 0x00, 0x90, 0xB0, 0xF0, 0x30, 0xD0, 0x10, 0x50, 0x70, 0x4C, 0x6C, 0x20 };
static private List<byte> NESCPUJamProtection_Protect_2 = new List<byte>() { 0x90, 0xB0, 0xF0, 0x30, 0xD0, 0x10, 0x50, 0x70, 0x4C, 0x6C, 0x20 };
static private List<byte> NESCPUJamProtection_Protect_3 = new List<byte>() { 0x4C, 0x6C, 0x20 };
public static byte[] Run
(byte[] ROM, bool ByteCorruptionEnable, long StartByte, long EndByte, ByteCorruptionOptions ByteCorruptionOption,
uint EveryNthByte, int AddXtoByte, int ShiftRightXBytes, byte ReplaceByteXwithYByteX, byte ReplaceByteXwithYByteY, bool EnableNESCPUJamProtection,
bool TextReplacementEnable, bool TextUseByteCorruptionRange, string RawTextToReplace, string RawReplaceWith, string RawAnchorWords,
bool ColorReplacementEnable, bool ColorUseByteCorruptionRange, string RawColorsToReplace, string RawReplaceWithColors)
{
// Areas to not corrupt.
List<long[]> ProtectedRegions = new List<long[]>();
// Delimeter for text sections.
char[] Delimeter = new char[1] { '|' };
// Do text replacement if desired.
if (TextReplacementEnable)
{
// Translation dictionary.
Dictionary<char, byte> TranslationDictionary = new Dictionary<char, byte>();
// Read in the text and its replacement.
string[] TextToReplace = RawTextToReplace.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
string[] ReplaceWith = RawReplaceWith.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
// Make sure they have equal length.
if (TextToReplace.Length != ReplaceWith.Length)
{
MessageBox.Show("Number of text sections to replace does not match number of replacements.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
// Create relative offset arrays of the anchors.
string[] Anchors = RawAnchorWords.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
int[][] RelativeAnchors = new int[Anchors.Length][];
for (int i = 0; i < Anchors.Length; i++)
{
RelativeAnchors[i] = new int[Anchors[i].Length];
for (int j = 0; j < Anchors[i].Length; j++)
{
RelativeAnchors[i][j] = Anchors[i][j] - Anchors[i][0];
}
}
// Look for the anchors.
for (int i = 0; i < RelativeAnchors.Length; i++)
{
// Position in ROM.
long j = 0;
// Scan the entire ROM.
while (j < ROM.LongLength)
{
// If a match has been found.
bool Match = true;
// Look for the relative values.
for (int k = 0; k < RelativeAnchors[i].Length; k++)
{
// Make sure its in range.
if (j + k < ROM.LongLength)
{
// Ignore non-letter characters for matching purposes.
if (!Char.IsLetter(Anchors[i][k]))
{
continue;
}
// Check if the relative value doesn't match.
if ((ROM[j + k] - ROM[j]) != RelativeAnchors[i][k])
{
// It doesn't, break.
Match = false;
break;
}
}
else
{
// Out of range before matching.
Match = false;
break;
}
}
// If a match was found, update the dictionary.
if (Match)
{
int k = 0;
for (k = 0; k < Anchors[i].Length; k++)
{
if (!TranslationDictionary.ContainsKey(Anchors[i][k]))
{
TranslationDictionary.Add(Anchors[i][k], ROM[j + k]);
}
}
// Move ahead to the correct location in the ROM.
j = j + k + 1;
}
else
{
// Move ahead one byte.
j = j + 1;
}
}
}
// Calculate the offset to translate unknown text, assuming ASCII structure.
int ASCIIOffset = 0;
if (TranslationDictionary.Count > 0)
{
ASCIIOffset = TranslationDictionary.First().Value - TranslationDictionary.First().Key;
}
// Create arrays of the text to be replaced in ROM format.
byte[][] ByteTextToReplace = new byte[TextToReplace.Length][];
for (int i = 0; i < TextToReplace.Length; i++)
{
ByteTextToReplace[i] = new byte[TextToReplace[i].Length];
for (int j = 0; j < TextToReplace[i].Length; j++)
{
if (TranslationDictionary.ContainsKey(TextToReplace[i][j]))
{
ByteTextToReplace[i][j] = TranslationDictionary[TextToReplace[i][j]];
}
else
{
int ASCIITranslated = TextToReplace[i][j] + ASCIIOffset;
if (ASCIITranslated >= Byte.MinValue && ASCIITranslated <= Byte.MaxValue)
{
ByteTextToReplace[i][j] = (byte)(ASCIITranslated);
}
else
{
// Could not translate.
ByteTextToReplace[i][j] = (byte)(TextToReplace[i][j]);
}
}
}
}
// Create arrays of the replacement text in ROM format.
byte[][] ByteReplaceWith = new byte[ReplaceWith.Length][];
for (int i = 0; i < ReplaceWith.Length; i++)
{
ByteReplaceWith[i] = new byte[ReplaceWith[i].Length];
for (int j = 0; j < ReplaceWith[i].Length; j++)
{
if (TranslationDictionary.ContainsKey(ReplaceWith[i][j]))
{
ByteReplaceWith[i][j] = TranslationDictionary[ReplaceWith[i][j]];
}
else
{
int ASCIITranslated = ReplaceWith[i][j] + ASCIIOffset;
if (ASCIITranslated >= Byte.MinValue && ASCIITranslated <= Byte.MaxValue)
{
ByteReplaceWith[i][j] = (byte)(ASCIITranslated);
}
else
{
// Could not translate.
ByteReplaceWith[i][j] = (byte)(ReplaceWith[i][j]);
}
}
}
}
// Area of ROM to consider.
long TextReplacementStartByte = 0;
long TextReplacementEndByte = ROM.LongLength - 1;
// Change area if using the byte corruption range.
if (TextUseByteCorruptionRange)
{
TextReplacementStartByte = StartByte;
TextReplacementEndByte = EndByte;
}
// Look for the text to replace.
for (int i = 0; i < ByteTextToReplace.Length; i++)
{
// Position in ROM.
long j = TextReplacementStartByte;
// Scan the entire ROM.
while (j <= TextReplacementEndByte)
{
// If a match has been found.
bool Match = true;
// Look for the text.
for (int k = 0; k < ByteTextToReplace[i].Length; k++)
{
// Make sure its in range.
if (j + k <= TextReplacementEndByte)
{
// Ignore non-letter characters for matching purposes.
if (!Char.IsLetter(TextToReplace[i][k]))
{
continue;
}
// Check if the relative value doesn't match.
if (ROM[j + k] != ByteTextToReplace[i][k])
{
// It doesn't, break.
Match = false;
break;
}
}
else
{
// Out of range before matching.
Match = false;
break;
}
}
// If the entire string matched, replace it.
if (Match)
{
// If the area is protected.
bool Protected = false;
// Length of the replacement.
int k = ByteReplaceWith[i].Length - 1;
// Check if the area is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if ((j >= ProtectedRegion[0] && j <= ProtectedRegion[1]) || (j + k >= ProtectedRegion[0] && j + k <= ProtectedRegion[1]) || (j < ProtectedRegion[0] && j + k > ProtectedRegion[1]))
{
// Yes, its protected.
Protected = true;
break;
}
}
// If not protected, replace the text.
if (!Protected)
{
for (k = 0; k < ByteReplaceWith[i].Length; k++)
{
ROM[j + k] = ByteReplaceWith[i][k];
}
// Protect the inserted text.
ProtectedRegions.Add(new long[2] { j, j + k });
}
// Move ahead to the correct location in the ROM.
j = j + k + 1;
}
else
{
// Move ahead one byte.
j = j + 1;
}
}
}
}
// Do color replacement if desired.
if (ColorReplacementEnable)
{
// Read in the text and its replacement.
string[] ColorsToReplace = RawColorsToReplace.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
string[] ColorsReplaceWith = RawReplaceWithColors.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
// Make sure they have equal length.
if (ColorsToReplace.Length != ColorsReplaceWith.Length)
{
MessageBox.Show("Number of colors to replace does not match number of replacements.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
// Convert the strings.
byte[] ColorsToReplaceBytes = new byte[ColorsToReplace.Length];
byte[] ColorsReplaceWithBytes = new byte[ColorsReplaceWith.Length];
for (int i = 0; i < ColorsToReplace.Length; i++)
{
try
{
byte Converted = Convert.ToByte(ColorsToReplace[i], 16);
ColorsToReplaceBytes[i] = Converted;
}
catch
{
MessageBox.Show("Invalid color to replace.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}
for (int i = 0; i < ColorsReplaceWithBytes.Length; i++)
{
try
{
byte Converted = Convert.ToByte(ColorsReplaceWith[i], 16);
ColorsReplaceWithBytes[i] = Converted;
}
catch
{
MessageBox.Show("Invalid color replacement.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}
// Area of ROM to consider.
long ColorReplacementStartByte = 0;
long ColorReplacementEndByte = ROM.LongLength - 1;
// Change area if using the byte corruption range.
if (ColorUseByteCorruptionRange)
{
ColorReplacementStartByte = StartByte;
ColorReplacementEndByte = EndByte;
}
// Position in ROM.
long j = ColorReplacementStartByte;
// Scan the entire ROM.
while (j <= ColorReplacementEndByte)
{
// If a palette has been found.
bool Palette = true;
// Look for a palette.
for (int k = 0; k < 4; k++)
{
// Make sure its in range.
if (j + k <= ColorReplacementEndByte)
{
// Check if value exceeds the maximum valid color value.
if (ROM[j + k] > 0x3F)
{
// It does, break.
Palette = false;
break;
}
}
else
{
// Out of range before matching.
Palette = false;
break;
}
}
// If a possible palette was found, do color replacement.
if (Palette)
{
for (int i = 0; i < ColorsToReplaceBytes.Length; i++)
{
for (int k = 0; k < 4; k++)
{
if (ROM[j + k] == ColorsToReplaceBytes[i])
{
// If the byte is protected.
bool Protected = false;
// Check if the byte is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if (j + k >= ProtectedRegion[0] && j + k <= ProtectedRegion[1])
{
// Yes, its protected.
Protected = true;
break;
}
}
// If its not protected, do the replacement.
if (!Protected)
{
ROM[j + k] = ColorsReplaceWithBytes[i];
ProtectedRegions.Add(new long[2] { j + k, j + k });
}
}
}
}
// Move ahead to the correct location in the ROM.
j = j + 4;
}
else
{
// Move ahead one byte.
j = j + 1;
}
}
}
// Do byte corruption if desired.
if (ByteCorruptionEnable)
{
if (ByteCorruptionOption == ByteCorruptionOptions.AddXToByte && AddXtoByte != 0)
{
for (long i = StartByte + EveryNthByte; i <= EndByte; i = i + EveryNthByte)
{
// If the byte is protected.
bool Protected = false;
// Check if the byte is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if (i >= ProtectedRegion[0] && i <= ProtectedRegion[1])
{
// Yes, its protected.
Protected = true;
break;
}
}
// Do NES CPU jam protection if desired.
if (EnableNESCPUJamProtection)
{
if (!Protected && i >= 2)
{
if (NESCPUJamProtection_Avoid.Contains((byte)((ROM[i] + AddXtoByte) % (Byte.MaxValue + 1)))
|| NESCPUJamProtection_Protect_1.Contains(ROM[i])
|| NESCPUJamProtection_Protect_2.Contains(ROM[i - 1])
|| NESCPUJamProtection_Protect_3.Contains(ROM[i - 2]))
{
Protected = true;
}
}
}
// If the byte is not protected, corrupt it.
if (!Protected)
{
int NewValue = (ROM[i] + AddXtoByte) % (Byte.MaxValue + 1);
ROM[i] = (byte)NewValue;
}
}
}
else if (ByteCorruptionOption == ByteCorruptionOptions.ShiftRightXBytes && ShiftRightXBytes != 0)
{
for (long i = StartByte + EveryNthByte; i <= EndByte; i = i + EveryNthByte)
{
long j = i + ShiftRightXBytes;
if (j >= StartByte && j <= EndByte)
{
// If the byte is protected.
bool Protected = false;
// Check if the byte is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if (j >= ProtectedRegion[0] && j <= ProtectedRegion[1])
{
// Yes, its protected.
Protected = true;
break;
}
}
// Do NES CPU jam protection if desired.
if (EnableNESCPUJamProtection)
{
if (!Protected && j >= 2)
{
if (NESCPUJamProtection_Avoid.Contains(ROM[i])
|| NESCPUJamProtection_Protect_1.Contains(ROM[j])
|| NESCPUJamProtection_Protect_2.Contains(ROM[j - 1])
|| NESCPUJamProtection_Protect_3.Contains(ROM[j - 2]))
{
Protected = true;
}
}
}
// If the byte is not protected, corrupt it.
if (!Protected)
{
ROM[j] = ROM[i];
}
}
}
}
else if (ByteCorruptionOption == ByteCorruptionOptions.ReplaceByteXwithY && ReplaceByteXwithYByteX != ReplaceByteXwithYByteY)
{
for (long i = StartByte + EveryNthByte; i <= EndByte; i = i + EveryNthByte)
{
if (ROM[i] == ReplaceByteXwithYByteX)
{
// If the byte is protected.
bool Protected = false;
// Check if the byte is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if (i >= ProtectedRegion[0] && i <= ProtectedRegion[1])
{
// Yes, its protected.
Protected = true;
break;
}
}
// If the byte is not protected, corrupt it.
if (!Protected)
{
ROM[i] = ReplaceByteXwithYByteY;
}
}
}
}
}
return ROM;
}
}
}
+77 -5
View File
@@ -136,6 +136,11 @@ namespace Vinesauce_ROM_Corruptor
this.checkBox_HotkeyEnable = new System.Windows.Forms.CheckBox();
this.button_HotkeySet = new System.Windows.Forms.Button();
this.button_HotkeyHelp = new System.Windows.Forms.Button();
this.groupBox_Queue = new System.Windows.Forms.GroupBox();
this.button_QueueHelp = new System.Windows.Forms.Button();
this.checkBox_QueueEnable = new System.Windows.Forms.CheckBox();
this.button_QueueManage = new System.Windows.Forms.Button();
this.button_QueueAdd = new System.Windows.Forms.Button();
this.groupBox_FileSelection.SuspendLayout();
this.groupBox_EmulatorSelection.SuspendLayout();
this.groupBox_TextReplace.SuspendLayout();
@@ -144,6 +149,7 @@ namespace Vinesauce_ROM_Corruptor
this.groupBox_NESPalette.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox_NESPalette)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.groupBox_Queue.SuspendLayout();
this.SuspendLayout();
//
// button_RomDirectoryBrowse
@@ -247,7 +253,7 @@ namespace Vinesauce_ROM_Corruptor
this.listView_Files.Margin = new System.Windows.Forms.Padding(2);
this.listView_Files.MultiSelect = false;
this.listView_Files.Name = "listView_Files";
this.listView_Files.Size = new System.Drawing.Size(344, 188);
this.listView_Files.Size = new System.Drawing.Size(344, 183);
this.listView_Files.TabIndex = 47;
this.listView_Files.UseCompatibleStateImageBehavior = false;
this.listView_Files.View = System.Windows.Forms.View.Details;
@@ -256,7 +262,7 @@ namespace Vinesauce_ROM_Corruptor
// listViewC_fileName
//
this.listViewC_fileName.Text = "File Name";
this.listViewC_fileName.Width = 344;
this.listViewC_fileName.Width = 340;
//
// groupBox_EmulatorSelection
//
@@ -928,9 +934,9 @@ namespace Vinesauce_ROM_Corruptor
this.groupBox_ColorReplacement.Controls.Add(this.label_ColorsToReplace);
this.groupBox_ColorReplacement.Controls.Add(this.checkBox_ColorReplacementEnable);
this.groupBox_ColorReplacement.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.groupBox_ColorReplacement.Location = new System.Drawing.Point(10, 583);
this.groupBox_ColorReplacement.Location = new System.Drawing.Point(10, 580);
this.groupBox_ColorReplacement.Name = "groupBox_ColorReplacement";
this.groupBox_ColorReplacement.Size = new System.Drawing.Size(359, 169);
this.groupBox_ColorReplacement.Size = new System.Drawing.Size(359, 172);
this.groupBox_ColorReplacement.TabIndex = 16;
this.groupBox_ColorReplacement.TabStop = false;
this.groupBox_ColorReplacement.Text = "Color Replacement";
@@ -1091,7 +1097,7 @@ namespace Vinesauce_ROM_Corruptor
this.pictureBox1.Image = global::Vinesauce_ROM_Corruptor.Properties.Resources.Vinesauce_Mushroom;
this.pictureBox1.Location = new System.Drawing.Point(376, 11);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(358, 307);
this.pictureBox1.Size = new System.Drawing.Size(358, 233);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.pictureBox1.TabIndex = 39;
this.pictureBox1.TabStop = false;
@@ -1153,12 +1159,71 @@ namespace Vinesauce_ROM_Corruptor
this.button_HotkeyHelp.UseVisualStyleBackColor = true;
this.button_HotkeyHelp.Click += new System.EventHandler(this.button_HotkeyHelp_Click);
//
// groupBox_Queue
//
this.groupBox_Queue.Controls.Add(this.button_QueueHelp);
this.groupBox_Queue.Controls.Add(this.checkBox_QueueEnable);
this.groupBox_Queue.Controls.Add(this.button_QueueManage);
this.groupBox_Queue.Controls.Add(this.button_QueueAdd);
this.groupBox_Queue.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.groupBox_Queue.Location = new System.Drawing.Point(376, 250);
this.groupBox_Queue.Name = "groupBox_Queue";
this.groupBox_Queue.Size = new System.Drawing.Size(358, 68);
this.groupBox_Queue.TabIndex = 46;
this.groupBox_Queue.TabStop = false;
this.groupBox_Queue.Text = "Queue";
//
// button_QueueHelp
//
this.button_QueueHelp.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button_QueueHelp.Location = new System.Drawing.Point(236, 16);
this.button_QueueHelp.Name = "button_QueueHelp";
this.button_QueueHelp.Size = new System.Drawing.Size(26, 23);
this.button_QueueHelp.TabIndex = 45;
this.button_QueueHelp.Text = "?";
this.button_QueueHelp.UseVisualStyleBackColor = true;
this.button_QueueHelp.Click += new System.EventHandler(this.button_QueueHelp_Click);
//
// checkBox_QueueEnable
//
this.checkBox_QueueEnable.AutoSize = true;
this.checkBox_QueueEnable.Location = new System.Drawing.Point(6, 20);
this.checkBox_QueueEnable.Name = "checkBox_QueueEnable";
this.checkBox_QueueEnable.Size = new System.Drawing.Size(65, 17);
this.checkBox_QueueEnable.TabIndex = 2;
this.checkBox_QueueEnable.Text = "Enable";
this.checkBox_QueueEnable.UseVisualStyleBackColor = true;
this.checkBox_QueueEnable.CheckedChanged += new System.EventHandler(this.checkBox_QueueEnable_CheckedChanged);
//
// button_QueueManage
//
this.button_QueueManage.Enabled = false;
this.button_QueueManage.Location = new System.Drawing.Point(155, 16);
this.button_QueueManage.Name = "button_QueueManage";
this.button_QueueManage.Size = new System.Drawing.Size(75, 23);
this.button_QueueManage.TabIndex = 1;
this.button_QueueManage.Text = "Manage";
this.button_QueueManage.UseVisualStyleBackColor = true;
this.button_QueueManage.Click += new System.EventHandler(this.button_QueueManage_Click);
//
// button_QueueAdd
//
this.button_QueueAdd.Enabled = false;
this.button_QueueAdd.Location = new System.Drawing.Point(74, 16);
this.button_QueueAdd.Name = "button_QueueAdd";
this.button_QueueAdd.Size = new System.Drawing.Size(75, 23);
this.button_QueueAdd.TabIndex = 0;
this.button_QueueAdd.Text = "Add";
this.button_QueueAdd.UseVisualStyleBackColor = true;
this.button_QueueAdd.Click += new System.EventHandler(this.button_QueueAdd_Click);
//
// MainForm
//
this.AcceptButton = this.button_Run;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(742, 791);
this.Controls.Add(this.groupBox_Queue);
this.Controls.Add(this.button_HotkeyHelp);
this.Controls.Add(this.button_HotkeySet);
this.Controls.Add(this.checkBox_HotkeyEnable);
@@ -1193,6 +1258,8 @@ namespace Vinesauce_ROM_Corruptor
this.groupBox_NESPalette.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pictureBox_NESPalette)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.groupBox_Queue.ResumeLayout(false);
this.groupBox_Queue.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@@ -1287,6 +1354,11 @@ namespace Vinesauce_ROM_Corruptor
private System.Windows.Forms.Button button_HotkeyHelp;
private System.Windows.Forms.ListView listView_Files;
private System.Windows.Forms.ColumnHeader listViewC_fileName;
private System.Windows.Forms.GroupBox groupBox_Queue;
private System.Windows.Forms.Button button_QueueHelp;
private System.Windows.Forms.CheckBox checkBox_QueueEnable;
private System.Windows.Forms.Button button_QueueManage;
private System.Windows.Forms.Button button_QueueAdd;
}
}
+231 -588
View File
@@ -264,595 +264,31 @@ namespace Vinesauce_ROM_Corruptor
return;
}
// Read in all of the text boxes.
long StartByte;
try
if (checkBox_QueueEnable.Checked)
{
StartByte = Convert.ToInt64(textBox_StartByte.Text, 16);
}
catch
{
MessageBox.Show("Invalid start byte.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
long EndByte;
try
{
EndByte = Convert.ToInt64(textBox_EndByte.Text, 16);
}
catch
{
MessageBox.Show("Invalid end byte.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
uint EveryNthByte;
try
{
EveryNthByte = Convert.ToUInt32(textBox_EveryNBytes.Text);
}
catch
{
MessageBox.Show("Invalid byte corruption interval.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (EveryNthByte == 0)
{
MessageBox.Show("Invalid byte corruption interval.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
int AddXtoByte;
try
{
AddXtoByte = Convert.ToInt32(textBox_AddXToByte.Text);
}
catch
{
MessageBox.Show("Invalid byte addition value.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
int ShiftRightXBytes;
try
{
ShiftRightXBytes = Convert.ToInt32(textBox_ShiftRightXBytes.Text);
}
catch
{
MessageBox.Show("Invalid right shift value.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
byte ReplaceByteXwithYByteX;
try
{
ReplaceByteXwithYByteX = Convert.ToByte(textBox_ReplaceByteXwithYByteX.Text, 16);
}
catch
{
MessageBox.Show("Invalid byte to match.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
byte ReplaceByteXwithYByteY;
try
{
ReplaceByteXwithYByteY = Convert.ToByte(textBox_ReplaceByteXwithYByteY.Text, 16);
}
catch
{
MessageBox.Show("Invalid byte replacement.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// Limit the end byte.
if (EndByte > (ROM.LongLength - 1))
{
EndByte = ROM.LongLength - 1;
}
// Areas to not corrupt.
List<long[]> ProtectedRegions = new List<long[]>();
// Delimeter for text sections.
char[] Delimeter = new char[1] { '|' };
// Do text replacement if desired.
if (checkBox_TextReplacementEnable.Checked)
{
// Translation dictionary.
Dictionary<char, byte> TranslationDictionary = new Dictionary<char, byte>();
// Read in the text and its replacement.
string[] TextToReplace = textBox_TextToReplace.Text.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
string[] ReplaceWith = textBox_ReplaceWith.Text.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
// Make sure they have equal length.
if (TextToReplace.Length != ReplaceWith.Length)
QueueForm.CorruptionQueue.Add(new string[] { "Current", CorruptionSettingsToString() });
foreach (string[] Entry in QueueForm.CorruptionQueue)
{
MessageBox.Show("Number of text sections to replace does not match number of replacements.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// Create relative offset arrays of the anchors.
string[] Anchors = textBox_AnchorWords.Text.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
int[][] RelativeAnchors = new int[Anchors.Length][];
for (int i = 0; i < Anchors.Length; i++)
{
RelativeAnchors[i] = new int[Anchors[i].Length];
for (int j = 0; j < Anchors[i].Length; j++)
StringToCorruptionSettings(Entry[1]);
ROM = Corrupt(ROM);
if (ROM == null)
{
RelativeAnchors[i][j] = Anchors[i][j] - Anchors[i][0];
}
}
// Look for the anchors.
for (int i = 0; i < RelativeAnchors.Length; i++)
{
// Position in ROM.
long j = 0;
// Scan the entire ROM.
while (j < ROM.LongLength)
{
// If a match has been found.
bool Match = true;
// Look for the relative values.
for (int k = 0; k < RelativeAnchors[i].Length; k++)
{
// Make sure its in range.
if (j + k < ROM.LongLength)
{
// Ignore non-letter characters for matching purposes.
if (!Char.IsLetter(Anchors[i][k]))
{
continue;
}
// Check if the relative value doesn't match.
if ((ROM[j + k] - ROM[j]) != RelativeAnchors[i][k])
{
// It doesn't, break.
Match = false;
break;
}
}
else
{
// Out of range before matching.
Match = false;
break;
}
}
// If a match was found, update the dictionary.
if (Match)
{
int k = 0;
for (k = 0; k < Anchors[i].Length; k++)
{
if (!TranslationDictionary.ContainsKey(Anchors[i][k]))
{
TranslationDictionary.Add(Anchors[i][k], ROM[j + k]);
}
}
// Move ahead to the correct location in the ROM.
j = j + k + 1;
}
else
{
// Move ahead one byte.
j = j + 1;
}
}
}
// Calculate the offset to translate unknown text, assuming ASCII structure.
int ASCIIOffset = 0;
if (TranslationDictionary.Count > 0)
{
ASCIIOffset = TranslationDictionary.First().Value - TranslationDictionary.First().Key;
}
// Create arrays of the text to be replaced in ROM format.
byte[][] ByteTextToReplace = new byte[TextToReplace.Length][];
for (int i = 0; i < TextToReplace.Length; i++)
{
ByteTextToReplace[i] = new byte[TextToReplace[i].Length];
for (int j = 0; j < TextToReplace[i].Length; j++)
{
if (TranslationDictionary.ContainsKey(TextToReplace[i][j]))
{
ByteTextToReplace[i][j] = TranslationDictionary[TextToReplace[i][j]];
}
else
{
int ASCIITranslated = TextToReplace[i][j] + ASCIIOffset;
if (ASCIITranslated >= Byte.MinValue && ASCIITranslated <= Byte.MaxValue)
{
ByteTextToReplace[i][j] = (byte)(ASCIITranslated);
}
else
{
// Could not translate.
ByteTextToReplace[i][j] = (byte)(TextToReplace[i][j]);
}
}
}
}
// Create arrays of the replacement text in ROM format.
byte[][] ByteReplaceWith = new byte[ReplaceWith.Length][];
for (int i = 0; i < ReplaceWith.Length; i++)
{
ByteReplaceWith[i] = new byte[ReplaceWith[i].Length];
for (int j = 0; j < ReplaceWith[i].Length; j++)
{
if (TranslationDictionary.ContainsKey(ReplaceWith[i][j]))
{
ByteReplaceWith[i][j] = TranslationDictionary[ReplaceWith[i][j]];
}
else
{
int ASCIITranslated = ReplaceWith[i][j] + ASCIIOffset;
if (ASCIITranslated >= Byte.MinValue && ASCIITranslated <= Byte.MaxValue)
{
ByteReplaceWith[i][j] = (byte)(ASCIITranslated);
}
else
{
// Could not translate.
ByteReplaceWith[i][j] = (byte)(ReplaceWith[i][j]);
}
}
}
}
// Area of ROM to consider.
long TextReplacementStartByte = 0;
long TextReplacementEndByte = ROM.LongLength - 1;
// Change area if using the byte corruption range.
if (checkBox_TextUseByteCorruptionRange.Checked)
{
TextReplacementStartByte = StartByte;
TextReplacementEndByte = EndByte;
}
// Look for the text to replace.
for (int i = 0; i < ByteTextToReplace.Length; i++)
{
// Position in ROM.
long j = TextReplacementStartByte;
// Scan the entire ROM.
while (j <= TextReplacementEndByte)
{
// If a match has been found.
bool Match = true;
// Look for the text.
for (int k = 0; k < ByteTextToReplace[i].Length; k++)
{
// Make sure its in range.
if (j + k <= TextReplacementEndByte)
{
// Ignore non-letter characters for matching purposes.
if (!Char.IsLetter(TextToReplace[i][k]))
{
continue;
}
// Check if the relative value doesn't match.
if (ROM[j + k] != ByteTextToReplace[i][k])
{
// It doesn't, break.
Match = false;
break;
}
}
else
{
// Out of range before matching.
Match = false;
break;
}
}
// If the entire string matched, replace it.
if (Match)
{
// If the area is protected.
bool Protected = false;
// Length of the replacement.
int k = ByteReplaceWith[i].Length - 1;
// Check if the area is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if ((j >= ProtectedRegion[0] && j <= ProtectedRegion[1]) || (j + k >= ProtectedRegion[0] && j + k <= ProtectedRegion[1]) || (j < ProtectedRegion[0] && j + k > ProtectedRegion[1]))
{
// Yes, its protected.
Protected = true;
break;
}
}
// If not protected, replace the text.
if (!Protected)
{
for (k = 0; k < ByteReplaceWith[i].Length; k++)
{
ROM[j + k] = ByteReplaceWith[i][k];
}
// Protect the inserted text.
ProtectedRegions.Add(new long[2] { j, j + k });
}
// Move ahead to the correct location in the ROM.
j = j + k + 1;
}
else
{
// Move ahead one byte.
j = j + 1;
}
}
}
}
// Do color replacement if desired.
if (checkBox_ColorReplacementEnable.Checked)
{
// Read in the text and its replacement.
string[] ColorsToReplace = textBox_ColorsToReplace.Text.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
string[] ColorsReplaceWith = textBox_ReplaceWithColors.Text.Split(Delimeter, StringSplitOptions.RemoveEmptyEntries);
// Make sure they have equal length.
if (ColorsToReplace.Length != ColorsReplaceWith.Length)
{
MessageBox.Show("Number of colors to replace does not match number of replacements.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// Convert the strings.
byte[] ColorsToReplaceBytes = new byte[ColorsToReplace.Length];
byte[] ColorsReplaceWithBytes = new byte[ColorsReplaceWith.Length];
for (int i = 0; i < ColorsToReplace.Length; i++)
{
try
{
byte Converted = Convert.ToByte(ColorsToReplace[i], 16);
ColorsToReplaceBytes[i] = Converted;
}
catch
{
MessageBox.Show("Invalid color to replace.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBox.Show("Previous error encountered corrupting using \"" + Entry[0] + "\" corruption settings in queue.",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
StringToCorruptionSettings(Enumerable.Last(QueueForm.CorruptionQueue)[1]);
QueueForm.CorruptionQueue.RemoveAt(QueueForm.CorruptionQueue.Count - 1);
return;
}
}
for (int i = 0; i < ColorsReplaceWithBytes.Length; i++)
{
try
{
byte Converted = Convert.ToByte(ColorsReplaceWith[i], 16);
ColorsReplaceWithBytes[i] = Converted;
}
catch
{
MessageBox.Show("Invalid color replacement.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
// Area of ROM to consider.
long ColorReplacementStartByte = 0;
long ColorReplacementEndByte = ROM.LongLength - 1;
// Change area if using the byte corruption range.
if (checkBox_ColorUseByteCorruptionRange.Checked)
{
ColorReplacementStartByte = StartByte;
ColorReplacementEndByte = EndByte;
}
// Position in ROM.
long j = ColorReplacementStartByte;
// Scan the entire ROM.
while (j <= ColorReplacementEndByte)
{
// If a palette has been found.
bool Palette = true;
// Look for a palette.
for (int k = 0; k < 4; k++)
{
// Make sure its in range.
if (j + k <= ColorReplacementEndByte)
{
// Check if value exceeds the maximum valid color value.
if (ROM[j + k] > 0x3F)
{
// It does, break.
Palette = false;
break;
}
}
else
{
// Out of range before matching.
Palette = false;
break;
}
}
// If a possible palette was found, do color replacement.
if (Palette)
{
for (int i = 0; i < ColorsToReplaceBytes.Length; i++)
{
for (int k = 0; k < 4; k++)
{
if (ROM[j + k] == ColorsToReplaceBytes[i])
{
// If the byte is protected.
bool Protected = false;
// Check if the byte is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if (j + k >= ProtectedRegion[0] && j + k <= ProtectedRegion[1])
{
// Yes, its protected.
Protected = true;
break;
}
}
// If its not protected, do the replacement.
if (!Protected)
{
ROM[j + k] = ColorsReplaceWithBytes[i];
ProtectedRegions.Add(new long[2] { j + k, j + k });
}
}
}
}
// Move ahead to the correct location in the ROM.
j = j + 4;
}
else
{
// Move ahead one byte.
j = j + 1;
}
}
StringToCorruptionSettings(Enumerable.Last(QueueForm.CorruptionQueue)[1]);
QueueForm.CorruptionQueue.RemoveAt(QueueForm.CorruptionQueue.Count - 1);
}
// Do byte corruption if desired.
if (checkBox_ByteCorruptionEnable.Checked)
else
{
if (radioButton_AddXToByte.Checked && AddXtoByte != 0)
ROM = Corrupt(ROM);
if (ROM == null)
{
for (long i = StartByte + EveryNthByte; i <= EndByte; i = i + EveryNthByte)
{
// If the byte is protected.
bool Protected = false;
// Check if the byte is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if (i >= ProtectedRegion[0] && i <= ProtectedRegion[1])
{
// Yes, its protected.
Protected = true;
break;
}
}
// Do NES CPU jam protection if desired.
if (checkBox_EnableNESCPUJamProtection.Checked)
{
if (!Protected && i >= 2)
{
if (NESCPUJamProtection_Avoid.Contains((byte)((ROM[i] + AddXtoByte) % (Byte.MaxValue + 1)))
|| NESCPUJamProtection_Protect_1.Contains(ROM[i])
|| NESCPUJamProtection_Protect_2.Contains(ROM[i - 1])
|| NESCPUJamProtection_Protect_3.Contains(ROM[i - 2]))
{
Protected = true;
}
}
}
// If the byte is not protected, corrupt it.
if (!Protected)
{
int NewValue = (ROM[i] + AddXtoByte) % (Byte.MaxValue + 1);
ROM[i] = (byte)NewValue;
}
}
}
else if (radioButton_ShiftRightXBytes.Checked && ShiftRightXBytes != 0)
{
for (long i = StartByte + EveryNthByte; i <= EndByte; i = i + EveryNthByte)
{
long j = i + ShiftRightXBytes;
if (j >= StartByte && j <= EndByte)
{
// If the byte is protected.
bool Protected = false;
// Check if the byte is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if (j >= ProtectedRegion[0] && j <= ProtectedRegion[1])
{
// Yes, its protected.
Protected = true;
break;
}
}
// Do NES CPU jam protection if desired.
if (checkBox_EnableNESCPUJamProtection.Checked)
{
if (!Protected && j >= 2)
{
if (NESCPUJamProtection_Avoid.Contains(ROM[i])
|| NESCPUJamProtection_Protect_1.Contains(ROM[j])
|| NESCPUJamProtection_Protect_2.Contains(ROM[j - 1])
|| NESCPUJamProtection_Protect_3.Contains(ROM[j - 2]))
{
Protected = true;
}
}
}
// If the byte is not protected, corrupt it.
if (!Protected)
{
ROM[j] = ROM[i];
}
}
}
}
else if (radioButton_ReplaceByteXwithY.Checked && ReplaceByteXwithYByteX != ReplaceByteXwithYByteY)
{
for (long i = StartByte + EveryNthByte; i <= EndByte; i = i + EveryNthByte)
{
if (ROM[i] == ReplaceByteXwithYByteX)
{
// If the byte is protected.
bool Protected = false;
// Check if the byte is protected.
foreach (long[] ProtectedRegion in ProtectedRegions)
{
if (i >= ProtectedRegion[0] && i <= ProtectedRegion[1])
{
// Yes, its protected.
Protected = true;
break;
}
}
// If the byte is not protected, corrupt it.
if (!Protected)
{
ROM[i] = ReplaceByteXwithYByteY;
}
}
}
return;
}
}
@@ -1365,7 +801,7 @@ namespace Vinesauce_ROM_Corruptor
UriBuilder ub = new UriBuilder();
ub.Host = "tinyurl.com";
ub.Path = "/api-create.php";
ub.Query = "url=" + SettingsToString();
ub.Query = "url=" + FileSettingsToString() + CorruptionSettingsToString() + QueueSettingsToString();
response = wc.DownloadString(ub.Uri);
}
catch
@@ -1424,7 +860,7 @@ namespace Vinesauce_ROM_Corruptor
StreamWriter sw = new StreamWriter(fDialog.FileName);
// Write the settings to the file.
sw.Write(SettingsToString());
sw.Write(FileSettingsToString() + CorruptionSettingsToString() + QueueSettingsToString());
// Close the file.
sw.Close();
@@ -1476,7 +912,9 @@ namespace Vinesauce_ROM_Corruptor
text = Uri.UnescapeDataString(text);
// Load the settings.
StringToSettings(text);
StringToFileSettings(text);
StringToCorruptionSettings(text);
StringToQueueSettings(text);
EnforceAutoEnd();
}
catch
@@ -1499,7 +937,10 @@ namespace Vinesauce_ROM_Corruptor
try
{
// Load the settings from the file.
StringToSettings(File.ReadAllText(fDialog.FileName));
string text = File.ReadAllText(fDialog.FileName);
StringToFileSettings(text);
StringToCorruptionSettings(text);
StringToQueueSettings(text);
EnforceAutoEnd();
}
catch
@@ -1534,7 +975,7 @@ namespace Vinesauce_ROM_Corruptor
"Replace Byte X with Y Help");
}
private string SettingsToString()
private string FileSettingsToString()
{
StringBuilder sb = new StringBuilder();
@@ -1544,6 +985,13 @@ namespace Vinesauce_ROM_Corruptor
sb.AppendLine("ROM.FileLength=" + String.Format("{0:X}", SelectedROM.FileLength));
sb.AppendLine("ROM.Hash=" + SelectedROM.HashStringBase64);
return sb.ToString();
}
private string CorruptionSettingsToString()
{
StringBuilder sb = new StringBuilder();
// General settings.
sb.AppendLine("checkBox_EnableNESCPUJamProtection.Checked=" + checkBox_EnableNESCPUJamProtection.Checked.ToString());
@@ -1578,9 +1026,26 @@ namespace Vinesauce_ROM_Corruptor
return sb.ToString();
}
private void StringToSettings(string text)
private string QueueSettingsToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("checkBox_QueueEnable.Checked=" + checkBox_QueueEnable.Checked.ToString());
foreach (string[] Entry in QueueForm.CorruptionQueue)
{
sb.AppendLine("Queue_Entry_Start");
sb.AppendLine("Identifier=" + Entry[0]);
sb.Append(Entry[1]);
sb.AppendLine("Queue_Entry_End");
}
return sb.ToString();
}
private void StringToFileSettings(string text)
{
// ROM to corrupt.
string TargetROMFileName = "";
long TargetROMFileLength = 0;
@@ -1631,10 +1096,13 @@ namespace Vinesauce_ROM_Corruptor
"Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
public void StringToCorruptionSettings(string text)
{
// Enable checkboxes.
// Text replacement.
m = Regex.Match(text, "(?<=checkBox_TextReplacementEnable\\.Checked=).*?(?=\r)");
Match m = Regex.Match(text, "(?<=checkBox_TextReplacementEnable\\.Checked=).*?(?=\r)");
if (m.Success)
{
if (m.Groups[0].Value == "True")
@@ -1854,6 +1322,38 @@ namespace Vinesauce_ROM_Corruptor
}
}
public void StringToQueueSettings(string text)
{
Match m = Regex.Match(text, "(?<=checkBox_QueueEnable\\.Checked=).*?(?=\r)");
if (m.Success)
{
if (m.Groups[0].Value == "True")
{
checkBox_QueueEnable.Checked = true;
}
else
{
checkBox_QueueEnable.Checked = false;
}
}
QueueForm.CorruptionQueue.Clear();
MatchCollection entries = Regex.Matches(text, "(?<=Queue_Entry_Start\r\n).*?(?=Queue_Entry_End\r\n)", RegexOptions.Singleline);
foreach (Match entry in entries)
{
if (entry.Success)
{
string id = "";
m = Regex.Match(entry.Groups[0].Value, "(?<=Identifier=).*?(?=\r)");
if (m.Success)
{
id = m.Groups[0].Value;
}
QueueForm.CorruptionQueue.Add(new string[] { id, entry.Groups[0].Value });
}
}
}
private void button_UseTinyURLHelp_Click(object sender, EventArgs e)
{
button_Run.Focus();
@@ -1967,7 +1467,7 @@ namespace Vinesauce_ROM_Corruptor
listView_Files.Focus();
if (item.Index >= 4)
{
listView_Files.TopItem = listView_Files.Items[item.Index-4];
listView_Files.TopItem = listView_Files.Items[item.Index - 4];
}
item.Selected = true;
break;
@@ -2006,5 +1506,148 @@ namespace Vinesauce_ROM_Corruptor
EnforceAutoEnd();
}
}
private void button_QueueHelp_Click(object sender, EventArgs e)
{
button_Run.Focus();
MessageBox.Show("Checking this box enables queue mode, which allows for multiple corruptions to be executed on the file sequentially. This allows corruption of multiple byte ranges among other things. "
+ "When the \"Add\" button is clicked, the current corruption settings will be saved to the queue and you will be asked for an identifier for these settings. "
+ "When the \"Manage\" button is clicked a new window will appear which will allow you to move corruption settings up and down in the queue, remove corruption settings from the queue, "
+ "or overwrite the current settings with a set of queued settings. The corruption settings at the top of the queue list will be executed first, and the current corruption settings will be executed last. "
+ "For example, one item in the queue means the ROM is corrupted twice, first using the queued settings and then using the current settings."
, "Queue Help");
}
private void button_QueueAdd_Click(object sender, EventArgs e)
{
// Get an identifier of the corruption settings from the user.
string name = Interaction.InputBox("Please enter a brief description of these corruption settings below.", "Add to Queue", "");
if (name == "")
{
MessageBox.Show("No description entered, addition to queue aborted.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
QueueForm.CorruptionQueue.Add(new string[] { name, CorruptionSettingsToString() });
}
private void checkBox_QueueEnable_CheckedChanged(object sender, EventArgs e)
{
button_QueueAdd.Enabled = checkBox_QueueEnable.Checked;
button_QueueManage.Enabled = checkBox_QueueEnable.Checked;
}
private void button_QueueManage_Click(object sender, EventArgs e)
{
QueueForm form = new QueueForm(this);
form.StartPosition = FormStartPosition.CenterParent;
form.ShowDialog();
while (form.Visible == true)
this.Enabled = false;
}
private byte[] Corrupt(byte[] ROM)
{
// Read in all of the text boxes.
long StartByte;
try
{
StartByte = Convert.ToInt64(textBox_StartByte.Text, 16);
}
catch
{
MessageBox.Show("Invalid start byte.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
long EndByte;
try
{
EndByte = Convert.ToInt64(textBox_EndByte.Text, 16);
}
catch
{
MessageBox.Show("Invalid end byte.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
uint EveryNthByte;
try
{
EveryNthByte = Convert.ToUInt32(textBox_EveryNBytes.Text);
}
catch
{
MessageBox.Show("Invalid byte corruption interval.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
if (EveryNthByte == 0)
{
MessageBox.Show("Invalid byte corruption interval.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
int AddXtoByte;
try
{
AddXtoByte = Convert.ToInt32(textBox_AddXToByte.Text);
}
catch
{
MessageBox.Show("Invalid byte addition value.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
int ShiftRightXBytes;
try
{
ShiftRightXBytes = Convert.ToInt32(textBox_ShiftRightXBytes.Text);
}
catch
{
MessageBox.Show("Invalid right shift value.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
byte ReplaceByteXwithYByteX;
try
{
ReplaceByteXwithYByteX = Convert.ToByte(textBox_ReplaceByteXwithYByteX.Text, 16);
}
catch
{
MessageBox.Show("Invalid byte to match.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
byte ReplaceByteXwithYByteY;
try
{
ReplaceByteXwithYByteY = Convert.ToByte(textBox_ReplaceByteXwithYByteY.Text, 16);
}
catch
{
MessageBox.Show("Invalid byte replacement.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
// Limit the end byte.
if (EndByte > (ROM.LongLength - 1))
{
EndByte = ROM.LongLength - 1;
}
// Set byte corruption option.
Corruption.ByteCorruptionOptions ByteCorruptionOption = Corruption.ByteCorruptionOptions.AddXToByte;
if (radioButton_ShiftRightXBytes.Checked) ByteCorruptionOption = Corruption.ByteCorruptionOptions.ShiftRightXBytes;
else if (radioButton_ReplaceByteXwithY.Checked) ByteCorruptionOption = Corruption.ByteCorruptionOptions.ReplaceByteXwithY;
// Corrupt.
ROM = Corruption.Run(ROM, checkBox_ByteCorruptionEnable.Checked, StartByte, EndByte, ByteCorruptionOption,
EveryNthByte, AddXtoByte, ShiftRightXBytes, ReplaceByteXwithYByteX, ReplaceByteXwithYByteY, checkBox_EnableNESCPUJamProtection.Checked,
checkBox_TextReplacementEnable.Checked, checkBox_TextUseByteCorruptionRange.Checked, textBox_TextToReplace.Text, textBox_ReplaceWith.Text, textBox_AnchorWords.Text,
checkBox_ColorReplacementEnable.Checked, checkBox_ColorUseByteCorruptionRange.Checked, textBox_ColorsToReplace.Text, textBox_ReplaceWithColors.Text);
return ROM;
}
}
}
+147
View File
@@ -0,0 +1,147 @@
namespace Vinesauce_ROM_Corruptor
{
partial class QueueForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(QueueForm));
this.listView_Queue = new System.Windows.Forms.ListView();
this.listViewC_Identifier = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.button_Up = new System.Windows.Forms.Button();
this.button_Down = new System.Windows.Forms.Button();
this.button_Remove = new System.Windows.Forms.Button();
this.button_Overwrite = new System.Windows.Forms.Button();
this.button_Close = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// listView_Queue
//
this.listView_Queue.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.listViewC_Identifier});
this.listView_Queue.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.listView_Queue.FullRowSelect = true;
this.listView_Queue.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.listView_Queue.HideSelection = false;
this.listView_Queue.Location = new System.Drawing.Point(12, 74);
this.listView_Queue.Margin = new System.Windows.Forms.Padding(2);
this.listView_Queue.MultiSelect = false;
this.listView_Queue.Name = "listView_Queue";
this.listView_Queue.Size = new System.Drawing.Size(258, 183);
this.listView_Queue.TabIndex = 48;
this.listView_Queue.UseCompatibleStateImageBehavior = false;
this.listView_Queue.View = System.Windows.Forms.View.Details;
//
// listViewC_Identifier
//
this.listViewC_Identifier.Text = "Identifier";
this.listViewC_Identifier.Width = 254;
//
// button_Up
//
this.button_Up.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button_Up.Location = new System.Drawing.Point(12, 42);
this.button_Up.Name = "button_Up";
this.button_Up.Size = new System.Drawing.Size(75, 23);
this.button_Up.TabIndex = 49;
this.button_Up.Text = "Move Up";
this.button_Up.UseVisualStyleBackColor = true;
this.button_Up.Click += new System.EventHandler(this.button_Up_Click);
//
// button_Down
//
this.button_Down.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button_Down.Location = new System.Drawing.Point(93, 42);
this.button_Down.Name = "button_Down";
this.button_Down.Size = new System.Drawing.Size(96, 23);
this.button_Down.TabIndex = 50;
this.button_Down.Text = "Move Down";
this.button_Down.UseVisualStyleBackColor = true;
this.button_Down.Click += new System.EventHandler(this.button_Down_Click);
//
// button_Remove
//
this.button_Remove.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button_Remove.Location = new System.Drawing.Point(195, 42);
this.button_Remove.Name = "button_Remove";
this.button_Remove.Size = new System.Drawing.Size(75, 23);
this.button_Remove.TabIndex = 51;
this.button_Remove.Text = "Remove";
this.button_Remove.UseVisualStyleBackColor = true;
this.button_Remove.Click += new System.EventHandler(this.button_Remove_Click);
//
// button_Overwrite
//
this.button_Overwrite.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button_Overwrite.Location = new System.Drawing.Point(12, 12);
this.button_Overwrite.Name = "button_Overwrite";
this.button_Overwrite.Size = new System.Drawing.Size(224, 23);
this.button_Overwrite.TabIndex = 52;
this.button_Overwrite.Text = "Load and Overwrite Current Settings";
this.button_Overwrite.UseVisualStyleBackColor = true;
this.button_Overwrite.Click += new System.EventHandler(this.button_Overwrite_Click);
//
// button_Close
//
this.button_Close.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button_Close.Location = new System.Drawing.Point(12, 262);
this.button_Close.Name = "button_Close";
this.button_Close.Size = new System.Drawing.Size(75, 23);
this.button_Close.TabIndex = 53;
this.button_Close.Text = "Close";
this.button_Close.UseVisualStyleBackColor = true;
this.button_Close.Click += new System.EventHandler(this.button_Close_Click);
//
// QueueForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(282, 290);
this.Controls.Add(this.button_Close);
this.Controls.Add(this.button_Overwrite);
this.Controls.Add(this.button_Remove);
this.Controls.Add(this.button_Down);
this.Controls.Add(this.button_Up);
this.Controls.Add(this.listView_Queue);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "QueueForm";
this.Text = "Manage Queue";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ListView listView_Queue;
private System.Windows.Forms.ColumnHeader listViewC_Identifier;
private System.Windows.Forms.Button button_Up;
private System.Windows.Forms.Button button_Down;
private System.Windows.Forms.Button button_Remove;
private System.Windows.Forms.Button button_Overwrite;
private System.Windows.Forms.Button button_Close;
}
}
+116
View File
@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Vinesauce_ROM_Corruptor
{
public partial class QueueForm : Form
{
static public List<string[]> CorruptionQueue = new List<string[]>();
public MainForm MainWindow;
public QueueForm(MainForm MainWindow)
{
InitializeComponent();
this.MainWindow = MainWindow;
PopulateQueueList();
}
private void button_Close_Click(object sender, EventArgs e)
{
this.Close();
}
private void button_Up_Click(object sender, EventArgs e)
{
if (listView_Queue.SelectedIndices.Count == 0)
{
return;
}
int index = listView_Queue.SelectedIndices[0];
if (index == 0)
{
return;
}
string[] temp = CorruptionQueue[index - 1];
CorruptionQueue[index - 1] = CorruptionQueue[index];
CorruptionQueue[index] = temp;
PopulateQueueList();
listView_Queue.Items[index - 1].Selected = true;
}
private void button_Down_Click(object sender, EventArgs e)
{
if (listView_Queue.SelectedIndices.Count == 0)
{
return;
}
int index = listView_Queue.SelectedIndices[0];
if (index == listView_Queue.Items.Count - 1)
{
return;
}
string[] temp = CorruptionQueue[index + 1];
CorruptionQueue[index + 1] = CorruptionQueue[index];
CorruptionQueue[index] = temp;
PopulateQueueList();
listView_Queue.Items[index + 1].Selected = true;
}
private void PopulateQueueList()
{
listView_Queue.Items.Clear();
listView_Queue.Focus();
foreach (string[] Entry in CorruptionQueue)
{
listView_Queue.Items.Add(new ListViewItem(new string[] { Entry[0] }));
}
}
private void button_Remove_Click(object sender, EventArgs e)
{
if (listView_Queue.SelectedIndices.Count == 0)
{
return;
}
int index = listView_Queue.SelectedIndices[0];
CorruptionQueue.RemoveAt(index);
PopulateQueueList();
}
private void button_Overwrite_Click(object sender, EventArgs e)
{
if (listView_Queue.SelectedIndices.Count == 0)
{
return;
}
if (MessageBox.Show("The current corruption settings will be overwritten, are you sure you wish to do this?",
"Confirm Overwrite", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
int index = listView_Queue.SelectedIndices[0];
string[] entry = CorruptionQueue[index];
MainWindow.StringToCorruptionSettings(entry[1]);
this.Close();
}
}
}
}
+659
View File
@@ -0,0 +1,659 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAQAEBAAAAAAIABoBAAARgAAACAgAAAAACAAqBAAAK4EAAAwMAAAAAAgAKglAABWFQAAQEAAAAAA
IAAoQgAA/joAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD////b////////
/////////v7+//39/f/n5+f/1tbW/9fX1//y8vL//v7+//7+/v/////////////////////b////2///
//////////////z8/P/g4OD/7+/v//r6+v/29vb/19fX/8bGxv/+/v7/////////////////////2///
/9v//////////////////////v7+//Hx8f/Nzc3/6urq//7+/v/Y2Nj//v7+////////////////////
/9v////b//////////////////////7+/v/U2sD//v79/9bbwf/9/fr/2NjX//7+/v//////////////
///////b////2//////////////////////+/v7/vtC0//z+/P/A0rj/+fz5/9jY1//+/v7/////////
////////////2////9v//v///v7+//3+/f/8+/r/7Ovl/9fZzf/Q0Mb/0NLF/93e1f/j4+H//f38//7+
/v///////////////9v+/v7b9/f3/+Df4f/d3d3/n6lN/4aWCf+InQX/i58D/4ygBP+HmQX/gZEV/8TG
u//IyMf/2dnZ//39/f/+/v7b5ejW2+Xm3P/6+/L/yteP/4umB/+MqBD/vMx1/7O/bv/I04r/lbAo/4mm
Bf+wxWH/9ffq/+np5f+tsp///v7+28TUj9uMqyb/i6wp/4eqGv+KrCT/4+rG/+boz/9/iQ7/xcmR//T3
6/+ZuEX/hKsp/4atNP+MsUT/haJL//7+/tvY5MHbha8//4OvPf+Brz3/s8yG//38+v+ztl3/mZ4i/56k
Lf/09Of/0uK+/3yvQ/9+sEb/f7JM/5m0ef/+/v7b9vrx24a2Yf+Atlr/f7dd/7/ar//t7tj/u7lY/+Hh
t/++vV//29mp/+Lv3f93tV3/drVe/3a4Zf+8z7T///7+2/79/dvO5cj/sdat/4jBgv+czp7/5+bC/+np
x//9/v3/8/Pf/9/crf/C4cX/bLxz/5/RoP/H3cb/8vTy//7+/tv//v7b/v7+//7+/v/y+vT/jtGo/7/k
y//7/v3//v7+//3+/f/b8uP/ds2g/6vewP/5/Pv/8/Ly//7+/v/+/v7b////2/7+/v/+/v7//v7+/9nz
6f9k0Kv/fti6/57kz/+P38v/Z9W3/2rWuf/v+ff/9vf2//7+/v//////////2////9v///////////7+
/v/0/fz/etzJ/1TUu/9R18D/U9jC/2bdyv+j6N3/9/v7//39/v///////////////9v////b////////
///+/v7//v7+//r+/v/x/Pv/4vj2/+v7+f/5/v3//f7+//7+/v/+///////////////////bAAD//wAA
//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//ygA
AAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAD///+3////////////////////////
//////////////////////////////7+/v/+/v7//f39//7+/v/+/v7//v7+//7+/v/+/v7/////////
////////////////////////////////////////////////////////////t////7f/////////////
//////////////////////////////7+/v/+/v7/+vr6/9/f3//BwcH/sLCw/6urq/+oqKj/urq6/9XV
1f/19fX//v7+//7+/v/+/v7//v7+//////////////////////////////////////////+3////t///
////////////////////////////////////////9/f3/8XFxf/BwcH/1dXV/+/v7//5+fn//f39//f3
9//k5OT/xcXF/5ycnP+SkpL/4eHh//39/f/+/v7/////////////////////////////////////////
/7f///+3///////////////////////////////////////////7+/v//f39//39/f/9/f3//f39//b2
9v/9/f3//f39//7+/v/9/f3//v7+//Dw8P+0tLT//f39//7+/v//////////////////////////////
////////////t////7f//////////////////////////////////////////////////////v7+//z8
/P/w8PD/4eHh//7+/v/9/f3//f39//7+/v//////+Pj4/7i4uP/+/v7/////////////////////////
//////////////////////+3////t///////////////////////////////////////////////////
///+/v7//f39/9ra2v+oqKj/rq6u/7Gxsf/8/Pz//v7+///+///4+Pj/uLi4//7+/v//////////////
/////////////////////////////////7f///+3////////////////////////////////////////
//////////////7+/v/7/Pf/8/Tp//79/v/+/v7//vz9//T35P/+/f3///7+//j39f+4uLf//v7+////
////////////////////////////////////////////t////7f/////////////////////////////
/////////////////////////v7+/9PYu/+PnmX//v35//3+/v/j59L/gpRS//r88f/+/v7/9/f3/7i4
uP/+/v7///////////////////////////////////////////////+3////t///////////////////
///////////////////////////////////+/v7/w9K0/4KeZP/6/vj//f7+/87exf98mV3/8Pfu//7+
/P/4+Pf/uLi4//7+/v/+/v7//////////////////////////////////////////7f///+3////////
//////////////////////////////////////////////3+/v/o9e3/ytzL//z+/P/+/f7/8Pv1/8XV
yP/3/fz//v7+//j49f+4uLj//v7+//7+/v//////////////////////////////////////////t///
/7f///////7////+//////7//v7+/////v/+//3//v3+//3+/P/9/v7//v3+//38/v/4/fn//vz8//38
/f/7/vf//Pr9//3++v/9/f3/9/j5/8bHxv/+/v7//v78//7+/v///v7/////////////////////////
//////+3////t////////v////7//////v/9/fz//f39//v9+//++/3/9vTx/+Xl2//Ozb//u76n/6yv
lf+kpJD/oaON/6Kliv+pqZb/tLWm/8XHuP/d3db/8fDv//v7+v/9/Pz//vz+//7+/f//////////////
/////////////////7f///+3/////////v////7///7///v6/P/a2dv/vMC//7Gxlf+Bhi//e4kW/3+Q
DP+Glgn/i5sG/4ycBv+NnAf/jpwG/4uaB/+GlAf/gIsN/3Z8E/91fDf/mZiS/5ibnP/Jycr/+fj1////
////////////////////////////t/7+/rf9/f3//Pz8/+Tk5P/Ew8X/w8LD/+Hi4P/7+/j/vspw/46j
AP+QoAL/jaAB/4ihAv+HoQH/iKMB/4qiAf+LowH/jKUB/4ujAf+KogD/jaYB/42nCv/r7sr/8/X0/8bI
xP+Ylpj/mZmZ/8/Pz//5+fn//f39//7+/v////+3/v7+t+Hh4f/Ly8v/3t7d//z7/P/9/fz//f74/9zk
rf+NpRT/jaQC/4mjAf+IogD/hKAF/5OqKf+rv03/r8FU/6a3Rf+KpBb/hqMD/4ejAP+LpgH/jaUF/6S6
Q//3+ub//f37//z8/f/y8vL/urq6/46Ojv+7u7v//v7+/////7f//fu3xNGU//Hy2P/9/fH//v70//P2
3f/F04T/iKUV/4mnBP+IpwL/gqQE/5y0O//e57X/+/3w/97hw/+UnVP/+vrr//b44//C0Ir/hagU/4Om
Bv+IqAr/h6cS/5+3Sv/h6b7/+vvw//7++P/7/PD/3+jA/46Xc//+/v7/////t/7997eSsjL/iqga/5av
Ov+YsUX/i60k/4iqEP+HqA//iKkS/4epEv+mvk//9/fk//z8/P/z8+b/g5Ap/3F+BP+2u37//vz5//38
+//f5rz/iqoj/4SrFf+Hqx3/h6sh/4SrJ/+Sskf/mbZX/5O1Rv+DrCr/hZda//7+/v////+3//34t6K9
Vf+IqiL/iaok/4SqHf+EqiH/hqgj/4itJP+EqyH/lbJK//X35//7/P3/+/33/6y0Yv+EjAb/hIsE/3+L
DP/i48D/+v36//r9+//W4q3/gast/4GsLf+CqDf/ga0t/4GrNf+DrTr/gq06/4CnO/+Nn2z//v7+////
/7f+/fu3scd//4WuMv+Grjr/g641/4CrNP+CrzT/gK0z/4WsP//O3qX//f38//z++//k5cL/j5Ye/5WY
GP+QlxH/kZoO/6WsTP/7+vP/+/z+//r7+P+Wumb/e602/32uPf9+rzz/gK9D/4CvSf+Cs0j/g65I/6Kx
jv/+/v7/////t/z9/bfJ27D/hLBI/4OwR/+Fskb/g7JD/4KvSP+Ar0b/iK1Q//H25f/++/7//fz0/7a6
Zv+jpC3/nqQs/6GnMv+jpSv/nqQv/9vdsP/+/vv//P38/7rVn/98sEv/fbNN/32xTf98sUv/fbRR/3uz
Tf9/qFX/wcq4//7+/v////+3/v79t+bx3P+CsVb/grRX/4O0VP+CtFH/f7NS/3y2VP+Ptmn/+fvy//z8
/v/p6cr/sbBN/7WyRP+2uWP/4+Ow/66xRf+zs0D/vb9t//38+P/8/fz/zuHA/3i1Vf96s1r/e7NW/3i0
Vv95tV7/drZc/3mkYP/o6+X///7//////7f+/f63+f71/5W8ef9/tlz/frhg/365ZP+CuWn/gLlm/4G6
b//1+vD//P38/9XVnv/DwGb/w8Jq/+zsz//+/Pr/1dGb/8O/XP/DvWr/7+3T//n++v/G37z/drVh/3S4
Y/90tWT/crlm/3K8af94t3H/k7KP//v8+v///v7/////t//+/rf8/f3/yeC+/4W4eP+Cunr/fLl1/3q7
cf97uG//c7hx/9/v2//6+vL/1tKQ/9DQhv/q6Mj//v78//z+/f/7+/D/1taf/9TQif/m4rf/+vz8/6bQ
pP9vuWz/ab5o/225bf9+vHv/nc2Y/63Pq//Q29L//v39///+/v////+3//78t/77/v/4/vj/8v70/+35
7f/Y7tf/rNSq/36+gP9zv37/qdSs/+/z4P/b2Kf/7O3T//3++//9/f7//v77//7+/f/7+/H/5eLB/9zd
sv/r9+r/e8OL/2q9ff9uvnv/qNSw/+n56P/4/fn/2tzc//v7/P/+/P7//v7+/////7f//v23//3+//7+
/v/+/v7//v3+//7+/v/5/vz/1u7Z/4DGmP93xY7/x+XI//f47f/7/vz//P7+//7+/v/+/v3//v79//39
/v/9/Pn/5PPb/6HVsP9px47/Z8GL/7jgwf/0/vr//v39/+7t7v/y8PH//v79//7+/v/+/v7/////t///
/7f///////////7+/v/+/v7////////////9/v3/0O7d/3LJm/97yZ//w+za//f+/P/+/f7//v3+//7+
/v/6/v3//v38/+369P+f3sT/Z82i/2bKn/+Y2rr/9f75//z9/v/39/f/7u7u//39/f//////////////
//////+3////t//////+/v7//v7+//7+/v/+/v7///////79/v/8/fv/nN/F/2LOpP9qzaX/i9W7/7vr
2//Y9u3/4Pnx/9X06/+x5db/fda6/2XTsv9m1bT/bNKy/9f07P/+/P7/+ff4/+zx8P/9/f3//v7+////
/////////////////7f///+3/////////////////////////////////v7+//3+/f/R8+n/ZdC0/13U
sP9Z0qj/W86p/2DOrv9g0bH/XtG1/1bStv9Z1rb/YdW5/1zWu/953MT/7/37//n39//29vP//P79////
////////////////////////////t////7f////////////////////////////////+/f7/+/39/+f7
9/9q1L3/Vde4/1TTtP9R07f/UdW6/1TWvP9T17z/Vde+/1XZwf9T2cL/WNjC/43d0f/r9Pb/+fv5//v8
/P/+/P7///////////////////////////////+3////t/////////////////////////////////3+
///+/v7/7/38/6/p4f953c3/WdbB/1HWwP9Q2cT/UdnH/1LZx/9T2cb/ZNzL/43k2f+67+n/7fz6//r+
/v/+/v7//v7///7+/////////////////////////////////7f///+3////////////////////////
/////////P7+//7+/v/+/f7//P3+//X+/v/t/fv/3Pj1/8vy7//D8u7/z/Tx/+T7+P/w/v3/+f7+//z+
/v/7/v7//v7+//7+/v/+/////v//////////////////////////////////t////7f/////////////
///////////////////+/v7//v7+//z////8/v7//P7+//7+/v/9/v7//P7///z+///7/v7//f7+//7+
/v/+/v7//f7+//7+/v///v7///////7////+//////////////////////////////////+3AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAA////k////////////v7+////
/////////v7+/////////////v7+/////////////v7+//7+/v///////v7+//7+/v/+/v7//v7+//7+
/v/9/f3//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+///////+/v7//v7+////
///+/v7//v7+///////+/v7//v7+///////+/v7//v7+///////+/v7//v7+//////////+T////k///
//////////////////////////////////////////////7+/v/////////////////+/v7/////////
///+/v7//v7+//7+/v/+/v7//f39//7+/v/+/v7//v7+//39/f/+/v7//v7+//7+/v//////////////
///+/v7/////////////////////////////////////////////////////////////////////////
//////+T////k/7+/v/+/v7//v7+///////+/v7///////7+/v///////v7+//7+/v/+/v7//v7+//7+
/v/+/v7//v7+//39/f/19fX/19fX/7e3t/+cnJz/i4uL/4WFhf+BgYH/fHx8/4eHh/+dnZ3/uLi4/9zc
3P/29vb//f39//7+/v/9/f3//v7+//7+/v///////v7+///////+/v7//v7+/////////////v7+////
/////////v7+//////////+T////k/7+/v//////////////////////////////////////////////
///////////////////6+vr/0dHR/6enp/+np6f/urq6/9TU1P/v7+//8/Pz//39/f/9/f3/9/f3/+jo
6P/S0tL/t7e3/4eHh/9qamr/iYmJ/9LS0v/7+/v//f39//7+/v////////////7+/v////////////7+
/v////////////7+/v////////////7+/v////+T////k///////////////////////////////////
///////////////////////////////////r6+v/19fX//f39//9/f3//f39//39/f/8/Pz//f39//z8
/P/+/v7//v7+//7+/v/+/v7//v7+//39/f/09PT/x8fH/3Fxcf/g4OD//v7+//39/f//////////////
//////////////////////////////////////////////////////+T////k//////+/v7/////////
///+/v7//v7+///////+/v7//v7+///////+/v7//v7+//7+/v/+/v7//v7+//7+/v/9/f3//f39//7+
/v/9/f3/8vLy//n5+f/8/Pz//f39//7+/v/+/v7//f39//39/f/+/v7//f39/62trf/a2tr//Pz8//7+
/v/+/v7//v7+///////+/v7//v7+/////////////v7+//7+/v/+/v7//v7+//////////+T/v7+k///
/////////v7+//7+/v/////////////////+/v7////////////+/v7///////7+/v/+/v7/////////
///+/v7/+/v7//39/f/z8/P/0NDQ//39/f///////f39//39/f/9/f3//f39//7+/v///////////66u
rv/b29v//v7+//7+/v////////////7+/v////////////7+/v////////////7+/v////////////7+
/v/+/v6T////k////////////////////////////v7+////////////////////////////////////
///////////////////+/v7//f39//39/f/Nzc3/xcXF/+Tk5P/l5eX/5OTk//Dw8P/9/f3//f39//7+
/v///////////66urv/b29v//v7+////////////////////////////////////////////////////
//////////////////////+T////k//////+/v7////////////+/v7////////////+/v7//v7+////
///+/v7//v7+///////+/v7///////7+/v/+/v7//f39//39/P/Ozs7/nZ2d/6CgoP+goKD/n5+f/9TU
1P/9/fz//v7+//7+/v/+/v7//v7+/66vrv/b29v//v7+///////+/v7//v7+///////+/v7//v7+////
///+/v7//v7+///////+/v7//v7+//////////+T////k/////////////////////////////////7+
/v////////////7+/v////////////7+/v////////////7+/v/+/v7//P38//3+9//9/fj//v3+//7+
/v/+/f7//vv///79+P/9/vL//vz9//7+/v/+/f7//v39/66vq//b29v//v7+///////+/v7/////////
///+/v7////////////+/v7////////////+/v7//v7+//////////+T////k///////////////////
/////////v7+///////////////////////////////////////////////////////+/v7//f32/7a9
mf/V2r////78///9/v///v7///37/8vQsf/Dy6L//v73//7+/f///f7///39/66vrP/b29v//v7+////
///////////////////////////////////+/v7///////////////////////////////+T////k/7+
/v/+/v7//v7+//7+/v/+/v7//v7+///////+/v7//v7+///////+/v7//v7+//7+/v/+/v7//v7+//7+
/v/+/v7/7vHd/3aJQv+Somj//f71//38/v/9//7//f7x/4CSUf+BllH/9fjn//7+/f/+/v7//f3+/66u
rv/b29v//v7+///////+/v7//v7+//7+/v/+/v7//v7+/////////////v7+///////+/v7//v7+////
//////+T////k//////////////////////////////////////+/v7//v7+/////////////v7+//7+
/v////////////7+/v/+/v7/4uvX/3SSTP+HoGb/+P3z//7+/v/9/v7/8/3t/3aTU/9/m1v/6vPj//z+
/v////z//v7+/66urv/a2tr//v7+///////////////////////////////////////+/v7/////////
//////////////////////+T////k////////////v7+/////////////v7+////////////////////
///////////////////////////////////8/v7/7Prv/4Gfdv+guJf/+v/6//7//v/+/v7/9f75/4+s
if+Qqof/7vny//v+/v////z////7/6+urf/b29v//v7+//7+/v//////////////////////////////
//////////////////////////////////////+T////k/7+/v/+/v7///////7+/v/+/v7//v7+////
/////////v7+///////+/v7//v7+//7+/v///////v7+//7+/v/9/v7/+P78/9/v5f/q+O3//P77//78
/v/+/f7/+P78/+Pw6v/m8ez/+P79//z+/v/+/v7//v78/6+vrf/b29v//v7+//7+/v/+/v7//v7+////
///+/v7//v7+///////+/v7//v7+//7+/v/+/v7//v7+//////////+T////k/////////////////7+
/v/////////////////+/v7///////7+/v////7///7+///+/v/+/v7//v7+//7+/////v7//vz9//n8
/f/3/fj//v37//75/v/8/f3/+f72//z9+//7+v3//f75//7+/P/+/P///v3+/7Gysf/b29v//v7+//7+
/f////7///7+//7+/v////////////7+/v////////////7+/v////////////7+/v/+/v6T////k///
///////////////+/////v///v7+//7+/f/+/v3//f78//7+/P/9/vr//fz9//78/v/7/vb/+vz8//z6
/v/+/f7//vz+//39/f/8/fr//v39//77/v/8/fz/+/73//79/P/9+/7//f39//z+/P/8/vz/+vz8/+js
6f/09fb/+/v9//7++f/+/vn//v38//79/v/+/v7/////////////////////////////////////////
//////+T////k//////+/v7//v7+//7+/v/+/v7///////39/f/9/P3//f39//7+/v/4+/v//fz9//z1
+//w7ef/4eDP/8nItv+xsZf/naGB/46Tb/+AhF//eHhZ/3V1Wf9zd1X/dHlS/3h6WP+AgWb/jY12/5ye
hv+ur5v/yMi7/+Hh2f/w7e//+vr3//z9/f/8+/7//fr+//7+/P/+/v3///////7+/v///////v7+//7+
/v/+/v7//v7+//////////+T////k//////+/v7//////////v////7//v7+//79/v/+/f7//fz+/+zs
7f/AxsP/q6qh/42JZP96eDv/cnoi/3SCFv96ig//gI8M/4WVDP+ImAj/iZkJ/4mYCv+KmQr/ipkJ/4qZ
Cf+Glgj/gZAH/32JDP92fRT/bGwY/2RnIv9qakj/gX55/5WWl//Ex8r/7u/x//7+9v/+/vv//v7+////
///+/v7//v7+///////+/v7//v7+//////////+T/v7+k/7+/v/+/v7//v7+//7+/f/+/v7//Pv8/+3s
7v+9vL7/np6f/6+vsP/T1Nb/5ObG/5CkIf+OoQP/jqAE/46hAv+OoQH/jKEB/42hAf+OoAD/j6EA/5Gj
Af+SogH/kqIA/5SkAf+RogH/kKAC/4+gA/+PogL/j6MD/4uiBv+QpSj/5OXQ/8HCwf+QlpP/bnBx/317
ff++vL3/8PDw//z8/P/+/v7//f39//7+/v/+/v7//v7+//////////+T/v7+k/z8/P/9/f3//v7+//Lz
8f/MzMz/qqmr/7OytP/j4uP//f38//7+/P/+/vb/ytSG/4qhB/+QpAD/kKEB/4+gAv+MnwD/h6AD/4ah
Av+GogH/hqMA/4ejAP+IoQL/iaID/4qkAP+LpgH/i6YA/4mjAP+KogD/jKUB/46nAv+Npwv/2uKf//36
/P/6/fr/+/33/93d2/+cm5z/b29v/4aGhv/Kysr/9fX1//39/f/9/f3//v7+//7+/v////+T/v7+k/39
/f/s7Oz/v7+//7q7uf/W1tb/+vn7//z8/f/+/v3//f74//7+9P/l6rf/kqcn/4yiBf+NogH/i6QA/4mi
AP+JogD/hqEC/4WfBv+Dngn/iKUS/5GsG/+RqCD/i6EZ/4agCP+HpAP/iKUB/4mkAP+KowD/jaYA/4+n
Af+NpAn/l7Ar/+/0z//+/vf//f76//37/f/9/f3/9vb2/8rKyv+IiIj/b29v/7CwsP/u7u7//v7+////
///+/v6T//7/k/r79v/Fx7z/7u7r//38/f/9/Pz//v3+//79/v/9/fn//v7v/+Dov/+PqSb/iacD/4ql
AP+KpgD/hKMC/4SkAf+Eogf/iage/7bIa//j6rn/9PbZ/9bas//e4bj/8/XT/9virf+wwGn/h6Il/3+i
B/+BpAD/haUC/4qnAv+KpQX/h6YM/5qzQP/r8Mv//v70//39/f/9/f7//f39//z8/P/8/Pz/5ubk/5mb
kP+IiYX//f39///////+/v6T//3+k9nfu/+twWb/5um+//b44P/+/u7//v7w//n86P/p78T/uMlt/4yn
IP+Hpgf/iqcG/4qnBf+IpwT/g6YC/4SjEv+5ym//8/bY//3+9v/8/fn/7+/b/32KLv+Nl0D/9vXh//39
+P/9/ff/8PPW/6jAWf+Cpw//gqcG/4amCv+IqQ3/iagV/4aoFP+Urjr/ydeR/+3y1f/7/O3//v70//79
9f/3+uX/3+m9/6K6Zf+EiW///f39//7+/v/+/v6T//3+k9njsP9/pQ7/iKYa/5ewNf+gtFL/pbZg/5ix
SP+KrCL/h6oP/4elDf+Gpwv/iakP/4imEv+Iqwz/hqkV/8vYiv/+/e///f37//78/v/5+O3/mqRV/25+
A/9uegf/pqts//z88f/+/fr//f37//r67P+/zoH/haUc/4SpDf+FqhX/h6kc/4arFf+IqyD/gqgk/4yu
PP+bt1j/pr5s/6C4aP+YuE7/hKss/3ylIP+KkXH//v7+//7+/v/+/v6T/vv+k+PqwP+CpRn/hacR/4uq
HP+IqRv/hqkY/4SpFf+Hqxj/iaoZ/4uqGv+Hqxj/hqsY/4aqGf+HqSb/xNOO//789P/8+f3/+fv8//79
+P/AxYn/eYcI/3qFAP95hAH/eocS/9TWqf/++/r/+/38//r8/f/5+vH/usx8/4OqG/+Erh//h60p/4Sp
KP+IqjX/g60o/4OtKv+EqzP/g6wv/4OvLf+Criz/hKw2/3qeMP+Rmnz//v7+///////+/v6T/v78k+/2
0f+IqTD/h6oh/4qrKf+Iqib/g6kf/4SrIv+DqST/hKgl/4mtKf+Hryf/g6wk/4OpKf+ovnD/+/3t//z7
/v/6/f3/+/36/+rtx/+FkCD/ho4H/4iMB/+GjQX/gI0C/42WMP/09dj//P35//j++//7/vv//P7p/5m1
Xv9/qy7/ga0u/32oLv+BqDr/g7Ax/36rLv+BrTb/gqw7/4KtP/+CrT//f6c8/3aaOP+iro///v7+//7+
/v////+T//79k/r95f+LqkX/hK0q/4mvN/+IsDf/hrAz/3+pLv+BqzP/ga0x/4CvKv+BrTL/gqs3/4ir
Q//j8ML//f76//v9/f/8/vz//fzx/6yzY/+KkxP/kZQV/5GWEP+OlA3/j5gI/4qVEP+/wn7//fz0//v9
/v/7/f7//Pz8/9PivP9/qkH/e60y/3yuNf99rTr/f7A3/4CvO/+BsD7/f65D/4OySP+CskX/gq9F/3SV
Qv+5w67//v7+///////+/v6T/fv/k/z99v+btW//ha5A/4SuQf+DrUH/hK1B/4OuPv+Crz3/hLJA/4Ct
Pv+BrT//h69I/568bf/8/ur//vv+//78/v/9/vb/4uK5/5efMf+dnyX/m58j/5igHf+Xnhz/mp4a/5me
Hf+YoDX/6+vO//77/v/9/vz//Pz9/+/36f+Ks1z/fK9A/3yuR/99r0X/fa5J/3+tTP98rUr/f7BT/36x
T/9/tEv/g7NM/3GQS//Y3tL//v7+//////////+T/f7+k/v++f+40Jj/g7BK/4OxSf+Eskn/hbNI/4Oy
RP+Dskb/grBJ/4CuTf9+sEb/ha9L/7rNm//9/fv//vv+//78/v/7++v/trhr/6OmMf+ppzH/oqcw/6Cn
OP+kqDj/pacw/6SnLf+hqDX/vsN3//799f/+/vr//f77//j9+P+lxoL/e7BK/32zVP99tE3/fbNN/3uy
S/98tEr/frZR/3m0Tf97tE//g7FY/3eQXv/t8Oz//v7+//////////+T/v78k/7+/v/S48D/grBU/4Cz
Uv+CtFT/hLRS/3+vTP+Cs1D/fbJP/320Uv98tVL/ha9b/8vbsf/+/vv//f3+//36/P/n6MH/qqxK/7Ov
Qv+xrz3/p6xE/9TVmf/NzYf/q7A+/66vPP+vsD7/q7JL//Py2//+/f3//f38//38/f+10aD/d7NQ/3e0
WP99s1j/fbRU/3SyUP96s1P/fLVb/3i1XP93t1f/e65b/5Clfv/8+/v//v7+///////+/v6T//7+k/3+
/f/x++f/irNn/4O1W/+Bs1v/gbRa/4O3W/+Ct1v/g7dd/4G2XP99uFv/fbNg/8jgtP/+/vz/+/z+//z+
9f/Ky5H/vbpf/765U/+7u1X/wMN4//v66f/39eD/u7xu/7u3Tf++u0v/uLdW/9LPpP/+/vj/+f75//n+
/P+41ab/e7Zc/3a1X/96tGD/e7Rf/3e0X/92uGH/c7dj/3K3Zf91tWj/fKlw/7nLtf/9+/3///7/////
///+/v6T//3+k/7+/P/3/vX/p8aS/4K1Xv9+uF3/f7tj/3u5ZP98uWj/grtt/4G4bP+Aumj/eLho/7XZ
qv/+/fz//Pz+//b44f/Gw33/xsJr/8PAY//Ix3v/7+7S//78/P/+/fv/6ebH/8W/cf/Hw2D/yMBq/8nG
hf/7+uj/+v75//b++f+qzJz/d7Rg/3K4Zf9zumX/crZk/3S5aP9xumf/c75q/3a8bf98tnf/ep54/+r0
6P/8/Pv//v7+//7+/v/+/v6T//3+k/7+/f/5/fz/2e3Q/4a2cP98tmr/e7hv/3q5cf94uG//erpw/3q5
b/99uG7/crlu/5vKlv/7/ff//fv9/+boxP/TzYP/0tF//83Mhv/t6sz//v76//3+/f/8/v7//v73/+Xi
uv/JyYH/0cuC/9DNgf/x7ND//fz9/+z68f+SwIr/dLhq/2q7aP9ovGT/a7pp/3C6bf95unX/fbh2/4zB
hf+awZf/qbyr//v++v///vz///7+//7+/v/+/v6T/v7+k/79/v/9/P7/9f3z/8Xhw/+83bz/tdi1/6bP
pf+Qwo3/gbt6/328dP95unT/cbx2/3y3f//o+Ob//P34/+Dhtv/b1ZX/0tSX/+vp0P/+/vf//v7+//3+
/f/8//r//f78//398//o6cX/2Nak/93bmv/m5MD//vz8/9Tw3P98u4D/bLp0/2m/cv9ovm7/crh3/4zE
jf+63Lr/4fbh/+//7//J1Mz/6+/v//77////+////v7+///////+/v6T//76k/78/v/+/P7/+/76//n+
+v/5/vr/+f76//n++P/s/Ov/y+jL/5nGm/96wIH/c8GA/3a8gf+x2bT/9Pvt/9zdsf/e2rD/7/HY//38
/P/8/vv//P39//79/v///vr//v7+//7+/P/9/fX/8O7Y/9vYsv/c4Lb/9vzv/6DTrf9wwoP/a7+A/2m+
f/90vYD/rNm3/+j46f/4/vf/+v37//Py9P/X1df//Pz8//79/f/9/P7//v7+//////////+T//76k//9
/v/+/f7//v79//7+/v/+/v7//v3+///9/v/9/v7/+P78/+z78v+03rn/ecCP/3HCiP+Bx5P/yunN/+Xo
zf/8+u///f77//z+/f/7/v3//f7+//7+/v/+/v3//v79//7+/f/9/f7//v37//f36f/b68r/yenL/3rC
kf9nxon/YsGH/3S9jP+54sH/7v72//z9/f/+/f3//fv8/9vX2v/49/j//v78//3//P/9/v7//v7+////
//////+T////k/7+/v/////////////////+/v7//v7+/////////////////////v/4/vj/uOPL/3jG
lv9rx5D/i82j/9705f/w/fv/9/38//r+/f/+/v7//v7+//7+/v/9/v3/+//9//z+/f/+/P7//vz9//b9
+P/K8tz/fsuh/2jIlv9lypb/Z8aU/67hwf/1/fb/+f79//3+/v/+/f3/5eXl/+7u7v/+/v7/////////
//////////////////////+T////k/7+/v/+/v7//v7+//7+/v/+/v7//v7+///////+/v7//v7+//7+
/v/9/f7/8P32/5/Yuv9sypv/bMeZ/4jLqf++7Nj/9f76//z9/f/+/f7//v3+//79/v/9/v7/+v7+//3+
+//9/fr/8v73/7rn1v97z7D/Zc6m/2LNov9ny6L/iNKx/+f98//7/fz//fz+//z9/v/v8PD/7e3t//z8
/P/9/f3//v7+//7+/v///////v7+//7+/v////+T////k/////////////////7+/v/+/v7//v7+//7+
/v///////v7+///+///9/P7//v38/9346/93zqz/YM2i/2rNov9uyqL/ldO8/8Lu4P/i/PT/7/76//X+
/P/2/vz/8v36/+b79P/E7d//k9vD/2vPsP9l1LL/aNWz/2XSrv9uz7D/vOvc//v9/f/+/P7//vv+/+3x
8P/q7e3//Pz8//39/f/+/v7////////////+/v7///////////////+T////k///////////////////
///////////////////////////////////+/f7//v39//n++f+f4s3/Yc+t/2XSrP9e0qr/W8+m/2LM
p/9zz6//iNm//47awv+S3cX/i9nD/3vRvP9ozrP/ZNS0/2bWtf9k1LX/Yta5/2DWt/972L7/3fr0//78
/v/+/P7/8/Hw/+/y8P/7/v7///////////////////////////////////////////////+T////k/7+
/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/9/f3/+/79//79/P/D8eX/adC3/2DU
tf9a07D/WNOp/1nRqv9Yz6v/XNGw/1nQr/9Z1LL/V9O0/1XTuP9Q1Lf/U9a3/13Wuf9e1Ln/WtS6/1vZ
vf+K38z/6v77//78/v/x8O//9/fz//z9/f/+/v7//v7+///////+/v7//v7+///////+/v7//v7+////
//////+T////k//////+/v7//v7+///////////////////////+/v7//v7+///////+/f7/+f7+//3+
/f/c+fP/cNG8/1XXuP9Y1bb/VtSz/1LSsv9T1Lb/VNW5/1PUuP9W1rr/Vde6/1PWu/9X2L//V9m//1XZ
wf9S2L//Vde//1rYwf+V39T/5PP1/+zu7//8/vv/+v37//36/f/+/f7///////7+/v////////////7+
/v///////v7+//7+/v/+/v6T////k///////////////////////////////////////////////////
///+/f7//f7+//j+/f/e+vj/g9fH/1vXv/9P1rz/UNS7/07UvP9L1b3/StfA/07Yw/9Q18P/UdjD/0/Y
wv9R2MP/UtrF/1Tbx/9X2cb/YdjG/5Lj1v/P7+v/9Pz9//3//v/+/v7//f7+//79///+/v//////////
///////////////////////////////////+/v6T////k//////+/v7//v7+//7+/v/+/v7//v7+//7+
/v/+/v7//v7+//7+/v/8/v7//v7+//3+/v/x/v3/0fby/6jo4P+D4NH/YdjE/1fVwP9U1sL/UtjE/1Pa
yP9T2cf/VNrI/1Tbx/9X2cb/ZdvK/4jk1/+v6+T/1Pb0/+39/P/2/v7/+v7+//3+/v/+/v7//v7+//3/
///+/v7//v7+///////+/v7//v7+///////+/v7//v7+//////////+T////k///////////////////
//////////////7+/v////////////7+/v/7/v7//v7////+///+/f7//P3+//f+/v/w/v7/6P37/9z6
9v/L9PD/uO3o/67r5f+o7Ob/tO7p/9D08P/e+/j/6v38//P+/v/5/v3//P7+//v+/v/6/v7//f7+//7+
/v/+/v7//v7+//3////+/v7//v7+///////+/v7//v7+///////+/v7//v7+///////+/v6T/v7+k///
///////////////////////////////////////////////////9/v7//v7+//7+/v/+/v///f7+//z+
/v/7/v7//P7+//v+/v/5/v3/+v7+//r+/v/7/v7/+v7///j//v/5//7/+v7+//v+/f/8/v3//f7+//3+
/v/+/v7///7+//7+/v////////////3////+////////////////////////////////////////////
///+/v6T////k/7+/v////////////7+/v/+/v7////////////+/v7////////////+/v7///////7/
///7/v7//P////z////9/v///v7///7+///9/v///P////z////8////+/////z//v/+/v7///7+///9
/v///v7//f7+//7//v/+/v7////////////+/v7///////7////+////////////////////////////
///+/v7///////////////+TAAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA
AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA
//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA
AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA
//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA
AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA
//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//KAAAAEAAAACAAAAAAQAgAAAA
AAAAQgAAAAAAAAAAAAAAAAAAAAAAAP///2//////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///+/v7//f39//39/f/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////2////9v////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////7+/v/+/v7//v7+//7+/v/9/f3//f39//7+/v/+/v7//v7+//7+/v/9/f3//v7+//7+
/v/+/v7//v7+////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////9v////b///
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////v7+//39/f/8/Pz/+Pj4//Pz8//v7+//7e3t/+zs
7P/u7u7/7+/v//X19f/6+vr//f39//7+/v//////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////b////2//////////////////////////////////////////////////////////////
///////////////////////////////////+/v7//v7+//7+/v/6+vr/8PDw/9DQ0P+wsLD/kpKS/35+
fv9wcHD/bm5u/2tra/9oaGj/YWFh/2NjY/9zc3P/hISE/56env+7u7v/4eHh//b29v/8/Pz//f39//39
/f/9/f3//v7+//7+/v/+/v7/////////////////////////////////////////////////////////
/////////////////////////////////2////9v////////////////////////////////////////
/////////////////////////////////////////////////////////f39//Dw8P+6urr/jo6O/5GR
kf+dnZ3/vr6+/9bW1v/r6+v/7+/v//r6+v/9/f3//f39//b29v/q6ur/1dXV/8DAwP+kpKT/enp6/11d
Xf9XV1f/k5OT/9TU1P/6+vr//f39//39/f/+/v7//v7+////////////////////////////////////
//////////////////////////////////////////////////////9v////b///////////////////
/////////////////////////////////////////////////////////////////////////////+Hh
4f+jo6P/ycnJ/+7u7v/4+Pj//Pz8//7+/v/9/f3//Pz8//7+/v/8/Pz//f39//39/f/+/v7//v7+//7+
/v/+/v7//v7+//n5+f/w8PD/zc3N/4iIiP9aWlr/kZGR//v7+//+/v7//Pz8////////////////////
////////////////////////////////////////////////////////////////////////////b///
/2//////////////////////////////////////////////////////////////////////////////
///////////////////z8/P/+vr6//39/f/9/f3//f39//39/f/9/f3//f39//z8/P/8/Pz//Pz8//39
/f/+/v7//v7+//7+/v/+/v7//f39//7+/v/8/Pz//v7+//7+/v/7+/v/19fX/2lpaf/39/f//Pz8//7+
/v/+/v7/////////////////////////////////////////////////////////////////////////
/////////////////2////9v////////////////////////////////////////////////////////
/////////////////////////////////////////v7+//7+/v/9/f3//v7+//39/f/8/Pz//v7+//39
/f/9/f3/9fX1/+rq6v/9/f3//f39//39/f/9/f3//v7+//7+/v/+/v7//f39//7+/v/+/v7//f39//Hx
8f94eHj/9vb2//39/f/9/f3/////////////////////////////////////////////////////////
//////////////////////////////////////9v////b///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///+/v7/+/v7//39/f/+/v7/9fX1/8LCwv/6+vr//f39///////8/Pz//f39//39/f/9/f3//f39//7+
/v/////////////////x8fH/eHh4//j4+P/+/v7//v7+////////////////////////////////////
////////////////////////////////////////////////////////////b////2//////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////v7+//39/f/9/f3//Pz8/9LS0v/Hx8f//v7+//7+/v/+/v7//v7+//z8
/P/7+/v//f39//7+/v/+/v7/////////////////8fHx/3h4eP/4+Pj//v7+//7+/v//////////////
////////////////////////////////////////////////////////////////////////////////
/2////9v////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////7+/v/8/Pz//v7+//39/f+goKD/jo6O/6Wl
pf+kpKT/p6en/6ampv+srKz//Pz8//7+/v/9/f3//f39//////////////////Hx8f94eHj/+Pj4//7+
/v/+/v7/////////////////////////////////////////////////////////////////////////
//////////////////////9v////b///////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////+/v7//f39//7+
/v/8/Pz/0NDQ/7a2tv+3t7f/tra2/7a2tv+2tbb/vr2+//v7+//8/Pz//v7+//7+/v////////7////+
/v/x8vH/eHh3//j4+P/+/v7//v7+////////////////////////////////////////////////////
////////////////////////////////////////////b////2//////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////v7+//z8/f/9/fr//f74//39+//+/f7//v7///7+/v/+/P3//vz///77/v/9/vX//v/3//79
/f/+/f7////////9/////f7/8fLt/3h4d//4+Pj//v7+//7+/v//////////////////////////////
/////////////////////////////////////////////////////////////////2////9v////////
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////79/v/8/fz/9/rp/9vexf/5+e3//v79///9/////v7///7+///8
/v/+/Pn/4OTG//T63f/+/vn//v3+/////v///P////39//Hy7P94eHb/+Pj4//7+/v/+/v7/////////
////////////////////////////////////////////////////////////////////////////////
//////9v////b///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////+/v7//f33/73Enf9te0H/ytGt///+
+P///f///v7///7//v/+/vr/3uLH/29+QP+msoD//P7u///+/P////7//v3+//79/v/x8vD/eHh3//j4
+P/+/v7//v7+////////////////////////////////////////////////////////////////////
////////////////////////////b////2//////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v7+//j6
7f+YqGz/aoIx/5uqdP/8/vH//vz///39///8//7//P71/7K9kP9pgTD/iZ1a//D03v/+//z////9//7+
/v/9/f//8PHx/3h4eP/4+Pj//v7+//7+/v//////////////////////////////////////////////
/////////////////////////////////////////////////2////9v////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////7+/v/1+e3/iaBk/2+OPf+OpW7/9v3u//7+///+/v7//P7+//f+8/+ft4P/cJBB/4Gb
XP/l7tj/+/78//7//f////z///7+//Hx8f93d3f/+Pj4//7+/v/+/v7/////////////////////////
//////////////////////////////////////////////////////////////////////9v////b///
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////8/v7/8vv0/5q2iv9ukFb/nbOP//n/9//+//7////+//3+
/v/3/vr/rMak/3GSW/+MqHz/5/Tn//j9/v/9/v3////7////+//y8vH/eHd3//j4+P/+/v7//v7+//7+
/v//////////////////////////////////////////////////////////////////////////////
////////////b////2//////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////P7+//T++//E28X/h6OF/8zf
y//5//r//v7+///+/v/+/v7/+P7+/9vw4v+Gn4b/ucy5//H79//5/v7//f7+///+/P////v/8vHu/3d2
dv/5+fn//v7+//7+/v/+/v7/////////////////////////////////////////////////////////
/////////////////////////////////2////9v////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////3+
/v/6/v3/8fz3/+Hx6P/y/fX/+/76///9/v///P///f3+//n//P/0/vn/4u7p//L69//4/v3/+v79//3+
/////v7///79//Ly7/94eHf/+fn5//7+/v/9/f3//v7+////////////////////////////////////
//////////////////////////////////////////////////////9v////b///////////////////
//////////////////////////////////////////////////////7////+///+/v///v////7+//7/
/v/+/v7//v7////+/////v7//vz9//v8/v/3/v3/9/33//3++v//+/7//vr///z+/f/5//f/+/74//z8
/v/7+/3//P75//3/+f/+/v7//vz///79/v/y8fH/eHh4//f39//+/v7//v7+//7+/v////7///7+///+
////////////////////////////////////////////////////////////////////////////b///
/2////////////////////////7////+/////////////////v/+/v3//v/+/////v////7//v/8//7/
+//+/f3//vv///3+/P/7//j/+/79//z8///+/f///v3+///6/f/+/P//+fv6//v++P/+/fv///r+//76
///6/fv/+f/1//7++P/9+v3//fn9//79/P/9//v//f78//z9/f/6+/z/9Pf2/66zr//5+vv//f3+//7+
/P/+//v//v75//7++//+/f////7+////////////////////////////////////////////////////
/////////////////2////9v///////////////////////+/////v////////////////7//f79//39
/P/8/fz//v79//z9+//8/fr//f38//75///+/Pz//P71//r9+v/7+v///vz+//78/f/8+/z/+Pj3//Ly
7v/t7On/6Obm/+bj5v/l4+X/4+Tj/+Pl4P/l5uH/6ujp//Ds8f/18vj/9/j7//v9+//8/vv//P79//n7
+//4+/n//Pr+//r6/P/9/vr//P35//79/P/9+/3//vv///79/v//////////////////////////////
//////////////////////////////////////9v////b///////////////////////////////////
//////////////z8/P/9/f3//fz9//7+/v/8/v3/9/v6//39/P/+9/3/9u/0/+nm3f/b2sX/xcWt/6in
jP+Wl3P/gYdd/3Z8Tv9sc0P/Zms7/2JkOf9fYTr/X2E5/11jNf9fZDP/YGU1/2JmO/9naUP/bXBN/3d6
WP+FiWn/l5h//7KxoP/NzMD/4eDZ/+7p7f/5+Pb//f37//z8/v/8+/7//fr+//7+/f/+/vr////+////
////////////////////////////////////////////////////////////b////2//////////////
///////////+/////v/////////////+///+/f7//fz+//38/v/8/P3/8/b0/+Dm4v/AwL3/oJmK/4N6
YP9zbkL/am0q/2t2Hf9vexX/dYQR/3uKDv9+jw3/g5QN/4WVCv+FlQv/hpUM/4aWDf+Glg3/h5cM/4aX
C/+Hlw3/gZIK/3uLCP94hQr/c3wP/21wF/9gXxj/Wlcd/1laLf9mYVL/hYJ+/6Oio//Nz9P/6u3w//j5
+v/+/vj////0/////f//////////////////////////////////////////////////////////////
/2////9v/////////////////////////v////7//////////////v///Pv9//X09v/T0tP/nZye/4uN
jv+Tlpj/t7as/6u3Yv+Bkw7/i5wN/4ueCv+LoQb/jaEF/42gBP+OngT/kaAE/5GgAv+SoQH/k6IA/5Oi
AP+UogD/laIA/5WhAf+WogL/lKEC/5KfAf+SoAP/kqAF/5KgBv+Rngj/kp4L/42cDf+Hmhn/jZpE/7a1
of+Hh4b/Wl9b/01TUv97fYD/tLO0/+jm5P////7/////////////////////////////////////////
//////////////////////9v////b/39/f/9/f3//f39//39/f/9/f3//f79//7+/v/19Pb/y8rM/6Gg
ov+Xlpj/pqam/+Xl5P/29fb/+/r7//v85P+aqzT/jKMC/5ChAP+QnwP/kKAD/4+gAv+NoAD/iaIA/4mi
AP+JoQD/iqEB/4uhAf+NpAL/i6EA/46jAv+OogH/j6QA/4+lAf+OowL/jKEC/42hA/+LoQL/i6MA/4yl
AP+NpwD/jKkA/5CqGf/s8MT//Pr6//X49v/g5uL/rrGw/3h4dv9aVVz/bm1u/66urv/g4OD/+vr6//7+
/v/9/f3//Pz8//7+/v/9/f3//v7+////////////////b////2/9/f3//Pz8//39/f/+/v7/+fn5/97f
3v+2tbb/mZiZ/7a1t//e3d7/9PT1//3+/P/9/vr//v78//7+8v/Y4Jv/iqAP/4yjAP+RowD/kaIB/4+h
Av+OnwH/i58A/4igBP+GoAT/hqEC/4ShAP+FowD/hKMA/4mkAP+GnwL/iKAD/4mjAf+JpQD/i6cA/4uo
AP+KpAD/iaIA/4qiAP+MpAL/jqYD/46mAf+MpQ3/xtJ8//397v/7+v3/+/75//v+9//3+PH/5OLj/7Oz
s/98fHz/W1tb/39/f//FxcX/7+/v//z8/P/+/v7//Pz8//7+/v///////////////2////9v/f39//39
/f/19fX/2NjY/6qqqv+vsK7/z8/P//n4+f/8+/3//fz9//7+/f/9/fn//f74//7/8f/r8L//nK48/4ig
Bv+OowT/jqMB/4ykAP+KogD/iqIA/4mhAP+HoQL/hp8D/4WgBf+CoAP/g6IG/4enCf+Iowv/iaER/4if
Ef+GoAb/iaYD/4imAf+IpQD/iqUA/4qjAP+KowD/jKUA/4+mAf+PpQP/i6IK/5StJ//d56f//v70//3+
+P/8/vf//vz9//37/f/8/P3/+Pj4/9XV1f+ZmZn/W1tb/2xsbP+wsLD/6Ojo//r6+v/+/v7/////////
//////9v////b/7+/v/v7+//oaGh/7m5uf/x8fD//f79//z8/P/9/P3//fz9//39/f/9/fr//v/5//3/
9v/q8cf/nLBA/4ikC/+JogL/jKMB/4ulAf+HpAL/haMB/4ejAP+FowD/gqMB/4GdD/+NojH/t8Zr/8zX
i//V35n/1eCW/9ffm//S2pT/t8Rr/5SoO/+CnBj/g6EK/4OiAv+EpAD/haQA/4ilAP+KpwH/jaYA/42m
CP+Jpwv/la41/+Xut//+/vT//v77//38/f/8+/7//f3+//39/f/8/Pz//Pz8//f39/+0tLT/Z2dn/1FR
Uf+5ubn//v7+////////////////b//+/2///vz/2+PD//H11//9/PL//vz9//77/v/9/f3//v79//79
/v/+/v3//v70//3/4f/f6q7/kKU6/4OjBv+JqQD/iaYA/4mmAP+IpQH/g6MC/4KkAv+Eowj/g6AX/6S7
U//e6aj/+f3b//7+8P/+/vn/7e/X/4KJUf/a3bT//v7v//7+8P/8/eX/4em4/66/bf+DoCT/faMG/3+l
AP+CpQP/hqYG/4mnA/+HpQf/hqQL/4amEv+KozH/2+Ws//v94v/+/vX//v3+//79/v/9/f3//v3+//79
/f/+/f7//v36//n85/+mr43/ioqF//39/f///////////////2///v9v//32/6GzYv+it1L/2eCk/+7x
zP/5/OD///7p////7P/8/uj/8fbV/9/orf+svl3/jacj/4ekDf+Ipwb/iqgI/4qnCP+JqAX/iKgF/4On
Af+BpAn/lK00/9XhmP/4+uD//v74//v++//8/Pr/9vfl/5igV/9oeQf/jpZA/+/u0//+/vn//Pz2//79
+//6++v/2+Wr/5ayPP+DqA//gaYG/4WmCv+IqQ7/iaoP/4moFf+JqhT/iKoY/46oM/+zxXH/2eSu/+/0
2f/8/ur//v7v//7+9P/8/uz/8/ja/9vntv+owWn/e5U7/42Ogf/9/f3///////////////9v//3/b/7+
8v+gulH/f6QN/4ajG/+WrzT/orlO/6q6Zf+uvHP/p7ll/5eyRP+KrCL/hqkQ/4imDv+GpAz/hqcJ/4mp
Dv+JpxH/iqcT/4irCP+CqAj/mrU9/+PrsP/+/e7//v34//78/v/+/P7/+/vx/7a9gP9tfQz/bXwB/214
DP+eomH/+Pjq//398//+/vv//v38//799//u9Mv/obhT/4WmGv+EqA3/haoR/4aqFv+IqRv/iKwX/4it
Fv+HqyH/hKcm/4erMv+Xs1L/p8Bq/7LGff+uv4H/qb5x/5u5VP+HrDP/fqkc/3SWJf+Wl4j//f39////
////////////b//7/2///fX/rMRi/36mCP+Bpgf/iKkS/4emGP+GpRz/hqYf/4apHP+FqRb/h60T/4ms
EP+MqxP/iqoU/4eqE/+Iqhb/hqgU/4aoGP+GqhX/jqo1/+3yw//+/fb//Pj9//r7/f/8/f3//vv7/9fZ
rf95hhr/cYIA/3aDAP9zgAL/d4MW/8nPl//+/Pn//fv8//z8/P/7+/3//fv8/+/y1f+dsVP/g6gS/4Gq
Ev+FrBv/h6sj/4WqIP+DqCL/ia4t/4WuJv+Aqxz/h64w/4KoMP+CqS7/gaku/4OuKP+FsCv/ha4u/4Kr
Kv9wkC3/m56Q//7+/v///////////////2//+/9v//34/7/Sgf9+nxj/hKYY/42sJP+MqyP/iKgc/4er
Gf+CqBX/gaYX/4iqH/+IqCD/h6Yf/4urIf+HrB7/haob/4SrGf+DpyL/jao//9zotv/+/Pv//fr9//v8
/P/5/fz//f71//Dw1P+Nlzf/fowF/4CJAf+BiAL/f4gA/3uIBP97iB7/6eXL///+9//9/vz/+P37//r9
/v/7/Pj/7fXJ/5q2TP+AqyL/gq4l/4WtK/+Dqiv/g6g0/4SmOv+ErDH/gKwn/4OqNf+CqjT/hK01/4Ww
Nv+CrzH/gaw1/4GoO/+Apjj/aIUv/6qwnf/+/v3///////////////9v//79b//+9P/O4Jf/f6Ij/4is
Iv+KrCj/iKoq/4msKP+EqiP/g6oi/4WsJv+Dqyf/g6km/4arKf+Iryr/hrAp/4KsJf+FrCn/hqg4/73O
j//8/u7//f39//v8/f/6/fz/+/37//397/+zvGv/gIwS/4ePCf+Kjgn/h4wI/4iPBv+EjwP/gY0M/6iv
Wv/5+eL//P34//j++v/4/vz/+/76//3/8P/T3rD/gaY+/3+sL/+Ari//fqst/36pM/+Bqjr/gq8z/36u
Kf9+qjT/g682/4GsO/+Bq0D/g65C/4KtQf9/qD3/gKg8/2iFNf+6wrD//v7+////////////////b//+
/W///vb/3euz/32gL/+ErSf/iLAw/4iuN/+JsDX/h7Ey/3+pK/+AqS7/gqsy/4GsMP+Arir/gK4q/4Gt
Mf+BqzP/h6w9/5e2V//r887//f73//3+/v/6/Pz//P78//79+P/l5r//iZUm/4mREf+PkhP/kpUR/42T
Dv+NlAv/jZcG/4uVC/+Hkxv/19in//388//8/v3/+fz+//v9/v/8/Pv/9fjr/527c/9+qjn/e60x/3ut
Mv9+rjf/faw5/3+wN/9/sTT/gbA+/4CxO/9/rkD/hLJI/4KyRv+BsET/ga5D/4SqSf9kfz3/0tjL//7+
/v///////////////2/+/P9v/v38/+nu0P+Cokj/hK04/4WvO/+Frj//hK09/4WvPv+CrTr/f6s4/4Ct
Of+EsTz/g7I5/36tNf+BrDv/hK1D/4esS/+604n/+/7m//79/f/9+////f78//7++P/7++z/sbZn/5KZ
JP+Wmh3/mZsf/5meHP+UnBb/k5sV/5eeEv+XnBX/j5ka/6WrVf/089z//vv+//78///7/P3//P3+//v8
+//C2Kr/fapD/3uuOv96rT3/fa9B/3utQf99rkP/fq1D/4CtSv9+rkf/f65O/3+vTv+Bs0v/grZJ/4Ky
R/+FrE//Zn1G/+3y6v/+/v7///////////////9v/fz/b/v9/f/u9eD/lrVq/4WvRv+Er0T/hK9E/4Sv
RP+Er0T/hbFD/4ayQv+EsUH/hLFD/4OuRf+Aq0T/g7BD/4WwRP+Epk//2+rA//7+9v/9+v///vr///79
/f/+/vX/5uW7/5qiOf+coSj/oaIq/56hJv+ZoSH/m6Mj/5yiJP+eoST/oqIk/5mfIv+YoTT/ztCa///9
+P///f7////6//z9+//7/f3/4fHW/4KuT/98rkP/fa5L/3+yTP99sUj/fbBM/3+vTf9/sE3/eK1H/3+z
U/98sVD/fLNN/32yTP+Ds1L/fqNU/3SIXv/5/Pr//v7+////////////////b/3+/W/8/v3/9/3v/6vG
h/+CsEv/g7NL/4GwSf+Es0r/hrRL/4OyRv+CskT/grFG/4GvSP+Ar03/f7BN/32wRv+Gskz/j61h/+/0
4//9/f3//vz+//77///+/f3/+fnh/7a4bP+jpzn/p6cu/6moMv+lqTP/nKM1/6muSP+jpzn/pqkz/6Wn
L/+nqzH/oac2/6uyWP/19tb///38//7++//+/vr//Pz9//f+8v+OtWb/e7FL/3yzU/9+tVX/fbNN/32z
Tf96skz/erRL/361TP9/tlL/e7VQ/3izTf97tlD/gbJX/3eaV/+ZqIv//v3+//7+/v//////////////
/2////tv/v39//z++v/A1an/gq5U/4G1UP9/s1L/g7VU/4a2U/9/r0v/gLBM/4KzT/99sk7/frNR/3u0
Uf98tVL/g69Y/524df/0+Oj//f77//z+/v/9+v7//vz4/+TmuP+nqkn/r65D/7KsPf+vrzr/p6w+/6qt
XP/x8Lf/vLxp/6mvOv+srj3/ra46/62vPf+rskX/2duk///8+//+/f3//v78//78/v/7/fn/nMCB/3iy
Uf91tVP/eLJY/32zVv9+tFP/drNQ/3SzT/98s1L/fbVa/3q1XP93tlj/d7dU/3yyWP9zllj/xM24//77
/f///v////////////////9v//79b//+/v/8/vr/4fPR/4WuX/+DtFb/g7Nb/4O0W/+EtVn/hLZX/4S2
Vv+BtVT/f7RU/4C1Vv9+tlb/fLdY/4CzXf+cv3z/8/np//7+/P/7/f7//P3+//z87f/Fxo7/tLNY/7u3
T/+9t03/tbVJ/6+1U//X2J///v7t/+Lgsv+vslT/tLRJ/7i1Q/+5t0b/srRL/7y7ff/7+u3//v78//v+
+v/6/v7/+v75/6XJjf98tln/d7ZZ/3i0Xf98s1z/frRb/3mzWv92tFr/fLhf/3i2YP91tWL/dbdj/3a2
Yv9+smr/dZVm/+Lr3v//+/////7/////////////////b//+/2/+/v7//P75//X87f+UuHr/g7Nb/4K1
XP9/tFv/f7Rb/3+1XP+AuGD/g7pj/4a7Zf+EuGP/grhi/324X/94tGD/lMJ+//D55//+/f3/+/z///r+
+//v8NH/wsF+/8G9Zv/CvV3/wLxX/76/YP/Fx4X/+/rm///8/v/9++7/0dCb/725YP+/ulH/wr5Q/766
Wv+5tW//5uTF//7+9//5//f/9//8//b/9v+hxov/erRe/3W2X/90tWL/ebZi/3m0Yv92s2P/dLVi/3C3
Yv9wuWT/cbpn/3O4af93tG//fKl1/5Krjf/3/ff//fr9///+/////////////////2///f9v/v3+//3+
+v/2/vX/u9Ss/4SyYv+AuF3/fLhd/3+8Y/99vGb/eLhl/3u5af+Bu2//f7ht/4K5bP+Aumn/d7pp/4K6
dP/o9uH//v39//z7/v/9/vf/3+Cw/8bBd//Gwm3/xMJn/8XDav/LyYf/8vDU///9/P/+/f7//v78//b0
4v/PyY7/w79q/8rGZf/Lw2z/yMJ0/9jVov/9/e//+/74//j+/f/x//H/j7h+/3ezYv9zuGT/cLll/3K7
Zf9wt2T/crdo/3S8av9xvGn/c79r/3W+bP94unD/frV6/3OZcv/L3cn/+v33//79+////v7/////////
//////9v//3/b//9/v/+/vz/+Pz7/+f34P+PuHj/gLhp/3y3aP96uGz/fLtx/3m5b/92tmz/eLlu/3y8
cf98uG7/fLds/3O7bv93tXH/1OzP//3++//++v7/+/zv/9TTmv/TzID/0tB+/8zNe//Sz5H/7+vP///+
+P///v7//P79//z+/v/+/vr/9fLW/8vKj//Lynz/zsl9/9HNff/Sz5D/+/fi//39/P/3/f3/2/Pd/4O0
eP92uGr/bLlm/2y+af9nu2P/a7pn/265bP9yu23/erx2/3q4c/9/u3f/ir6E/5G4j/+QqJH/7vfv//3+
+v///vz///7+////////////////b//+/m///v7//v3+//v8/v/3//X/uNWt/424hv+Muof/irqH/4i7
hf+CuX7/f7t6/3y7df95u2//e7pw/3q4cf9xu3P/crZz/7LUr//4/vX//fz9//P03//Y1pz/2dKL/9PV
if/Pz5b/6+nL//799P///v7//v7+//z//P/7//v//f77//7+9f/u7tD/1NWf/9XSl//b2JH/1tOS//Tx
1v/+/P3/9fz7/7/ixP98tnn/cLlw/2m7bv9qwW3/Zrxo/2q5bf9zuXX/e7p5/5C9kP+y2LH/yurH/9jx
1/+/08H/x9HL//v9/v///f7///z+///+/v///////////////2////xv//7+///7///9/P7/+v75//D9
8P/q/u3/6f3s/+P35f/Z8dn/yObH/6zUqP+LvYb/g7t8/327eP95vXn/cr16/3K7ev+OwJL/4/bh//r+
+P/r7NH/2dah/9vWm//T2J7/6+nT//79+P/+/vn//v7+//79///+/vz//v/5//7//f/8/Pv////2//Hz
1v/d27T/2dai/9rYoP/k48P//f34/+779f+UzaD/dr5//2y7eP9pvXj/Z79z/22+df94uYH/jL6R/8bp
xf/u/+//8/70//T+9f/z+/X/uL26//f4+v/9+/////v////8/////v////////////////9v///4b//9
/P//+v///v3+//z++v/7/vz/+//7//r++//7/vz//P38//r++f/z/vL/5/vo/7rbvP+Jvo//eMKC/3PC
gv91woT/fLuF/7feuf/0/vD/4+bG/9rZqf/g3bj/8/Xd//7+/P/8/f7/+/77//z9/f/+/P////79///+
/P///f7//v79//7+/f/+/vn/+fjo/+TfxP/Y2a3/2+K6//T67P/L6M7/c7+I/2/EhP9rwIH/ab2C/23A
gP93uoT/st6+/+r88P/2/vP/+/75//z9/P/9+/3/3Nfc/+Tg4//8/Pz//v79//3+/v/8/P7//v7+////
////////////b///+W///v3///v////9/v/+/v3//v7+//7+/v///f7///z+///8/v/+/f7//f7+//f/
/P/x/fj/1PDa/53Tpf92vYr/csSK/3fCiP+Hx5b/0/LX/9few//t7ND/+/ru//7++v/8/f3/+v79//r+
/v/8/v7///7////+/v///v7///7+//7++//+/f///fz+//79+v/8+/H/7O/V/9Tlwf/X8Nb/msuk/2/F
jf9mxYb/YsGG/2e8hv98vY7/vObE/+n98v/3/v3//vz9//79/P/+/P3/7+zv/9bR1f/+/f3//v78//7+
+//9//z//f7+//7+/v///////////////2////5v//7+///+/////v7////+///////+/v7//v7+//7+
/v/+/v7///7///7////+//7//f/+//3/+//p+On/pde5/3PCkv9yxo7/bMWN/5PSqP/e8t3/+vz5//n9
/f/5/fz/+v79//z+/f/9/v7//v7+///+/v/9/v7//f/8//3//P/+/v3//fz9//78/v/+/P7//v38//X/
9f/a+eL/ntex/3bElf9ox5L/Z8uT/2DFjf9ywpP/td7A//X+9P/2/vv/+f7+//79/v/+/f3/+Pj4/9PT
0//19PT//////////v////7////+//////////////////////////9v////b///////////////////
/////////v7+//7+/v/+/v7//v7+///////////////////////+/v7/+f36/+L67v+Tz6v/cMWU/2zJ
lP92xZf/ns+w/9/67v/p/vn/9v79//j9/f/8/v7//v3+//79/v///v////7///3+/v/7//7/+P79//7+
/f//+/7//vz9//r8+P/j/fD/ntq+/3HJoP9ky5z/ZcmZ/2PIl/9qxpj/nd27/+f+8P/4/fr/+v7+//v+
/v/+/f7//v39/+Dg4P/t7e3//Pz8////////////////////////////////////////////////b///
/2///////////////////////////////////////////////////////////////////////v3///39
/v/4/vz/1PPg/3/MqP9sy53/ZsiZ/3PHnP+IzKr/vOrW//L9+P/8/vz//v39///9/v///P7///3////9
///8/v//+//+//z//P/+/vr//P35//H/9//L8eP/i9G4/2/OrP9l0Kj/YM6k/2XOpf9pzKX/hc+w/9P3
5//2//v//v3+//78/v/9/P7/+v39/+bm5v/t7e3//Pz8//v7+//+/v7/////////////////////////
/////////////////2////9v//////////////////////7+/v/+/v7//v7+//7+/v/+/v7//v7+////
//////////////79///9/P///v39//X++P+q48v/b8un/1/NoP9ky5//bs2i/3TJpP+a0r3/w+3f/9/7
8//t/vr/9f78//n+/f/7/v7/+v79//j//f/z//r/6Pz0/87y5v+k483/ec+z/2rSsv9k1LH/Z9Wy/2nU
sP9m0q7/b82v/6jhzv/w/vr//v3+//77////+/7/+/v8/+Lq6P/q6+v/+/v7//z8/P/9/f3//v7+////
//////////////////////////////////////9v////b//////////////////////+/v7//v7+//7+
/v/+/v7//v7+//7+/v/////////////////+/v7//v3+///8/f/9/vv/1/fp/4HVuf9fz6n/ZNGp/2bR
qP9gzqX/Ysqm/23Lq/+B07f/nuHK/7Xt2/++8N//x/Tl/8bz5P+97t//rePW/5XZxv97z7f/btGz/2jV
s/9j07L/ZNW0/2XWuP9j1Lb/ZNaz/3fRt//K9On/+f7+///7/v///P///fn7/+3t7P/n7+3//f7+//7+
/v/+/v7//v7+//7+/v//////////////////////////////////////////b////2//////////////
///////////////////////////////////////////////////////////+//3+/f/9/v3///78//T+
+f+Z38z/Ys2w/2TSsf9j1LD/XNOr/1jRpv9az6b/Xs2n/2HKp/9ozK3/aMqs/2jMrv9ozrD/Z86y/2fO
tv9gz7X/WdGz/1vUtP9h1rb/ZtW3/2TVuP9g1rr/XNe6/2DXt/+M38n/3fv2//v8/f/++v3//Pr7/+zq
6P/29vP/+P78//3/////////////////////////////////////////////////////////////////
/2////9v///////////////////////////////////////////////////////////////////////+
/v/9/f3/+v/+///+/f/6/vv/u/Dj/27PuP9h07f/XNW0/1nTsP9X0qn/WtSs/1bPqf9Y0a3/WtKx/1jR
sP9Y1LP/V9Wz/1XUtP9V1bn/UNS4/07VuP9R17j/V9a4/17Wuv9c07n/WtO6/1jXvf9f2L3/mePU/+f+
/P/9/v////3+/+np5v/5+vb//f38//z8/f///v//////////////////////////////////////////
//////////////////////9v////b///////////////////////////////////////////////////
/////////////////////v///v3+//j+/v/9/f3/+/79/9P27/930Lz/V9S3/1bXuP9Y1bX/V9Wy/1TS
sP9T0rP/U9O1/1TUt/9U1Lf/VdW4/1fWuf9X17n/UtW5/1TWu/9X2b//Vtm//1TYv/9W2cD/U9a+/1XX
vv9Y2cD/XdfA/6Pj2//j9ff/6ezu/+/x8P/8/vr/+v36//r6/P/++v7///7/////////////////////
////////////////////////////////////////////b////2//////////////////////////////
//////////////////////////////////////////7///78/v/6/v7/+/z8//X+/f/Z+PT/g9bE/1rY
vf9S2bz/Uta5/1TVuP9Q0bf/T9O5/07UvP9N1b3/Tta+/1DXwP9S18D/U9i//1HYv/9U2L//VtfB/1fZ
w/9U2sT/UdvF/1Haw/9V2cP/X9jE/33Zyv+14t3/6Pb4//f7/P/8/v7//P78//v+/f/8/P7///v////+
/////////////////////////////////////////////////////////////////2////9v////////
//////////////////////////////////////////////////////////////7+///+/v////////3/
/v/z//7/2/r3/5rb0f9z1sX/XdfC/0/Uvf9O1Lz/TdS9/07Ywf9I1b//SNfB/0zZxP9O2cb/T9jF/0/Y
xv9L2MT/TNnF/07axv9P2sb/VNnH/1/byv9o2Mn/eNvO/5rp3v/Y9vH/8f79//f+/v/8/v7//v7+////
/v///////v7///3+////////////////////////////////////////////////////////////////
//////9v////b///////////////////////////////////////////////////////////////////
///9/////P////7+/////v///f7+//T+/f/k/vv/yfby/6rp4P+M49T/advH/17Wwv9X07//WNfE/1XY
xP9V2sf/VNnI/1XZyP9X28n/V9vI/1jax/9b2MX/advK/4Pk1f+l6uH/yPPv/+b8/P/y/f7/9f79//f+
/v/6/v7//f7+//7+/v////////////7////9////////////////////////////////////////////
////////////////////////////b////2//////////////////////////////////////////////
/////////////////////////P/+//v//v/+/v////7////+///+/f7//P3+//f9/f/y/v7/7P79/+T9
+v/b/Pf/yvTu/73x6/+q6OH/oOXd/5jl3f+W5t//n+fg/7zs5v/N9fD/2fv3/+T9+//t/v3/9P79//n9
/f/8/v7//P7+//r+/v/6/v7//P39//7+/v/+/v7////////////+/////f//////////////////////
/////////////////////////////////////////////////2////9v////////////////////////
//////////////////////////////////////////////7+/v/8/v7//v7+///+/////v////7+//79
/v/+/v7//P7+//r9/f/7/v7/+f7+//f+/v/z/f3/8v7+//D+/v/v/f7/8P7+//H+/v/z//7/9P/+//X/
/f/3/v7/+P39//v//v/7/v3//P7+//z+/v/8/v7//f7+//7+/v/+/v7//v7+/////////////v////3/
//////////////////////////////////////////////////////////////////////9v////b///
///////////////////////////////////////////////////////////////////+/v7//v7+//7+
/v///////f////z////7/v7/+/7+//v////7/v7//f7+//z+/v/8/v7/+/7+//z+///8/v///f7///3+
///9/v///P/+//3//v/9//7//f7+//3+/f/9/v7//f79//7+/v/9/v3//v7+/////////v7///7+////
//////////////7////9////////////////////////////////////////////////////////////
////////////b////2//////////////////////////////////////////////////////////////
//////////////////////////////z////8/////P////3////9/////v7////+/////v///v7///7+
///9/////P////z////8////+/////r//v/8//7//v7+///+/v///f7///3+///+/v/9//7//P/+////
///////////////////////////////////+/////v//////////////////////////////////////
/////////////////////////////////28AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
</value>
</data>
</root>
@@ -50,6 +50,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Corruption.cs" />
<Compile Include="HotkeyForm.cs">
<SubType>Form</SubType>
</Compile>
@@ -64,6 +65,12 @@
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="QueueForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="QueueForm.Designer.cs">
<DependentUpon>QueueForm.cs</DependentUpon>
</Compile>
<Compile Include="RomId.cs" />
<EmbeddedResource Include="HotkeyForm.resx">
<DependentUpon>HotkeyForm.cs</DependentUpon>
@@ -81,6 +88,9 @@
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<EmbeddedResource Include="QueueForm.resx">
<DependentUpon>QueueForm.cs</DependentUpon>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>