diff --git a/BW_tool.sln b/BW_tool.sln
new file mode 100644
index 0000000..94fe3a0
--- /dev/null
+++ b/BW_tool.sln
@@ -0,0 +1,18 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+# SharpDevelop 5.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BW_tool", "BW_tool\BW_tool.csproj", "{41ABAC38-D34B-489D-A450-3E9FADD07419}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {41ABAC38-D34B-489D-A450-3E9FADD07419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {41ABAC38-D34B-489D-A450-3E9FADD07419}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {41ABAC38-D34B-489D-A450-3E9FADD07419}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {41ABAC38-D34B-489D-A450-3E9FADD07419}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/BW_tool/BW_tool.csproj b/BW_tool/BW_tool.csproj
new file mode 100644
index 0000000..003fa3e
--- /dev/null
+++ b/BW_tool/BW_tool.csproj
@@ -0,0 +1,82 @@
+
+
+
+ {41ABAC38-D34B-489D-A450-3E9FADD07419}
+ {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Debug
+ AnyCPU
+ WinExe
+ BW_tool
+ BW_tool
+ v4.0
+ Properties
+
+
+ x86
+
+
+ bin\Debug\
+ True
+ Full
+ False
+ True
+ DEBUG;TRACE
+
+
+ bin\Release\
+ False
+ None
+ True
+ False
+ TRACE
+
+
+
+ 4.0
+
+
+
+ 3.5
+
+
+
+ 3.5
+
+
+
+
+
+ 3.5
+
+
+
+
+
+ Dumper.cs
+
+
+
+ MainForm.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dumper.cs
+
+
+ MainForm.cs
+
+
+
+
\ No newline at end of file
diff --git a/BW_tool/Dumper.Designer.cs b/BW_tool/Dumper.Designer.cs
new file mode 100644
index 0000000..94af06e
--- /dev/null
+++ b/BW_tool/Dumper.Designer.cs
@@ -0,0 +1,193 @@
+/*
+ * Created by SharpDevelop.
+ * User: suloku
+ * Date: 02/03/2016
+ * Time: 0:19
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+namespace BW_tool
+{
+ partial class Dumper
+ {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+ private System.Windows.Forms.Button dump_but;
+ private System.Windows.Forms.Button inject_but;
+ private System.Windows.Forms.Button dump_dec_but;
+ private System.Windows.Forms.Button inject_crypt_but;
+ private System.Windows.Forms.ComboBox selectedblock;
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ this.dump_but = new System.Windows.Forms.Button();
+ this.inject_but = new System.Windows.Forms.Button();
+ this.dump_dec_but = new System.Windows.Forms.Button();
+ this.inject_crypt_but = new System.Windows.Forms.Button();
+ this.selectedblock = new System.Windows.Forms.ComboBox();
+ this.SuspendLayout();
+ //
+ // dump_but
+ //
+ this.dump_but.Location = new System.Drawing.Point(254, 39);
+ this.dump_but.Name = "dump_but";
+ this.dump_but.Size = new System.Drawing.Size(75, 23);
+ this.dump_but.TabIndex = 1;
+ this.dump_but.Text = "Dump";
+ this.dump_but.UseVisualStyleBackColor = true;
+ this.dump_but.Click += new System.EventHandler(this.Dump_butClick);
+ //
+ // inject_but
+ //
+ this.inject_but.Location = new System.Drawing.Point(353, 39);
+ this.inject_but.Name = "inject_but";
+ this.inject_but.Size = new System.Drawing.Size(75, 23);
+ this.inject_but.TabIndex = 2;
+ this.inject_but.Text = "Inject";
+ this.inject_but.UseVisualStyleBackColor = true;
+ this.inject_but.Click += new System.EventHandler(this.Inject_butClick);
+ //
+ // dump_dec_but
+ //
+ this.dump_dec_but.Location = new System.Drawing.Point(204, 68);
+ this.dump_dec_but.Name = "dump_dec_but";
+ this.dump_dec_but.Size = new System.Drawing.Size(125, 23);
+ this.dump_dec_but.TabIndex = 3;
+ this.dump_dec_but.Text = "Dump and Decrypt";
+ this.dump_dec_but.UseVisualStyleBackColor = true;
+ this.dump_dec_but.Click += new System.EventHandler(this.Dump_dec_butClick);
+ //
+ // inject_crypt_but
+ //
+ this.inject_crypt_but.Location = new System.Drawing.Point(353, 68);
+ this.inject_crypt_but.Name = "inject_crypt_but";
+ this.inject_crypt_but.Size = new System.Drawing.Size(125, 23);
+ this.inject_crypt_but.TabIndex = 4;
+ this.inject_crypt_but.Text = "Inject and Recrypt";
+ this.inject_crypt_but.UseVisualStyleBackColor = true;
+ this.inject_crypt_but.Click += new System.EventHandler(this.Inject_crypt_butClick);
+ //
+ // selectedblock
+ //
+ this.selectedblock.FormattingEnabled = true;
+ this.selectedblock.Items.AddRange(new object[] {
+ "00 - Box Names",
+ "01 - Box 1",
+ "02 - Box 2",
+ "03 - Box 3",
+ "04 - Box 4",
+ "05 - Box 5",
+ "06 - Box 6",
+ "07 - Box 7",
+ "08 - Box 8",
+ "09 - Box 9",
+ "10 - Box 10",
+ "11 - Box 11",
+ "12 - Box 12",
+ "13 - Box 13",
+ "14 - Box 14",
+ "15 - Box 15",
+ "16 - Box 16",
+ "17 - Box 17",
+ "18 - Box 18",
+ "19 - Box 19",
+ "20 - Box 20",
+ "21 - Box 21",
+ "22 - Box 22",
+ "23 - Box 23",
+ "24 - Box 24",
+ "25 - Inventory",
+ "26 - Party Pokemon",
+ "27 - Trainer Data",
+ "28 - Trainer Position",
+ "29 - Unity Tower and survey stuff",
+ "30 - Pal Pad Player Data (30d)",
+ "31 - Pal Pad Friend Data",
+ "32 - C-Gear",
+ "33 - Card Signature Block & ????",
+ "34 - Mystery Gift",
+ "35 - Dream World Stuff (Catalog)",
+ "36 - Chatter",
+ "37 - Adventure data http://projectpokemon.org/forums/showthread.php?24589-B2W2-Ge" +
+ "neral-ROM-Info&p=167300&viewfull=1#post167300",
+ "38 - Trainer Card Records",
+ "39 - Unknown",
+ "40 - (40d)",
+ "41 - Unknown",
+ "42 - Contains flags and references for downloaded data (Musical)",
+ "43 - Fused Reshiram/Zekrom Storage",
+ "44 - Unknown",
+ "45 - Const Data Block and Event Flag Block (0x35E is the split)",
+ "46 - Unknown",
+ "47 - Tournament Block",
+ "48 - Unknown",
+ "49 - Battle Box Block",
+ "50 - Daycare Block (50d)",
+ "51 - Strength Boulder Status Block",
+ "52 - Badge Flags, Money, Trainer Sayings",
+ "53 - Entralink (Level & Powers etc)",
+ "54 - Pokedex",
+ "55 - Swarm and other overworld info - 2C - swarm, 2D - repel steps, 2E repel type" +
+ "",
+ "56 - Unknown",
+ "57 - Unknown",
+ "58 - Unknown",
+ "59 - Online Records",
+ "60 - Entralink Forest - encrypted (60d)",
+ "61 - Unknown",
+ "62 - Unknown",
+ "63 - Unknown",
+ "64 - Unknown",
+ "65 - Unknown",
+ "66 - Hollow/Rival Block",
+ "67 - Join Avenue Block",
+ "68 - Medal data",
+ "69 - Key-related data",
+ "70 - Unknown (70d)",
+ "71 - Unknown",
+ "72 - Unknown",
+ "73 - Checksum Block (73d)"});
+ this.selectedblock.Location = new System.Drawing.Point(12, 12);
+ this.selectedblock.MaxDropDownItems = 10;
+ this.selectedblock.Name = "selectedblock";
+ this.selectedblock.Size = new System.Drawing.Size(692, 21);
+ this.selectedblock.TabIndex = 5;
+ //
+ // Dumper
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(716, 103);
+ this.Controls.Add(this.selectedblock);
+ this.Controls.Add(this.inject_crypt_but);
+ this.Controls.Add(this.dump_dec_but);
+ this.Controls.Add(this.inject_but);
+ this.Controls.Add(this.dump_but);
+ this.Name = "Dumper";
+ this.Text = "Block Dumper&Injector";
+ this.ResumeLayout(false);
+
+ }
+ }
+}
diff --git a/BW_tool/Dumper.cs b/BW_tool/Dumper.cs
new file mode 100644
index 0000000..9e75257
--- /dev/null
+++ b/BW_tool/Dumper.cs
@@ -0,0 +1,86 @@
+/*
+ * Created by SharpDevelop.
+ * User: suloku
+ * Date: 02/03/2016
+ * Time: 0:19
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+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;
+using System.IO;
+
+namespace BW_tool
+{
+ ///
+ /// Description of Form1.
+ ///
+ public partial class Dumper : Form
+ {
+ public Dumper()
+ {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+ selectedblock.SelectedIndex = 0;
+ selectedblock.DropDownStyle = ComboBoxStyle.DropDownList;
+
+ //
+ // TODO: Add constructor code after the InitializeComponent() call.
+ //
+ }
+ public string binaryfilter = "Binary data|*.bin|All Files (*.*)|*.*";
+ void Dump_butClick(object sender, EventArgs e)
+ {
+ SaveFileDialog saveFD = new SaveFileDialog();
+ //saveFD.InitialDirectory = "c:\\";
+ saveFD.Filter = binaryfilter;
+ if (saveFD.ShowDialog() == DialogResult.OK)
+ {
+ System.IO.FileStream saveFile;
+ saveFile = new FileStream(saveFD.FileName, FileMode.Create);
+ //Write file
+ saveFile.Write(MainForm.save.getBlock((int)selectedblock.SelectedIndex), 0, MainForm.save.getBlockLength((int)selectedblock.SelectedIndex));
+ saveFile.Close();
+ MessageBox.Show("File Saved.", "Save file");
+ }
+ }
+ public byte[] injectfile;
+ void Inject_butClick(object sender, EventArgs e)
+ {
+ string path = null;
+ FileIO.load_file(ref injectfile, ref path, binaryfilter);
+ MainForm.save.setBlock( injectfile, (int)selectedblock.SelectedIndex);
+ //MessageBox.Show(injectfile.Length.ToString());
+ }
+ void Dump_dec_butClick(object sender, EventArgs e)
+ {
+ SaveFileDialog saveFD = new SaveFileDialog();
+ //saveFD.InitialDirectory = "c:\\";
+ saveFD.Filter = binaryfilter;
+ if (saveFD.ShowDialog() == DialogResult.OK)
+ {
+ System.IO.FileStream saveFile;
+ saveFile = new FileStream(saveFD.FileName, FileMode.Create);
+ //Write file
+ saveFile.Write(MainForm.save.getBlockDec((int)selectedblock.SelectedIndex), 0, MainForm.save.getBlockLength((int)selectedblock.SelectedIndex));
+ saveFile.Close();
+ MessageBox.Show("File Saved.", "Save file");
+ }
+ }
+ void Inject_crypt_butClick(object sender, EventArgs e)
+ {
+ string path = null;
+ FileIO.load_file(ref injectfile, ref path, binaryfilter);
+ MainForm.save.setBlockCrypt( injectfile, (int)selectedblock.SelectedIndex);
+ //MessageBox.Show(injectfile.Length.ToString());
+ }
+ }
+}
diff --git a/BW_tool/Dumper.resx b/BW_tool/Dumper.resx
new file mode 100644
index 0000000..29dcb1b
--- /dev/null
+++ b/BW_tool/Dumper.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/BW_tool/MainForm.Designer.cs b/BW_tool/MainForm.Designer.cs
new file mode 100644
index 0000000..f5b006d
--- /dev/null
+++ b/BW_tool/MainForm.Designer.cs
@@ -0,0 +1,125 @@
+/*
+ * Created by SharpDevelop.
+ * User: suloku
+ * Date: 01/03/2016
+ * Time: 20:03
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+namespace BW_tool
+{
+ partial class MainForm
+ {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+ private System.Windows.Forms.Button loadsave_but;
+ private System.Windows.Forms.TextBox savegamename;
+ private System.Windows.Forms.Button save_but;
+ private System.Windows.Forms.Label versiontext;
+ private System.Windows.Forms.Button dumper_but;
+ private System.Windows.Forms.Button chk_but;
+
+ ///
+ /// Disposes resources used by the form.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ this.loadsave_but = new System.Windows.Forms.Button();
+ this.savegamename = new System.Windows.Forms.TextBox();
+ this.save_but = new System.Windows.Forms.Button();
+ this.versiontext = new System.Windows.Forms.Label();
+ this.dumper_but = new System.Windows.Forms.Button();
+ this.chk_but = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // loadsave_but
+ //
+ this.loadsave_but.Location = new System.Drawing.Point(12, 12);
+ this.loadsave_but.Name = "loadsave_but";
+ this.loadsave_but.Size = new System.Drawing.Size(132, 23);
+ this.loadsave_but.TabIndex = 0;
+ this.loadsave_but.Text = "Load Savegame";
+ this.loadsave_but.UseVisualStyleBackColor = true;
+ this.loadsave_but.Click += new System.EventHandler(this.Loadsave_butClick);
+ //
+ // savegamename
+ //
+ this.savegamename.Location = new System.Drawing.Point(12, 41);
+ this.savegamename.Name = "savegamename";
+ this.savegamename.Size = new System.Drawing.Size(484, 20);
+ this.savegamename.TabIndex = 1;
+ //
+ // save_but
+ //
+ this.save_but.Location = new System.Drawing.Point(421, 12);
+ this.save_but.Name = "save_but";
+ this.save_but.Size = new System.Drawing.Size(75, 23);
+ this.save_but.TabIndex = 2;
+ this.save_but.Text = "Save";
+ this.save_but.UseVisualStyleBackColor = true;
+ this.save_but.Click += new System.EventHandler(this.Save_butClick);
+ //
+ // versiontext
+ //
+ this.versiontext.Location = new System.Drawing.Point(150, 17);
+ this.versiontext.Name = "versiontext";
+ this.versiontext.Size = new System.Drawing.Size(100, 18);
+ this.versiontext.TabIndex = 3;
+ //
+ // dumper_but
+ //
+ this.dumper_but.Location = new System.Drawing.Point(12, 80);
+ this.dumper_but.Name = "dumper_but";
+ this.dumper_but.Size = new System.Drawing.Size(92, 23);
+ this.dumper_but.TabIndex = 4;
+ this.dumper_but.Text = "Block dumper";
+ this.dumper_but.UseVisualStyleBackColor = true;
+ this.dumper_but.Click += new System.EventHandler(this.Dumper_butClick);
+ //
+ // chk_but
+ //
+ this.chk_but.Location = new System.Drawing.Point(316, 12);
+ this.chk_but.Name = "chk_but";
+ this.chk_but.Size = new System.Drawing.Size(99, 23);
+ this.chk_but.TabIndex = 5;
+ this.chk_but.Text = "Verify Checksums";
+ this.chk_but.UseVisualStyleBackColor = true;
+ this.chk_but.Click += new System.EventHandler(this.Chk_butClick);
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(503, 119);
+ this.Controls.Add(this.chk_but);
+ this.Controls.Add(this.dumper_but);
+ this.Controls.Add(this.versiontext);
+ this.Controls.Add(this.save_but);
+ this.Controls.Add(this.savegamename);
+ this.Controls.Add(this.loadsave_but);
+ this.Name = "MainForm";
+ this.Text = "Gen V save tool";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+ }
+}
diff --git a/BW_tool/MainForm.cs b/BW_tool/MainForm.cs
new file mode 100644
index 0000000..f11f7dc
--- /dev/null
+++ b/BW_tool/MainForm.cs
@@ -0,0 +1,74 @@
+/*
+ * Created by SharpDevelop.
+ * User: suloku
+ * Date: 01/03/2016
+ * Time: 20:03
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+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;
+using System.IO;
+
+namespace BW_tool
+{
+ ///
+ /// Description of MainForm.
+ ///
+ public partial class MainForm : Form
+ {
+ public MainForm()
+ {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+
+ //
+ // TODO: Add constructor code after the InitializeComponent() call.
+ //
+ }
+ public string dsfilter = "NDS save data|*.sav;*.dsv|All Files (*.*)|*.*";
+ public byte[] savebuffer;
+ public static SAV5 save;
+
+
+ void Loadsave_butClick(object sender, EventArgs e)
+ {
+ versiontext.Text = "";
+ string path = null;
+ if(FileIO.load_file(ref savebuffer, ref path, dsfilter) == 1)
+ {
+ savegamename.Text = path;
+ save = new SAV5(savebuffer);
+ if (save.B2W2) versiontext.Text = "Black/White 2";
+ else if (save.BW) versiontext.Text = "Black/White 1";
+ else versiontext.Text = "Invalid file";
+
+ }else{
+ savegamename.Text = "";
+ }
+ }
+ void Save_butClick(object sender, EventArgs e)
+ {
+ if (save.Edited)
+ FileIO.save_data(save.Data);
+ else MessageBox.Show("Save has not been edited");
+ }
+ void Dumper_butClick(object sender, EventArgs e)
+ {
+ Form dumper = new Dumper();
+ dumper.Show();
+ }
+ void Chk_butClick(object sender, EventArgs e)
+ {
+ save.chkCheck();
+ }
+ }
+}
diff --git a/BW_tool/MainForm.resx b/BW_tool/MainForm.resx
new file mode 100644
index 0000000..29dcb1b
--- /dev/null
+++ b/BW_tool/MainForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/BW_tool/Program.cs b/BW_tool/Program.cs
new file mode 100644
index 0000000..eb2abe6
--- /dev/null
+++ b/BW_tool/Program.cs
@@ -0,0 +1,31 @@
+/*
+ * Created by SharpDevelop.
+ * User: suloku
+ * Date: 01/03/2016
+ * Time: 20:03
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+using System;
+using System.Windows.Forms;
+
+namespace BW_tool
+{
+ ///
+ /// Class with program entry point.
+ ///
+ internal sealed class Program
+ {
+ ///
+ /// Program entry point.
+ ///
+ [STAThread]
+ private static void Main(string[] args)
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
+ }
+
+ }
+}
diff --git a/BW_tool/Properties/AssemblyInfo.cs b/BW_tool/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c5e94fd
--- /dev/null
+++ b/BW_tool/Properties/AssemblyInfo.cs
@@ -0,0 +1,31 @@
+#region Using directives
+
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+#endregion
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BW_tool")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BW_tool")]
+[assembly: AssemblyCopyright("Copyright 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+// The assembly version has following format :
+//
+// Major.Minor.Build.Revision
+//
+// You can specify all the values or you can use the default the Revision and
+// Build Numbers by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.*")]
diff --git a/BW_tool/SAV/FileIO.cs b/BW_tool/SAV/FileIO.cs
new file mode 100644
index 0000000..d3b6efc
--- /dev/null
+++ b/BW_tool/SAV/FileIO.cs
@@ -0,0 +1,98 @@
+/*
+ * Created by SharpDevelop.
+ * User: suloku
+ * Date: 02/03/2016
+ * Time: 8:01
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+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;
+using System.IO;
+
+namespace BW_tool
+{
+ ///
+ /// Description of FileIO.
+ ///
+ public class FileIO
+ {
+ ///
+ /// Reads data into a complete array, throwing an EndOfStreamException
+ /// if the stream runs out of data first, or if an IOException
+ /// naturally occurs.
+ ///
+ /// The stream to read data from
+ /// The array to read bytes into. The array
+ /// will be completely filled from the stream, so an appropriate
+ /// size must be given.
+ private static void ReadWholeArray (Stream stream, ref byte[] data)
+ {
+ int offset=0;
+ int remaining = data.Length;
+ while (remaining > 0)
+ {
+ int read = stream.Read(data, offset, remaining);
+ if (read <= 0)
+ throw new EndOfStreamException
+ (String.Format("End of stream reached with {0} bytes left to read", remaining));
+ remaining -= read;
+ offset += read;
+ }
+ }
+ private static void _read_data(ref byte [] buffer, string path)
+ {
+ System.IO.FileStream saveFile;
+ saveFile = new FileStream(path, FileMode.Open);
+ if (saveFile.Length < 1){
+ MessageBox.Show("Invalid file length", "Error");
+ return;
+ }
+ buffer = new byte[saveFile.Length];
+ //MessageBox.Show(buffer.Length.ToString());
+ ReadWholeArray(saveFile, ref buffer);
+ saveFile.Close();
+ return;
+ }
+ public static int load_file(ref byte[] buffer, ref string path, string filter)
+ {
+ OpenFileDialog openFD = new OpenFileDialog();
+ //openFD.InitialDirectory = "c:\\";
+ openFD.Filter = filter;
+ if (openFD.ShowDialog() == DialogResult.OK)
+ {
+ #region filename
+ path = openFD.FileName;
+ //MessageBox.Show(path.ToString());
+ #endregion
+ _read_data(ref buffer, path);
+ return 1;
+ }else{
+ return -1;
+ }
+
+ }
+ public static void save_data(byte[] buffer)
+ { //if (savegamename.Text.Length < 1) return;
+ if (buffer == null) return;
+ SaveFileDialog saveFD = new SaveFileDialog();
+ //saveFD.InitialDirectory = "c:\\";
+ saveFD.Filter = "NDS save data|*.sav;*.dsv|All Files (*.*)|*.*";
+ if (saveFD.ShowDialog() == DialogResult.OK)
+ {
+ System.IO.FileStream saveFile;
+ saveFile = new FileStream(saveFD.FileName, FileMode.Create);
+ //Write file
+ saveFile.Write(buffer, 0, buffer.Length);
+ saveFile.Close();
+ MessageBox.Show("File Saved.", "Save file");
+ }
+ }
+ }
+}
diff --git a/BW_tool/SAV/PKX5.cs b/BW_tool/SAV/PKX5.cs
new file mode 100644
index 0000000..4f52c75
--- /dev/null
+++ b/BW_tool/SAV/PKX5.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Drawing;
+using System.Drawing.Text;
+using System.Linq;
+
+namespace BW_tool
+{
+ public class PKX5
+ {
+ // C# PKX Function Library
+ // No WinForm object related code, only to calculate information.
+ // May require re-referencing to main form for string array referencing.
+ // Relies on Util for some common operations.
+
+/* // Data
+ internal static uint LCRNG(uint seed)
+ {
+ const uint a = 0x41C64E6D;
+ const uint c = 0x00006073;
+
+ return seed * a + c;
+ }
+ internal static uint LCRNG(ref uint seed)
+ {
+ const uint a = 0x41C64E6D;
+ const uint c = 0x00006073;
+
+ return seed = seed * a + c;
+ }
+
+ internal static byte[] decryptArray(byte[] ekx, int start_offset, int length, int seed_offset)
+ {
+ byte[] pkx = (byte[])ekx.Clone();
+
+ uint pv = BitConverter.ToUInt32(pkx, seed_offset);
+ uint sv = (pv >> 0xD & 0x1F) % 24;
+
+ uint seed = pv;
+
+ // Decrypt Blocks with RNG Seed
+ for (int i = start_offset; i < length-4; i += 2)
+ BitConverter.GetBytes((ushort)(BitConverter.ToUInt16(pkx, i) ^ LCRNG(ref seed) >> 16)).CopyTo(pkx, i);
+
+ return pkx;
+ }
+*/
+ internal static UInt32 LCRNG(UInt32 seed)
+ // --------------------------------------------------
+ {
+ UInt32 a = 0x41c64e6d;
+ UInt32 c = 0x00006073;
+ return (UInt32)(((UInt64)seed * (UInt64)a + (UInt64)c)&0x00000000FFFFFFFF);
+ }
+ internal static byte[] cryptoArray(byte[] ekx, int start_offset, int length, int seed_offset)
+ // --------------------------------------------------
+ {
+ byte[] buffer_dec = (byte[])ekx.Clone();
+
+ UInt32 pv = BitConverter.ToUInt32(buffer_dec, seed_offset);
+ byte sv = (byte)((((pv & 0x3e000) >> 0xd) % 24)&0x000000FF);
+
+ UInt32 seed = pv;
+ UInt16 tmp;
+
+ for (Int32 i = start_offset; i < length-4; i += 0x2)
+ {
+ tmp = BitConverter.ToUInt16(buffer_dec, i);
+
+ seed = LCRNG(seed);
+ tmp ^= (UInt16)((seed >> 16)&0x0000FFFF);
+ Array.Copy(BitConverter.GetBytes(tmp), 0, buffer_dec, i, 2);
+ }
+ return buffer_dec;
+ }
+
+ // SAV Manipulation
+ /// Calculates the CRC16-CCITT checksum over an input byte array.
+ /// Input byte array
+ /// Checksum
+ //adapted from Gocario's PHBank (www.github.com/gocario/phbank)
+ internal static ushort ccitt16(byte[] data)
+ // --------------------------------------------------
+ {
+ int len = data.Length;
+ UInt16 crc = 0xFFFF;
+
+ for (UInt32 i = 0; i < len; i++)
+ {
+ crc ^= ((UInt16)((data[i] << 8)&0x0000FFFF));
+
+ for (UInt32 j = 0; j < 0x8; j++)
+ {
+ if ((crc & 0x8000) > 0)
+ crc = (UInt16)(((UInt16)((crc << 1)&0x0000FFFF ) ^ 0x1021) &0x0000FFFF);
+ else
+ crc <<= 1;
+ }
+ }
+
+ return crc;
+ }
+ }
+}
\ No newline at end of file
diff --git a/BW_tool/SAV/SAV5.cs b/BW_tool/SAV/SAV5.cs
new file mode 100644
index 0000000..7d46ada
--- /dev/null
+++ b/BW_tool/SAV/SAV5.cs
@@ -0,0 +1,329 @@
+//Base file from kaphotic's pkhex
+
+using System;
+using System.Linq;
+
+
+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;
+using System.IO;
+
+namespace BW_tool
+{
+ public class BlockInfo
+ {
+ public int Offset;
+ public int Length;
+ public int ID;
+ public int updtcnt;
+ public int Checksum;
+ public bool encrypted;
+ public int seed;
+ }
+ public class SAV5 : PKX5
+ {
+ private static int[] BlockTableBW2 =
+ {0x00000, 0x00400, 0x01400, 0x02400, 0x03400, 0x04400, 0x05400, //6
+ 0x06400, 0x07400, 0x08400, 0x09400, 0x0A400, 0x0B400, 0x0C400, //13
+ 0x0D400, 0x0E400, 0x0F400, 0x10400, 0x11400, 0x12400, 0x13400, //20
+ 0x14400, 0x15400, 0x16400, 0x17400, 0x18400, 0x18E00, 0x19400, //27
+ 0x19500, 0x19600, 0x1AA00, 0x1B200, 0x1C000, 0x1C100, 0x1C800, //34
+ 0x1D300, 0x1D500, 0x1D900, 0x1DA00, 0x1DC00, 0x1DD00, 0x1E200, //41
+ 0x1F700, 0x1FA00, 0x1FB00, 0x1FF00, 0x20400, 0x20500, 0x20800, //48
+ 0x20900, 0x20D00, 0x20F00, 0x21100, 0x21200, 0x21400, 0x21900, //55
+ 0x21A00, 0x21B00, 0x21D00, 0x22900, 0x22A00, 0x23300, 0x23600, //62
+ 0x23700, 0x23800, 0x23A00, 0x23B00, 0x23C00, 0x25300, 0x25800, //69
+ 0x25900, 0x25A00, 0x25E00, 0x25F00}; //73
+
+ private static int[] BlockTableLengthBW2 =
+ {0x3E0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, //6
+ 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, //13
+ 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0xFF0, //20
+ 0xFF0, 0xFF0, 0xFF0, 0xFF0, 0x9EC, 0X534, 0xB0, //27
+ 0xA8, 0x1338, 0x7C4, 0xD54, 0X94, 0x658, 0xA94, //34
+ 0x1AC, 0x3EC, 0x5C, 0x1E0, 0xA8, 0x460, 0x1400, //41
+ 0x2A4, 0xE0, 0x34C, 0x4E0, 0xF8, 0x2FC, 0x94, //48
+ 0x35C, 0x1D4, 0x1E0, 0xF0, 0x1B4, 0x4DC, 0x34, //55
+ 0X3C, 0x1AC, 0xB90, 0xAC, 0x850, 0x284, 0x10, //62
+ 0xA8, 0x16C, 0x80, 0xFC, 0x16A8, 0x498, 0x60, //69
+ 0xFC, 0x3E4, 0xF0, 0x94};
+
+ internal const int SIZERAW = 0x80000; // 512KB
+ internal const int SIZE1 = 0x24000; // B/W
+ internal const int SIZE2 = 0x26000; // B2/W2
+
+ // Global Settings
+ // Save Data Attributes
+ public byte[] Data;
+ public bool Edited;
+ public readonly bool Exportable;
+ public readonly byte[] BAK;
+ public string FileName, FilePath;
+ public BlockInfo[] blocks = new BlockInfo[74];
+ public bool B2W2;
+ public bool BW;
+ public SAV5(byte[] data)
+ {
+ Data = (byte[])(data ?? new byte[SIZERAW]).Clone();
+ BAK = (byte[])Data.Clone();
+ Exportable = !Data.SequenceEqual(new byte[Data.Length]);
+
+ // Get Version
+ // Validate Checksum over the Checksum Block to find BW or B2W2
+ ushort chk2 = BitConverter.ToUInt16(Data, SIZE2 - 0x100 + 0x94 + 0xE);
+ ushort actual2 = ccitt16(Data.Skip(SIZE2 - 0x100).Take(0x94).ToArray());
+ B2W2 = chk2 == actual2;
+ ushort chk1 = BitConverter.ToUInt16(Data, SIZE1 - 0x100 + 0x8C + 0xE);
+ ushort actual1 = ccitt16(Data.Skip(SIZE1 - 0x100).Take(0x8C).ToArray());
+ BW = chk1 == actual1;
+
+ if (!BW && !B2W2 && data != null){
+ Data = null; // Invalid/Not G5 Save File
+ }else if (B2W2)
+ {
+
+ //Build blockinfos
+ int i;
+ for (i=0;i<74;i++)
+ {
+ blocks[i] = new BlockInfo();
+ blocks[i].Offset=BlockTableBW2[i];
+ blocks[i].Length=BlockTableLengthBW2[i];
+ blocks[i].ID= i;
+ blocks[i].updtcnt=blocks[i].Offset+blocks[i].Length;
+ if (i != 73)
+ {
+ blocks[i].Checksum=blocks[i].Offset+blocks[i].Length+2;
+ }
+ else
+ {
+ blocks[i].Checksum=0x25FA2;
+ }
+
+ blocks[i].encrypted=false;
+ blocks[i].seed=blocks[i].Offset+blocks[i].Length-4;
+
+ }
+
+ // Different Offsets for different games.
+ BattleBox = B2W2 ? 0x20A00 : 0x20900;
+ }
+ }
+
+ private const int Box = 0x400;
+ private const int Party = 0x18E00;
+ private readonly int BattleBox;
+ private const int Trainer = 0x19400;
+ private const int Wondercard = 0x1C800;
+ private const int wcSeed = 0x1D290;
+
+ public byte[] getData(int Offset, int Length)
+ {
+ return Data.Skip(Offset).Take(Length).ToArray();
+ }
+ public byte[] getBlock(int index)
+ {
+ if (B2W2)
+ {
+ if (index <73)
+ {
+ return Data.Skip(blocks[index].Offset).Take(blocks[index+1].Offset-blocks[index].Offset).ToArray();
+ }
+ else if (index == 73)
+ {
+ return Data.Skip(blocks[index].Offset).Take(SIZE2-blocks[index].Offset).ToArray();
+ }
+ else return null;
+ }
+ else return null;
+ }
+ public byte[] getBlockDec(int index)
+ {
+ byte[] decrypt = new byte[getBlockLength(index)];
+
+ if (B2W2)
+ {
+ if (index <73)
+ {
+ //MessageBox.Show(decrypt.Length.ToString());
+ //MessageBox.Show((blocks[index].Length-4).ToString());
+ decrypt = PKX5.cryptoArray(Data.Skip(blocks[index].Offset).Take(blocks[index+1].Offset-blocks[index].Offset).ToArray(), 0, blocks[index].Length, blocks[index].Length-4);
+ //MessageBox.Show((blocks[index].Length-4).ToString());
+ return decrypt;
+ }
+ else if (index == 73)
+ {
+ return Data.Skip(blocks[index].Offset).Take(SIZE2-blocks[index].Offset).ToArray();
+ }
+ else return null;
+ }
+ else return null;
+ }
+ public int getBlockLength(int index)
+ {
+ if (B2W2){
+ if (index < 73)
+ return blocks[index+1].Offset-blocks[index].Offset;
+ else if (index == 73)
+ return SIZE2-blocks[index].Offset;
+ else return -1;
+ }
+ else return -1;
+ }
+ public void setBlock(byte[] input, int index)
+ {
+ if (getBlockLength(index) != input.Length)
+ {
+ MessageBox.Show("Block has invalid size!");
+ return;
+ }
+
+ if (B2W2)
+ {
+ if (index <74)
+ {
+ //Recalculate checksum before applying to savedata
+ ushort crc = ccitt16(input.Take(blocks[index].Length).ToArray());
+ if (crc != BitConverter.ToUInt16(input, blocks[index].Checksum-blocks[index].Offset) )
+ {
+ Array.Copy(BitConverter.GetBytes(crc), 0, input, blocks[index].Checksum-blocks[index].Offset, 2);
+ MessageBox.Show("Block's checksum updated");
+ }else
+ {
+ MessageBox.Show("Checksum doesn't need update");
+ }
+
+
+
+ input.CopyTo(Data, blocks[index].Offset);
+ input.CopyTo(Data, blocks[index].Offset+SIZE2);
+ Edited = true;
+ }
+ else return;
+ }
+ else return;
+ }
+ public void setBlockCrypt(byte[] input, int index)
+ {
+ if (getBlockLength(index) != input.Length)
+ {
+ MessageBox.Show("Block has invalid size!");
+ return;
+ }
+
+ if (B2W2)
+ {
+ if (index <74)
+ {
+ //Recalculate checksum before applying to savedata
+ ushort crc = ccitt16(input.Take(blocks[index].Length).ToArray());
+ if (crc != BitConverter.ToUInt16(input, blocks[index].Checksum-blocks[index].Offset) )
+ {
+ Array.Copy(BitConverter.GetBytes(crc), 0, input, blocks[index].Checksum-blocks[index].Offset, 2);
+ MessageBox.Show("Block's checksum updated");
+ }else
+ {
+ MessageBox.Show("Checksum doesn't need update");
+ }
+
+
+
+ input.CopyTo(Data, blocks[index].Offset);
+ input.CopyTo(Data, blocks[index].Offset+SIZE2);
+ Edited = true;
+ }
+ else return;
+ }
+ else return;
+ }
+ public void setData(byte[] input, int Offset)
+ {
+ input.CopyTo(Data, Offset);
+ Edited = true;
+ }
+ public void chkCheck()
+ {
+ int i = 0;
+ string badblocks;
+ badblocks = "Found bad checksums in MAIN save at blocks: ";
+ bool badcheck = false;
+ if (B2W2)
+ {
+ //Main save checksums
+ for(i=0; i<74; i++)
+ {
+ ushort crc = ccitt16(Data.Skip(blocks[i].Offset).Take(blocks[i].Length).ToArray());
+ if ( crc != BitConverter.ToUInt16(Data, blocks[i].Checksum) )
+ {
+ //Array.Copy(BitConverter.GetBytes(crc), 0, input, blocks[index].Checksum-blocks[index].Offset, 2);
+ //MessageBox.Show("Block's checksum is wrong " + i.ToString());
+ if (!badcheck)
+ {
+ badcheck = true;
+ badblocks = badblocks + i.ToString();
+ }else
+ {
+ badblocks = badblocks + ", " + i.ToString();
+ }
+ }
+ else
+ {
+ //MessageBox.Show("Checksum doesn't need update " + i.ToString());
+ }
+ }
+
+ if(badcheck)
+ MessageBox.Show(badblocks);
+ else
+ MessageBox.Show("All 74 checksums OK in MAIN save");
+
+ //Backup save checksums
+ badcheck = false;
+ badblocks = "Found bad checksums in BACKUP save at blocks: ";
+ for(i=0; i<74; i++)
+ {
+ ushort crc = ccitt16(Data.Skip(blocks[i].Offset+SIZE2).Take(blocks[i].Length).ToArray());
+ if ( crc != BitConverter.ToUInt16(Data, blocks[i].Checksum+SIZE2) )
+ {
+ //Array.Copy(BitConverter.GetBytes(crc), 0, input, blocks[index].Checksum-blocks[index].Offset, 2);
+ //MessageBox.Show("Block's checksum is wrong " + i.ToString());
+ if (!badcheck)
+ {
+ badcheck = true;
+ badblocks = badblocks + i.ToString();
+ }else
+ {
+ badblocks = badblocks + ", " + i.ToString();
+ }
+ }
+ else
+ {
+ //MessageBox.Show("Checksum doesn't need update " + i.ToString());
+ }
+ }
+
+ if(badcheck)
+ MessageBox.Show(badblocks);
+ else
+ MessageBox.Show("All 74 checksums OK in BACKUP save");
+
+ return;
+ }
+ else if (BW)
+ {
+ MessageBox.Show("Not yet implemented for BW 1");
+ }
+ else
+ {
+ MessageBox.Show("Invalid file");
+ return;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/BW_tool/app.config b/BW_tool/app.config
new file mode 100644
index 0000000..88f2be5
--- /dev/null
+++ b/BW_tool/app.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file