2014-12-12 05:44:05 +00:00
|
|
|
|
using System;
|
2017-04-09 21:06:50 +00:00
|
|
|
|
using System.Collections.Generic;
|
2014-12-12 05:44:05 +00:00
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Windows.Forms;
|
2017-04-09 21:06:50 +00:00
|
|
|
|
using PKHeX.Core;
|
2014-12-12 05:44:05 +00:00
|
|
|
|
|
2017-01-08 07:54:09 +00:00
|
|
|
|
namespace PKHeX.WinForms
|
2014-12-12 05:44:05 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public partial class TrashEditor : Form
|
2014-12-12 05:44:05 +00:00
|
|
|
|
{
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private readonly SaveFile SAV;
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public TrashEditor(TextBoxBase TB_NN, SaveFile sav) : this(TB_NN, Array.Empty<byte>(), sav) { }
|
|
|
|
|
|
2021-06-30 03:58:06 +00:00
|
|
|
|
public TrashEditor(TextBoxBase TB_NN, Span<byte> raw, SaveFile sav)
|
2014-12-12 05:44:05 +00:00
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
2017-06-18 01:37:19 +00:00
|
|
|
|
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
|
2018-04-03 03:36:13 +00:00
|
|
|
|
SAV = sav;
|
2017-04-09 21:06:50 +00:00
|
|
|
|
|
|
|
|
|
FinalString = TB_NN.Text;
|
2021-06-30 03:58:06 +00:00
|
|
|
|
Raw = FinalBytes = raw.ToArray();
|
2017-04-09 21:06:50 +00:00
|
|
|
|
|
|
|
|
|
editing = true;
|
2020-10-18 18:02:39 +00:00
|
|
|
|
if (raw.Length != 0)
|
2017-06-18 01:37:19 +00:00
|
|
|
|
AddTrashEditing(raw.Length);
|
2017-04-09 21:06:50 +00:00
|
|
|
|
|
2019-10-27 06:14:00 +00:00
|
|
|
|
var f = FontUtil.GetPKXFont();
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
AddCharEditing(f);
|
2017-04-09 21:06:50 +00:00
|
|
|
|
TB_Text.MaxLength = TB_NN.MaxLength;
|
|
|
|
|
TB_Text.Text = TB_NN.Text;
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
TB_Text.Font = f;
|
2017-04-09 21:06:50 +00:00
|
|
|
|
|
2017-04-10 04:53:53 +00:00
|
|
|
|
if (FLP_Characters.Controls.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
FLP_Characters.Visible = false;
|
|
|
|
|
FLP_Hex.Height *= 2;
|
|
|
|
|
}
|
|
|
|
|
else if (FLP_Hex.Controls.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
FLP_Characters.Location = FLP_Hex.Location;
|
|
|
|
|
FLP_Characters.Height *= 2;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-09 21:06:50 +00:00
|
|
|
|
editing = false;
|
|
|
|
|
CenterToParent();
|
|
|
|
|
}
|
2018-05-12 15:13:39 +00:00
|
|
|
|
|
2020-12-22 07:37:07 +00:00
|
|
|
|
private readonly List<NumericUpDown> Bytes = new();
|
2017-04-09 21:06:50 +00:00
|
|
|
|
public string FinalString;
|
2021-01-07 07:30:30 +00:00
|
|
|
|
public byte[] FinalBytes;
|
2017-04-09 21:06:50 +00:00
|
|
|
|
private readonly byte[] Raw;
|
|
|
|
|
private bool editing;
|
|
|
|
|
private void B_Cancel_Click(object sender, EventArgs e) => Close();
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-04-09 21:06:50 +00:00
|
|
|
|
private void B_Save_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
FinalString = TB_Text.Text;
|
2020-10-18 18:02:39 +00:00
|
|
|
|
if (FinalBytes.Length == 0)
|
2017-04-09 21:06:50 +00:00
|
|
|
|
FinalBytes = Raw;
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
private void AddCharEditing(Font f)
|
2017-04-09 21:06:50 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
ushort[] chars = GetChars(SAV.Generation);
|
2017-04-09 21:06:50 +00:00
|
|
|
|
if (chars.Length == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
FLP_Characters.Visible = true;
|
|
|
|
|
foreach (ushort c in chars)
|
2014-12-12 05:44:05 +00:00
|
|
|
|
{
|
2018-09-29 19:22:13 +00:00
|
|
|
|
var l = GetLabel(((char)c).ToString());
|
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-17 01:47:31 +00:00
|
|
|
|
l.Font = f;
|
2017-04-09 21:06:50 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void AddTrashEditing(int count)
|
2017-04-09 21:06:50 +00:00
|
|
|
|
{
|
|
|
|
|
FLP_Hex.Visible = true;
|
|
|
|
|
GB_Trash.Visible = true;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
NUD_Generation.Value = SAV.Generation;
|
2017-05-11 05:52:14 +00:00
|
|
|
|
for (int i = 0; i < count; i++)
|
2014-12-12 05:44:05 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
var l = GetLabel($"${i:X2}");
|
2020-01-06 02:46:30 +00:00
|
|
|
|
l.Font = NUD_Generation.Font;
|
2018-08-03 03:11:42 +00:00
|
|
|
|
var n = GetNUD(min: 0, max: 255, hex: true);
|
2017-04-09 21:06:50 +00:00
|
|
|
|
n.Click += (s, e) =>
|
|
|
|
|
{
|
|
|
|
|
switch (ModifierKeys)
|
|
|
|
|
{
|
2017-04-10 04:53:53 +00:00
|
|
|
|
case Keys.Shift: n.Value = n.Maximum; break;
|
2017-04-09 21:06:50 +00:00
|
|
|
|
case Keys.Alt: n.Value = n.Minimum; break;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
n.Value = Raw[i];
|
2020-10-18 18:02:39 +00:00
|
|
|
|
n.ValueChanged += (o, args) => UpdateNUD(n, args);
|
2018-05-12 15:13:39 +00:00
|
|
|
|
|
2017-04-09 21:06:50 +00:00
|
|
|
|
FLP_Hex.Controls.Add(l);
|
|
|
|
|
FLP_Hex.Controls.Add(n);
|
|
|
|
|
Bytes.Add(n);
|
2014-12-12 05:44:05 +00:00
|
|
|
|
}
|
2020-10-18 18:02:39 +00:00
|
|
|
|
TB_Text.TextChanged += (o, args) => UpdateString(TB_Text, args);
|
2017-04-09 21:06:50 +00:00
|
|
|
|
|
2018-07-14 23:00:28 +00:00
|
|
|
|
CB_Species.InitializeBinding();
|
2017-04-09 21:06:50 +00:00
|
|
|
|
CB_Species.DataSource = new BindingSource(GameInfo.SpeciesDataSource, null);
|
|
|
|
|
|
2018-07-14 23:00:28 +00:00
|
|
|
|
CB_Language.InitializeBinding();
|
2018-07-14 23:53:14 +00:00
|
|
|
|
CB_Language.DataSource = GameInfo.LanguageDataSource(SAV.Generation);
|
2014-12-12 05:44:05 +00:00
|
|
|
|
}
|
2016-01-17 21:27:24 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void UpdateNUD(object sender, EventArgs e)
|
2014-12-12 05:44:05 +00:00
|
|
|
|
{
|
2017-04-09 21:06:50 +00:00
|
|
|
|
if (editing)
|
|
|
|
|
return;
|
|
|
|
|
editing = true;
|
|
|
|
|
// build bytes
|
2020-12-23 05:24:41 +00:00
|
|
|
|
if (sender is not NumericUpDown nud)
|
2020-10-18 18:02:39 +00:00
|
|
|
|
throw new Exception();
|
2017-04-09 21:06:50 +00:00
|
|
|
|
int index = Bytes.IndexOf(nud);
|
|
|
|
|
Raw[index] = (byte)nud.Value;
|
|
|
|
|
|
2019-11-26 18:45:36 +00:00
|
|
|
|
TB_Text.Text = GetString();
|
2017-04-09 21:06:50 +00:00
|
|
|
|
editing = false;
|
2014-12-12 05:44:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void UpdateString(object sender, EventArgs e)
|
2017-04-09 21:06:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (editing)
|
|
|
|
|
return;
|
|
|
|
|
editing = true;
|
|
|
|
|
// build bytes
|
2017-09-23 04:34:15 +00:00
|
|
|
|
byte[] data = SetString(TB_Text.Text);
|
2017-04-24 04:44:12 +00:00
|
|
|
|
Array.Copy(data, Raw, Math.Min(data.Length, Raw.Length));
|
|
|
|
|
for (int i = 0; i < Raw.Length; i++)
|
2017-04-09 21:06:50 +00:00
|
|
|
|
Bytes[i].Value = Raw[i];
|
|
|
|
|
editing = false;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-04-09 21:06:50 +00:00
|
|
|
|
private void B_ApplyTrash_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2019-09-19 02:58:23 +00:00
|
|
|
|
string species = SpeciesName.GetSpeciesNameGeneration(WinFormsUtil.GetIndex(CB_Species),
|
2017-06-18 01:37:19 +00:00
|
|
|
|
WinFormsUtil.GetIndex(CB_Language), (int) NUD_Generation.Value);
|
2017-04-09 21:06:50 +00:00
|
|
|
|
|
2018-09-03 21:23:27 +00:00
|
|
|
|
if (string.IsNullOrEmpty(species)) // no result
|
2017-04-09 21:06:50 +00:00
|
|
|
|
species = CB_Species.Text;
|
|
|
|
|
|
2017-09-23 04:34:15 +00:00
|
|
|
|
byte[] current = SetString(TB_Text.Text);
|
|
|
|
|
byte[] data = SetString(species);
|
2017-04-09 21:06:50 +00:00
|
|
|
|
if (data.Length <= current.Length)
|
|
|
|
|
{
|
2017-04-10 03:07:24 +00:00
|
|
|
|
WinFormsUtil.Alert("Trash byte layer is hidden by current text.",
|
|
|
|
|
$"Current Bytes: {current.Length}" + Environment.NewLine + $"Layer Bytes: {data.Length}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (data.Length > Bytes.Count)
|
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Alert("Trash byte layer is too long to apply.");
|
2017-04-09 21:06:50 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-03-08 00:58:19 +00:00
|
|
|
|
for (int i = current.Length; i < data.Length; i++)
|
2017-04-09 21:06:50 +00:00
|
|
|
|
Bytes[i].Value = data[i];
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-04-09 21:06:50 +00:00
|
|
|
|
private void B_ClearTrash_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2017-09-23 04:34:15 +00:00
|
|
|
|
byte[] current = SetString(TB_Text.Text);
|
2017-04-09 21:06:50 +00:00
|
|
|
|
for (int i = current.Length; i < Bytes.Count; i++)
|
|
|
|
|
Bytes[i].Value = 0;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2022-01-03 05:35:59 +00:00
|
|
|
|
private byte[] SetString(string text)
|
|
|
|
|
{
|
|
|
|
|
Span<byte> temp = stackalloc byte[Raw.Length];
|
|
|
|
|
var written = SAV.SetString(temp, text.AsSpan(), text.Length, StringConverterOption.None);
|
|
|
|
|
return temp[..written].ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetString() => SAV.GetString(Raw.AsSpan());
|
2017-04-09 21:06:50 +00:00
|
|
|
|
|
|
|
|
|
// Helpers
|
2020-12-22 07:37:07 +00:00
|
|
|
|
private static Label GetLabel(string str) => new() {Text = str, AutoSize = true};
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2020-12-22 07:37:07 +00:00
|
|
|
|
private static NumericUpDown GetNUD(int min, int max, bool hex) => new()
|
2017-04-09 21:06:50 +00:00
|
|
|
|
{
|
|
|
|
|
Maximum = max,
|
|
|
|
|
Minimum = min,
|
|
|
|
|
Hexadecimal = hex,
|
|
|
|
|
Width = 36,
|
|
|
|
|
Padding = new Padding(0),
|
|
|
|
|
Margin = new Padding(0),
|
|
|
|
|
};
|
|
|
|
|
|
2021-01-02 01:08:49 +00:00
|
|
|
|
private static ushort[] GetChars(int generation) => generation switch
|
2017-04-09 21:06:50 +00:00
|
|
|
|
{
|
2021-01-02 01:08:49 +00:00
|
|
|
|
6 => chars67,
|
|
|
|
|
7 => chars67,
|
|
|
|
|
_ => Array.Empty<ushort>(), // Undocumented
|
|
|
|
|
};
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-04-09 21:06:50 +00:00
|
|
|
|
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,
|
|
|
|
|
};
|
2014-12-12 05:44:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|