From fa4318ae2f4ca0a6e15c2f4fa5a25438b4fc50d9 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 19 Feb 2019 20:46:58 -0800 Subject: [PATCH] Add gen3 record editing in misc edits window --- PKHeX.Core/Saves/SAV3.cs | 2 +- .../Saves/Substructures/Gen3/Record3.cs | 277 ++++++++++++++++++ .../Save Editors/Gen3/SAV_Misc3.Designer.cs | 55 +++- .../Subforms/Save Editors/Gen3/SAV_Misc3.cs | 32 ++ 4 files changed, 357 insertions(+), 9 deletions(-) create mode 100644 PKHeX.Core/Saves/Substructures/Gen3/Record3.cs diff --git a/PKHeX.Core/Saves/SAV3.cs b/PKHeX.Core/Saves/SAV3.cs index ce96dd57b..7bac8b32f 100644 --- a/PKHeX.Core/Saves/SAV3.cs +++ b/PKHeX.Core/Saves/SAV3.cs @@ -325,7 +325,7 @@ public override string ChecksumInfo // Trainer Info public override GameVersion Version { get; protected set; } - private uint SecurityKey + public uint SecurityKey { get { diff --git a/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs b/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs new file mode 100644 index 000000000..444ed4173 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections.Generic; + +namespace PKHeX.Core +{ + public sealed class Record3 + { + private readonly SAV3 SAV; + + public uint GetRecord(int record) => BitConverter.ToUInt32(SAV.Data, GetRecordOffset(record)) ^ GetKey(SAV); + public void SetRecord(int record, uint value) => SAV.SetData(BitConverter.GetBytes(value ^ GetKey(SAV)), GetRecordOffset(record)); + + private int GetRecordOffset(int record) + { + var baseOffset = GetOffset(SAV.Version); + var offset = baseOffset + (4 * record); + + SAV3.GetLargeBlockOffset(offset, out var chunk, out var ofs); + return SAV.GetBlockOffset(chunk) + ofs; + } + + public Record3(SAV3 sav) => SAV = sav; + + public static int GetOffset(GameVersion ver) + { + switch (ver) + { + case GameVersion.RS: + return 0x1540; + case GameVersion.FRLG: + return 0x1200; + case GameVersion.E: + return 0x159C; + default: + throw new ArgumentException(nameof(ver)); + } + } + + public static uint GetKey(SAV3 sav) + { + if (sav.Version == GameVersion.RS) + return 0; + return sav.SecurityKey; + } + + public static int[] GetEnumValues(GameVersion ver) + { + switch (ver) + { + case GameVersion.RS: + return (int[])Enum.GetValues(typeof(RecID3RuSa)); + case GameVersion.FRLG: + return (int[])Enum.GetValues(typeof(RecID3FRLG)); + case GameVersion.E: + return (int[])Enum.GetValues(typeof(RecID3Emerald)); + default: + throw new ArgumentException(nameof(ver)); + } + } + + public static string[] GetEnumNames(GameVersion ver) + { + switch (ver) + { + case GameVersion.RS: + return Enum.GetNames(typeof(RecID3RuSa)); + case GameVersion.FRLG: + return Enum.GetNames(typeof(RecID3FRLG)); + case GameVersion.E: + return Enum.GetNames(typeof(RecID3Emerald)); + default: + throw new ArgumentException(nameof(ver)); + } + } + + public static IList GetItems(SAV3 sav) + { + var ver = sav.Version; + var names = GetEnumNames(ver); + var values = GetEnumValues(ver); + + var result = new ComboItem[values.Length]; + for (int i = 0; i < result.Length; i++) + result[i] = new ComboItem {Text = Util.ToTitleCase(names[i].Replace('_', ' ')), Value = values[i]}; + return result; + } + } + + /// + /// Record IDs for and + /// + /// + /// https://github.com/pret/pokeruby/blob/f839afb24aa2c7b70e9c28a5c069aacc46993099/include/constants/game_stat.h + /// + public enum RecID3RuSa + { + SAVED_GAME = 0, + FIRST_HOF_PLAY_TIME = 1, + STARTED_TRENDS = 2, + PLANTED_BERRIES = 3, + TRADED_BIKES = 4, + STEPS = 5, + GOT_INTERVIEWED = 6, + TOTAL_BATTLES = 7, + WILD_BATTLES = 8, + TRAINER_BATTLES = 9, + ENTERED_HOF = 10, + POKEMON_CAPTURES = 11, + FISHING_CAPTURES = 12, + HATCHED_EGGS = 13, + EVOLVED_POKEMON = 14, + USED_POKECENTER = 15, + RESTED_AT_HOME = 16, + ENTERED_SAFARI_ZONE = 17, + USED_CUT = 18, + USED_ROCK_SMASH = 19, + MOVED_SECRET_BASE = 20, + POKEMON_TRADES = 21, + UNKNOWN_22 = 22, + LINK_BATTLE_WINS = 23, + LINK_BATTLE_LOSSES = 24, + LINK_BATTLE_DRAWS = 25, + USED_SPLASH = 26, + USED_STRUGGLE = 27, + SLOT_JACKPOTS = 28, + CONSECUTIVE_ROULETTE_WINS = 29, + ENTERED_BATTLE_TOWER = 30, + UNKNOWN_31 = 31, + BATTLE_TOWER_BEST_STREAK = 32, + POKEBLOCKS = 33, + POKEBLOCKS_WITH_FRIENDS = 34, + WON_LINK_CONTEST = 35, + ENTERED_CONTEST = 36, + WON_CONTEST = 37, + SHOPPED = 38, + USED_ITEMFINDER = 39, + GOT_RAINED_ON = 40, + CHECKED_POKEDEX = 41, + RECEIVED_RIBBONS = 42, + JUMPED_DOWN_LEDGES = 43, + WATCHED_TV = 44, + CHECKED_CLOCK = 45, + WON_POKEMON_LOTTERY = 46, + USED_DAYCARE = 47, + RODE_CABLE_CAR = 48, + ENTERED_HOT_SPRINGS = 49, + // NUM_GAME_STATS = 50 + } + + /// + /// Record IDs for + /// + /// + /// https://github.com/pret/pokeemerald/blob/3a40f5203baafb29f94dda8abdce6489d81635ae/include/constants/game_stat.h + /// + public enum RecID3Emerald + { + SAVED_GAME = 0, + FIRST_HOF_PLAY_TIME = 1, + STARTED_TRENDS = 2, + PLANTED_BERRIES = 3, + TRADED_BIKES = 4, + STEPS = 5, + GOT_INTERVIEWED = 6, + TOTAL_BATTLES = 7, + WILD_BATTLES = 8, + TRAINER_BATTLES = 9, + ENTERED_HOF = 10, + POKEMON_CAPTURES = 11, + FISHING_CAPTURES = 12, + HATCHED_EGGS = 13, + EVOLVED_POKEMON = 14, + USED_POKECENTER = 15, + RESTED_AT_HOME = 16, + ENTERED_SAFARI_ZONE = 17, + USED_CUT = 18, + USED_ROCK_SMASH = 19, + MOVED_SECRET_BASE = 20, + POKEMON_TRADES = 21, + UNKNOWN_22 = 22, + LINK_BATTLE_WINS = 23, + LINK_BATTLE_LOSSES = 24, + LINK_BATTLE_DRAWS = 25, + USED_SPLASH = 26, + USED_STRUGGLE = 27, + SLOT_JACKPOTS = 28, + CONSECUTIVE_ROULETTE_WINS = 29, + ENTERED_BATTLE_TOWER = 30, + UNKNOWN_31 = 31, + BATTLE_TOWER_BEST_STREAK = 32, + POKEBLOCKS = 33, + POKEBLOCKS_WITH_FRIENDS = 34, + WON_LINK_CONTEST = 35, + ENTERED_CONTEST = 36, + WON_CONTEST = 37, + SHOPPED = 38, + USED_ITEMFINDER = 39, + GOT_RAINED_ON = 40, + CHECKED_POKEDEX = 41, + RECEIVED_RIBBONS = 42, + JUMPED_DOWN_LEDGES = 43, + WATCHED_TV = 44, + CHECKED_CLOCK = 45, + WON_POKEMON_LOTTERY = 46, + USED_DAYCARE = 47, + RODE_CABLE_CAR = 48, + ENTERED_HOT_SPRINGS = 49, + STAT_50 = 50, + STAT_51 = 51, + + // NUM_USED_GAME_STATS = 52, + // NUM_GAME_STATS = 64 + } + + + /// + /// Record IDs for and + /// + /// + /// https://github.com/pret/pokefirered/blob/8367b0015fbf99070cc5a5244d8213420419d2c8/include/constants/game_stat.h + /// + public enum RecID3FRLG + { + SAVED_GAME = 0, + FIRST_HOF_PLAY_TIME = 1, + STARTED_TRENDS = 2, + PLANTED_BERRIES = 3, + TRADED_BIKES = 4, + STEPS = 5, + GOT_INTERVIEWED = 6, + TOTAL_BATTLES = 7, + WILD_BATTLES = 8, + TRAINER_BATTLES = 9, + ENTERED_HOF = 10, + POKEMON_CAPTURES = 11, + FISHING_CAPTURES = 12, + HATCHED_EGGS = 13, + EVOLVED_POKEMON = 14, + USED_POKECENTER = 15, + RESTED_AT_HOME = 16, + ENTERED_SAFARI_ZONE = 17, + USED_CUT = 18, + USED_ROCK_SMASH = 19, + MOVED_SECRET_BASE = 20, + POKEMON_TRADES = 21, + UNKNOWN_22 = 22, + LINK_BATTLE_WINS = 23, + LINK_BATTLE_LOSSES = 24, + LINK_BATTLE_DRAWS = 25, + USED_SPLASH = 26, + USED_STRUGGLE = 27, + SLOT_JACKPOTS = 28, + CONSECUTIVE_ROULETTE_WINS = 29, + ENTERED_BATTLE_TOWER = 30, + UNKNOWN_31 = 31, + BATTLE_TOWER_BEST_STREAK = 32, + POKEBLOCKS = 33, + POKEBLOCKS_WITH_FRIENDS = 34, + WON_LINK_CONTEST = 35, + ENTERED_CONTEST = 36, + WON_CONTEST = 37, + SHOPPED = 38, + USED_ITEMFINDER = 39, + GOT_RAINED_ON = 40, + CHECKED_POKEDEX = 41, + RECEIVED_RIBBONS = 42, + JUMPED_DOWN_LEDGES = 43, + WATCHED_TV = 44, + CHECKED_CLOCK = 45, + WON_POKEMON_LOTTERY = 46, + USED_DAYCARE = 47, + RODE_CABLE_CAR = 48, + ENTERED_HOT_SPRINGS = 49, + + // NUM_GAME_STATS = 64, + } +} diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.Designer.cs index 084b7774e..f2585abfd 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.Designer.cs @@ -100,6 +100,9 @@ private void InitializeComponent() this.BTN_SymbolT = new System.Windows.Forms.Button(); this.BTN_SymbolA = new System.Windows.Forms.Button(); this.CHK_ActivatePass = new System.Windows.Forms.CheckBox(); + this.Tab_Records = new System.Windows.Forms.TabPage(); + this.NUD_RecordValue = new System.Windows.Forms.NumericUpDown(); + this.CB_Record = new System.Windows.Forms.ComboBox(); this.tabControl1.SuspendLayout(); this.TAB_Main.SuspendLayout(); this.GB_TCM.SuspendLayout(); @@ -117,12 +120,14 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.NUD_Stat0)).BeginInit(); this.GB_FrontierPass.SuspendLayout(); this.GB_Icons.SuspendLayout(); + this.Tab_Records.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_RecordValue)).BeginInit(); this.SuspendLayout(); // // B_Save // this.B_Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.B_Save.Location = new System.Drawing.Point(213, 262); + this.B_Save.Location = new System.Drawing.Point(252, 262); this.B_Save.Name = "B_Save"; this.B_Save.Size = new System.Drawing.Size(75, 23); this.B_Save.TabIndex = 73; @@ -133,7 +138,7 @@ private void InitializeComponent() // B_Cancel // this.B_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.B_Cancel.Location = new System.Drawing.Point(132, 262); + this.B_Cancel.Location = new System.Drawing.Point(171, 262); this.B_Cancel.Name = "B_Cancel"; this.B_Cancel.Size = new System.Drawing.Size(75, 23); this.B_Cancel.TabIndex = 72; @@ -150,10 +155,11 @@ private void InitializeComponent() this.tabControl1.Controls.Add(this.TAB_Joyful); this.tabControl1.Controls.Add(this.TAB_Ferry); this.tabControl1.Controls.Add(this.TAB_BF); + this.tabControl1.Controls.Add(this.Tab_Records); this.tabControl1.Location = new System.Drawing.Point(12, 12); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(274, 244); + this.tabControl1.Size = new System.Drawing.Size(313, 244); this.tabControl1.TabIndex = 74; // // TAB_Main @@ -168,7 +174,7 @@ private void InitializeComponent() this.TAB_Main.Location = new System.Drawing.Point(4, 22); this.TAB_Main.Name = "TAB_Main"; this.TAB_Main.Padding = new System.Windows.Forms.Padding(3); - this.TAB_Main.Size = new System.Drawing.Size(266, 218); + this.TAB_Main.Size = new System.Drawing.Size(305, 218); this.TAB_Main.TabIndex = 0; this.TAB_Main.Text = "Main"; this.TAB_Main.UseVisualStyleBackColor = true; @@ -333,7 +339,7 @@ private void InitializeComponent() this.TAB_Joyful.Location = new System.Drawing.Point(4, 22); this.TAB_Joyful.Name = "TAB_Joyful"; this.TAB_Joyful.Padding = new System.Windows.Forms.Padding(3); - this.TAB_Joyful.Size = new System.Drawing.Size(266, 218); + this.TAB_Joyful.Size = new System.Drawing.Size(305, 218); this.TAB_Joyful.TabIndex = 1; this.TAB_Joyful.Text = "Joyful"; this.TAB_Joyful.UseVisualStyleBackColor = true; @@ -473,7 +479,7 @@ private void InitializeComponent() this.TAB_Ferry.Location = new System.Drawing.Point(4, 22); this.TAB_Ferry.Name = "TAB_Ferry"; this.TAB_Ferry.Padding = new System.Windows.Forms.Padding(3); - this.TAB_Ferry.Size = new System.Drawing.Size(266, 218); + this.TAB_Ferry.Size = new System.Drawing.Size(305, 218); this.TAB_Ferry.TabIndex = 2; this.TAB_Ferry.Text = "Ferry"; this.TAB_Ferry.UseVisualStyleBackColor = true; @@ -621,7 +627,7 @@ private void InitializeComponent() this.TAB_BF.Controls.Add(this.GB_FrontierPass); this.TAB_BF.Location = new System.Drawing.Point(4, 22); this.TAB_BF.Name = "TAB_BF"; - this.TAB_BF.Size = new System.Drawing.Size(266, 218); + this.TAB_BF.Size = new System.Drawing.Size(305, 218); this.TAB_BF.TabIndex = 3; this.TAB_BF.Text = "Battle Frontier"; this.TAB_BF.UseVisualStyleBackColor = true; @@ -932,11 +938,39 @@ private void InitializeComponent() this.CHK_ActivatePass.Text = "Activated"; this.CHK_ActivatePass.UseVisualStyleBackColor = true; // + // Tab_Records + // + this.Tab_Records.Controls.Add(this.NUD_RecordValue); + this.Tab_Records.Controls.Add(this.CB_Record); + this.Tab_Records.Location = new System.Drawing.Point(4, 22); + this.Tab_Records.Name = "Tab_Records"; + this.Tab_Records.Padding = new System.Windows.Forms.Padding(3); + this.Tab_Records.Size = new System.Drawing.Size(305, 218); + this.Tab_Records.TabIndex = 4; + this.Tab_Records.Text = "Records"; + this.Tab_Records.UseVisualStyleBackColor = true; + // + // NUD_RecordValue + // + this.NUD_RecordValue.Location = new System.Drawing.Point(74, 33); + this.NUD_RecordValue.Name = "NUD_RecordValue"; + this.NUD_RecordValue.Size = new System.Drawing.Size(120, 20); + this.NUD_RecordValue.TabIndex = 1; + // + // CB_Record + // + this.CB_Record.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_Record.FormattingEnabled = true; + this.CB_Record.Location = new System.Drawing.Point(6, 6); + this.CB_Record.Name = "CB_Record"; + this.CB_Record.Size = new System.Drawing.Size(188, 21); + this.CB_Record.TabIndex = 0; + // // SAV_Misc3 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(295, 297); + this.ClientSize = new System.Drawing.Size(334, 297); this.Controls.Add(this.tabControl1); this.Controls.Add(this.B_Save); this.Controls.Add(this.B_Cancel); @@ -969,6 +1003,8 @@ private void InitializeComponent() this.GB_FrontierPass.ResumeLayout(false); this.GB_FrontierPass.PerformLayout(); this.GB_Icons.ResumeLayout(false); + this.Tab_Records.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.NUD_RecordValue)).EndInit(); this.ResumeLayout(false); } @@ -1045,5 +1081,8 @@ private void InitializeComponent() private System.Windows.Forms.ComboBox CB_TCM3; private System.Windows.Forms.ComboBox CB_TCM2; private System.Windows.Forms.ComboBox CB_TCM1; + private System.Windows.Forms.TabPage Tab_Records; + private System.Windows.Forms.NumericUpDown NUD_RecordValue; + private System.Windows.Forms.ComboBox CB_Record; } } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs index dca51a6e5..91bd24bac 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs @@ -17,6 +17,8 @@ public SAV_Misc3(SaveFile sav) WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage); SAV = (SAV3)(Origin = sav).Clone(); + LoadRecords(); + if (SAV.FRLG || SAV.E) ReadJoyful(); else @@ -441,5 +443,35 @@ private void BTN_Symbol_Click(object sender, EventArgs e) } #endregion + private void LoadRecords() + { + var records = new Record3(SAV); + var items = Record3.GetItems(SAV); + CB_Record.InitializeBinding(); + CB_Record.DataSource = items; + NUD_RecordValue.Minimum = int.MinValue; + NUD_RecordValue.Maximum = int.MaxValue; + + CB_Record.SelectedIndexChanged += (s, e) => + { + if (CB_Record.SelectedValue == null) + return; + + var index = WinFormsUtil.GetIndex(CB_Record); + LoadRecordID(index); + }; + CB_Record.SelectedIndex = 0; + LoadRecordID(0); + NUD_RecordValue.ValueChanged += (s, e) => + { + if (CB_Record.SelectedValue == null) + return; + + var index = WinFormsUtil.GetIndex(CB_Record); + records.SetRecord(index, (uint)NUD_RecordValue.Value); + }; + + void LoadRecordID(int index) => NUD_RecordValue.Value = records.GetRecord(index); + } } }