using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Media; using System.Text; using System.Threading; using System.Windows.Forms; using PKHeX.Core; using PKHeX.WinForms.Properties; using System.Configuration; using System.Threading.Tasks; namespace PKHeX.WinForms { public partial class Main : Form { public Main() { #region Initialize Form new Thread(() => new SplashScreen().ShowDialog()).Start(); DragInfo.slotPkmSource = SAV.BlankPKM.EncryptedPartyData; InitializeComponent(); // Check for Updates L_UpdateAvailable.Click += (sender, e) => Process.Start(ThreadPath); new Thread(() => { string data = NetUtil.getStringFromURL(VersionPath); if (data == null) return; try { DateTime upd = DateTime.ParseExact(data, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None); DateTime cur = DateTime.ParseExact(Resources.ProgramVersion, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None); if (upd <= cur) return; string message = $"New Update Available! {upd:d}"; if (InvokeRequired) try { Invoke((MethodInvoker) delegate { L_UpdateAvailable.Visible = true; L_UpdateAvailable.Text = message; }); } catch { L_UpdateAvailable.Visible = true; L_UpdateAvailable.Text = message; } else { L_UpdateAvailable.Visible = true; L_UpdateAvailable.Text = message; } } catch { } }).Start(); setPKMFormatMode(SAV.Generation, SAV.Version); // Set up form properties and arrays. SlotPictureBoxes = new[] { bpkx1, bpkx2, bpkx3, bpkx4, bpkx5, bpkx6, bpkx7, bpkx8, bpkx9, bpkx10,bpkx11,bpkx12, bpkx13,bpkx14,bpkx15,bpkx16,bpkx17,bpkx18, bpkx19,bpkx20,bpkx21,bpkx22,bpkx23,bpkx24, bpkx25,bpkx26,bpkx27,bpkx28,bpkx29,bpkx30, ppkx1, ppkx2, ppkx3, ppkx4, ppkx5, ppkx6, bbpkx1,bbpkx2,bbpkx3,bbpkx4,bbpkx5,bbpkx6, dcpkx1, dcpkx2, gtspkx, fusedpkx,subepkx1,subepkx2,subepkx3, }; relearnPB = new[] { PB_WarnRelearn1, PB_WarnRelearn2, PB_WarnRelearn3, PB_WarnRelearn4 }; movePB = new[] { PB_WarnMove1, PB_WarnMove2, PB_WarnMove3, PB_WarnMove4 }; Label_Species.ResetForeColor(); // Set up Language Selection foreach (var cbItem in main_langlist) CB_MainLanguage.Items.Add(cbItem); // ToolTips for Drag&Drop new ToolTip().SetToolTip(dragout, "PKM QuickSave"); // Box Drag & Drop foreach (PictureBox pb in SlotPictureBoxes) { pb.AllowDrop = true; // The PictureBoxes have their own drag&drop event handlers (pbBoxSlot) pb.GiveFeedback += (sender, e) => { e.UseDefaultCursors = false; }; } dragout.GiveFeedback += (sender, e) => { e.UseDefaultCursors = false; }; GiveFeedback += (sender, e) => { e.UseDefaultCursors = false; }; foreach (TabPage tab in tabMain.TabPages) { tab.AllowDrop = true; tab.DragDrop += tabMain_DragDrop; tab.DragEnter += tabMain_DragEnter; } foreach (TabPage tab in tabBoxMulti.TabPages) { tab.AllowDrop = true; tab.DragDrop += tabMain_DragDrop; tab.DragEnter += tabMain_DragEnter; } GB_OT.Click += clickGT; GB_nOT.Click += clickGT; GB_Daycare.Click += switchDaycare; GB_CurrentMoves.Click += clickMoves; GB_RelearnMoves.Click += clickMoves; TB_Nickname.Font = FontUtil.getPKXFont(11); TB_OT.Font = (Font)TB_Nickname.Font.Clone(); TB_OTt2.Font = (Font)TB_Nickname.Font.Clone(); Menu_Modify.DropDown.Closing += (sender, e) => { if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked) e.Cancel = true; }; Menu_Options.DropDown.Closing += (sender, e) => { if (!Menu_Unicode.Selected) return; if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked) e.Cancel = true; }; // Box to Tabs D&D dragout.AllowDrop = true; FLP_SAVtools.Scroll += WinFormsUtil.PanelScroll; // Add Legality check to right click context menus // ToolStripItem can't be in multiple contextmenus, so put the item back when closing. var cm = new[]{mnuV, mnuVSD}; foreach (var c in cm) { c.Opening += (sender, e) => { var items = ((ContextMenuStrip)sender).Items; if (ModifierKeys == Keys.Control) items.Add(mnuLLegality); else if (items.Contains(mnuLLegality)) items.Remove(mnuLLegality); }; } mnuL.Opening += (sender, e) => { if (mnuL.Items[0] != mnuLLegality) mnuL.Items.Insert(0, mnuLLegality); }; // Load Event Databases refreshMGDB(); #endregion #region Localize & Populate Fields string[] args = Environment.GetCommandLineArgs(); string filename = args.Length > 0 ? Path.GetFileNameWithoutExtension(args[0])?.ToLower() : ""; HaX = filename?.IndexOf("hax", StringComparison.Ordinal) >= 0; bool showChangelog = false; bool BAKprompt = false; int languageID = 1; // English try { ConfigUtil.checkConfig(); loadConfig(out BAKprompt, out showChangelog, out languageID); } catch (ConfigurationErrorsException e) { // Delete the settings if they exist var settingsFilename = (e.InnerException as ConfigurationErrorsException)?.Filename; if (!string.IsNullOrEmpty(settingsFilename) && File.Exists(settingsFilename)) deleteConfig(settingsFilename); else WinFormsUtil.Error("Unable to load settings.", e); } CB_MainLanguage.SelectedIndex = languageID; InitializeFields(); #endregion #region Load Initial File(s) string pkmArg = null; foreach (string arg in args.Skip(1)) // skip .exe { var fi = new FileInfo(arg); if (!fi.Exists) continue; if (PKX.getIsPKM(fi.Length)) pkmArg = arg; else openQuick(arg, force: true); } if (!SAV.Exportable) // No SAV loaded from exe args { string path = null; try { string cgse = ""; string pathCache = CyberGadgetUtil.GetCacheFolder(); if (Directory.Exists(pathCache)) cgse = Path.Combine(pathCache); if (!PathUtilWindows.detectSaveFile(out path, cgse)) WinFormsUtil.Error(path); } catch (Exception ex) { ErrorWindow.ShowErrorDialog("An error occurred while attempting to auto-load your save file.", ex, true); } if (path != null && File.Exists(path)) openQuick(path, force: true); else { openSAV(SAV, null); SAV.Edited = false; // Prevents form close warning from showing until changes are made } } if (pkmArg != null) openQuick(pkmArg, force: true); formInitialized = true; // Splash Screen closes on its own. BringToFront(); WindowState = FormWindowState.Minimized; Show(); WindowState = FormWindowState.Normal; if (HaX) WinFormsUtil.Alert("Illegal mode activated.", "Please behave."); if (showChangelog) new About().ShowDialog(); if (BAKprompt && !Directory.Exists(BackupPath)) promptBackup(); #endregion } #region Important Variables public static SaveFile SAV = SaveUtil.getBlankSAV(GameVersion.SN, "PKHeX"); public static PKM pkm = SAV.BlankPKM; // Tab Pokemon Data Storage private LegalityAnalysis Legality = new LegalityAnalysis(pkm); public static string curlanguage = "en"; public static string[] gendersymbols = { "♂", "♀", "-" }; public static bool unicode; public static volatile bool formInitialized; private static bool fieldsInitialized, fieldsLoaded, loadingSAV; private static int colorizedbox = -1; private static Image colorizedcolor; private static int colorizedslot; public static bool HaX; private static readonly Image mixedHighlight = ImageUtil.ChangeOpacity(Resources.slotSet, 0.5); private static readonly string[] main_langlist = { "日本語", // JPN "English", // ENG "Français", // FRE "Italiano", // ITA "Deutsch", // GER "Español", // SPA "한국어", // KOR "中文", // CHN "Português", // Portuguese }; private static GameVersion origintrack; private readonly PictureBox[] SlotPictureBoxes, movePB, relearnPB; private readonly ToolTip Tip1 = new ToolTip(), Tip2 = new ToolTip(), Tip3 = new ToolTip(), NatureTip = new ToolTip(), EVTip = new ToolTip(); #endregion #region Path Variables public static string WorkingDirectory => WinFormsUtil.IsClickonceDeployed ? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "PKHeX") : Application.StartupPath; public static string DatabasePath => Path.Combine(WorkingDirectory, "pkmdb"); public static string MGDatabasePath => Path.Combine(WorkingDirectory, "mgdb"); private static string BackupPath => Path.Combine(WorkingDirectory, "bak"); private static string TemplatePath => Path.Combine(WorkingDirectory, "template"); private const string ThreadPath = @"https://projectpokemon.org/PKHeX/"; private const string VersionPath = @"https://raw.githubusercontent.com/kwsch/PKHeX/master/PKHeX/Resources/text/version.txt"; #endregion #region //// MAIN MENU FUNCTIONS //// private void loadConfig(out bool BAKprompt, out bool showChangelog, out int languageID) { BAKprompt = false; showChangelog = false; languageID = 1; var Settings = Properties.Settings.Default; Settings.Upgrade(); unicode = Menu_Unicode.Checked = Settings.Unicode; updateUnicode(); SaveFile.SetUpdateDex = Menu_ModifyDex.Checked = Settings.SetUpdateDex; SaveFile.SetUpdatePKM = Menu_ModifyPKM.Checked = Settings.SetUpdatePKM; Menu_FlagIllegal.Checked = Settings.FlagIllegal; Menu_ModifyUnset.Checked = Settings.ModifyUnset; // Select Language string l = Settings.Language; int lang = Array.IndexOf(GameInfo.lang_val, l); if (lang < 0) lang = Array.IndexOf(GameInfo.lang_val, "en"); if (lang > -1) languageID = lang; // Version Check if (Settings.Version.Length > 0) // already run on system { int lastrev; int.TryParse(Settings.Version, out lastrev); int currrev; int.TryParse(Resources.ProgramVersion, out currrev); showChangelog = lastrev < currrev; } // BAK Prompt if (!Settings.BAKPrompt) BAKprompt = Settings.BAKPrompt = true; Settings.Version = Resources.ProgramVersion; } private static void deleteConfig(string settingsFilename) { var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "PKHeX's settings are corrupt. Would you like to reset the settings?", "Yes to delete the settings or No to close the program."); if (dr == DialogResult.Yes) { File.Delete(settingsFilename); WinFormsUtil.Alert("The settings have been deleted", "Please restart the program."); } Process.GetCurrentProcess().Kill(); } // Main Menu Strip UI Functions private void mainMenuOpen(object sender, EventArgs e) { string pkx = pkm.Extension; string ekx = 'e' + pkx.Substring(1, pkx.Length-1); string supported = string.Join(";", SAV.PKMExtensions.Select(s => "*."+s).Concat(new[] {"*.pkm"})); OpenFileDialog ofd = new OpenFileDialog { Filter = "All Files|*.*" + $"|Supported Files|main;*.sav;*.dat;*.gci;*.bin;*.{ekx};{supported};*.bak" + "|3DS Main Files|main" + "|Save Files|*.sav;*.dat;*.gci" + $"|Decrypted PKM File|{supported}" + $"|Encrypted PKM File|*.{ekx}" + "|Binary File|*.bin" + "|Backup File|*.bak" }; // Detect main string cgse = ""; string path; string pathCache = CyberGadgetUtil.GetCacheFolder(); if (Directory.Exists(pathCache)) cgse = Path.Combine(pathCache); if (!PathUtilWindows.detectSaveFile(out path, cgse)) WinFormsUtil.Error(path); if (path != null) { ofd.FileName = path; } if (ofd.ShowDialog() == DialogResult.OK) openQuick(ofd.FileName); } private void mainMenuSave(object sender, EventArgs e) { if (!verifiedPKM()) return; PKM pk = preparePKM(); string pkx = pk.Extension; string ekx = 'e' + pkx.Substring(1, pkx.Length - 1); SaveFileDialog sfd = new SaveFileDialog { Filter = $"Decrypted PKM File|*.{pkx}" + (SAV.Generation > 2 ? "" : $"|Encrypted PKM File|*.{ekx}") + "|Binary File|*.bin" + "|All Files|*.*", DefaultExt = pkx, FileName = Util.CleanFileName(pk.FileName) }; if (sfd.ShowDialog() != DialogResult.OK) return; string path = sfd.FileName; string ext = Path.GetExtension(path); if (File.Exists(path)) { // File already exists, save a .bak string bakpath = path + ".bak"; if (!File.Exists(bakpath)) { byte[] backupfile = File.ReadAllBytes(path); File.WriteAllBytes(bakpath, backupfile); } } if (new[] {".ekx", "."+ekx, ".bin"}.Contains(ext)) File.WriteAllBytes(path, pk.EncryptedPartyData); else if (new[] { "."+pkx }.Contains(ext)) File.WriteAllBytes(path, pk.DecryptedBoxData); else { WinFormsUtil.Error($"Foreign File Extension: {ext}", "Exporting as encrypted."); File.WriteAllBytes(path, pkm.EncryptedPartyData); } } private void mainMenuExit(object sender, EventArgs e) { if (ModifierKeys == Keys.Control) // Hotkey Triggered if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Quit PKHeX?")) return; Close(); } private void mainMenuAbout(object sender, EventArgs e) { // Open a new form with the About details. new About().ShowDialog(); } // Sub Menu Options private void mainMenuBoxReport(object sender, EventArgs e) { var z = Application.OpenForms.Cast