2016-06-20 04:22:43 +00:00
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using System.IO ;
using System.Linq ;
using System.Windows.Forms ;
2017-01-08 07:54:09 +00:00
using PKHeX.Core ;
2016-06-20 04:22:43 +00:00
2017-01-08 07:54:09 +00:00
namespace PKHeX.WinForms
2016-06-20 04:22:43 +00:00
{
public partial class SAV_EventFlags : Form
{
2017-05-23 04:55:05 +00:00
private readonly SaveFile Origin ;
private readonly SaveFile SAV ;
public SAV_EventFlags ( SaveFile sav )
2016-06-20 04:22:43 +00:00
{
2017-05-23 04:55:05 +00:00
SAV = ( Origin = sav ) . Clone ( ) ;
2016-06-20 04:22:43 +00:00
InitializeComponent ( ) ;
DragEnter + = tabMain_DragEnter ;
DragDrop + = tabMain_DragDrop ;
flags = SAV . EventFlags ;
Constants = SAV . EventConsts ;
CB_Stats . Items . Clear ( ) ;
for ( int i = 0 ; i < Constants . Length ; i + + )
CB_Stats . Items . Add ( i . ToString ( ) ) ;
2016-07-24 22:04:04 +00:00
TLP_Flags . SuspendLayout ( ) ;
TLP_Const . SuspendLayout ( ) ;
2017-01-08 07:54:09 +00:00
TLP_Flags . Scroll + = WinFormsUtil . PanelScroll ;
TLP_Const . Scroll + = WinFormsUtil . PanelScroll ;
2016-07-31 03:57:45 +00:00
TLP_Flags . Controls . Clear ( ) ;
2016-06-20 04:22:43 +00:00
TLP_Const . Controls . Clear ( ) ;
addFlagList ( getStringList ( "flags" ) ) ;
addConstList ( getStringList ( "const" ) ) ;
2016-07-24 22:04:04 +00:00
TLP_Flags . ResumeLayout ( ) ;
TLP_Const . ResumeLayout ( ) ;
2017-01-08 07:54:09 +00:00
WinFormsUtil . TranslateInterface ( this , Main . curlanguage ) ;
2016-11-14 13:31:33 +00:00
Text = $"Event Flag Editor ({gamePrefix.ToUpper()})" ;
2016-06-20 04:22:43 +00:00
CB_Stats . SelectedIndex = 0 ;
2016-12-30 00:24:01 +00:00
NUD_Flag . Maximum = flags . Length - 1 ;
NUD_Flag . Text = "0" ;
2016-06-20 04:22:43 +00:00
}
private readonly bool [ ] flags ;
private readonly ushort [ ] Constants ;
private const string flagTag = "bool_" ;
private const string constTag = "const_" ;
2016-11-14 13:31:33 +00:00
private const string constCBTag = "cbconst_" ;
2016-06-20 04:22:43 +00:00
private const string flagLabelTag = "flag_" ;
private const string constLabelTag = "L_" ;
private bool editing ;
private int constEntry = - 1 ;
2016-11-12 20:08:50 +00:00
private string gamePrefix = "unk" ;
2016-06-20 04:22:43 +00:00
2016-11-12 22:57:54 +00:00
private const ulong MagearnaConst = 0xCBE05F18356504AC ;
2016-06-20 04:22:43 +00:00
private void B_Cancel_Click ( object sender , EventArgs e )
{
Close ( ) ;
}
private void B_Save_Click ( object sender , EventArgs e )
{
// Gather Updated Flags
2016-07-28 22:53:13 +00:00
foreach ( CheckBox flag in TLP_Flags . Controls . OfType < CheckBox > ( ) )
2016-06-20 04:22:43 +00:00
flags [ getControlNum ( flag ) ] = flag . Checked ;
SAV . EventFlags = flags ;
2016-11-12 22:57:54 +00:00
HandleSpecialFlags ( ) ;
2016-06-20 04:22:43 +00:00
// Copy back Constants
changeConstantIndex ( null , null ) ; // Trigger Saving
SAV . EventConsts = Constants ;
2017-05-23 04:55:05 +00:00
SAV . Data . CopyTo ( Origin . Data , 0 ) ;
Origin . Edited = true ;
2016-06-20 04:22:43 +00:00
Close ( ) ;
}
2016-11-12 22:57:54 +00:00
private void HandleSpecialFlags ( )
{
if ( SAV . SM ) // Ensure magearna event flag has magic constant
{
2016-12-30 00:24:01 +00:00
BitConverter . GetBytes ( flags [ 3100 ] ? MagearnaConst : 0 ) . CopyTo ( SAV . Data , ( ( SAV7 ) SAV ) . QRSaveData + 0x168 ) ;
2016-11-12 22:57:54 +00:00
}
}
2016-06-20 04:22:43 +00:00
private string [ ] getStringList ( string type )
{
2016-11-12 20:08:50 +00:00
switch ( SAV . Version )
{
case GameVersion . X :
case GameVersion . Y :
gamePrefix = "xy" ;
break ;
case GameVersion . OR :
case GameVersion . AS :
gamePrefix = "oras" ;
break ;
case GameVersion . SN :
case GameVersion . MN :
gamePrefix = "sm" ;
break ;
2017-05-13 01:15:04 +00:00
case GameVersion . DP :
gamePrefix = "dp" ;
break ;
2017-06-10 13:12:51 +00:00
case GameVersion . Pt :
gamePrefix = "pt" ;
break ;
2017-05-19 02:20:19 +00:00
case GameVersion . HGSS :
gamePrefix = "hgss" ;
break ;
2017-05-26 09:05:58 +00:00
case GameVersion . BW :
gamePrefix = "bw" ;
break ;
2017-06-02 15:43:08 +00:00
case GameVersion . B2W2 :
gamePrefix = "b2w2" ;
break ;
2016-11-12 20:08:50 +00:00
default :
return null ;
}
return Util . getStringList ( $"{type}_{gamePrefix}" ) ;
2016-06-20 04:22:43 +00:00
}
private void addFlagList ( string [ ] list )
{
if ( list = = null | | list . Length = = 0 )
{
TLP_Flags . Controls . Add ( new Label { Text = "Needs more research." , Name = "TLP_Flags_Research" , ForeColor = Color . Red , AutoSize = true } , 0 , 0 ) ;
return ;
}
// Get list
List < int > num = new List < int > ( ) ;
List < string > desc = new List < string > ( ) ;
foreach ( string [ ] split in list . Select ( s = > s . Split ( '\t' ) ) . Where ( split = > split . Length = = 2 ) )
{
try
{
int n = Convert . ToInt32 ( split [ 0 ] ) ;
if ( num . Contains ( n ) )
continue ;
num . Add ( n ) ;
desc . Add ( split [ 1 ] ) ;
} catch { }
}
if ( num . Count = = 0 )
{
TLP_Flags . Controls . Add ( new Label { Text = "Needs more research." , Name = "TLP_Flags_Research" , ForeColor = Color . Red , AutoSize = true } , 0 , 0 ) ;
return ;
}
for ( int i = 0 ; i < num . Count ; i + + )
{
var lbl = new Label
{
Text = desc [ i ] ,
2016-11-12 20:08:50 +00:00
Name = gamePrefix + flagLabelTag + num [ i ] . ToString ( "0000" ) ,
2016-06-20 04:22:43 +00:00
Margin = Padding . Empty ,
AutoSize = true
} ;
var chk = new CheckBox
{
Name = flagTag + num [ i ] . ToString ( "0000" ) ,
CheckAlign = ContentAlignment . MiddleLeft ,
Margin = Padding . Empty ,
Checked = flags [ num [ i ] ] ,
AutoSize = true
} ;
chk . CheckStateChanged + = toggleFlag ;
2016-07-29 15:31:02 +00:00
lbl . Click + = ( sender , e ) = > { chk . Checked ^ = true ; } ;
2016-06-20 04:22:43 +00:00
TLP_Flags . Controls . Add ( chk , 0 , i ) ;
TLP_Flags . Controls . Add ( lbl , 1 , i ) ;
}
}
private void addConstList ( string [ ] list )
{
if ( list = = null | | list . Length = = 0 )
{
TLP_Const . Controls . Add ( new Label { Text = "Needs more research." , Name = "TLP_Const_Research" , ForeColor = Color . Red , AutoSize = true } , 0 , 0 ) ;
return ;
}
// Get list
List < int > num = new List < int > ( ) ;
List < string > desc = new List < string > ( ) ;
2016-11-14 13:31:33 +00:00
List < string > enums = new List < string > ( ) ;
2016-06-20 04:22:43 +00:00
2016-11-14 13:31:33 +00:00
foreach ( string [ ] split in list . Select ( s = > s . Split ( '\t' ) ) . Where ( split = > split . Length = = 2 | | split . Length = = 3 ) )
2016-06-20 04:22:43 +00:00
{
try
{
int n = Convert . ToInt32 ( split [ 0 ] ) ;
if ( num . Contains ( n ) )
continue ;
num . Add ( n ) ;
desc . Add ( split [ 1 ] ) ;
2016-12-30 00:24:01 +00:00
enums . Add ( split . Length = = 3 ? split [ 2 ] : "" ) ;
2016-06-20 04:22:43 +00:00
} catch { }
}
if ( num . Count = = 0 )
{
TLP_Const . Controls . Add ( new Label { Text = "Needs more research." , Name = "TLP_Const_Research" , ForeColor = Color . Red , AutoSize = true } , 0 , 0 ) ;
return ;
}
for ( int i = 0 ; i < num . Count ; i + + )
{
var lbl = new Label
{
Text = desc [ i ] ,
2016-11-12 20:08:50 +00:00
Name = gamePrefix + constLabelTag + num [ i ] . ToString ( "0000" ) ,
2016-06-20 04:22:43 +00:00
Margin = Padding . Empty ,
AutoSize = true
} ;
var mtb = new NumericUpDown
{
2016-08-25 00:46:24 +00:00
Maximum = ushort . MaxValue ,
Minimum = ushort . MinValue ,
2016-06-20 04:22:43 +00:00
Value = Constants [ num [ i ] ] ,
Name = constTag + num [ i ] . ToString ( "0000" ) ,
Margin = Padding . Empty ,
2016-11-14 13:31:33 +00:00
Width = 50 ,
2016-06-20 04:22:43 +00:00
} ;
2016-11-14 13:31:33 +00:00
var map = new [ ] { new { Text = "Custom" , Value = - 1 } } . ToList ( ) ;
if ( ! string . IsNullOrWhiteSpace ( enums [ i ] ) )
{
foreach ( var entry in enums [ i ] . Split ( ',' ) )
{
var spl = entry . Split ( ':' ) ;
2016-12-30 00:24:01 +00:00
map . Add ( new { Text = spl [ 1 ] , Value = Convert . ToInt32 ( spl [ 0 ] ) } ) ;
2016-11-14 13:31:33 +00:00
}
}
2016-12-30 00:24:01 +00:00
var cb = new ComboBox
2016-11-14 13:31:33 +00:00
{
ValueMember = "Value" ,
DisplayMember = "Text" ,
Margin = Padding . Empty ,
Width = 80 ,
Name = constCBTag + num [ i ] . ToString ( "0000" ) ,
DropDownStyle = ComboBoxStyle . DropDownList ,
2016-12-30 00:24:01 +00:00
BindingContext = BindingContext ,
DataSource = map ,
SelectedIndex = 0
2016-11-14 13:31:33 +00:00
} ;
cb . SelectedValueChanged + = toggleConst ;
2016-06-20 04:22:43 +00:00
mtb . TextChanged + = toggleConst ;
2016-11-14 13:31:33 +00:00
TLP_Const . Controls . Add ( lbl , 0 , i ) ;
TLP_Const . Controls . Add ( cb , 1 , i ) ;
TLP_Const . Controls . Add ( mtb , 2 , i ) ;
2016-12-30 00:24:01 +00:00
if ( map . Any ( val = > val . Value = = Constants [ num [ i ] ] ) )
2016-11-14 13:31:33 +00:00
{
cb . SelectedValue = ( int ) Constants [ num [ i ] ] ;
}
2016-06-20 04:22:43 +00:00
}
}
2016-11-12 20:08:50 +00:00
private int getControlNum ( Control c )
2016-06-20 04:22:43 +00:00
{
try
{
2016-11-12 20:08:50 +00:00
string source = c . Name . Split ( '_' ) [ 1 ] ;
return Convert . ToInt32 ( source ) ;
2016-06-20 04:22:43 +00:00
}
catch { return 0 ; }
}
private void changeCustomBool ( object sender , EventArgs e )
{
if ( editing )
return ;
editing = true ;
2016-12-30 00:24:01 +00:00
flags [ ( int ) NUD_Flag . Value ] = c_CustomFlag . Checked ;
CheckBox c = TLP_Flags . Controls [ flagTag + NUD_Flag . Value . ToString ( "0000" ) ] as CheckBox ;
2016-06-20 04:22:43 +00:00
if ( c ! = null )
{
c . Checked = c_CustomFlag . Checked ;
}
editing = false ;
}
private void changeCustomFlag ( object sender , EventArgs e )
{
2016-12-30 00:24:01 +00:00
int flag = ( int ) NUD_Flag . Value ;
2016-06-20 04:22:43 +00:00
if ( flag > = flags . Length )
{
c_CustomFlag . Checked = false ;
c_CustomFlag . Enabled = false ;
2016-12-30 00:24:01 +00:00
NUD_Flag . BackColor = Color . Red ;
2016-06-20 04:22:43 +00:00
}
else
{
c_CustomFlag . Enabled = true ;
2016-12-30 00:24:01 +00:00
NUD_Flag . ResetBackColor ( ) ;
2016-06-20 04:22:43 +00:00
c_CustomFlag . Checked = flags [ flag ] ;
}
}
private void changeCustomFlag ( object sender , KeyEventArgs e )
{
changeCustomFlag ( null , ( EventArgs ) e ) ;
}
private void toggleFlag ( object sender , EventArgs e )
{
if ( editing )
return ;
editing = true ;
int flagnum = getControlNum ( ( CheckBox ) sender ) ;
flags [ flagnum ] = ( ( CheckBox ) sender ) . Checked ;
2016-12-30 00:24:01 +00:00
if ( NUD_Flag . Value = = flagnum )
2016-06-20 04:22:43 +00:00
c_CustomFlag . Checked = flags [ flagnum ] ;
editing = false ;
}
private void changeCustomConst ( object sender , EventArgs e )
{
if ( editing )
return ;
editing = true ;
2017-03-20 07:03:31 +00:00
2016-06-20 04:22:43 +00:00
Constants [ CB_Stats . SelectedIndex ] = ( ushort ) ( Util . ToUInt32 ( ( ( MaskedTextBox ) sender ) . Text ) & 0xFFFF ) ;
MaskedTextBox m = TLP_Flags . Controls [ constTag + CB_Stats . SelectedIndex . ToString ( "0000" ) ] as MaskedTextBox ;
if ( m ! = null )
m . Text = MT_Stat . Text ;
editing = false ;
}
private void changeConstantIndex ( object sender , EventArgs e )
{
if ( constEntry > - 1 ) // Set Entry
Constants [ constEntry ] = ( ushort ) Math . Min ( Util . ToUInt32 ( MT_Stat . Text ) , 0xFFFF ) ;
constEntry = CB_Stats . SelectedIndex ; // Get Entry
MT_Stat . Text = Constants [ constEntry ] . ToString ( ) ;
}
private void toggleConst ( object sender , EventArgs e )
{
if ( editing )
return ;
2016-11-14 13:31:33 +00:00
int constnum = getControlNum ( ( Control ) sender ) ;
if ( sender is ComboBox )
{
var nud = ( NumericUpDown ) TLP_Const . GetControlFromPosition ( 2 , TLP_Const . GetRow ( ( Control ) sender ) ) ;
var sel_val = ( int ) ( ( ComboBox ) sender ) . SelectedValue ;
editing = true ;
nud . Enabled = sel_val = = - 1 ;
if ( sel_val ! = - 1 )
nud . Value = ( ushort ) sel_val ;
Constants [ constnum ] = ( ushort ) ( Util . ToUInt32 ( nud . Text ) & 0xFFFF ) ;
editing = false ;
}
else if ( sender is NumericUpDown )
{
editing = true ;
Constants [ constnum ] = ( ushort ) ( Util . ToUInt32 ( ( ( NumericUpDown ) sender ) . Text ) & 0xFFFF ) ;
if ( constnum = = CB_Stats . SelectedIndex )
MT_Stat . Text = Constants [ constnum ] . ToString ( ) ;
editing = false ;
}
2016-06-20 04:22:43 +00:00
}
private void changeSAV ( object sender , EventArgs e )
{
if ( TB_NewSAV . Text . Length > 0 & & TB_OldSAV . Text . Length > 0 )
diffSaves ( ) ;
}
private void openSAV ( object sender , EventArgs e )
{
OpenFileDialog ofd = new OpenFileDialog ( ) ;
if ( ofd . ShowDialog ( ) = = DialogResult . OK )
loadSAV ( sender , ofd . FileName ) ;
}
private void loadSAV ( object sender , string path )
{
if ( sender = = B_LoadOld )
TB_OldSAV . Text = path ;
else
TB_NewSAV . Text = path ;
}
private void diffSaves ( )
{
2017-01-08 07:54:09 +00:00
if ( ! File . Exists ( TB_OldSAV . Text ) ) { WinFormsUtil . Alert ( "Save 1 path invalid." ) ; return ; }
if ( ! File . Exists ( TB_NewSAV . Text ) ) { WinFormsUtil . Alert ( "Save 2 path invalid." ) ; return ; }
if ( new FileInfo ( TB_OldSAV . Text ) . Length > 0x100000 ) { WinFormsUtil . Alert ( "Save 1 file invalid." ) ; return ; }
if ( new FileInfo ( TB_NewSAV . Text ) . Length > 0x100000 ) { WinFormsUtil . Alert ( "Save 2 file invalid." ) ; return ; }
2016-06-20 04:22:43 +00:00
SaveFile s1 = SaveUtil . getVariantSAV ( File . ReadAllBytes ( TB_OldSAV . Text ) ) ;
SaveFile s2 = SaveUtil . getVariantSAV ( File . ReadAllBytes ( TB_NewSAV . Text ) ) ;
2017-01-08 07:54:09 +00:00
if ( s1 . GetType ( ) ! = s2 . GetType ( ) ) { WinFormsUtil . Alert ( "Save types are different." , $"S1: {s1.GetType().Name}" , $"S2: {s2.GetType().Name}" ) ; return ; }
if ( s1 . Version ! = s2 . Version ) { WinFormsUtil . Alert ( "Save versions are different." , $"S1: {s1.Version}" , $"S2: {s2.Version}" ) ; return ; }
2016-06-20 04:22:43 +00:00
string tbIsSet = "" ;
string tbUnSet = "" ;
try
{
bool [ ] oldBits = s1 . EventFlags ;
bool [ ] newBits = s2 . EventFlags ;
if ( oldBits . Length ! = newBits . Length )
2017-01-08 07:54:09 +00:00
{ WinFormsUtil . Alert ( "Event flag lengths for games are different." , $"S1: {(GameVersion)s1.Game}" , $"S2: {(GameVersion)s2.Game}" ) ; return ; }
2016-06-20 04:22:43 +00:00
for ( int i = 0 ; i < oldBits . Length ; i + + )
{
if ( oldBits [ i ] = = newBits [ i ] ) continue ;
if ( newBits [ i ] )
tbIsSet + = i . ToString ( "0000" ) + "," ;
else
tbUnSet + = i . ToString ( "0000" ) + "," ;
}
}
catch ( Exception e )
{
2017-01-08 07:54:09 +00:00
WinFormsUtil . Error ( "An unexpected error has occurred." , e ) ;
2016-06-20 04:22:43 +00:00
Console . Write ( e ) ;
}
TB_IsSet . Text = tbIsSet ;
TB_UnSet . Text = tbUnSet ;
string r = "" ;
try
{
ushort [ ] oldConst = s1 . EventConsts ;
ushort [ ] newConst = s2 . EventConsts ;
if ( oldConst . Length ! = newConst . Length )
2017-01-08 07:54:09 +00:00
{ WinFormsUtil . Alert ( "Event flag lengths for games are different." , $"S1: {(GameVersion)s1.Game}" , $"S2: {(GameVersion)s2.Game}" ) ; return ; }
2016-06-20 04:22:43 +00:00
for ( int i = 0 ; i < newConst . Length ; i + + )
if ( oldConst [ i ] ! = newConst [ i ] )
r + = $"{i}: {oldConst[i]}->{newConst[i]}{Environment.NewLine}" ;
}
catch ( Exception e )
{
2017-01-08 07:54:09 +00:00
WinFormsUtil . Error ( "An unexpected error has occurred." , e ) ;
2016-06-20 04:22:43 +00:00
Console . Write ( e ) ;
}
2017-03-09 07:31:22 +00:00
if ( string . IsNullOrEmpty ( r ) )
{
WinFormsUtil . Alert ( "No Event Constant diff found." ) ;
return ;
}
2017-01-08 07:54:09 +00:00
if ( DialogResult . Yes ! = WinFormsUtil . Prompt ( MessageBoxButtons . YesNo , "Copy Event Constant diff to clipboard?" ) )
2016-06-20 04:22:43 +00:00
return ;
Clipboard . SetText ( r ) ;
}
private void tabMain_DragEnter ( object sender , DragEventArgs e )
{
if ( e . Data . GetDataPresent ( DataFormats . FileDrop ) ) e . Effect = DragDropEffects . Copy ;
}
private void tabMain_DragDrop ( object sender , DragEventArgs e )
{
string [ ] files = ( string [ ] ) e . Data . GetData ( DataFormats . FileDrop ) ;
2017-01-08 07:54:09 +00:00
loadSAV ( WinFormsUtil . Prompt ( MessageBoxButtons . YesNo , "FlagDiff Researcher:" , "Yes: Old Save" + Environment . NewLine + "No: New Save" ) = = DialogResult . Yes ? B_LoadOld : B_LoadNew , files [ 0 ] ) ;
2016-06-20 04:22:43 +00:00
}
}
}