2014-07-19 23:56:40 +00:00
using System ;
2014-07-20 04:28:35 +00:00
using System.Globalization ;
using System.IO ;
2015-03-11 01:44:51 +00:00
using System.Linq ;
2014-07-20 04:28:35 +00:00
using System.Text.RegularExpressions ;
2015-03-11 01:44:51 +00:00
using System.Windows.Forms ;
2014-07-19 23:56:40 +00:00
namespace PKHeX
{
public partial class CodeGenerator : Form
{
2014-12-12 05:45:01 +00:00
byte [ ] codedata = new byte [ 232 ] ;
byte [ ] newdata = new byte [ 232 ] ;
2014-12-25 00:20:39 +00:00
PKX . Structures . SaveGame SaveGame = new PKX . Structures . SaveGame ( null ) ;
2014-10-10 02:59:57 +00:00
Form1 m_parent ;
2015-03-11 01:44:51 +00:00
byte [ ] tabdata ;
2014-12-24 07:29:57 +00:00
public CodeGenerator ( Form1 frm1 , byte [ ] formdata )
2014-07-19 23:56:40 +00:00
{
2014-10-10 02:59:57 +00:00
m_parent = frm1 ;
2014-12-24 07:29:57 +00:00
tabdata = formdata ;
2014-07-19 23:56:40 +00:00
InitializeComponent ( ) ;
2015-03-11 01:44:51 +00:00
CenterToParent ( ) ;
2014-07-20 04:28:35 +00:00
RTB_Code . Clear ( ) ;
TB_Write . Clear ( ) ;
SaveGame = m_parent . SaveGame ;
CB_Box . Items . Clear ( ) ;
for ( int i = 1 ; i < = 31 ; i + + )
CB_Box . Items . Add ( i . ToString ( ) ) ;
CB_Source . SelectedIndex = 0 ;
CB_Slot . SelectedIndex = 0 ;
CB_Box . SelectedIndex = 0 ;
}
private bool loaddata ( )
{
if ( CB_Source . SelectedIndex = = 0 )
{
2014-12-24 07:29:57 +00:00
if ( tabdata ! = null )
2014-07-20 04:28:35 +00:00
{
2014-12-24 07:29:57 +00:00
byte [ ] pkx = tabdata ;
2014-12-12 05:45:01 +00:00
newdata = new byte [ 232 ] ;
2014-10-10 02:59:57 +00:00
Array . Copy ( PKX . encryptArray ( pkx ) , newdata , 232 ) ;
2014-07-20 04:28:35 +00:00
}
else return false ;
}
else if ( CB_Source . SelectedIndex = = 1 )
{
2014-12-12 05:45:01 +00:00
newdata = new byte [ 0xE8 ] ;
2014-07-20 04:28:35 +00:00
Array . Copy ( m_parent . savefile ,
SaveGame . Box // Box Offset
+ CB_Box . SelectedIndex * ( 232 * 30 ) // Box Shift
+ CB_Slot . SelectedIndex * 232 , // Slot Shift
newdata , 0 , 0xE8 ) ;
2014-07-20 19:51:45 +00:00
2015-03-12 04:44:12 +00:00
if ( ! newdata . SequenceEqual ( new byte [ 0xE8 ] ) ) return true ;
System . Media . SystemSounds . Exclamation . Play ( ) ;
return false ;
2014-07-20 04:28:35 +00:00
}
else if ( CB_Source . SelectedIndex = = 2 )
{
// Wondercard
2014-12-12 05:45:01 +00:00
newdata = new byte [ 0x108 ] ;
2014-07-20 04:28:35 +00:00
// Wondercard #
int wcn = CB_Slot . SelectedIndex ;
// copy from save, the chosen wondercard offset, to new data
2014-07-20 07:09:08 +00:00
Array . Copy ( m_parent . savefile , SaveGame . Wondercard + wcn * 0x108 + 0x100 , newdata , 0 , 0x108 ) ;
2014-12-12 05:45:01 +00:00
byte [ ] zerodata = new byte [ 0x108 ] ;
2015-03-12 04:44:12 +00:00
if ( ! newdata . SequenceEqual ( zerodata ) ) return true ;
System . Media . SystemSounds . Exclamation . Play ( ) ;
return false ;
2014-07-20 04:28:35 +00:00
}
return true ;
}
private void changeDataSource ( object sender , EventArgs e )
{
int sourceindex = CB_Source . SelectedIndex ;
B_Add . Enabled = true ;
if ( sourceindex = = 0 )
{
// Hide Box/Etc
CB_Box . Visible = false ;
L_Box . Visible = false ;
CB_Slot . Visible = false ;
L_Slot . Visible = false ;
2014-07-26 21:56:06 +00:00
2014-07-24 16:42:40 +00:00
TB_Write . Text = ( 0x27A00 - 0x5400 ) . ToString ( "X8" ) ; // Box 1, Slot 1
2014-07-20 04:28:35 +00:00
}
else if ( sourceindex = = 1 )
{
2014-12-23 06:39:22 +00:00
CB_Box . Visible = L_Box . Visible = true ;
CB_Slot . Visible = L_Slot . Visible = true ;
2014-07-20 04:28:35 +00:00
L_Slot . Text = "Slot:" ;
CB_Slot . Items . Clear ( ) ;
for ( int i = 1 ; i < = 30 ; i + + )
CB_Slot . Items . Add ( i . ToString ( ) ) ;
CB_Slot . SelectedIndex = 0 ;
2014-07-24 16:42:40 +00:00
TB_Write . Text = ( 0x27A00 - 0x5400 ) . ToString ( "X8" ) ; // Box 1, Slot 1
2014-07-20 04:28:35 +00:00
}
else if ( sourceindex = = 2 )
{
2014-12-23 06:39:22 +00:00
CB_Box . Visible = L_Box . Visible = false ;
CB_Slot . Visible = L_Slot . Visible = true ;
2014-07-20 04:28:35 +00:00
L_Slot . Text = "Card:" ;
// Set up cards
CB_Slot . Items . Clear ( ) ;
for ( int i = 1 ; i < = 24 ; i + + )
CB_Slot . Items . Add ( i . ToString ( ) ) ;
CB_Slot . SelectedIndex = 0 ;
2014-07-24 16:42:40 +00:00
TB_Write . Text = ( 0x22000 - 0x5400 ) . ToString ( "X8" ) ; // WC Slot 1
2014-07-20 04:28:35 +00:00
}
}
2014-10-10 02:59:57 +00:00
2014-07-20 04:28:35 +00:00
private void B_Add_Click ( object sender , EventArgs e )
{
// Add the new code to the textbox.
if ( ! loaddata ( ) ) return ;
2014-10-10 02:59:57 +00:00
uint writeoffset = Util . getHEXval ( TB_Write ) ;
2014-07-20 04:28:35 +00:00
2014-07-24 16:42:40 +00:00
for ( int i = 0 ; i < newdata . Length / 4 ; i + + )
{
RTB_Code . AppendText ( ( writeoffset + i * 4 + 0x20000000 ) . ToString ( "X8" ) + " " ) ;
2014-12-11 07:00:25 +00:00
RTB_Code . AppendText ( BitConverter . ToUInt32 ( newdata , i * 4 ) . ToString ( "X8" ) + Environment . NewLine ) ;
2014-07-20 04:28:35 +00:00
}
2014-07-24 16:42:40 +00:00
// Mat's Code - Unfinished
//for (int i = 0; i < newdata.Length / (4); i++)
//{
// // Add Operator
// RTB_Code.AppendText("00000001 "); // 01 00 00 00
// RTB_Code.AppendText((writeoffset + i * 4).ToString("X8") + " ");
2014-12-11 07:00:25 +00:00
// RTB_Code.AppendText(BitConverter.ToUInt32(newdata,i*4).ToString("X8") + Environment.NewLine);
2014-07-24 16:42:40 +00:00
//}
2014-07-20 04:28:35 +00:00
}
private void B_Clear_Click ( object sender , EventArgs e )
{
RTB_Code . Clear ( ) ;
}
private void B_Load_Click ( object sender , EventArgs e )
{
2015-03-11 01:44:51 +00:00
OpenFileDialog ofd = new OpenFileDialog { Filter = "Code File|*.bin" } ;
2015-03-12 04:44:12 +00:00
if ( ofd . ShowDialog ( ) ! = DialogResult . OK ) return ;
2014-07-20 04:28:35 +00:00
2015-03-12 04:44:12 +00:00
string path = ofd . FileName ;
byte [ ] ncf = File . ReadAllBytes ( path ) ;
uint length = BitConverter . ToUInt32 ( ncf , 0 ) ;
if ( ncf . Length ! = length + 4 )
{
Util . Error ( "Not a valid code file." ) ;
return ;
}
if ( RTB_Code . Text . Length > 0 )
{
DialogResult ld = Util . Prompt ( MessageBoxButtons . YesNo , "Replace current code?" ) ;
if ( ld = = DialogResult . Yes )
RTB_Code . Clear ( ) ;
else if ( ld ! = DialogResult . No )
2014-07-20 04:28:35 +00:00
return ;
2015-03-12 04:44:12 +00:00
}
for ( int i = 4 ; i < = ncf . Length - 12 ; i + = 12 )
{
RTB_Code . AppendText ( BitConverter . ToUInt32 ( ncf , i + 0 * 4 ) . ToString ( "X8" ) + " " ) ;
RTB_Code . AppendText ( BitConverter . ToUInt32 ( ncf , i + 1 * 4 ) . ToString ( "X8" ) + " " ) ;
RTB_Code . AppendText ( BitConverter . ToUInt32 ( ncf , i + 2 * 4 ) . ToString ( "X8" ) + Environment . NewLine ) ;
2014-07-20 04:28:35 +00:00
}
}
private void B_Save_Click ( object sender , EventArgs e )
{
// Gotta read in the textbox.
if ( RTB_Code . Text . Length < 1 ) return ;
2014-12-12 05:45:01 +00:00
byte [ ] ncf = new byte [ 4 + ( RTB_Code . Lines . Count ( ) - 1 ) * ( 3 * 4 ) ] ;
2014-07-20 04:28:35 +00:00
Array . Copy ( BitConverter . GetBytes ( ncf . Length - 4 ) , ncf , 4 ) ;
for ( int i = 0 ; i < RTB_Code . Lines . Count ( ) - 1 ; i + + )
{
string line = RTB_Code . Lines [ i ] ;
string [ ] rip = Regex . Split ( line , " " ) ;
// Write the 3 u32's to an array.
Array . Copy ( BitConverter . GetBytes ( UInt32 . Parse ( rip [ 0 ] , NumberStyles . HexNumber ) ) , 0 , ncf , 4 + i * 12 + 0 , 4 ) ;
Array . Copy ( BitConverter . GetBytes ( UInt32 . Parse ( rip [ 1 ] , NumberStyles . HexNumber ) ) , 0 , ncf , 4 + i * 12 + 4 , 4 ) ;
Array . Copy ( BitConverter . GetBytes ( UInt32 . Parse ( rip [ 2 ] , NumberStyles . HexNumber ) ) , 0 , ncf , 4 + i * 12 + 8 , 4 ) ;
}
2015-03-11 01:44:51 +00:00
SaveFileDialog sfd = new SaveFileDialog { FileName = "code.bin" , Filter = "Code File|*.bin" } ;
2015-03-12 04:44:12 +00:00
if ( sfd . ShowDialog ( ) ! = DialogResult . OK ) return ;
string path = sfd . FileName ;
if ( File . Exists ( path ) )
2014-07-20 04:35:06 +00:00
{
2015-03-12 04:44:12 +00:00
// File already exists, save a .bak
byte [ ] backupfile = File . ReadAllBytes ( path ) ;
File . WriteAllBytes ( path + ".bak" , backupfile ) ;
2014-07-20 04:35:06 +00:00
}
2015-03-12 04:44:12 +00:00
File . WriteAllBytes ( path , ncf ) ;
2014-07-19 23:56:40 +00:00
}
2014-07-26 21:56:06 +00:00
private void B_Copy_Click ( object sender , EventArgs e )
{
2014-07-28 01:53:06 +00:00
if ( RTB_Code . Text . Length > 0 )
Clipboard . SetText ( RTB_Code . Text ) ;
else
{
B_Diff . PerformClick ( ) ;
try
{
Clipboard . SetText ( RTB_Code . Text ) ;
2014-12-11 06:50:40 +00:00
Util . Alert ( "Code generated and copied to clipboard!" , "Next time click [Create Diff] first." ) ;
2014-07-28 01:53:06 +00:00
}
catch
2014-12-11 06:50:40 +00:00
{ Util . Alert ( "No code created!" , "Click [Create Diff], then make sure that data appears in the Text Box below. If no code appears, then you didn't save your changes." , "Be sure to Set the Pokemon you edited back into a Box/Party slot!" ) ; }
2014-07-28 01:53:06 +00:00
}
2014-07-26 21:56:06 +00:00
}
private void B_Diff_Click ( object sender , EventArgs e )
{
2014-07-27 03:21:31 +00:00
string result = "" ;
2014-07-26 21:56:06 +00:00
RTB_Code . Clear ( ) ;
byte [ ] cybersav = m_parent . cyberSAV ;
byte [ ] editedsav = m_parent . savefile ;
2014-12-12 05:45:01 +00:00
byte [ ] newcyber = new byte [ m_parent . cyberSAV . Length ] ;
2014-11-25 03:53:10 +00:00
Array . Copy ( editedsav , 0x5400 , newcyber , 0 , newcyber . Length ) ;
int boxoffset = 0x22600 ;
if ( m_parent . savegame_oras ) boxoffset = 0x33000 ;
if ( ! m_parent . cybergadget ) Array . Copy ( editedsav , m_parent . savindex * 0x7F000 + 0x5400 , newcyber , 0 , newcyber . Length ) ;
2014-07-26 21:56:06 +00:00
2014-08-05 01:48:03 +00:00
int lines = 0 ; // 65400
2014-11-25 03:53:10 +00:00
for ( int i = 0 ; i < newcyber . Length - 0x200 ; i + = 4 )
2014-07-26 21:56:06 +00:00
{
2014-08-05 01:48:03 +00:00
// Skip Party and Boxes
2014-08-07 00:10:51 +00:00
if ( i = = 0x14200 ) i + = ( 260 * 6 + 4 ) ; // +4 to skip over party count
2014-11-25 03:53:10 +00:00
if ( i = = boxoffset ) i + = ( 232 * 30 * 31 ) ;
2015-03-12 04:44:12 +00:00
if ( BitConverter . ToUInt32 ( cybersav , i ) = = BitConverter . ToUInt32 ( newcyber , i ) ) continue ;
2014-08-05 01:48:03 +00:00
2015-03-12 04:44:12 +00:00
result + = ( ( 0x20000000 + i ) . ToString ( "X8" ) + " " ) ;
result + = ( BitConverter . ToUInt32 ( newcyber , i ) . ToString ( "X8" ) + Environment . NewLine ) ;
lines + + ;
if ( ( lines % 128 = = 0 ) & & CHK_Break . Checked )
{ result + = ( Environment . NewLine + "--- Segment " + ( lines / 128 + 1 ) + " ---" + Environment . NewLine + Environment . NewLine ) ; }
if ( lines > 10000 ) goto toomany ;
2014-07-26 21:56:06 +00:00
}
2014-08-05 01:48:03 +00:00
// Loop Through Party
for ( int i = 0x14200 ; i < 0x14200 + 260 * 6 ; i + = 260 )
{
2014-12-12 05:45:01 +00:00
byte [ ] newdata = new byte [ 260 ] ; Array . Copy ( newcyber , i , newdata , 0 , 260 ) ;
byte [ ] olddata = new byte [ 260 ] ; Array . Copy ( cybersav , i , olddata , 0 , 260 ) ;
2015-03-12 04:44:12 +00:00
if ( newdata . SequenceEqual ( olddata ) ) continue ;
for ( int z = 0 ; z < newdata . Length ; z + = 4 )
2014-08-05 01:48:03 +00:00
{
2015-03-12 04:44:12 +00:00
result + = ( ( 0x20000000 + i + z ) . ToString ( "X8" ) + " " ) ;
result + = ( BitConverter . ToUInt32 ( newdata , z ) . ToString ( "X8" ) + Environment . NewLine ) ;
lines + + ;
if ( ( lines % 128 = = 0 ) & & CHK_Break . Checked )
{ result + = ( Environment . NewLine + "--- Segment " + ( lines / 128 + 1 ) + " ---" + Environment . NewLine + Environment . NewLine ) ; }
if ( lines > 10000 ) goto toomany ;
2014-08-05 01:48:03 +00:00
}
}
// Fix Party Count if Necessary
if ( cybersav [ 0x14818 ] ! = newcyber [ 0x14818 ] )
{
result + = ( ( 0x00000000 + 0x14818 ) . ToString ( "X8" ) + " " ) ;
2014-12-11 07:00:25 +00:00
result + = ( newcyber [ 0x14818 ] . ToString ( "X8" ) + Environment . NewLine ) ;
2014-08-05 01:48:03 +00:00
lines + + ;
if ( ( lines % 128 = = 0 ) & & CHK_Break . Checked )
2015-03-11 01:44:51 +00:00
{ result + = ( Environment . NewLine + "--- Segment " + ( lines / 128 + 1 ) + " ---" + Environment . NewLine + Environment . NewLine ) ; }
2014-08-05 01:48:03 +00:00
if ( lines > 10000 ) goto toomany ;
}
// Loop Through Boxes
2014-11-25 03:53:10 +00:00
for ( int i = boxoffset ; i < boxoffset + ( 232 * 30 * 31 ) ; i + = 232 )
2014-08-05 01:48:03 +00:00
{
2014-12-12 05:45:01 +00:00
byte [ ] newdata = new byte [ 232 ] ; Array . Copy ( newcyber , i , newdata , 0 , 232 ) ;
byte [ ] olddata = new byte [ 232 ] ; Array . Copy ( cybersav , i , olddata , 0 , 232 ) ;
2015-03-12 04:44:12 +00:00
if ( newdata . SequenceEqual ( olddata ) ) continue ;
for ( int z = 0 ; z < newdata . Length ; z + = 4 )
2014-08-05 01:48:03 +00:00
{
2015-03-12 04:44:12 +00:00
result + = ( ( 0x20000000 + i + z ) . ToString ( "X8" ) + " " ) ;
result + = ( BitConverter . ToUInt32 ( newdata , z ) . ToString ( "X8" ) + Environment . NewLine ) ;
lines + + ;
if ( ( lines % 128 = = 0 ) & & CHK_Break . Checked )
{ result + = ( Environment . NewLine + "--- Segment " + ( lines / 128 + 1 ) + " ---" + Environment . NewLine + Environment . NewLine ) ; }
if ( lines > 10000 ) goto toomany ;
2014-08-05 01:48:03 +00:00
}
}
2014-07-28 01:30:54 +00:00
if ( ( lines / 128 > 0 ) & & CHK_Break . Checked )
2014-07-27 01:00:17 +00:00
{
2015-03-12 04:44:12 +00:00
Util . Alert ( String . Format ( "{0} Code Segments." , ( 1 + ( lines / 128 ) ) ) , String . Format ( "{0} Lines." , lines ) ) ;
2014-07-27 01:00:17 +00:00
}
2014-07-27 03:21:31 +00:00
RTB_Code . Text = result ; return ;
2014-08-05 01:48:03 +00:00
2014-07-27 03:21:31 +00:00
toomany :
{
2014-12-11 06:50:40 +00:00
Util . Alert ( "Too many differences detected." , "Export your save instead." ) ;
2014-07-27 03:21:31 +00:00
}
2014-07-26 21:56:06 +00:00
}
2014-07-28 22:28:06 +00:00
// Import
public byte [ ] returnArray { get ; set ; }
private void B_Paste_Click ( object sender , EventArgs e )
{
RTB_Code . Text = Clipboard . GetText ( ) ;
}
private void B_Import_Click ( object sender , EventArgs e )
{
// Gotta read in the textbox.
if ( RTB_Code . Text . Length < 1 ) return ;
2014-12-12 05:45:01 +00:00
byte [ ] data = new byte [ 0 ] ;
2014-07-28 22:28:06 +00:00
// Get Actual Lines
for ( int i = 0 ; i < RTB_Code . Lines . Count ( ) ; i + + )
{
2015-03-12 04:44:12 +00:00
if ( RTB_Code . Lines [ i ] . Length < = 0 ) continue ;
if ( RTB_Code . Lines [ i ] . Length < = 2 * 8 & & RTB_Code . Lines [ i ] . Length > 2 * 8 + 2 )
{ Util . Error ( "Invalid code pasted (Type)" ) ; return ; }
try
2014-07-28 22:28:06 +00:00
{
2015-03-12 04:44:12 +00:00
// Grab Line Data
string line = RTB_Code . Lines [ i ] ;
string [ ] rip = Regex . Split ( line , " " ) ;
Array . Resize ( ref data , data . Length + 4 ) ;
Array . Copy ( BitConverter . GetBytes ( UInt32 . Parse ( rip [ 1 ] , NumberStyles . HexNumber ) ) , 0 , data , data . Length - 4 , 4 ) ;
2014-07-28 22:28:06 +00:00
}
2015-03-12 04:44:12 +00:00
catch ( Exception x )
{ Util . Error ( "Invalid code pasted (Content):" , x . ToString ( ) ) ; return ; }
2014-07-28 22:28:06 +00:00
}
// Go over the data
if ( ( data . Length = = 232 - 4 ) | | ( data . Length = = 260 - 4 ) )
{
Array . Resize ( ref data , data . Length + 4 ) ;
Array . Copy ( data , 0 , data , 4 , data . Length ) ;
data [ 0 ] = data [ 1 ] = data [ 2 ] = data [ 3 ] = 0 ;
}
if ( ( data . Length = = 232 ) | | ( data . Length = = 260 ) )
2015-03-11 01:44:51 +00:00
{ returnArray = data ; Close ( ) ; }
else { Util . Error ( "Invalid code pasted (Length)" ) ; }
2014-07-28 22:28:06 +00:00
}
2014-07-19 23:56:40 +00:00
}
}