From 691493cafe98dffdbf5026f5fff983f64879d17b Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 9 Apr 2017 14:06:50 -0700 Subject: [PATCH] String editing refactor Move all sanitization operations from PK* and SAV* to PKX; add general method for fetching a generation specific string Changes the Text subform editor to show trash bytes when appropriate. Special characters to be shown can be easily inserted in the future. --- PKHeX.WinForms/MainWindow/Main.cs | 30 +- .../Subforms/PKM Editors/Text.Designer.cs | 522 ++++++------------ PKHeX.WinForms/Subforms/PKM Editors/Text.cs | 201 ++++++- .../Subforms/Save Editors/Gen3/SAV_Misc3.cs | 4 +- .../Save Editors/Gen6/SAV_HallOfFame.cs | 13 +- .../Subforms/Save Editors/Gen6/SAV_Trainer.cs | 7 +- .../Save Editors/Gen7/SAV_Trainer7.cs | 7 +- PKHeX/MysteryGifts/PGT.cs | 2 +- PKHeX/PKM/BK4.cs | 57 +- PKHeX/PKM/CK3.cs | 13 +- PKHeX/PKM/PK1.cs | 24 +- PKHeX/PKM/PK2.cs | 24 +- PKHeX/PKM/PK3.cs | 22 +- PKHeX/PKM/PK4.cs | 53 +- PKHeX/PKM/PK5.cs | 52 +- PKHeX/PKM/PK6.cs | 48 +- PKHeX/PKM/PK7.cs | 48 +- PKHeX/PKM/PKM.cs | 17 + PKHeX/PKM/PKX.cs | 353 +++++++++--- PKHeX/PKM/XK3.cs | 13 +- PKHeX/Saves/SAV1.cs | 18 +- PKHeX/Saves/SAV2.cs | 17 +- PKHeX/Saves/SAV3.cs | 32 +- PKHeX/Saves/SAV3Colosseum.cs | 20 +- PKHeX/Saves/SAV3RSBox.cs | 15 +- PKHeX/Saves/SAV3XD.cs | 16 +- PKHeX/Saves/SAV4.cs | 37 +- PKHeX/Saves/SAV4BR.cs | 8 + PKHeX/Saves/SAV5.cs | 18 +- PKHeX/Saves/SAV6.cs | 12 +- PKHeX/Saves/SAV7.cs | 12 +- PKHeX/Saves/SaveFile.cs | 3 + Tests/PKHeX.Tests/PKM/DateTestPKM.cs | 18 +- 33 files changed, 922 insertions(+), 814 deletions(-) diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index 9d0a53ec6..fa775961e 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -1070,7 +1070,7 @@ private void openSAV(SaveFile sav, string path) Menu_ExportSAV.Enabled = B_VerifyCHK.Enabled = SAV.Exportable; // Close subforms that are save dependent - Type[] f = { typeof(SAV_BoxViewer), typeof(f2_Text) }; + Type[] f = { typeof(SAV_BoxViewer) }; foreach (var form in Application.OpenForms.Cast
().Where(form => f.Contains(form.GetType())).ToArray()) form.Close(); @@ -2765,10 +2765,30 @@ private void updateNicknameClick(object sender, MouseEventArgs e) if (ModifierKeys != Keys.Control) return; - var z = Application.OpenForms.Cast().FirstOrDefault(form => form.GetType() == typeof(f2_Text)) as f2_Text; - if (z != null) - { WinFormsUtil.CenterToForm(z, this); z.BringToFront(); return; } - new f2_Text(tb).Show(); + if (tb == TB_Nickname) + { + pkm.Nickname = tb.Text; + var d = new f2_Text(tb, pkm.Nickname_Trash); + d.ShowDialog(); + tb.Text = d.FinalString; + pkm.Nickname_Trash = d.FinalBytes; + } + else if (tb == TB_OT) + { + pkm.OT_Name = tb.Text; + var d = new f2_Text(tb, pkm.OT_Trash); + d.ShowDialog(); + tb.Text = d.FinalString; + pkm.OT_Trash = d.FinalBytes; + } + else if (tb == TB_OTt2) + { + pkm.HT_Name = tb.Text; + var d = new f2_Text(tb, pkm.HT_Trash); + d.ShowDialog(); + tb.Text = d.FinalString; + pkm.HT_Trash = d.FinalBytes; + } } private void updateNotOT(object sender, EventArgs e) { diff --git a/PKHeX.WinForms/Subforms/PKM Editors/Text.Designer.cs b/PKHeX.WinForms/Subforms/PKM Editors/Text.Designer.cs index 2beb48e52..8d4cdfaaa 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/Text.Designer.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/Text.Designer.cs @@ -29,365 +29,188 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(f2_Text)); - this.L04 = new System.Windows.Forms.Label(); - this.L0C = new System.Windows.Forms.Label(); - this.L0D = new System.Windows.Forms.Label(); - this.L05 = new System.Windows.Forms.Label(); - this.L0E = new System.Windows.Forms.Label(); - this.L06 = new System.Windows.Forms.Label(); - this.L0F = new System.Windows.Forms.Label(); - this.L07 = new System.Windows.Forms.Label(); - this.L1E = new System.Windows.Forms.Label(); - this.L16 = new System.Windows.Forms.Label(); - this.L1F = new System.Windows.Forms.Label(); - this.L17 = new System.Windows.Forms.Label(); - this.L18 = new System.Windows.Forms.Label(); - this.L10 = new System.Windows.Forms.Label(); - this.L19 = new System.Windows.Forms.Label(); - this.L11 = new System.Windows.Forms.Label(); - this.L0B = new System.Windows.Forms.Label(); - this.L03 = new System.Windows.Forms.Label(); - this.L0A = new System.Windows.Forms.Label(); - this.L02 = new System.Windows.Forms.Label(); - this.L09 = new System.Windows.Forms.Label(); - this.L01 = new System.Windows.Forms.Label(); - this.L08 = new System.Windows.Forms.Label(); - this.L00 = new System.Windows.Forms.Label(); - this.L1B = new System.Windows.Forms.Label(); - this.L13 = new System.Windows.Forms.Label(); - this.L1A = new System.Windows.Forms.Label(); - this.L12 = new System.Windows.Forms.Label(); - this.L1D = new System.Windows.Forms.Label(); - this.L15 = new System.Windows.Forms.Label(); - this.L1C = new System.Windows.Forms.Label(); - this.L14 = new System.Windows.Forms.Label(); + this.TB_Text = new System.Windows.Forms.TextBox(); + this.CB_Species = new System.Windows.Forms.ComboBox(); + this.B_Cancel = new System.Windows.Forms.Button(); + this.B_Save = new System.Windows.Forms.Button(); + this.FLP_Characters = new System.Windows.Forms.FlowLayoutPanel(); + this.FLP_Hex = new System.Windows.Forms.FlowLayoutPanel(); + this.CB_Language = new System.Windows.Forms.ComboBox(); + this.B_ApplyTrash = new System.Windows.Forms.Button(); + this.GB_Trash = new System.Windows.Forms.GroupBox(); + this.L_Language = new System.Windows.Forms.Label(); + this.L_Species = new System.Windows.Forms.Label(); + this.NUD_Generation = new System.Windows.Forms.NumericUpDown(); + this.L_Generation = new System.Windows.Forms.Label(); + this.B_ClearTrash = new System.Windows.Forms.Button(); + this.GB_Trash.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Generation)).BeginInit(); this.SuspendLayout(); // - // L04 + // TB_Text // - this.L04.AutoSize = true; - this.L04.Location = new System.Drawing.Point(92, 12); - this.L04.Name = "L04"; - this.L04.Size = new System.Drawing.Size(14, 13); - this.L04.TabIndex = 3; - this.L04.Text = "X"; + this.TB_Text.Location = new System.Drawing.Point(76, 12); + this.TB_Text.Name = "TB_Text"; + this.TB_Text.Size = new System.Drawing.Size(136, 20); + this.TB_Text.TabIndex = 35; // - // L0C + // CB_Species // - this.L0C.AutoSize = true; - this.L0C.Location = new System.Drawing.Point(92, 34); - this.L0C.Name = "L0C"; - this.L0C.Size = new System.Drawing.Size(14, 13); - this.L0C.TabIndex = 4; - this.L0C.Text = "X"; + this.CB_Species.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.CB_Species.FormattingEnabled = true; + this.CB_Species.Location = new System.Drawing.Point(76, 16); + this.CB_Species.Name = "CB_Species"; + this.CB_Species.Size = new System.Drawing.Size(86, 21); + this.CB_Species.TabIndex = 36; // - // L0D + // B_Cancel // - this.L0D.AutoSize = true; - this.L0D.Location = new System.Drawing.Point(112, 34); - this.L0D.Name = "L0D"; - this.L0D.Size = new System.Drawing.Size(14, 13); - this.L0D.TabIndex = 6; - this.L0D.Text = "X"; + 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(333, 184); + this.B_Cancel.Name = "B_Cancel"; + this.B_Cancel.Size = new System.Drawing.Size(76, 23); + this.B_Cancel.TabIndex = 37; + this.B_Cancel.Text = "Cancel"; + this.B_Cancel.UseVisualStyleBackColor = true; + this.B_Cancel.Click += new System.EventHandler(this.B_Cancel_Click); // - // L05 + // B_Save // - this.L05.AutoSize = true; - this.L05.Location = new System.Drawing.Point(112, 12); - this.L05.Name = "L05"; - this.L05.Size = new System.Drawing.Size(14, 13); - this.L05.TabIndex = 5; - this.L05.Text = "X"; + 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(415, 184); + this.B_Save.Name = "B_Save"; + this.B_Save.Size = new System.Drawing.Size(76, 23); + this.B_Save.TabIndex = 38; + this.B_Save.Text = "Save"; + this.B_Save.UseVisualStyleBackColor = true; + this.B_Save.Click += new System.EventHandler(this.B_Save_Click); // - // L0E + // FLP_Characters // - this.L0E.AutoSize = true; - this.L0E.Location = new System.Drawing.Point(132, 34); - this.L0E.Name = "L0E"; - this.L0E.Size = new System.Drawing.Size(14, 13); - this.L0E.TabIndex = 8; - this.L0E.Text = "X"; + this.FLP_Characters.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_Characters.Location = new System.Drawing.Point(12, 126); + this.FLP_Characters.Name = "FLP_Characters"; + this.FLP_Characters.Size = new System.Drawing.Size(305, 82); + this.FLP_Characters.TabIndex = 39; // - // L06 + // FLP_Hex // - this.L06.AutoSize = true; - this.L06.Location = new System.Drawing.Point(132, 12); - this.L06.Name = "L06"; - this.L06.Size = new System.Drawing.Size(14, 13); - this.L06.TabIndex = 7; - this.L06.Text = "X"; + this.FLP_Hex.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_Hex.AutoScroll = true; + this.FLP_Hex.Location = new System.Drawing.Point(12, 38); + this.FLP_Hex.Name = "FLP_Hex"; + this.FLP_Hex.Size = new System.Drawing.Size(305, 82); + this.FLP_Hex.TabIndex = 40; + this.FLP_Hex.Visible = false; // - // L0F + // CB_Language // - this.L0F.AutoSize = true; - this.L0F.Location = new System.Drawing.Point(152, 34); - this.L0F.Name = "L0F"; - this.L0F.Size = new System.Drawing.Size(14, 13); - this.L0F.TabIndex = 10; - this.L0F.Text = "X"; + this.CB_Language.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.CB_Language.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_Language.FormattingEnabled = true; + this.CB_Language.Location = new System.Drawing.Point(76, 43); + this.CB_Language.Name = "CB_Language"; + this.CB_Language.Size = new System.Drawing.Size(86, 21); + this.CB_Language.TabIndex = 41; // - // L07 + // B_ApplyTrash // - this.L07.AutoSize = true; - this.L07.Location = new System.Drawing.Point(152, 12); - this.L07.Name = "L07"; - this.L07.Size = new System.Drawing.Size(14, 13); - this.L07.TabIndex = 9; - this.L07.Text = "X"; + this.B_ApplyTrash.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.B_ApplyTrash.Location = new System.Drawing.Point(6, 129); + this.B_ApplyTrash.Name = "B_ApplyTrash"; + this.B_ApplyTrash.Size = new System.Drawing.Size(156, 23); + this.B_ApplyTrash.TabIndex = 42; + this.B_ApplyTrash.Text = "Apply Trash"; + this.B_ApplyTrash.UseVisualStyleBackColor = true; + this.B_ApplyTrash.Click += new System.EventHandler(this.B_ApplyTrash_Click); // - // L1E + // GB_Trash // - this.L1E.AutoSize = true; - this.L1E.Location = new System.Drawing.Point(132, 81); - this.L1E.Name = "L1E"; - this.L1E.Size = new System.Drawing.Size(14, 13); - this.L1E.TabIndex = 12; - this.L1E.Text = "X"; + this.GB_Trash.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Right))); + this.GB_Trash.Controls.Add(this.B_ClearTrash); + this.GB_Trash.Controls.Add(this.L_Generation); + this.GB_Trash.Controls.Add(this.NUD_Generation); + this.GB_Trash.Controls.Add(this.L_Language); + this.GB_Trash.Controls.Add(this.L_Species); + this.GB_Trash.Controls.Add(this.CB_Species); + this.GB_Trash.Controls.Add(this.B_ApplyTrash); + this.GB_Trash.Controls.Add(this.CB_Language); + this.GB_Trash.Location = new System.Drawing.Point(323, 12); + this.GB_Trash.Name = "GB_Trash"; + this.GB_Trash.Size = new System.Drawing.Size(168, 158); + this.GB_Trash.TabIndex = 43; + this.GB_Trash.TabStop = false; + this.GB_Trash.Text = "Trash Byte Layers"; + this.GB_Trash.Visible = false; // - // L16 + // L_Language // - this.L16.AutoSize = true; - this.L16.Location = new System.Drawing.Point(132, 59); - this.L16.Name = "L16"; - this.L16.Size = new System.Drawing.Size(14, 13); - this.L16.TabIndex = 11; - this.L16.Text = "X"; + this.L_Language.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.L_Language.Location = new System.Drawing.Point(6, 43); + this.L_Language.Name = "L_Language"; + this.L_Language.Size = new System.Drawing.Size(64, 23); + this.L_Language.TabIndex = 44; + this.L_Language.Text = "Language"; + this.L_Language.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // L1F + // L_Species // - this.L1F.AutoSize = true; - this.L1F.Location = new System.Drawing.Point(152, 81); - this.L1F.Name = "L1F"; - this.L1F.Size = new System.Drawing.Size(14, 13); - this.L1F.TabIndex = 14; - this.L1F.Text = "X"; + this.L_Species.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.L_Species.Location = new System.Drawing.Point(6, 16); + this.L_Species.Name = "L_Species"; + this.L_Species.Size = new System.Drawing.Size(64, 23); + this.L_Species.TabIndex = 43; + this.L_Species.Text = "Species"; + this.L_Species.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // L17 + // NUD_Generation // - this.L17.AutoSize = true; - this.L17.Location = new System.Drawing.Point(152, 59); - this.L17.Name = "L17"; - this.L17.Size = new System.Drawing.Size(14, 13); - this.L17.TabIndex = 13; - this.L17.Text = "X"; + this.NUD_Generation.Location = new System.Drawing.Point(115, 70); + this.NUD_Generation.Name = "NUD_Generation"; + this.NUD_Generation.Size = new System.Drawing.Size(47, 20); + this.NUD_Generation.TabIndex = 45; // - // L18 + // L_Generation // - this.L18.AutoSize = true; - this.L18.Location = new System.Drawing.Point(12, 81); - this.L18.Name = "L18"; - this.L18.Size = new System.Drawing.Size(14, 13); - this.L18.TabIndex = 16; - this.L18.Text = "X"; + this.L_Generation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.L_Generation.Location = new System.Drawing.Point(6, 67); + this.L_Generation.Name = "L_Generation"; + this.L_Generation.Size = new System.Drawing.Size(103, 23); + this.L_Generation.TabIndex = 46; + this.L_Generation.Text = "Generation"; + this.L_Generation.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // L10 + // B_ClearTrash // - this.L10.AutoSize = true; - this.L10.Location = new System.Drawing.Point(12, 59); - this.L10.Name = "L10"; - this.L10.Size = new System.Drawing.Size(14, 13); - this.L10.TabIndex = 15; - this.L10.Text = "X"; - // - // L19 - // - this.L19.AutoSize = true; - this.L19.Location = new System.Drawing.Point(32, 81); - this.L19.Name = "L19"; - this.L19.Size = new System.Drawing.Size(14, 13); - this.L19.TabIndex = 18; - this.L19.Text = "X"; - // - // L11 - // - this.L11.AutoSize = true; - this.L11.Location = new System.Drawing.Point(32, 59); - this.L11.Name = "L11"; - this.L11.Size = new System.Drawing.Size(14, 13); - this.L11.TabIndex = 17; - this.L11.Text = "X"; - // - // L0B - // - this.L0B.AutoSize = true; - this.L0B.Location = new System.Drawing.Point(72, 34); - this.L0B.Name = "L0B"; - this.L0B.Size = new System.Drawing.Size(14, 13); - this.L0B.TabIndex = 26; - this.L0B.Text = "X"; - // - // L03 - // - this.L03.AutoSize = true; - this.L03.Location = new System.Drawing.Point(72, 12); - this.L03.Name = "L03"; - this.L03.Size = new System.Drawing.Size(14, 13); - this.L03.TabIndex = 25; - this.L03.Text = "X"; - // - // L0A - // - this.L0A.AutoSize = true; - this.L0A.Location = new System.Drawing.Point(52, 34); - this.L0A.Name = "L0A"; - this.L0A.Size = new System.Drawing.Size(14, 13); - this.L0A.TabIndex = 24; - this.L0A.Text = "X"; - // - // L02 - // - this.L02.AutoSize = true; - this.L02.Location = new System.Drawing.Point(52, 12); - this.L02.Name = "L02"; - this.L02.Size = new System.Drawing.Size(14, 13); - this.L02.TabIndex = 23; - this.L02.Text = "X"; - // - // L09 - // - this.L09.AutoSize = true; - this.L09.Location = new System.Drawing.Point(32, 34); - this.L09.Name = "L09"; - this.L09.Size = new System.Drawing.Size(14, 13); - this.L09.TabIndex = 22; - this.L09.Text = "X"; - // - // L01 - // - this.L01.AutoSize = true; - this.L01.Location = new System.Drawing.Point(32, 12); - this.L01.Name = "L01"; - this.L01.Size = new System.Drawing.Size(14, 13); - this.L01.TabIndex = 21; - this.L01.Text = "X"; - // - // L08 - // - this.L08.AutoSize = true; - this.L08.Location = new System.Drawing.Point(12, 34); - this.L08.Name = "L08"; - this.L08.Size = new System.Drawing.Size(14, 13); - this.L08.TabIndex = 20; - this.L08.Text = "X"; - // - // L00 - // - this.L00.AutoSize = true; - this.L00.Location = new System.Drawing.Point(12, 12); - this.L00.Name = "L00"; - this.L00.Size = new System.Drawing.Size(14, 13); - this.L00.TabIndex = 19; - this.L00.Text = "X"; - // - // L1B - // - this.L1B.AutoSize = true; - this.L1B.Location = new System.Drawing.Point(72, 81); - this.L1B.Name = "L1B"; - this.L1B.Size = new System.Drawing.Size(14, 13); - this.L1B.TabIndex = 30; - this.L1B.Text = "X"; - // - // L13 - // - this.L13.AutoSize = true; - this.L13.Location = new System.Drawing.Point(72, 59); - this.L13.Name = "L13"; - this.L13.Size = new System.Drawing.Size(14, 13); - this.L13.TabIndex = 29; - this.L13.Text = "X"; - // - // L1A - // - this.L1A.AutoSize = true; - this.L1A.Location = new System.Drawing.Point(52, 81); - this.L1A.Name = "L1A"; - this.L1A.Size = new System.Drawing.Size(14, 13); - this.L1A.TabIndex = 28; - this.L1A.Text = "X"; - // - // L12 - // - this.L12.AutoSize = true; - this.L12.Location = new System.Drawing.Point(52, 59); - this.L12.Name = "L12"; - this.L12.Size = new System.Drawing.Size(14, 13); - this.L12.TabIndex = 27; - this.L12.Text = "X"; - // - // L1D - // - this.L1D.AutoSize = true; - this.L1D.Location = new System.Drawing.Point(112, 81); - this.L1D.Name = "L1D"; - this.L1D.Size = new System.Drawing.Size(14, 13); - this.L1D.TabIndex = 34; - this.L1D.Text = "X"; - // - // L15 - // - this.L15.AutoSize = true; - this.L15.Location = new System.Drawing.Point(112, 59); - this.L15.Name = "L15"; - this.L15.Size = new System.Drawing.Size(14, 13); - this.L15.TabIndex = 33; - this.L15.Text = "X"; - // - // L1C - // - this.L1C.AutoSize = true; - this.L1C.Location = new System.Drawing.Point(92, 81); - this.L1C.Name = "L1C"; - this.L1C.Size = new System.Drawing.Size(14, 13); - this.L1C.TabIndex = 32; - this.L1C.Text = "X"; - // - // L14 - // - this.L14.AutoSize = true; - this.L14.Location = new System.Drawing.Point(92, 59); - this.L14.Name = "L14"; - this.L14.Size = new System.Drawing.Size(14, 13); - this.L14.TabIndex = 31; - this.L14.Text = "X"; + this.B_ClearTrash.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.B_ClearTrash.Location = new System.Drawing.Point(6, 100); + this.B_ClearTrash.Name = "B_ClearTrash"; + this.B_ClearTrash.Size = new System.Drawing.Size(156, 23); + this.B_ClearTrash.TabIndex = 47; + this.B_ClearTrash.Text = "Clear Trash"; + this.B_ClearTrash.UseVisualStyleBackColor = true; + this.B_ClearTrash.Click += new System.EventHandler(this.B_ClearTrash_Click); // // f2_Text // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(179, 107); - this.Controls.Add(this.L1D); - this.Controls.Add(this.L15); - this.Controls.Add(this.L1C); - this.Controls.Add(this.L14); - this.Controls.Add(this.L1B); - this.Controls.Add(this.L13); - this.Controls.Add(this.L1A); - this.Controls.Add(this.L12); - this.Controls.Add(this.L0B); - this.Controls.Add(this.L03); - this.Controls.Add(this.L0A); - this.Controls.Add(this.L02); - this.Controls.Add(this.L09); - this.Controls.Add(this.L01); - this.Controls.Add(this.L08); - this.Controls.Add(this.L00); - this.Controls.Add(this.L19); - this.Controls.Add(this.L11); - this.Controls.Add(this.L18); - this.Controls.Add(this.L10); - this.Controls.Add(this.L1F); - this.Controls.Add(this.L17); - this.Controls.Add(this.L1E); - this.Controls.Add(this.L16); - this.Controls.Add(this.L0F); - this.Controls.Add(this.L07); - this.Controls.Add(this.L0E); - this.Controls.Add(this.L06); - this.Controls.Add(this.L0D); - this.Controls.Add(this.L05); - this.Controls.Add(this.L0C); - this.Controls.Add(this.L04); + this.ClientSize = new System.Drawing.Size(503, 219); + this.Controls.Add(this.GB_Trash); + this.Controls.Add(this.FLP_Hex); + this.Controls.Add(this.FLP_Characters); + this.Controls.Add(this.B_Cancel); + this.Controls.Add(this.B_Save); + this.Controls.Add(this.TB_Text); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; @@ -395,44 +218,27 @@ private void InitializeComponent() this.Name = "f2_Text"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Special Characters"; + this.GB_Trash.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Generation)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion - - private System.Windows.Forms.Label L04; - private System.Windows.Forms.Label L0C; - private System.Windows.Forms.Label L0D; - private System.Windows.Forms.Label L05; - private System.Windows.Forms.Label L0E; - private System.Windows.Forms.Label L06; - private System.Windows.Forms.Label L0F; - private System.Windows.Forms.Label L07; - private System.Windows.Forms.Label L1E; - private System.Windows.Forms.Label L16; - private System.Windows.Forms.Label L1F; - private System.Windows.Forms.Label L17; - private System.Windows.Forms.Label L18; - private System.Windows.Forms.Label L10; - private System.Windows.Forms.Label L19; - private System.Windows.Forms.Label L11; - private System.Windows.Forms.Label L0B; - private System.Windows.Forms.Label L03; - private System.Windows.Forms.Label L0A; - private System.Windows.Forms.Label L02; - private System.Windows.Forms.Label L09; - private System.Windows.Forms.Label L01; - private System.Windows.Forms.Label L08; - private System.Windows.Forms.Label L00; - private System.Windows.Forms.Label L1B; - private System.Windows.Forms.Label L13; - private System.Windows.Forms.Label L1A; - private System.Windows.Forms.Label L12; - private System.Windows.Forms.Label L1D; - private System.Windows.Forms.Label L15; - private System.Windows.Forms.Label L1C; - private System.Windows.Forms.Label L14; + private System.Windows.Forms.TextBox TB_Text; + private System.Windows.Forms.ComboBox CB_Species; + private System.Windows.Forms.Button B_Cancel; + private System.Windows.Forms.Button B_Save; + private System.Windows.Forms.FlowLayoutPanel FLP_Characters; + private System.Windows.Forms.FlowLayoutPanel FLP_Hex; + private System.Windows.Forms.ComboBox CB_Language; + private System.Windows.Forms.Button B_ApplyTrash; + private System.Windows.Forms.GroupBox GB_Trash; + private System.Windows.Forms.Label L_Species; + private System.Windows.Forms.Label L_Language; + private System.Windows.Forms.NumericUpDown NUD_Generation; + private System.Windows.Forms.Label L_Generation; + private System.Windows.Forms.Button B_ClearTrash; } } \ No newline at end of file diff --git a/PKHeX.WinForms/Subforms/PKM Editors/Text.cs b/PKHeX.WinForms/Subforms/PKM Editors/Text.cs index 287736220..f12f15248 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/Text.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/Text.cs @@ -1,48 +1,189 @@ using System; +using System.Collections.Generic; using System.Drawing; +using System.Linq; using System.Windows.Forms; +using PKHeX.Core; namespace PKHeX.WinForms { public partial class f2_Text : Form { - public f2_Text(TextBox TB_NN) + public f2_Text(TextBoxBase TB_NN, byte[] raw) { - Hide(); InitializeComponent(); WinFormsUtil.TranslateInterface(this, Main.curlanguage); - TB_Nickname = TB_NN; - Font pkxFont = FontUtil.getPKXFont(12F); - Label[] lbla = - { - L00, L01, L02, L03, L04, L05, L06, L07, - L08, L09, L0A, L0B, L0C, L0D, L0E, L0F, - L10, L11, L12, L13, L14, L15, L16, L17, - L18, L19, L1A, L1B, L1C, L1D, L1E, L1F, - }; - ushort[] chars = - { - 0xE081, 0xE082, 0xE083, 0xE084, 0xE085, 0xE086, 0xE087, 0xE08D, - 0xE08E, 0xE08F, 0xE090, 0xE091, 0xE092, 0xE093, 0xE094, 0xE095, - 0xE096, 0xE097, 0xE098, 0xE099, 0xE09A, 0xE09B, 0xE09C, 0xE09D, - 0xE09E, 0xE09F, 0xE0A0, 0xE0A1, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, - }; - for (int i = 0; i < 32; i++) - { - lbla[i].Font = pkxFont; - lbla[i].Text = Convert.ToChar(chars[i]).ToString(); - lbla[i].Click += onClick; - } + + FinalString = TB_NN.Text; + Raw = FinalBytes = raw; + + editing = true; + if (raw != null) + addTrashEditing(TB_NN.MaxLength); + + addCharEditing(); + TB_Text.MaxLength = TB_NN.MaxLength; + TB_Text.Text = TB_NN.Text; + TB_Text.Font = pkxFont; + + editing = false; CenterToParent(); - Show(); + } + + private readonly List Bytes = new List(); + private readonly Font pkxFont = FontUtil.getPKXFont(12F); + public string FinalString; + public byte[] FinalBytes { get; private set; } + private readonly byte[] Raw; + private bool editing; + private readonly bool bigendian = new[] { GameVersion.COLO, GameVersion.XD, GameVersion.BATREV, }.Contains(Main.SAV.Version); + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + private void B_Save_Click(object sender, EventArgs e) + { + FinalString = TB_Text.Text; + if (FinalBytes != null) + FinalBytes = Raw; + Close(); } - readonly TextBox TB_Nickname; - private void onClick(object sender, EventArgs e) + private void addCharEditing() { - string nickname = TB_Nickname.Text; - if (nickname.Length < TB_Nickname.MaxLength) - TB_Nickname.Text += ((Label) sender).Text; + ushort[] chars = getChars(Main.SAV.Generation); + if (chars.Length == 0) + return; + + FLP_Characters.Visible = true; + foreach (ushort c in chars) + { + var l = getLabel((char)c+""); + l.Font = pkxFont; + l.AutoSize = false; + l.Size = new Size(20, 20); + l.Click += (s, e) => { if (TB_Text.Text.Length < TB_Text.MaxLength) TB_Text.AppendText(l.Text); }; + FLP_Characters.Controls.Add(l); + } } + private void addTrashEditing(int length) + { + FLP_Hex.Visible = true; + GB_Trash.Visible = true; + NUD_Generation.Value = Main.SAV.Generation; + int charct = length; + int bytesperchar = Main.SAV.Generation > 2 ? 2 : 1; + Font courier = new Font("Courier New", 8); + for (int i = 0; i < charct * bytesperchar; i++) + { + var l = getLabel($"${i:X2}"); + l.Font = courier; + var n = getNUD(hex: true, min: 0, max: 255); + n.Click += (s, e) => + { + switch (ModifierKeys) + { + case Keys.Control: n.Value = n.Maximum; break; + case Keys.Alt: n.Value = n.Minimum; break; + } + }; + n.Value = Raw[i]; + n.ValueChanged += updateNUD; + + + FLP_Hex.Controls.Add(l); + FLP_Hex.Controls.Add(n); + Bytes.Add(n); + } + TB_Text.TextChanged += updateString; + + CB_Species.DisplayMember = "Text"; + CB_Species.ValueMember = "Value"; + CB_Species.DataSource = new BindingSource(GameInfo.SpeciesDataSource, null); + + CB_Language.DisplayMember = "Text"; + CB_Language.ValueMember = "Value"; + var languages = Util.getUnsortedCBList("languages"); + if (Main.SAV.Generation < 7) + languages = languages.Where(l => l.Value <= 8).ToList(); // Korean + CB_Language.DataSource = languages; + } + + private void updateNUD(object sender, EventArgs e) + { + if (editing) + return; + editing = true; + // build bytes + var nud = sender as NumericUpDown; + int index = Bytes.IndexOf(nud); + Raw[index] = (byte)nud.Value; + + string str = PKX.getString(Raw, Main.SAV.Generation, Main.SAV.Japanese, bigendian, Raw.Length); + TB_Text.Text = str; + editing = false; + } + private void updateString(object sender, EventArgs e) + { + if (editing) + return; + editing = true; + // build bytes + byte[] data = PKX.setString(TB_Text.Text, Main.SAV.Generation, Main.SAV.Japanese, bigendian, Raw.Length, Main.SAV.Language); + Array.Copy(data, Raw, data.Length); + for (int i = 0; i < data.Length; i++) + Bytes[i].Value = Raw[i]; + editing = false; + } + private void B_ApplyTrash_Click(object sender, EventArgs e) + { + string species = PKX.getSpeciesNameGeneration(WinFormsUtil.getIndex(CB_Species), + WinFormsUtil.getIndex(CB_Language), (int) NUD_Generation.Value); + + if (species == "") // no result + species = CB_Species.Text; + + byte[] current = PKX.setString(TB_Text.Text, Main.SAV.Generation, Main.SAV.Japanese, bigendian, Raw.Length, Main.SAV.Language); + byte[] data = PKX.setString(species, Main.SAV.Generation, Main.SAV.Japanese, bigendian, Raw.Length, Main.SAV.Language); + if (data.Length <= current.Length) + { + return; + } + for (int i = current.Length; i < data.Length; i++) + Bytes[i].Value = data[i]; + } + private void B_ClearTrash_Click(object sender, EventArgs e) + { + byte[] current = PKX.setString(TB_Text.Text, Main.SAV.Generation, Main.SAV.Japanese, bigendian, Raw.Length, Main.SAV.Language); + for (int i = current.Length; i < Bytes.Count; i++) + Bytes[i].Value = 0; + } + + // Helpers + private static Label getLabel(string str) => new Label {Text = str, AutoSize = true}; + private static NumericUpDown getNUD(int min, int max, bool hex) => new NumericUpDown + { + Maximum = max, + Minimum = min, + Hexadecimal = hex, + Width = 36, + Padding = new Padding(0), + Margin = new Padding(0), + }; + + private static ushort[] getChars(int generation) + { + switch (generation) + { + case 6: + case 7: + return chars67; + default: return new ushort[0]; + } + } + private static readonly ushort[] chars67 = + { + 0xE081, 0xE082, 0xE083, 0xE084, 0xE085, 0xE086, 0xE087, 0xE08D, + 0xE08E, 0xE08F, 0xE090, 0xE091, 0xE092, 0xE093, 0xE094, 0xE095, + 0xE096, 0xE097, 0xE098, 0xE099, 0xE09A, 0xE09B, 0xE09C, 0xE09D, + 0xE09E, 0xE09F, 0xE0A0, 0xE0A1, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, + }; } } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs index e00abf729..b57b27e28 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs @@ -18,7 +18,7 @@ public SAV_Misc3() tabControl1.Controls.Remove(TAB_Joyful); if (SAV.FRLG) - TB_OTName.Text = PKX.getG3Str(SAV.getData(SAV.getBlockOffset(4) + 0xBCC, 8), SAV.Japanese); + TB_OTName.Text = PKX.getString3(SAV.Data, SAV.getBlockOffset(4) + 0xBCC, 8, SAV.Japanese); else TB_OTName.Visible = L_TrainerName.Visible = false; @@ -30,7 +30,7 @@ private void B_Save_Click(object sender, EventArgs e) if (tabControl1.Controls.Contains(TAB_Joyful)) saveJoyful(); if (SAV.FRLG) - SAV.setData(PKX.setG3Str(TB_OTName.Text, SAV.Japanese), SAV.getBlockOffset(4) + 0xBCC); + SAV.setData(SAV.setString(TB_OTName.Text, TB_OTName.MaxLength), SAV.getBlockOffset(4) + 0xBCC); SAV.BP = (ushort)NUD_BP.Value; SAV.Coin = (ushort)NUD_Coins.Value; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs index de4c7d914..8546025d3 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs @@ -412,9 +412,16 @@ private void changeNickname(object sender, MouseEventArgs e) if (ModifierKeys != Keys.Control) return; - if (Application.OpenForms.Cast().Any(form => form.Name == typeof(f2_Text).Name)) - { WinFormsUtil.Alert("Window is already open."); return; } - new f2_Text(tb).Show(); + int offset = LB_DataEntry.SelectedIndex * 0x1B4; + var nicktrash = data.Skip(offset + 0x18).Take(24).ToArray(); + SAV.setString(TB_Nickname.Text, 12).CopyTo(nicktrash, 0); + var d = new f2_Text(tb, nicktrash); + d.ShowDialog(); + tb.Text = d.FinalString; + d.FinalBytes.CopyTo(data, offset + 0x18); + + string nickname = Util.TrimFromZero(Encoding.Unicode.GetString(data, offset + 0x18, 24)); + TB_Nickname.Text = nickname; } } } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs index b7d32bcf9..789884714 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs @@ -578,10 +578,9 @@ private void clickOT(object sender, MouseEventArgs e) if (ModifierKeys != Keys.Control) return; - var z = Application.OpenForms.Cast().FirstOrDefault(form => form.Name == typeof(f2_Text).Name) as f2_Text; - if (z != null) - { z.Location = Location; z.BringToFront(); return; } - new f2_Text(tb).Show(); + var d = new f2_Text(tb, null); + d.ShowDialog(); + tb.Text = d.FinalString; } private void showTSV(object sender, EventArgs e) { diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs index 95d7611a5..d9284c1f4 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs @@ -347,10 +347,9 @@ private void clickOT(object sender, MouseEventArgs e) if (ModifierKeys != Keys.Control) return; - var z = Application.OpenForms.Cast().FirstOrDefault(form => form.Name == typeof(f2_Text).Name) as f2_Text; - if (z != null) - { z.Location = Location; z.BringToFront(); return; } - new f2_Text(tb).Show(); + var d = new f2_Text(tb, null); + d.ShowDialog(); + tb.Text = d.FinalString; } private void showTSV(object sender, EventArgs e) { diff --git a/PKHeX/MysteryGifts/PGT.cs b/PKHeX/MysteryGifts/PGT.cs index bc6cc0f27..bb199fe28 100644 --- a/PKHeX/MysteryGifts/PGT.cs +++ b/PKHeX/MysteryGifts/PGT.cs @@ -60,7 +60,7 @@ public override int CardID } public override string CardTitle { - get { return PKX.array2strG4(Data.Skip(0x104).Take(0x48).ToArray()); } + get { return PKX.array2strG4(Data, 0x104, 0x48); } set { byte[] data = PKX.str2arrayG4(value); diff --git a/PKHeX/PKM/BK4.cs b/PKHeX/PKM/BK4.cs index e9845ed8f..6a3128896 100644 --- a/PKHeX/PKM/BK4.cs +++ b/PKHeX/PKM/BK4.cs @@ -27,18 +27,21 @@ public BK4(byte[] decryptedData = null, string ident = null) Data = PKX.shuffleArray45(Data, sv); Identifier = ident; if (Sanity != 0 && Species <= 493 && !ChecksumValid) // We can only hope - { RefreshChecksum(); - } if (Valid && Sanity == 0) - { Sanity = 0x4000; - } if (Data.Length != SIZE_PARTY) Array.Resize(ref Data, SIZE_PARTY); } public override PKM Clone() { return new BK4(Encrypt()); } + public override string getString(int Offset, int Count) => PKX.getBEString4(Data, Offset, Count); + public override byte[] setString(string value, int maxLength) => PKX.setBEString4(value, maxLength); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return getData(0x48, 24); } set { if (value?.Length == 24) value.CopyTo(Data, 0x48); } } + public override byte[] OT_Trash { get { return getData(0x68, 16); } set { if (value?.Length == 16) value.CopyTo(Data, 0x68); } } + // Future Attributes public override uint EncryptionConstant { get { return PID; } set { } } public override int Nature { get { return (int)(PID%25); } set { } } @@ -182,28 +185,7 @@ public override uint EXP #endregion #region Block C - public override string Nickname - { - get - { - return PKX.array2strG4BE(Data.Skip(0x48).Take(22).ToArray()) - .Replace("\uFF0D", "\u30FC") // Japanese chōonpu - .Replace("\uE08F", "\u2640") // nidoran - .Replace("\uE08E", "\u2642") // nidoran - .Replace("\u2019", "\u0027"); // farfetch'd - } - set - { - if (value.Length > 11) - value = value.Substring(0, 11); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u30FC", "\uFF0D") // Japanese chōonpu - .Replace("\u2640", "\uE08F") // nidoran - .Replace("\u2642", "\uE08E") // nidoran - .Replace("\u0027", "\u2019"); // farfetch'd - PKX.str2arrayG4BE(TempNick).CopyTo(Data, 0x48); - } - } + public override string Nickname { get { return getString(0x48, 24); } set { setString(value, 11).CopyTo(Data, 0x48); } } // 0x5E unused public override int Version { get { return Data[0x5F]; } set { Data[0x5F] = (byte)value; } } private byte RIB8 { get { return Data[0x60]; } set { Data[0x60] = value; } } // Sinnoh 3 @@ -246,28 +228,7 @@ public override string Nickname #endregion #region Block D - public override string OT_Name - { - get - { - return PKX.array2strG4BE(Data.Skip(0x68).Take(16).ToArray()) - .Replace("\uFF0D", "\u30FC") // Japanese chōonpu - .Replace("\uE08F", "\u2640") // Nidoran ♂ - .Replace("\uE08E", "\u2642") // Nidoran ♀ - .Replace("\u2019", "\u0027"); // Farfetch'd - } - set - { - if (value.Length > 7) - value = value.Substring(0, 7); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u30FC", "\uFF0D") // Japanese chōonpu - .Replace("\u2640", "\uE08F") // Nidoran ♂ - .Replace("\u2642", "\uE08E") // Nidoran ♀ - .Replace("\u0027", "\u2019"); // Farfetch'd - PKX.str2arrayG4BE(TempNick).CopyTo(Data, 0x68); - } - } + public override string OT_Name { get { return getString(0x68, 16); } set { setString(value, 7).CopyTo(Data, 0x68); } } public override int Egg_Year { get { return Data[0x78]; } set { Data[0x78] = (byte)value; } } public override int Egg_Month { get { return Data[0x79]; } set { Data[0x79] = (byte)value; } } public override int Egg_Day { get { return Data[0x7A]; } set { Data[0x7A] = (byte)value; } } diff --git a/PKHeX/PKM/CK3.cs b/PKHeX/PKM/CK3.cs index 4521db7bb..21c65b827 100644 --- a/PKHeX/PKM/CK3.cs +++ b/PKHeX/PKM/CK3.cs @@ -27,6 +27,13 @@ public CK3(byte[] decryptedData = null, string ident = null) } public override PKM Clone() { return new CK3(Data); } + public override string getString(int Offset, int Count) => PKX.getBEString3(Data, Offset, Count); + public override byte[] setString(string value, int maxLength) => PKX.setBEString3(value, maxLength); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return getData(0x1E, 20); } set { if (value?.Length == 20) value.CopyTo(Data, 0x1E); } } + public override byte[] OT_Trash { get { return getData(0x18, 20); } set { if (value?.Length == 20) value.CopyTo(Data, 0x18); } } + // Future Attributes public override uint EncryptionConstant { get { return PID; } set { } } public override int Nature { get { return (int)(PID % 25); } set { } } @@ -57,9 +64,9 @@ public CK3(byte[] decryptedData = null, string ident = null) public override int OT_Gender { get { return Data[0x10]; } set { Data[0x10] = (byte)value; } } public override int SID { get { return BigEndian.ToUInt16(Data, 0x14); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x14); } } public override int TID { get { return BigEndian.ToUInt16(Data, 0x16); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x16); } } - public override string OT_Name { get { return PKX.getColoStr(Data, 0x18, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x18); } } // +2 terminator - public override string Nickname { get { return PKX.getColoStr(Data, 0x2E, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x2E); Nickname2 = value; } } // +2 terminator - private string Nickname2 { get { return PKX.getColoStr(Data, 0x44, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x44); } } // +2 terminator + public override string OT_Name { get { return getString(0x18, 20); } set { setString(value, 10).CopyTo(Data, 0x18); } } // +2 terminator + public override string Nickname { get { return getString(0x2E, 20); } set { setString(value, 10).CopyTo(Data, 0x2E); Nickname2 = value; } } // +2 terminator + private string Nickname2 { get { return getString(0x44, 20); } set { setString(value, 10).CopyTo(Data, 0x44); } } // +2 terminator public override uint EXP { get { return BigEndian.ToUInt32(Data, 0x5C); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x5C);} } public override int Stat_Level { get { return Data[0x60]; } set { Data[0x60] = (byte)value; } } diff --git a/PKHeX/PKM/PK1.cs b/PKHeX/PKM/PK1.cs index 57f74737f..d62c40727 100644 --- a/PKHeX/PKM/PK1.cs +++ b/PKHeX/PKM/PK1.cs @@ -20,6 +20,13 @@ public class PK1 : PKM internal const int STRLEN_U = 11; private int StringLength => Japanese ? STRLEN_J : STRLEN_U; + public override string getString(int Offset, int Count) => PKX.getString1(Data, Offset, Count, Japanese); + public override byte[] setString(string value, int maxLength) => PKX.setString1(value, maxLength, Japanese); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return nick; } set { if (value?.Length == nick.Length) nick = value; } } + public override byte[] OT_Trash { get { return otname; } set { if (value?.Length == otname.Length) otname = value; } } + public override int Format => 1; public bool Japanese => otname.Length == STRLEN_J; @@ -46,12 +53,10 @@ public override PKM Clone() } public override string Nickname { - get { return PKX.getG1Str(nick, Japanese); } + get { return PKX.getString1(nick, 0, nick.Length, Japanese); } set { - byte[] strdata = PKX.setG1Str(value, Japanese); - if (strdata.Length > StringLength) - throw new ArgumentOutOfRangeException($"Nickname {value} too long for given PK1"); + byte[] strdata = setString(value, StringLength); if (nick.Any(b => b == 0) && nick[StringLength - 1] == 0x50 && Array.FindIndex(nick, b => b == 0) == strdata.Length - 1) // Handle JP Mew event with grace { int firstInd = Array.FindIndex(nick, b => b == 0); @@ -66,12 +71,10 @@ public override string Nickname public override string OT_Name { - get { return PKX.getG1Str(otname, Japanese); } + get { return PKX.getString1(otname, 0, otname.Length, Japanese); } set { - byte[] strdata = PKX.setG1Str(value, Japanese); - if (strdata.Length > StringLength) - throw new ArgumentOutOfRangeException($"OT Name {value} too long for given PK1"); + byte[] strdata = setString(value, StringLength); if (otname.Any(b => b == 0) && otname[StringLength - 1] == 0x50 && Array.FindIndex(otname, b => b == 0) == strdata.Length - 1) // Handle JP Mew event with grace { int firstInd = Array.FindIndex(otname, b => b == 0); @@ -102,8 +105,7 @@ public override bool IsNicknamed get { string spName = PKX.getSpeciesNameGeneration(Species, Japanese ? 1 : 2, Format); - return !nick.SequenceEqual( - PKX.setG1Str(spName, Japanese) + return !nick.SequenceEqual(setString(spName, StringLength) .Concat(Enumerable.Repeat((byte) 0x50, StringLength - spName.Length - 1)) .Select(b => (byte)(b == 0xF2 ? 0xE8 : b))); } @@ -126,7 +128,7 @@ public bool IsNicknamedBank public void setNotNicknamed() { string spName = PKX.getSpeciesNameGeneration(Species, Japanese ? 1 : 2, Format); - nick = PKX.setG1Str(spName, Japanese) + nick = setString(spName, StringLength) .Concat(Enumerable.Repeat((byte)0x50, StringLength - spName.Length - 1)) .Select(b => (byte)(b == 0xF2 ? 0xE8 : b)) // Decimal point<->period fix .ToArray(); diff --git a/PKHeX/PKM/PK2.cs b/PKHeX/PKM/PK2.cs index 0b5d27245..6cca49593 100644 --- a/PKHeX/PKM/PK2.cs +++ b/PKHeX/PKM/PK2.cs @@ -20,6 +20,13 @@ public class PK2 : PKM internal const int STRLEN_U = 11; private int StringLength => Japanese ? STRLEN_J : STRLEN_U; + public override string getString(int Offset, int Count) => PKX.getString1(Data, Offset, Count, Japanese); + public override byte[] setString(string value, int maxLength) => PKX.setString1(value, maxLength, Japanese); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return nick; } set { if (value?.Length == nick.Length) nick = value; } } + public override byte[] OT_Trash { get { return otname; } set { if (value?.Length == otname.Length) otname = value; } } + public override int Format => 2; public bool Japanese => otname.Length == STRLEN_J; @@ -56,12 +63,10 @@ public override PKM Clone() } public override string Nickname { - get { return PKX.getG1Str(nick, Japanese); } + get { return PKX.getString1(nick, 0, nick.Length, Japanese); } set { - byte[] strdata = PKX.setG1Str(value, Japanese); - if (strdata.Length > StringLength) - throw new ArgumentOutOfRangeException($"Nickname {value} too long for given PK2"); + byte[] strdata = setString(value, StringLength); if (nick.Any(b => b == 0) && nick[StringLength - 1] == 0x50 && Array.FindIndex(nick, b => b == 0) == strdata.Length - 1) // Handle JP Mew event with grace { int firstInd = Array.FindIndex(nick, b => b == 0); @@ -76,12 +81,10 @@ public override string Nickname public override string OT_Name { - get { return PKX.getG1Str(otname, Japanese); } + get { return PKX.getString1(otname, 0, otname.Length, Japanese); } set { - byte[] strdata = PKX.setG1Str(value, Japanese); - if (strdata.Length > StringLength) - throw new ArgumentOutOfRangeException($"OT Name {value} too long for given PK1"); + byte[] strdata = setString(value, StringLength); if (otname.Any(b => b == 0) && otname[StringLength - 1] == 0x50 && Array.FindIndex(otname, b => b == 0) == strdata.Length - 1) // Handle JP Mew event with grace { int firstInd = Array.FindIndex(otname, b => b == 0); @@ -112,8 +115,7 @@ public override bool IsNicknamed get { string spName = PKX.getSpeciesNameGeneration(Species, Japanese ? 1 : 2, Format); - return !nick.SequenceEqual( - PKX.setG1Str(spName, Japanese) + return !nick.SequenceEqual(setString(spName, StringLength) .Concat(Enumerable.Repeat((byte) 0x50, StringLength - spName.Length - 1)) .Select(b => (byte)(b == 0xF2 ? 0xE8 : b))); } @@ -126,7 +128,7 @@ public override bool IsNicknamed public void setNotNicknamed() { string spName = PKX.getSpeciesNameGeneration(Species, Japanese ? 1 : 2, Format); - nick = PKX.setG1Str(spName, Japanese) + nick = setString(spName, StringLength) .Concat(Enumerable.Repeat((byte)0x50, StringLength - spName.Length - 1)) .Select(b => (byte)(b == 0xF2 ? 0xE8 : b)) // Decimal point<->period fix .ToArray(); diff --git a/PKHeX/PKM/PK3.cs b/PKHeX/PKM/PK3.cs index fd931c59f..f58e1d6ba 100644 --- a/PKHeX/PKM/PK3.cs +++ b/PKHeX/PKM/PK3.cs @@ -24,6 +24,13 @@ public PK3(byte[] decryptedData = null, string ident = null) } public override PKM Clone() { return new PK3(Data); } + public override string getString(int Offset, int Count) => PKX.getString3(Data, Offset, Count, Japanese); + public override byte[] setString(string value, int maxLength) => PKX.setString3(value, maxLength, Japanese); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return getData(0x08, 10); } set { if (value?.Length == 10) value.CopyTo(Data, 0x08); } } + public override byte[] OT_Trash { get { return getData(0x14, 7); } set { if (value?.Length == 7) value.CopyTo(Data, 0x14); } } + // Future Attributes public override uint EncryptionConstant { get { return PID; } set { } } public override int Nature { get { return (int)(PID % 25); } set { } } @@ -41,20 +48,9 @@ public PK3(byte[] decryptedData = null, string ident = null) public override uint PID { get { return BitConverter.ToUInt32(Data, 0x00); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x00); } } public override int TID { get { return BitConverter.ToUInt16(Data, 0x04); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x04); } } public override int SID { get { return BitConverter.ToUInt16(Data, 0x06); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x06); } } - public override string Nickname { - get { return PKX.getG3Str(Data.Skip(0x08).Take(10).ToArray(), Japanese); } - set { byte[] strdata = PKX.setG3Str(IsEgg ? "タマゴ" : value, Japanese); - if (strdata.Length > 10) - Array.Resize(ref strdata, 10); - strdata.CopyTo(Data, 0x08); } } + public override string Nickname { get { return getString(0x08, 10); } set { setString(IsEgg ? "タマゴ" : value, 10).CopyTo(Data, 0x08); } } public override int Language { get { return BitConverter.ToUInt16(Data, 0x12) & 0xFF; } set { BitConverter.GetBytes((ushort)(IsEgg ? 0x601 : value | 0x200)).CopyTo(Data, 0x12); } } - public override string OT_Name { - get { return PKX.getG3Str(Data.Skip(0x14).Take(7).ToArray(), Japanese); } - set { byte[] strdata = PKX.setG3Str(value, Japanese); - if (strdata.Length > 7) - Array.Resize(ref strdata, 7); - strdata.CopyTo(Data, 0x14); } } - + public override string OT_Name { get { return getString(0x14, 7); } set { setString(value, 7).CopyTo(Data, 0x14); } } public override int MarkValue { get { return Data[0x1B]; } protected set { Data[0x1B] = (byte)value; } } public override ushort Checksum { get { return BitConverter.ToUInt16(Data, 0x1C); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x1C); } } public override ushort Sanity { get { return BitConverter.ToUInt16(Data, 0x1E); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x1E); } } diff --git a/PKHeX/PKM/PK4.cs b/PKHeX/PKM/PK4.cs index b2975c2a5..5ab3160b7 100644 --- a/PKHeX/PKM/PK4.cs +++ b/PKHeX/PKM/PK4.cs @@ -24,6 +24,13 @@ public PK4(byte[] decryptedData = null, string ident = null) } public override PKM Clone() { return new PK4(Data); } + public override string getString(int Offset, int Count) => PKX.getString4(Data, Offset, Count); + public override byte[] setString(string value, int maxLength) => PKX.setString4(value, maxLength); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return getData(0x48, 22); } set { if (value?.Length == 22) value.CopyTo(Data, 0x48); } } + public override byte[] OT_Trash { get { return getData(0x68, 16); } set { if (value?.Length == 16) value.CopyTo(Data, 0x68); } } + // Future Attributes public override uint EncryptionConstant { get { return PID; } set { } } public override int Nature { get { return (int)(PID%25); } set { } } @@ -164,28 +171,7 @@ public PK4(byte[] decryptedData = null, string ident = null) #endregion #region Block C - public override string Nickname - { - get - { - return PKX.array2strG4(Data.Skip(0x48).Take(22).ToArray()) - .Replace("\uFF0D", "\u30FC") // Japanese chōonpu - .Replace("\uE08F", "\u2640") // nidoran - .Replace("\uE08E", "\u2642") // nidoran - .Replace("\u2019", "\u0027"); // farfetch'd - } - set - { - if (value.Length > 11) - value = value.Substring(0, 11); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u30FC", "\uFF0D") // Japanese chōonpu - .Replace("\u2640", "\uE08F") // nidoran - .Replace("\u2642", "\uE08E") // nidoran - .Replace("\u0027", "\u2019"); // farfetch'd - PKX.str2arrayG4(TempNick).CopyTo(Data, 0x48); - } - } + public override string Nickname { get { return getString(0x48, 22); } set { setString(value, 11).CopyTo(Data, 0x48); } } // 0x5E unused public override int Version { get { return Data[0x5F]; } set { Data[0x5F] = (byte)value; } } private byte RIB8 { get { return Data[0x60]; } set { Data[0x60] = value; } } // Sinnoh 3 @@ -228,28 +214,7 @@ public override string Nickname #endregion #region Block D - public override string OT_Name - { - get - { - return PKX.array2strG4(Data.Skip(0x68).Take(16).ToArray()) - .Replace("\uFF0D", "\u30FC") // Japanese chōonpu - .Replace("\uE08F", "\u2640") // Nidoran ♂ - .Replace("\uE08E", "\u2642") // Nidoran ♀ - .Replace("\u2019", "\u0027"); // Farfetch'd - } - set - { - if (value.Length > 7) - value = value.Substring(0, 7); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u30FC", "\uFF0D") // Japanese chōonpu - .Replace("\u2640", "\uE08F") // Nidoran ♂ - .Replace("\u2642", "\uE08E") // Nidoran ♀ - .Replace("\u0027", "\u2019"); // Farfetch'd - PKX.str2arrayG4(TempNick).CopyTo(Data, 0x68); - } - } + public override string OT_Name { get { return getString(0x68, 16); } set { setString(value, 7).CopyTo(Data, 0x68); } } public override int Egg_Year { get { return Data[0x78]; } set { Data[0x78] = (byte)value; } } public override int Egg_Month { get { return Data[0x79]; } set { Data[0x79] = (byte)value; } } public override int Egg_Day { get { return Data[0x7A]; } set { Data[0x7A] = (byte)value; } } diff --git a/PKHeX/PKM/PK5.cs b/PKHeX/PKM/PK5.cs index b2a07330b..8e2a8f998 100644 --- a/PKHeX/PKM/PK5.cs +++ b/PKHeX/PKM/PK5.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Text; namespace PKHeX.Core { @@ -25,6 +24,13 @@ public PK5(byte[] decryptedData = null, string ident = null) } public override PKM Clone() { return new PK5(Data); } + public override string getString(int Offset, int Count) => PKX.getString5(Data, Offset, Count); + public override byte[] setString(string value, int maxLength) => PKX.setString5(value, maxLength); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return getData(0x48, 22); } set { if (value?.Length == 22) value.CopyTo(Data, 0x48); } } + public override byte[] OT_Trash { get { return getData(0x68, 16); } set { if (value?.Length == 16) value.CopyTo(Data, 0x68); } } + // Future Attributes public override uint EncryptionConstant { get { return PID; } set { } } public override int CurrentFriendship { get { return OT_Friendship; } set { OT_Friendship = value; } } @@ -167,27 +173,7 @@ public PK5(byte[] decryptedData = null, string ident = null) #endregion #region Block C - public override string Nickname - { - get - { - return PKX.TrimFromFFFF(Encoding.Unicode.GetString(Data, 0x48, 22)) - .Replace("\uE08F", "\u2640") // nidoran - .Replace("\uE08E", "\u2642") // nidoran - .Replace("\u2019", "\u0027"); // farfetch'd - } - set - { - if (value.Length > 11) - value = value.Substring(0, 11); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u2640", "\uE08F") // nidoran - .Replace("\u2642", "\uE08E") // nidoran - .Replace("\u0027", "\u2019") // farfetch'd - .PadRight(value.Length + 1, (char)0xFFFF); // Null Terminator - Encoding.Unicode.GetBytes(TempNick).CopyTo(Data, 0x48); - } - } + public override string Nickname { get { return getString(0x48, 22); } set { setString(value, 11).CopyTo(Data, 0x48); } } // 0x5E unused public override int Version { get { return Data[0x5F]; } set { Data[0x5F] = (byte)value; } } private byte RIB8 { get { return Data[0x60]; } set { Data[0x60] = value; } } // Sinnoh 3 @@ -230,27 +216,7 @@ public override string Nickname #endregion #region Block D - public override string OT_Name - { - get - { - return PKX.TrimFromFFFF(Encoding.Unicode.GetString(Data, 0x68, 16)) - .Replace("\uE08F", "\u2640") // Nidoran ♂ - .Replace("\uE08E", "\u2642") // Nidoran ♀ - .Replace("\u2019", "\u0027"); // farfetch'd - } - set - { - if (value.Length > 7) - value = value.Substring(0, 7); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u2640", "\uE08F") // Nidoran ♂ - .Replace("\u2642", "\uE08E") // Nidoran ♀ - .Replace("\u0027", "\u2019") // Farfetch'd - .PadRight(value.Length + 1, (char)0xFFFF); // Null Terminator - Encoding.Unicode.GetBytes(TempNick).CopyTo(Data, 0x68); - } - } + public override string OT_Name { get { return getString(0x68, 0x16); } set { setString(value, 7).CopyTo(Data, 0x68); } } public override int Egg_Year { get { return Data[0x78]; } set { Data[0x78] = (byte)value; } } public override int Egg_Month { get { return Data[0x79]; } set { Data[0x79] = (byte)value; } } public override int Egg_Day { get { return Data[0x7A]; } set { Data[0x7A] = (byte)value; } } diff --git a/PKHeX/PKM/PK6.cs b/PKHeX/PKM/PK6.cs index aaeecbaa5..f7fd002eb 100644 --- a/PKHeX/PKM/PK6.cs +++ b/PKHeX/PKM/PK6.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Text; namespace PKHeX.Core { @@ -26,6 +25,14 @@ public PK6(byte[] decryptedData = null, string ident = null) } public override PKM Clone() { return new PK6(Data); } + public override string getString(int Offset, int Count) => PKX.getString6(Data, Offset, Count); + public override byte[] setString(string value, int maxLength) => PKX.setString6(value, maxLength); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return getData(0x40, 24); } set { if (value?.Length == 24) value.CopyTo(Data, 0x40); } } + public override byte[] HT_Trash { get { return getData(0x78, 24); } set { if (value?.Length == 24) value.CopyTo(Data, 0x78); } } + public override byte[] OT_Trash { get { return getData(0xB0, 24); } set { if (value?.Length == 24) value.CopyTo(Data, 0xB0); } } + // Structure #region Block A public override uint EncryptionConstant @@ -207,18 +214,7 @@ public override uint PID public byte _0x3F { get { return Data[0x3F]; } set { Data[0x3F] = value; } } #endregion #region Block B - public override string Nickname - { - get { return PKX.SanitizeString(Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0x40, 24))); } - set - { - if (value.Length > 12) - value = value.Substring(0, 12); // Hard cap - string TempNick = PKX.UnSanitizeString(value) - .PadRight(value.Length + 1, '\0'); // Null Terminator - Encoding.Unicode.GetBytes(TempNick).CopyTo(Data, 0x40); - } - } + public override string Nickname { get { return getString(0x40, 24); } set { setString(value, 12).CopyTo(Data, 0x40); } } public override int Move1 { get { return BitConverter.ToUInt16(Data, 0x5A); } @@ -281,18 +277,7 @@ public override int RelearnMove4 public override bool IsNicknamed { get { return ((IV32 >> 31) & 1) == 1; } set { IV32 = (IV32 & 0x7FFFFFFF) | (value ? 0x80000000 : 0); } } #endregion #region Block C - public override string HT_Name - { - get { return PKX.SanitizeString(Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0x78, 24))); } - set - { - if (value.Length > 12) - value = value.Substring(0, 12); // Hard cap - string TempNick = PKX.UnSanitizeString(value) - .PadRight(value.Length + 1, '\0'); // Null Terminator - Encoding.Unicode.GetBytes(TempNick).CopyTo(Data, 0x78); - } - } + public override string HT_Name { get { return getString(0x78, 24); } set { setString(value, 12).CopyTo(Data, 0x78); } } public override int HT_Gender { get { return Data[0x92]; } set { Data[0x92] = (byte)value; } } public override int CurrentHandler { get { return Data[0x93]; } set { Data[0x93] = (byte)value; } } public override int Geo1_Region { get { return Data[0x94]; } set { Data[0x94] = (byte)value; } } @@ -324,18 +309,7 @@ public override string HT_Name public override byte Enjoyment { get { return Data[0xAF]; } set { Data[0xAF] = value; } } #endregion #region Block D - public override string OT_Name - { - get { return PKX.SanitizeString(Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0xB0, 24))); } - set - { - if (value.Length > 12) - value = value.Substring(0, 12); // Hard cap - string TempNick = PKX.UnSanitizeString(value) - .PadRight(value.Length + 1, '\0'); // Null Terminator - Encoding.Unicode.GetBytes(TempNick).CopyTo(Data, 0xB0); - } - } + public override string OT_Name { get { return getString(0xB0, 24); } set { setString(value, 12).CopyTo(Data, 0xB0); } } public override int OT_Friendship { get { return Data[0xCA]; } set { Data[0xCA] = (byte)value; } } public override int OT_Affection { get { return Data[0xCB]; } set { Data[0xCB] = (byte)value; } } public override int OT_Intensity { get { return Data[0xCC]; } set { Data[0xCC] = (byte)value; } } diff --git a/PKHeX/PKM/PK7.cs b/PKHeX/PKM/PK7.cs index c8b93c760..13df5dccf 100644 --- a/PKHeX/PKM/PK7.cs +++ b/PKHeX/PKM/PK7.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Text; namespace PKHeX.Core { @@ -27,6 +26,14 @@ public PK7(byte[] decryptedData = null, string ident = null) } public override PKM Clone() { return new PK7(Data); } + public override string getString(int Offset, int Count) => PKX.getString7(Data, Offset, Count); + public override byte[] setString(string value, int maxLength) => PKX.setString7(value, maxLength, Language); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return getData(0x40, 24); } set { if (value?.Length == 24) value.CopyTo(Data, 0x40); } } + public override byte[] HT_Trash { get { return getData(0x78, 24); } set { if (value?.Length == 24) value.CopyTo(Data, 0x78); } } + public override byte[] OT_Trash { get { return getData(0xB0, 24); } set { if (value?.Length == 24) value.CopyTo(Data, 0xB0); } } + // Structure #region Block A public override uint EncryptionConstant @@ -215,18 +222,7 @@ public override uint PID public byte _0x3F { get { return Data[0x3F]; } set { Data[0x3F] = value; } } #endregion #region Block B - public override string Nickname - { - get { return PKX.bin2strG7_zh(PKX.SanitizeString(Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0x40, 24)))); } - set - { - if (value.Length > 12) - value = value.Substring(0, 12); // Hard cap - string TempNick = PKX.str2binG7_zh(PKX.UnSanitizeString(value),Language == 10) - .PadRight(value.Length + 1, '\0'); // Null Terminator - Encoding.Unicode.GetBytes(TempNick).CopyTo(Data, 0x40); - } - } + public override string Nickname { get { return getString(0x40, 24); } set { setString(value, 12).CopyTo(Data, 0x40); } } public override int Move1 { get { return BitConverter.ToUInt16(Data, 0x5A); } @@ -289,18 +285,7 @@ public override int RelearnMove4 public override bool IsNicknamed { get { return ((IV32 >> 31) & 1) == 1; } set { IV32 = (IV32 & 0x7FFFFFFF) | (value ? 0x80000000 : 0); } } #endregion #region Block C - public override string HT_Name - { - get { return PKX.SanitizeString(Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0x78, 24))); } - set - { - if (value.Length > 12) - value = value.Substring(0, 12); // Hard cap - string TempNick = PKX.UnSanitizeString(value) - .PadRight(value.Length + 1, '\0'); // Null Terminator - Encoding.Unicode.GetBytes(TempNick).CopyTo(Data, 0x78); - } - } + public override string HT_Name { get { return getString(0x78, 24); } set { setString(value, 12).CopyTo(Data, 0x78); } } public override int HT_Gender { get { return Data[0x92]; } set { Data[0x92] = (byte)value; } } public override int CurrentHandler { get { return Data[0x93]; } set { Data[0x93] = (byte)value; } } public override int Geo1_Region { get { return Data[0x94]; } set { Data[0x94] = (byte)value; } } @@ -332,18 +317,7 @@ public override string HT_Name public override byte Enjoyment { get { return Data[0xAF]; } set { Data[0xAF] = value; } } #endregion #region Block D - public override string OT_Name - { - get { return PKX.SanitizeString(Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0xB0, 24))); } - set - { - if (value.Length > 12) - value = value.Substring(0, 12); // Hard cap - string TempNick = PKX.UnSanitizeString(value) - .PadRight(value.Length + 1, '\0'); // Null Terminator - Encoding.Unicode.GetBytes(TempNick).CopyTo(Data, 0xB0); - } - } + public override string OT_Name { get { return getString(0xB0, 24); } set { setString(value, 12).CopyTo(Data, 0xB0); } } public override int OT_Friendship { get { return Data[0xCA]; } set { Data[0xCA] = (byte)value; } } public override int OT_Affection { get { return Data[0xCB]; } set { Data[0xCB] = (byte)value; } } public override int OT_Intensity { get { return Data[0xCC]; } set { Data[0xCC] = (byte)value; } } diff --git a/PKHeX/PKM/PKM.cs b/PKHeX/PKM/PKM.cs index fa888a8f2..465256973 100644 --- a/PKHeX/PKM/PKM.cs +++ b/PKHeX/PKM/PKM.cs @@ -23,6 +23,23 @@ public abstract class PKM public virtual byte[] DecryptedBoxData => Write().Take(SIZE_STORED).ToArray(); public virtual bool Valid { get { return ChecksumValid && Sanity == 0; } set { if (!value) return; Sanity = 0; RefreshChecksum(); } } + public abstract string getString(int Offset, int Length); + public abstract byte[] setString(string value, int maxLength); + + // Trash Bytes + public abstract byte[] Nickname_Trash { get; set; } + public abstract byte[] OT_Trash { get; set; } + public virtual byte[] HT_Trash { get; set; } + public byte[] getData(int Offset, int Length) + { + if (Offset + Length > Data.Length) + return null; + + byte[] data = new byte[Length]; + Array.Copy(Data, Offset, data, 0, Length); + return data; + } + protected virtual ushort CalculateChecksum() { ushort chk = 0; diff --git a/PKHeX/PKM/PKX.cs b/PKHeX/PKM/PKX.cs index 217432fe3..ad64ca9e7 100644 --- a/PKHeX/PKM/PKX.cs +++ b/PKHeX/PKM/PKX.cs @@ -1196,14 +1196,14 @@ public static int getUnownForm(uint PID) /// In-game chinese string. public static string str2binG7_zh(string inputstr, bool cht = false) { - int index; string resultstr = ""; + string resultstr = ""; bool IsCHT = inputstr.Any(chr => Gen7_CHT.Contains(chr) && !Gen7_CHS.Contains(chr)); IsCHT |= cht && !inputstr.Any(chr => Gen7_CHT.Contains(chr) ^ Gen7_CHS.Contains(chr)); // CHS and CHT have the same display name var table = IsCHT ? Gen7_CHT : Gen7_CHS; ushort ofs = IsCHT ? Gen7_CHT_Ofs : Gen7_CHS_Ofs; foreach (char chr in inputstr) { - index = Array.IndexOf(table, chr); + var index = Array.IndexOf(table, chr); resultstr += index > -1 ? (char)(ofs + index) : chr; } return resultstr; @@ -1216,13 +1216,13 @@ public static string str2binG7_zh(string inputstr, bool cht = false) public static string bin2strG7_zh(string inputstr) { string resultstr = ""; - foreach (ushort val in inputstr) + foreach (var val in inputstr) { if (Gen7_CHS_Ofs <= val && val < Gen7_CHS_Ofs + Gen7_CHS.Length) - { resultstr += Gen7_CHS[val - Gen7_CHS_Ofs]; continue; } - if (Gen7_CHT_Ofs <= val && val < Gen7_CHT_Ofs + Gen7_CHT.Length) - { resultstr += Gen7_CHT[val - Gen7_CHT_Ofs]; continue; } - resultstr += (char)val; + resultstr += Gen7_CHS[val - Gen7_CHS_Ofs]; + else if (Gen7_CHT_Ofs <= val && val < Gen7_CHT_Ofs + Gen7_CHT.Length) + resultstr += Gen7_CHT[val - Gen7_CHT_Ofs]; + else resultstr += val; } return resultstr; } @@ -1253,13 +1253,15 @@ public static ushort char2valG4(ushort chr) /// Converts Generation 4 Little Endian encoded character data to string. /// /// Byte array containing encoded character data. + /// Offset to read from + /// Length of data to read. /// Converted string. - public static string array2strG4(byte[] strdata) + public static string array2strG4(byte[] strdata, int offset, int count) { string s = ""; - for (int i = 0; i < strdata.Length; i += 2) + for (int i = 0; i < count; i += 2) { - ushort val = BitConverter.ToUInt16(strdata, i); + ushort val = BitConverter.ToUInt16(strdata, offset + i); if (val == 0xFFFF) break; ushort chr = val2charG4(val); if (chr == 0xFFFF) break; @@ -1292,13 +1294,15 @@ public static byte[] str2arrayG4(string str) /// Converts Generation 4 Big Endian encoded character data to string. /// /// Byte array containing encoded character data. + /// Offset to read from + /// Length of data to read. /// Converted string. - public static string array2strG4BE(byte[] strdata) + public static string getBEString4(byte[] strdata, int offset, int count) { string s = ""; - for (int i = 0; i < strdata.Length; i += 2) + for (int i = 0; i < count; i += 2) { - ushort val = BigEndian.ToUInt16(strdata, i); + ushort val = BigEndian.ToUInt16(strdata, offset + i); if (val == 0xFFFF) break; ushort chr = val2charG4(val); if (chr == 0xFFFF) break; @@ -1310,20 +1314,32 @@ public static string array2strG4BE(byte[] strdata) /// /// Converts a string to Generation 4 Big Endian encoded character data. /// - /// String to be converted. + /// String to be converted. + /// Maximum length of string + /// Pad to given length + /// Pad with value /// Byte array containing encoded character data - public static byte[] str2arrayG4BE(string str) + public static byte[] setBEString4(string value, int maxLength, int padTo = 0, ushort padWith = 0) { - byte[] strdata = new byte[str.Length * 2 + 2]; // +2 for 0xFFFF - for (int i = 0; i < str.Length; i++) + if (value.Length > maxLength) + value = value.Substring(0, maxLength); // Hard cap + byte[] strdata = new byte[value.Length * 2 + 2]; // +2 for 0xFFFF + for (int i = 0; i < value.Length; i++) { - ushort chr = str[i]; + ushort chr = value[i]; ushort val = char2valG4(chr); if (val == 0xFFFF || chr == 0xFFFF) { Array.Resize(ref strdata, i * 2); break; } BigEndian.GetBytes(val).CopyTo(strdata, i * 2); } BitConverter.GetBytes((ushort)0xFFFF).CopyTo(strdata, strdata.Length - 2); + if (padTo > strdata.Length) + { + int start = strdata.Length; + Array.Resize(ref strdata, padTo); + for (int i = start; i < padTo; i += 2) + BitConverter.GetBytes(padWith).CopyTo(strdata, i); + } return strdata; } @@ -1359,29 +1375,43 @@ public static byte setG3Char(ushort chr, bool jp) /// Converts a Generation 3 encoded value array to string. /// /// Byte array containing string data. + /// Offset to read from + /// Length of data to read. /// Value source is Japanese font. /// Decoded string. - public static string getG3Str(byte[] strdata, bool jp) + public static string getString3(byte[] strdata, int offset, int count, bool jp) { - return strdata - .TakeWhile(val => val < 247) // Take valid values - .Select(val => getG3Char(val, jp)) // Convert to Unicode - .TakeWhile(chr => chr != 0xFF) // Stop if Terminator - .Aggregate("", (current, chr) => current + (char)chr); + StringBuilder s = new StringBuilder(); + for (int i = 0; i < count; i++) + { + byte val = strdata[offset + i]; + if (val >= 247) // Take valid values + break; + var c = getG3Char(val, jp); // Convert to Unicode + if (c == 0xFF) // Stop if Terminator + break; + s.Append((char)c); + } + return SanitizeString(s.ToString()); } /// /// Converts a string to a Generation 3 encoded value array. /// - /// Decoded string. + /// Decoded string. /// String destination is Japanese font. + /// Maximum length of string + /// Pad to given length + /// Pad with value /// - public static byte[] setG3Str(string str, bool jp) + public static byte[] setString3(string value, int maxLength, bool jp, int padTo = 0, ushort padWith = 0) { - byte[] strdata = new byte[str.Length + 1]; // +1 for 0xFF - for (int i = 0; i < str.Length; i++) + if (value.Length > maxLength) + value = value.Substring(0, maxLength); // Hard cap + byte[] strdata = new byte[value.Length + 1]; // +1 for 0xFF + for (int i = 0; i < value.Length; i++) { - ushort chr = str[i]; + ushort chr = value[i]; byte val = setG3Char(chr, jp); if (val == 0xFF || chr == 0xFF) { Array.Resize(ref strdata, i); break; } @@ -1389,6 +1419,13 @@ public static byte[] setG3Str(string str, bool jp) } if (strdata.Length > 0) strdata[strdata.Length - 1] = 0xFF; + if (strdata.Length < padTo) + { + int start = strdata.Length; + Array.Resize(ref strdata, padTo); + for (int i = start; i < strdata.Length; i++) + strdata[i] = (byte)padWith; + } return strdata; } @@ -1871,9 +1908,9 @@ public static int getGender(int species, uint PID) #endregion #region Gen7 Chinese Character Tables public static readonly char[] Gen7_CHS = Util.getStringList("Char", "zh")[0].ToCharArray(); - public static readonly ushort Gen7_CHS_Ofs = 0xE800; + public const ushort Gen7_CHS_Ofs = 0xE800; public static readonly char[] Gen7_CHT = Util.getStringList("Char", "zh2")[0].ToCharArray(); - public static readonly ushort Gen7_CHT_Ofs = 0xEB09; + public const ushort Gen7_CHT_Ofs = 0xEB09; #endregion /// /// Trash Bytes for Generation 3->4 @@ -2593,16 +2630,26 @@ public static int setG1Species(int dex_id) /// Converts Generation 1 encoded data into a string. /// /// Encoded data. + /// Offset to read from + /// /// Data source is Japanese. /// Decoded string. - public static string getG1Str(byte[] strdata, bool jp) + public static string getString1(byte[] strdata, int offset, int count, bool jp) { Dictionary dict = jp ? RBY2U_J : RBY2U_U; - return strdata - .TakeWhile(b => dict.ContainsKey(b)) - .Select(b => dict[b]) - .TakeWhile(s => s != "\0") - .Aggregate("", (current, cur) => current + cur); + + StringBuilder s = new StringBuilder(); + for (int i = 0; i < count; i++) + { + byte val = strdata[offset + i]; + if (!dict.ContainsKey(val)) // Take valid values + break; + string c = dict[val]; // Convert to Unicode + if (c == "\0") // Stop if Terminator + break; + s.Append(c); + } + return SanitizeString(s.ToString()); } /// @@ -2634,49 +2681,225 @@ public static string getG1ConvertedString(byte[] strdata, bool jp) /// /// Converts a string to Generation 1 encoded data. /// - /// Decoded string. + /// Decoded string. + /// Maximum length /// Data destination is Japanese. + /// Pad to given length + /// Pad with value /// Encoded data. - public static byte[] setG1Str(string str, bool jp) + public static byte[] setString1(string value, int maxLength, bool jp, int padTo = 0, ushort padWith = 0) { + if (value.Length > maxLength) + value = value.Substring(0, maxLength); // Hard cap + Dictionary dict = jp ? U2RBY_J : U2RBY_U; - if (dict.ContainsKey(str)) // Handle "[TRAINER]" - return new[] {dict[str], dict["\0"]}; - return str - .TakeWhile(c => dict.ContainsKey(c.ToString())) - .Select(c => dict[c.ToString()]) - .Concat(new[] {dict["\0"]}) - .ToArray(); + if (dict.ContainsKey(value)) // Handle "[TRAINER]" + return new[] {dict[value], dict["\0"]}; + + List arr = new List(); + foreach (char c in value) + { + byte val; + if (!dict.TryGetValue(c.ToString(), out val)) + break; + arr.Add(val); + } + var term = dict["\0"]; // terminator + arr.Add(term); + while (arr.Count < padTo) + arr.Add((byte)padWith); + return arr.ToArray(); } - /// - /// Converts Big Endian encoded data to decoded string. - /// + /// Converts Big Endian encoded data to decoded string. /// Encoded data /// Offset to read from - /// Length of data to read. + /// Length of data to read. /// Decoded string. - public static string getColoStr(byte[] data, int offset, int length) + public static string getBEString3(byte[] data, int offset, int count) { - return Util.TrimFromZero(Encoding.BigEndianUnicode.GetString(data, offset, length * 2)); + return Util.TrimFromZero(Encoding.BigEndianUnicode.GetString(data, offset, count)); + } + + /// Gets the bytes for a BigEndian string. + /// Decoded string. + /// Maximum length + /// Pad to given length + /// Pad with value + /// Encoded data. + public static byte[] setBEString3(string value, int maxLength, int padTo = 0, ushort padWith = 0) + { + if (value.Length > maxLength) + value = value.Substring(0, maxLength); // Hard cap + string temp = SanitizeString(value) + .PadRight(value.Length + 1, (char)0) // Null Terminator + .PadRight(padTo, (char)padWith); + return Encoding.BigEndianUnicode.GetBytes(temp); + } + + /// Converts Generation 4 encoded data to decoded string. + /// Encoded data + /// Offset to read from + /// Length of data to read. + /// Decoded string. + public static string getString4(byte[] data, int offset, int count) + { + string value = array2strG4(data, offset, count); + return SanitizeString(value) + .Replace("\uFF0D", "\u30FC") // Japanese chōonpu + ; + } + + /// Gets the bytes for a 4th Generation String + /// Decoded string. + /// Maximum length + /// Pad to given length + /// Pad with value + /// Encoded data. + public static byte[] setString4(string value, int maxLength, int padTo = 0, ushort padWith = 0) + { + if (value.Length > maxLength) + value = value.Substring(0, maxLength); // Hard cap + string temp = UnSanitizeString(value) // Replace Special Characters and add Terminator + .Replace("\u30FC", "\uFF0D") // Japanese chōonpu + .PadRight(value.Length + 1, (char)0xFFFF) // Null Terminator + .PadRight(padTo, (char)padWith); // Padding + return str2arrayG4(temp); + } + + /// Converts Generation 5 encoded data to decoded string. + /// Encoded data + /// Offset to read from + /// Length of data to read. + /// Decoded string. + public static string getString5(byte[] data, int offset, int count) + { + return SanitizeString(TrimFromFFFF(Encoding.Unicode.GetString(data, offset, count))); + } + + /// Gets the bytes for a Generation 5 string. + /// Decoded string. + /// Maximum length + /// Pad to given length + /// Pad with value + /// Encoded data. + public static byte[] setString5(string value, int maxLength, int padTo = 0, ushort padWith = 0) + { + if (value.Length > maxLength) + value = value.Substring(0, maxLength); // Hard cap + string temp = UnSanitizeString(value) + .PadRight(value.Length + 1, (char)0xFFFF) // Null Terminator + .PadRight(padTo, (char)padWith); // Padding + return Encoding.Unicode.GetBytes(temp); + } + + /// Converts Generation 6 encoded data to decoded string. + /// Encoded data + /// Offset to read from + /// Length of data to read. + /// Decoded string. + public static string getString6(byte[] data, int offset, int count) + { + return SanitizeString(Util.TrimFromZero(Encoding.Unicode.GetString(data, offset, count))); + } + + /// Gets the bytes for a Generation 6 string. + /// Decoded string. + /// Maximum length + /// Pad to given length + /// Pad with value + /// Encoded data. + public static byte[] setString6(string value, int maxLength, int padTo = 0, ushort padWith = 0) + { + if (value.Length > maxLength) + value = value.Substring(0, maxLength); // Hard cap + string temp = UnSanitizeString(value) + .PadRight(value.Length + 1, '\0') // Null Terminator + .PadRight(padTo, (char)padWith); + return Encoding.Unicode.GetBytes(temp); + } + + /// Converts Generation 7 encoded data to decoded string. + /// Encoded data + /// Offset to read from + /// Length of data to read. + /// Decoded string. + public static string getString7(byte[] data, int offset, int count) + { + return bin2strG7_zh(SanitizeString(Util.TrimFromZero(Encoding.Unicode.GetString(data, offset, count)))); + } + + /// Gets the bytes for a Generation 7 string. + /// Decoded string. + /// Maximum length + /// Language specific conversion (Chinese) + /// Pad to given length + /// Pad with value + /// Encoded data. + public static byte[] setString7(string value, int maxLength, int language, int padTo = 0, ushort padWith = 0) + { + if (value.Length > maxLength) + value = value.Substring(0, 12); // Hard cap + string temp = str2binG7_zh(UnSanitizeString(value), language == 10) + .PadRight(value.Length + 1, '\0') // Null Terminator + .PadRight(padTo, (char)padWith); + return Encoding.Unicode.GetBytes(temp); } /// - /// Gets the bytes for a BigEndian string. + /// Converts bytes to a string according to the input parameters. /// - /// - /// - /// - public static byte[] setColoStr(string value, int length) + /// Encoded data + /// Generation string format + /// Encoding is Japanese + /// Encoding is BigEndian + /// Offset to read from + /// Length of data to read. + /// Decoded string. + public static string getString(byte[] data, int generation, bool jp, bool bigendian, int count, int offset = 0) { - if (value.Length > length) - value = value.Substring(0, length); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u2640", "\uE08F") // nidoran - .Replace("\u2642", "\uE08E") // nidoran - .Replace("\u0027", "\u2019") // farfetch'd - .PadRight(value.Length + 1, (char)0); // Null Terminator - return Encoding.BigEndianUnicode.GetBytes(TempNick); + if (bigendian) + return generation == 3 ? getBEString3(data, offset, count) : getBEString4(data, offset, count); + + switch (generation) + { + case 1: + case 2: return getString1(data, offset, count, jp); + case 3: return getString3(data, offset, count, jp); + case 4: return getString4(data, offset, count); + case 5: return getString5(data, offset, count); + case 6: return getString6(data, offset, count); + default: return getString7(data, offset, count); + } + } + + /// + /// Gets the bytes for a Generation specific string according to the input parameters. + /// + /// Decoded string. + /// Generation string format + /// Encoding is Japanese + /// Encoding is BigEndian + /// + /// + /// Pad to given length + /// Pad with value + /// Encoded data. + public static byte[] setString(string value, int generation, bool jp, bool bigendian, int maxLength, int language = 0, int padTo = 0, ushort padWith = 0) + { + if (bigendian) + return generation == 3 ? setBEString3(value, maxLength, padTo, padWith) : setBEString4(value, maxLength, padTo, padWith); + + switch (generation) + { + case 1: + case 2: return setString1(value, maxLength, jp, padTo, padWith); + case 3: return setString3(value, maxLength, jp, padTo, padWith); + case 4: return setString4(value, maxLength, padTo, padWith); + case 5: return setString5(value, maxLength, padTo, padWith); + case 6: return setString6(value, maxLength, padTo, padWith); + default: return setString7(value, maxLength, language, padTo, padWith); + } } /// diff --git a/PKHeX/PKM/XK3.cs b/PKHeX/PKM/XK3.cs index 630055c2d..9ced889dc 100644 --- a/PKHeX/PKM/XK3.cs +++ b/PKHeX/PKM/XK3.cs @@ -25,6 +25,13 @@ public XK3(byte[] decryptedData = null, string ident = null) } public override PKM Clone() { return new XK3(Data) {Purification = Purification}; } + public override string getString(int Offset, int Count) => PKX.getBEString3(Data, Offset, Count); + public override byte[] setString(string value, int maxLength) => PKX.setBEString3(value, maxLength); + + // Trash Bytes + public override byte[] Nickname_Trash { get { return getData(0x4E, 20); } set { if (value?.Length == 20) value.CopyTo(Data, 0x4E); } } + public override byte[] OT_Trash { get { return getData(0x38, 20); } set { if (value?.Length == 20) value.CopyTo(Data, 0x38); } } + // Future Attributes public override uint EncryptionConstant { get { return PID; } set { } } public override int Nature { get { return (int)(PID % 25); } set { } } @@ -82,9 +89,9 @@ public XK3(byte[] decryptedData = null, string ident = null) public int CurrentRegion { get { return Data[0x35]; } set { Data[0x35] = (byte)value; } } public int OriginalRegion { get { return Data[0x36]; } set { Data[0x36] = (byte)value; } } public override int Language { get { return PKX.getMainLangIDfromGC(Data[0x37]); } set { Data[0x37] = PKX.getGCLangIDfromMain((byte)value); } } - public override string OT_Name { get { return PKX.getColoStr(Data, 0x38, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x38); } } // +2 terminator - public override string Nickname { get { return PKX.getColoStr(Data, 0x4E, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x4E); Nickname2 = value; } } // +2 terminator - private string Nickname2 { get { return PKX.getColoStr(Data, 0x64, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x64); } } // +2 terminator + public override string OT_Name { get { return getString(0x38, 20); } set { setString(value, 10).CopyTo(Data, 0x38); } } // +2 terminator + public override string Nickname { get { return getString(0x4E, 20); } set { setString(value, 10).CopyTo(Data, 0x4E); Nickname2 = value; } } // +2 terminator + private string Nickname2 { get { return getString(0x64, 20); } set { setString(value, 10).CopyTo(Data, 0x64); } } // +2 terminator // 0x7A-0x7B Unknown private ushort RIB0 { get { return BigEndian.ToUInt16(Data, 0x7C); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x7C); } } public bool RibbonChampionG3Hoenn { get { return (RIB0 & (1 << 15)) == 1 << 15; } set { RIB0 = (ushort)(RIB0 & ~(1 << 15) | (ushort)(value ? 1 << 15 : 0)); } } diff --git a/PKHeX/Saves/SAV1.cs b/PKHeX/Saves/SAV1.cs index efebdbfcf..7d777b83c 100644 --- a/PKHeX/Saves/SAV1.cs +++ b/PKHeX/Saves/SAV1.cs @@ -224,14 +224,8 @@ public override bool ChecksumsValid public override string OT { - get { return PKX.getG1Str(Data.Skip(0x2598).Take(StringLength).ToArray(), Japanese); } - set - { - byte[] strdata = PKX.setG1Str(value, Japanese); - if (strdata.Length > StringLength) - throw new ArgumentException("OT Name too long for given save file."); - strdata.CopyTo(Data, 0x2598); - } + get { return getString(0x2598, OTLength); } + set { setString(value, OTLength).CopyTo(Data, 0x2598); } } public override int Gender { @@ -493,5 +487,13 @@ public override bool getCaught(int species) byte bitval = (byte)(1 << (bit & 7)); return (Data[PokedexCaughtOffset + ofs] & bitval) != 0; } + + public override string getString(int Offset, int Count) => PKX.getString1(Data, Offset, Count, Japanese); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setString1(value, maxLength, Japanese, PadToSize, PadWith); + } } } diff --git a/PKHeX/Saves/SAV2.cs b/PKHeX/Saves/SAV2.cs index 475b2112f..69cba406c 100644 --- a/PKHeX/Saves/SAV2.cs +++ b/PKHeX/Saves/SAV2.cs @@ -238,8 +238,6 @@ private void getSAVOffsets() public override int BoxSlotCount => Japanese ? 30 : 20; public override bool HasParty => true; - private int StringLength => Japanese ? PK2.STRLEN_J : PK2.STRLEN_U; - // Offsets private int OptionsOffset { get; set; } = int.MinValue; @@ -303,14 +301,8 @@ public override bool ChecksumsValid public override string OT { - get { return PKX.getG1Str(getData(0x200B, StringLength), Japanese); } - set - { - byte[] strdata = PKX.setG1Str(value, Japanese); - if (strdata.Length > StringLength) - throw new ArgumentException("OT Name too long for given save file."); - strdata.CopyTo(Data, 0x200B); - } + get { return getString(0x200B, OTLength); } + set { setString(value, OTLength).CopyTo(Data, 0x200B); } } public override int Gender { @@ -513,7 +505,7 @@ public override int CurrentBox } public override string getBoxName(int box) { - return PKX.getG1Str(getData(BoxNamesOffset + box*9, 9), Japanese); + return PKX.getString1(Data, BoxNamesOffset + box*9, 9, Japanese); } public override void setBoxName(int box, string value) { @@ -600,5 +592,8 @@ public override bool getCaught(int species) // Get the Caught Flag return (Data[PokedexCaughtOffset + ofs] & bitval) != 0; } + + public override string getString(int Offset, int Count) => PKX.getString1(Data, Offset, Count, Japanese); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) => PKX.setString1(value, maxLength, Japanese); } } diff --git a/PKHeX/Saves/SAV3.cs b/PKHeX/Saves/SAV3.cs index 01dd80b6d..77c7f87db 100644 --- a/PKHeX/Saves/SAV3.cs +++ b/PKHeX/Saves/SAV3.cs @@ -248,23 +248,8 @@ private uint SecurityKey } public override string OT { - get - { - return PKX.getG3Str(Data.Skip(BlockOfs[0]).Take(0x10).ToArray(), Japanese) - .Replace("\uE08F", "\u2640") // Nidoran ♂ - .Replace("\uE08E", "\u2642") // Nidoran ♀ - .Replace("\u2019", "\u0027"); // Farfetch'd - } - set - { - if (value.Length > 7) - value = value.Substring(0, 7); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u2640", "\uE08F") // Nidoran ♂ - .Replace("\u2642", "\uE08E") // Nidoran ♀ - .Replace("\u0027", "\u2019"); // Farfetch'd - PKX.setG3Str(TempNick, Japanese).CopyTo(Data, BlockOfs[0]); - } + get { return getString(BlockOfs[0], 0x10); } + set { setString(value, 7).CopyTo(Data, BlockOfs[0]); } } public override int Gender { @@ -457,14 +442,12 @@ protected override int getBoxWallpaperOffset(int box) public override string getBoxName(int box) { int offset = getBoxOffset(BoxCount); - return PKX.getG3Str(Data.Skip(offset + box * 9).Take(9).ToArray(), Japanese); + return PKX.getString3(Data, offset + box * 9, 9, Japanese); } public override void setBoxName(int box, string value) { - if (value.Length > 8) - value = value.Substring(0, 8); // Hard cap int offset = getBoxOffset(BoxCount); - PKX.setG3Str(value, Japanese).CopyTo(Data, offset + box * 9); + setString(value, 8).CopyTo(Data, offset + box * 9); } public override PKM getPKM(byte[] data) { @@ -593,5 +576,12 @@ public bool NationalDex } } } + public override string getString(int Offset, int Count) => PKX.getString3(Data, Offset, Count, Japanese); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setString3(value, maxLength, Japanese, PadToSize, PadWith); + } } } diff --git a/PKHeX/Saves/SAV3Colosseum.cs b/PKHeX/Saves/SAV3Colosseum.cs index b342de3d3..73b8bf1a6 100644 --- a/PKHeX/Saves/SAV3Colosseum.cs +++ b/PKHeX/Saves/SAV3Colosseum.cs @@ -281,13 +281,11 @@ public override int getBoxOffset(int box) } public override string getBoxName(int box) { - return PKX.getColoStr(Data, Box + 0x24A4*box, 8); + return getString(Box + 0x24A4*box, 16); } public override void setBoxName(int box, string value) { - if (value.Length > 8) - value = value.Substring(0, 8); // Hard cap - PKX.setColoStr(value, 8).CopyTo(Data, Box + 0x24A4*box); + setString(value, 8).CopyTo(Data, Box + 0x24A4*box); } public override PKM getPKM(byte[] data) { @@ -350,15 +348,15 @@ public override int PlayedSeconds } // Trainer Info (offset 0x78, length 0xB18, end @ 0xB90) - public override string OT { get { return PKX.getColoStr(Data, 0x78, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x78); OT2 = value; } } - private string OT2 { get { return PKX.getColoStr(Data, 0x8C, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0x8C); } } + public override string OT { get { return getString(0x78, 20); } set { setString(value, 10).CopyTo(Data, 0x78); OT2 = value; } } + private string OT2 { get { return getString(0x8C, 20); } set { setString(value, 10).CopyTo(Data, 0x8C); } } public override ushort SID { get { return BigEndian.ToUInt16(Data, 0xA4); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xA4); } } public override ushort TID { get { return BigEndian.ToUInt16(Data, 0xA6); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xA6); } } public override int Gender { get { return Data[0xAF8]; } set { Data[0xAF8] = (byte)value; } } public override uint Money { get { return BigEndian.ToUInt32(Data, 0xAFC); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xAFC); } } public uint Coupons { get { return BigEndian.ToUInt32(Data, 0xB00); } set { BigEndian.GetBytes(value).CopyTo(Data, 0xB00); } } - public string RUI_Name { get { return PKX.getColoStr(Data, 0xB3A, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, 0xB3A); } } + public string RUI_Name { get { return getString(0xB3A, 20); } set { setString(value, 10).CopyTo(Data, 0xB3A); } } public override InventoryPouch[] Inventory { @@ -394,5 +392,13 @@ public override InventoryPouch[] Inventory public override bool? getDaycareOccupied(int loc, int slot) { return null; } public override void setDaycareEXP(int loc, int slot, uint EXP) { } public override void setDaycareOccupied(int loc, int slot, bool occupied) { } + + public override string getString(int Offset, int Count) => PKX.getBEString3(Data, Offset, Count); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setBEString3(value, maxLength, PadToSize, PadWith); + } } } diff --git a/PKHeX/Saves/SAV3RSBox.cs b/PKHeX/Saves/SAV3RSBox.cs index 7b3046da4..167ce5850 100644 --- a/PKHeX/Saves/SAV3RSBox.cs +++ b/PKHeX/Saves/SAV3RSBox.cs @@ -166,17 +166,14 @@ public override string getBoxName(int box) int offset = Box + 0x1EC38 + 9 * box; if (Data[offset] == 0 || Data[offset] == 0xFF) boxName += $"BOX {box + 1}"; - boxName += PKX.getG3Str(getData(offset, 9), Japanese); + boxName += getString(offset, 9); return boxName; } public override void setBoxName(int box, string value) { int offset = Box + 0x1EC38 + 9 * box; - if (value.Length > 8) - value = value.Substring(0, 8); // Hard cap - - byte[] data = value == $"BOX {box + 1}" ? new byte[9] : PKX.setG3Str(value, Japanese); + byte[] data = value == $"BOX {box + 1}" ? new byte[9] : setString(value, 8); setData(data, offset); } public override PKM getPKM(byte[] data) @@ -206,5 +203,13 @@ public override void setStoredSlot(PKM pkm, int offset, bool? trade = null, bool BitConverter.GetBytes((ushort)pkm.SID).CopyTo(Data, offset + data.Length + 2); Edited = true; } + + public override string getString(int Offset, int Count) => PKX.getString3(Data, Offset, Count, Japanese); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setString3(value, maxLength, Japanese, PadToSize, PadWith); + } } } diff --git a/PKHeX/Saves/SAV3XD.cs b/PKHeX/Saves/SAV3XD.cs index 43b107205..8f158642c 100644 --- a/PKHeX/Saves/SAV3XD.cs +++ b/PKHeX/Saves/SAV3XD.cs @@ -234,7 +234,7 @@ private static byte[] setXDChecksums(byte[] input, int subOffset0) } // Trainer Info public override GameVersion Version { get { return GameVersion.XD; } protected set { } } - public override string OT { get { return PKX.getColoStr(Data, Trainer1 + 0x00, 10); } set { PKX.setColoStr(value, 10).CopyTo(Data, Trainer1 + 0x00); } } + public override string OT { get { return getString(Trainer1 + 0x00, 20); } set { setString(value, 10).CopyTo(Data, Trainer1 + 0x00); } } public override ushort SID { get { return BigEndian.ToUInt16(Data, Trainer1 + 0x2C); } set { BigEndian.GetBytes(value).CopyTo(Data, Trainer1 + 0x2C); } } public override ushort TID { get { return BigEndian.ToUInt16(Data, Trainer1 + 0x2E); } set { BigEndian.GetBytes(value).CopyTo(Data, Trainer1 + 0x2E); } } @@ -253,13 +253,13 @@ public override int getBoxOffset(int box) } public override string getBoxName(int box) { - return PKX.getColoStr(Data, Box + (30 * SIZE_STORED + 0x14)*box, 8); + return getString(Box + (30 * SIZE_STORED + 0x14)*box, 16); } public override void setBoxName(int box, string value) { if (value.Length > 8) value = value.Substring(0, 8); // Hard cap - PKX.setColoStr(value, 8).CopyTo(Data, Box + 0x24A4*box); + setString(value, 8).CopyTo(Data, Box + 0x24A4*box); } public override PKM getPKM(byte[] data) { @@ -358,5 +358,13 @@ public override InventoryPouch[] Inventory public override bool? getDaycareOccupied(int loc, int slot) { return null; } public override void setDaycareEXP(int loc, int slot, uint EXP) { } public override void setDaycareOccupied(int loc, int slot, bool occupied) { } - } + + public override string getString(int Offset, int Count) => PKX.getBEString3(Data, Offset, Count); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setBEString3(value, maxLength, PadToSize, PadWith); + } +} } diff --git a/PKHeX/Saves/SAV4.cs b/PKHeX/Saves/SAV4.cs index 5cfed4b3a..e41325373 100644 --- a/PKHeX/Saves/SAV4.cs +++ b/PKHeX/Saves/SAV4.cs @@ -318,25 +318,8 @@ public override int getPartyOffset(int slot) // Trainer Info public override string OT { - get - { - return PKX.array2strG4(getData(Trainer1, 16)) - .Replace("\uFF0D", "\u30FC") // Japanese chōonpu - .Replace("\uE08F", "\u2640") // Nidoran ♂ - .Replace("\uE08E", "\u2642") // Nidoran ♀ - .Replace("\u2019", "\u0027"); // Farfetch'd - } - set - { - if (value.Length > 7) - value = value.Substring(0, 7); // Hard cap - string TempNick = value // Replace Special Characters and add Terminator - .Replace("\u30FC", "\uFF0D") // Japanese chōonpu - .Replace("\u2640", "\uE08F") // Nidoran ♂ - .Replace("\u2642", "\uE08E") // Nidoran ♀ - .Replace("\u0027", "\u2019"); // Farfetch'd - setData(PKX.str2arrayG4(TempNick), Trainer1); - } + get { return getString(Trainer1, 16); } + set { setString(value, OTLength).CopyTo(Data, Trainer1); } } public override ushort TID { @@ -536,7 +519,7 @@ public override string getBoxName(int box) { int offset = getBoxOffset(BoxCount); if (Version == GameVersion.HGSS) offset += 0x8; - return PKX.array2strG4(getData(offset + box*0x28, 0x28)); + return PKX.array2strG4(Data, offset + box*0x28, 0x28); } public override void setBoxName(int box, string value) { @@ -1117,7 +1100,7 @@ public int PoketchApps get { int ret = 0; - int ofs = 0; + int ofs; switch (Version) { case GameVersion.DP: ofs = 0x114F; break; @@ -1133,7 +1116,7 @@ public int PoketchApps set { int c = 0; - int ofs = 0; + int ofs; switch (Version) { case GameVersion.DP: ofs = 0x114F; break; @@ -1154,5 +1137,13 @@ public int PoketchApps Data[ofs - 1] = 0; // current used, force set for first App. } } - } + + public override string getString(int Offset, int Count) => PKX.getString4(Data, Offset, Count); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setString4(value, maxLength, PadToSize, PadWith); + } +} } diff --git a/PKHeX/Saves/SAV4BR.cs b/PKHeX/Saves/SAV4BR.cs index 15a050580..fe3296c64 100644 --- a/PKHeX/Saves/SAV4BR.cs +++ b/PKHeX/Saves/SAV4BR.cs @@ -246,5 +246,13 @@ public static void SetChecksum(byte[] input, int offset, int len, int checksum_o BigEndian.GetBytes(checksums[i]).CopyTo(input, checksum_offset + i * 4); } } + + public override string getString(int Offset, int Count) => PKX.getBEString4(Data, Offset, Count); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setBEString4(value, maxLength, PadToSize, PadWith); + } } } diff --git a/PKHeX/Saves/SAV5.cs b/PKHeX/Saves/SAV5.cs index 889e995ec..7cee59b37 100644 --- a/PKHeX/Saves/SAV5.cs +++ b/PKHeX/Saves/SAV5.cs @@ -526,13 +526,9 @@ public override MysteryGiftAlbum GiftAlbum // Trainer Info public override string OT { - get { return PKX.TrimFromFFFF(Encoding.Unicode.GetString(Data, Trainer1 + 0x4, 16)); } - set - { - if (value.Length > 7) - value = value.Substring(0, 7); // Hard cap - Encoding.Unicode.GetBytes((value + '\uFFFF').PadRight(8, '\0')).CopyTo(Data, Trainer1 + 0x4); } - } + get { return getString(Trainer1 + 0x4, 16); } + set { setString(value, OTLength).CopyTo(Data, Trainer1 + 0x4); } + } public override ushort TID { get { return BitConverter.ToUInt16(Data, Trainer1 + 0x14 + 0); } @@ -695,5 +691,13 @@ public override bool getSeen(int species) return true; return false; } + + public override string getString(int Offset, int Count) => PKX.getString5(Data, Offset, Count); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setString5(value, maxLength, PadToSize, PadWith); + } } } diff --git a/PKHeX/Saves/SAV6.cs b/PKHeX/Saves/SAV6.cs index 5c89033be..a0ee8d800 100644 --- a/PKHeX/Saves/SAV6.cs +++ b/PKHeX/Saves/SAV6.cs @@ -395,8 +395,8 @@ public override int Language } public override string OT { - get { return Util.TrimFromZero(Encoding.Unicode.GetString(Data, TrainerCard + 0x48, 0x1A)); } - set { Encoding.Unicode.GetBytes(value.PadRight(13, '\0')).CopyTo(Data, TrainerCard + 0x48); } + get { return getString(TrainerCard + 0x48, 0x1A); } + set { setString(value, OTLength).CopyTo(Data, TrainerCard + 0x48); } } public string OT_Nick { @@ -1018,5 +1018,13 @@ public override string MiscSaveInfo() return Blocks.Aggregate("", (current, b) => current + $"{b.ID:00}: {b.Offset:X5}-{b.Offset + b.Length:X5}, {b.Length:X5}{Environment.NewLine}"); } + + public override string getString(int Offset, int Count) => PKX.getString6(Data, Offset, Count); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setString6(value, maxLength, PadToSize, PadWith); + } } } diff --git a/PKHeX/Saves/SAV7.cs b/PKHeX/Saves/SAV7.cs index 911a6d45b..394a0cb75 100644 --- a/PKHeX/Saves/SAV7.cs +++ b/PKHeX/Saves/SAV7.cs @@ -422,8 +422,8 @@ public override int Language } public override string OT { - get { return Util.TrimFromZero(Encoding.Unicode.GetString(Data, TrainerCard + 0x38, 0x1A)); } - set { Encoding.Unicode.GetBytes(value.PadRight(13, '\0')).CopyTo(Data, TrainerCard + 0x38); } + get { return getString(TrainerCard + 0x38, 0x1A); } + set { setString(value, OTLength).CopyTo(Data, TrainerCard + 0x38); } } public int DressUpSkinColor { @@ -1313,5 +1313,13 @@ public bool MegaUnlocked } public override bool RequiresMemeCrypto => true; + + public override string getString(int Offset, int Count) => PKX.getString7(Data, Offset, Count); + public override byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return PKX.setString7(value, maxLength, PadToSize, PadWith); + } } } diff --git a/PKHeX/Saves/SaveFile.cs b/PKHeX/Saves/SaveFile.cs index 679957580..1c7b8e0dd 100644 --- a/PKHeX/Saves/SaveFile.cs +++ b/PKHeX/Saves/SaveFile.cs @@ -626,6 +626,9 @@ public void setData(byte[] input, int Offset) Edited = true; } + public abstract string getString(int Offset, int Length); + public abstract byte[] setString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0); + public virtual bool RequiresMemeCrypto => false; } } diff --git a/Tests/PKHeX.Tests/PKM/DateTestPKM.cs b/Tests/PKHeX.Tests/PKM/DateTestPKM.cs index 8edaa9589..e4a5913de 100644 --- a/Tests/PKHeX.Tests/PKM/DateTestPKM.cs +++ b/Tests/PKHeX.Tests/PKM/DateTestPKM.cs @@ -4,9 +4,9 @@ namespace PKHeX.Tests.PKM { /// - /// A implementation designed to test and . + /// A implementation designed to test and . /// - class DateTestPKM : Core.PKM + internal class DateTestPKM : Core.PKM { public int MetYear { get; set; } public int MetMonth { get; set; } @@ -16,6 +16,20 @@ class DateTestPKM : Core.PKM public int EggMetDay { get; set; } public override PersonalInfo PersonalInfo => null; + public override string getString(int Offset, int Count) { throw new NotImplementedException(); } + public override byte[] setString(string value, int maxLength) { throw new NotImplementedException(); } + + public override byte[] Nickname_Trash + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + public override byte[] OT_Trash + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + public override int Met_Year { get