private void btnCompile_Click(object sender, EventArgs e)
{
this.Cursor = Cursors.WaitCursor;
freeSpaceByte = 0xFF;
decompiledOffsets.Clear();
Dictionary<string, int> compiledHashOrgLocations = new Dictionary<string, int>();
firstTime = true;
DialogResult dialogResult = DialogResult.OK;
if (selectedROMPath == null || selectedROMPath.Equals(""))
{
dialogResult = openFileDialog1.ShowDialog();
if (dialogResult == DialogResult.OK)
{
selectedROMPath = openFileDialog1.FileName;
numericUpDown1_ValueChanged(sender, e);
btnDecompile.Enabled = true;
txtDecompileOffset.Enabled = true;
}
}
if (File.Exists(selectedROMPath))
{
string romCode = GetROMCode();
string iniPath = System.Windows.Forms.Application.StartupPath + @"\Data\BattleScriptPro.ini";
if (File.Exists(iniPath))
{
string[] iniFile = File.ReadAllLines(iniPath);
ParseINI(iniFile, romCode);
}
iniPath = System.Windows.Forms.Application.StartupPath + @"\Data\std.bsh";
if (File.Exists(iniPath))
{
string[] iniFile = File.ReadAllLines(iniPath);
ParseHeaderFile(iniFile);
}
else
{
MessageBox.Show("The Ini file could not be parsed. The script can still be compiled, but keywords may not be used.");
}
bool result = DebugWrittenScript();
iniPath = System.Windows.Forms.Application.StartupPath + @"\Data\std.bsh";
if (File.Exists(iniPath))
{
string[] iniFile = File.ReadAllLines(iniPath);
ParseHeaderFile(iniFile);
}
if (result)
{
int lineNumber = 1;
FindStrings();
string[] hashOrgs = FindHashOrgs();
CompiledStrings x = CompileStrings(selectedROMPath);
List<byte> compiledScript = new List<byte>();
List<byte> compiledHashOrg;
Dictionary<string, int> dynamicGotos = new Dictionary<string, int>();
Dictionary<string, int> lengths = new Dictionary<string, int>();
foreach (string hashOrgName in hashOrgs)
{
lengths.Add(hashOrgName, DryRunForLength(hashOrgName));
}
foreach (string hashOrgName in hashOrgs)
{
compiledHashOrg = new List<byte>();
bool compile = false;
int scriptLength = lengths[hashOrgName];
int location2 = 0;
foreach (string line in scripts[tabControl1.SelectedIndex].Lines)
{
if (compile)
{
if (!line.Equals("") && !line.StartsWith("#"))
{
string newLine = line;
if (line.Contains(commentString))
{
newLine = Regex.Split(newLine, commentString)[0].TrimEnd();
}
string[] info = newLine.Split(' ');
Command c;
bool success = commands.TryGetValue(info[0].ToUpper(), out c);
if (success)
{
HashOrgAddCommand(compiledHashOrg, compiledHashOrgLocations, c, compile, info, lengths, lineNumber, out compile);
}
else
{
SuperCommand sc;
success = superCommands.TryGetValue(info[0].ToUpper(), out sc);
if (success)
{
switch (info[0].ToUpper())
{
case "FORCETYPE":
{
byte parameter = ParseByteParameter(info[1], 0, 1).Byte;
byte[] stuff = ForceTypeSuperCommand(parameter);
foreach (byte b in stuff)
{
compiledHashOrg.Add(b);
}
break;
}
case "PRINTMESSAGE":
{
byte position = 0;
uint locationNew = 0;
foreach (string s in dynamicStrings.Keys)
{
if (s.Equals(info[1]))
{
if (s.StartsWith("@"))
{
locationNew = 0x7FFEFEFE;
}
else
{
bool succeeded = UInt32.TryParse(s, out locationNew);
if (!succeeded)
{
UInt32.TryParse(ToDecimal(s), out locationNew);
}
}
break;
}
position++;
}
ushort parameter2 = ParseHalfWordParameter(info[2], 0, 2).HalfWord;
byte[] stuff = PrintMessageSuperCommand(position, locationNew, parameter2);
foreach (byte b in stuff)
{
compiledHashOrg.Add(b);
}
break;
}
case "SETHALFWORD":
{
uint ramLocation = ParseWordParameter(info[1], 0, 1, false).Word;
ushort value = ParseHalfWordParameter(info[2], 0, 2).HalfWord;
byte[] stuff = SetHalfWordSuperCommand(value, ramLocation);
foreach (byte b in stuff)
{
compiledHashOrg.Add(b);
}
}
break;
case "SETWORD":
{
uint ramLocation = ParseWordParameter(info[1], 0, 1, false).Word;
uint value = ParseWordParameter(info[2], 0, 2, false).Word;
byte[] stuff = SetWordSuperCommand(value, ramLocation);
foreach (byte b in stuff)
{
compiledHashOrg.Add(b);
}
}
break;
case "CALCULATEDAMAGE":
{
byte[] stuff = CalculateDamageSuperCommand();
foreach (byte b in stuff)
{
compiledHashOrg.Add(b);
}
break;
}
default:
break;
}
}
else
{
SQLiteConnection con = new SQLiteConnection("Data Source=" + System.Windows.Forms.Application.StartupPath + @"\Data\Commands.sqlite;Version=3;");
con.Open();
SQLiteCommand com = new SQLiteCommand("select * from commands where name = '" + info[0].ToUpper() + "'", con);
SQLiteDataReader reader = com.ExecuteReader();
if (reader != null)
{
c = GetCommand(reader, con);
HashOrgAddCommand(compiledHashOrg, compiledHashOrgLocations, c, compile, info, lengths, lineNumber, out compile);
}
}
}
}
}
if (line.StartsWith("#"))
{
string[] theLine = line.Split(' ');
switch (theLine[0])
{
case "#define":
{
int temp = 0;
bool success = Int32.TryParse(theLine[2], out temp);
if (success)
{
try
{
userDefinitions.Add(theLine[1].ToUpper(), UInt32.Parse(theLine[2]));
}
catch (FormatException)
{
MessageBox.Show("A number was expected for parameter 2 of the definition");
}
catch
{
MessageBox.Show("There was an unknown error with the custom definition");
}
}
else
{
try
{
userDefinitions.Add(theLine[1].ToUpper(), UInt32.Parse(ToDecimal(theLine[2])));
}
catch (FormatException)
{
MessageBox.Show("A number was expected for parameter 2 of the definition");
}
catch
{
MessageBox.Show("There was an unknown error with the custom definition");
}
}
break;
}
case "#dynamic":
{
freeSpaceLocation = 0;
bool success = Int32.TryParse(theLine[1], out freeSpaceLocation);
if (!success)
{
success = Int32.TryParse(ToDecimal(theLine[1]), out freeSpaceLocation);
if (!success)
{
MessageBox.Show("Error. Dynamic offset could not be parsed from script. Dynamic offset set to 0. WARNING: SLOW!");
}
}
if (success)
{
dynamicLocationSet = true;
}
break;
}
case "#include":
string filePath = System.Windows.Forms.Application.StartupPath + @"\Data\" + theLine[1];
if (!filePath.EndsWith(".bsh"))
{
filePath += ".bsh";
}
if (!File.Exists(filePath))
{
MessageBox.Show("The included header file could not be found.");
break;
}
else
{
if (!theLine[1].Equals("std"))
{
string[] rbhFile = File.ReadAllLines(filePath);
ParseHeaderFile(rbhFile);
}
}
break;
case "#clean":
{
if (scriptInserted)
{
byte[] romFile = File.ReadAllBytes(selectedROMPath);
for (int i = 0; i < lastInsertedScriptLength; i++)
{
romFile[lastInsertedScriptLocation + i] = 0xFF;
}
try
{
File.WriteAllBytes(selectedROMPath, romFile);
scriptInserted = false;
}
catch
{
MessageBox.Show("There was an error writing the compiled script to the ROM. Try closing any tools that the ROM is already open in. If the ROM is not open in any tools, contact Jambo51 on the tool's page.");
}
}
}
break;
case "#org":
if (hashOrgs.Contains(theLine[1]))
{
if (theLine[1].StartsWith("@"))
{
if (theLine[1].Equals(hashOrgName))
{
location2 = FindFreeSpace(scriptLength, freeSpaceLocation, File.ReadAllBytes(selectedROMPath));
compile = true;
}
else
{
if (compile)
{
compile = false;
}
}
}
else
{
if (theLine[1].Equals(hashOrgName))
{
compile = true;
}
else
{
if (compile)
{
compile = false;
}
}
}
}
else
{
if (theLine[1].Equals(hashOrgName))
{
compile = true;
}
else
{
if (compile)
{
compile = false;
}
}
}
break;
case "#freespacebyte":
{
bool success = Byte.TryParse(theLine[1], out freeSpaceByte);
if (!success)
{
success = Byte.TryParse(ToDecimal(theLine[1]), out freeSpaceByte);
if (!success)
{
MessageBox.Show("Error. Free space byte could not be parsed from script. Free Space Byte set to 0xFF.");
}
}
}
break;
default:
break;
}
}
lineNumber++;
}
byte[] rom = File.ReadAllBytes(selectedROMPath);
if (firstTime)
{
firstTime = false;
location = FindFreeSpace(lengths[hashOrgName], freeSpaceLocation, rom);
}
if (hashOrgName.StartsWith("@"))
{
location2 = FindFreeSpace(lengths[hashOrgName], freeSpaceLocation, rom);
}
else
{
bool succeeded = Int32.TryParse(hashOrgName, out location2);
if (!succeeded)
{
succeeded = Int32.TryParse(ToDecimal(hashOrgName), out location2);
}
}
compiledHashOrgLocations.Add(hashOrgName, location2);
int index = 0;
foreach (byte b in compiledHashOrg)
{
compiledScript.Add(b);
rom[location2 + index] = b;
index++;
}
File.WriteAllBytes(selectedROMPath, rom);
userDefinitions.Clear();
}
byte[] romNew = File.ReadAllBytes(selectedROMPath);
int searchLocation = freeSpaceLocation;
int tableLocation = 1;
while (tableLocation % 4 != 0)
{
tableLocation = FindFreeSpace(x.Table.Length * 4, searchLocation, romNew);
searchLocation++;
}
lastInsertedScriptLength = tableLocation - (location + compiledScript.Count);
int searchLocation2 = tableLocation + (x.Table.Length * 4);
searchLocation2 = FindFreeSpace(x.CompiledStringsArray.Length, searchLocation2, romNew);
int indexNew = 0;
foreach (byte b in x.CompiledStringsArray)
{
romNew[searchLocation2 + indexNew] = b;
indexNew++;
}
indexNew = 0;
foreach (int k in x.Table)
{
if (k < 0x8000000)
{
for (int j = 0; j < 4; j++)
{
romNew[tableLocation + j + (indexNew * 4)] = (Byte.Parse(ToDecimal("0x" + (k + 0x08000000 + searchLocation2).ToString("X8").Substring((k + 0x08000000 + searchLocation2).ToString("X8").Length - ((j * 2) + 2), 2))));
}
}
else
{
for (int j = 0; j < 4; j++)
{
romNew[tableLocation + j + (indexNew * 4)] = (Byte.Parse(ToDecimal("0x" + k.ToString("X8").Substring(k.ToString("X8").Length - ((j * 2) + 2), 2))));
}
}
indexNew++;
}
indexNew = 0;
int ignoreCounter = 0;
for (int i = 0; i < compiledScript.Count; i++)
{
byte b = romNew[location + i];
if (ignoreCounter == 0)
{
if (b == 0x13)
{
if (romNew[location + i + 1] == 0xFE && romNew[location + i + 2] == 0xFE && romNew[location + i + 3] == 0xFE && romNew[location + i + 4] == 0x7F)
{
romNew[location + i] = b;
for (int j = 0; j < 4; j++)
{
romNew[location + j + 1 + i] = (Byte.Parse(ToDecimal("0x" + (tableLocation + 0x08000000).ToString("X8").Substring((tableLocation + 0x08000000).ToString("X8").Length - ((j * 2) + 2), 2))));
}
indexNew += 4;
ignoreCounter = 4;
}
}
else
{
romNew[location + i] = b;
}
}
else
{
ignoreCounter--;
}
}
File.WriteAllBytes(selectedROMPath, romNew);
foreach (string s in hashOrgs)
{
lastInsertedScriptLength += lengths[s];
}
lastInsertedScriptLength += x.CompiledStringsArray.Length + 4 * x.Table.Length;
lastInsertedScriptLocation = location;
scriptInserted = true;
keywords.Clear();
dynamicStrings.Clear();
List<string> left = new List<string>();
List<string> right = new List<string>();
for (int i = 0; i < compiledHashOrgLocations.Count; i++)
{
left.Add(hashOrgs[i]);
right.Add("0x" + compiledHashOrgLocations[hashOrgs[i]].ToString("X6"));
}
toolStripStatusLabel1.Text = "Compilation Complete!";
Form8 fr = new Form8(left, right);
fr.Show();
}
else
{
MessageBox.Show("Compilation cancelled.");
}
}
this.Cursor = Cursors.Default;
keywords.Clear();
userDefinitions.Clear();
}