diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs index 9ffa65403..1565e729e 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs @@ -106,26 +106,26 @@ public SaveBlockAccessor9SV(SAV9SV sav) private const uint KFashionUnlockedPhoneCase = 0xED0AC675; // 8000-8999 // Profile Picture - private const uint KPictureProfileCurrentWidth = 0xFEAA87DA; - private const uint KPictureProfileCurrentHeight = 0x5361CEB5; - private const uint KPictureProfileCurrentSize = 0x1E505002; - private const uint KPictureProfileCurrent = 0x14C5A101; + public const uint KPictureProfileCurrentWidth = 0xFEAA87DA; + public const uint KPictureProfileCurrentHeight = 0x5361CEB5; + public const uint KPictureProfileCurrentSize = 0x1E505002; + public const uint KPictureProfileCurrent = 0x14C5A101; - private const uint KPictureProfileInitialWidth = 0xC0408301; - private const uint KPictureProfileInitialHeight = 0xCAABBA50; - private const uint KPictureProfileInitialSize = 0x902B64DB; - private const uint KPictureProfileInitial = 0xF8B14C88; + public const uint KPictureProfileInitialWidth = 0xC0408301; + public const uint KPictureProfileInitialHeight = 0xCAABBA50; + public const uint KPictureProfileInitialSize = 0x902B64DB; + public const uint KPictureProfileInitial = 0xF8B14C88; // Trainer Icon - private const uint KPictureIconCurrentWidth = 0x8FAB2C4D; - private const uint KPictureIconCurrentHeight = 0x0B384C24; - private const uint KPictureIconCurrentSize = 0xEA677637; - private const uint KPictureIconCurrent = 0xD41F4FC4; + public const uint KPictureIconCurrentWidth = 0x8FAB2C4D; + public const uint KPictureIconCurrentHeight = 0x0B384C24; + public const uint KPictureIconCurrentSize = 0xEA677637; + public const uint KPictureIconCurrent = 0xD41F4FC4; - private const uint KPictureIconInitialWidth = 0x6850A672; - private const uint KPictureIconInitialHeight = 0x74077ECD; - private const uint KPictureIconInitialSize = 0x83FC126A; - private const uint KPictureIconInitial = 0xBCB6F239; + public const uint KPictureIconInitialWidth = 0x6850A672; + public const uint KPictureIconInitialHeight = 0x74077ECD; + public const uint KPictureIconInitialSize = 0x83FC126A; + public const uint KPictureIconInitial = 0xBCB6F239; #region YMAP - Display & Fly Flags -- internal name Fnv1aHash32 public const uint FSYS_YMAP_FLY_01 = 0xEB597C90; diff --git a/PKHeX.Core/Saves/Substructures/Gen9/DXT1.cs b/PKHeX.Core/Saves/Substructures/Gen9/DXT1.cs new file mode 100644 index 000000000..1057377f6 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen9/DXT1.cs @@ -0,0 +1,96 @@ +using System; +using static System.Buffers.Binary.BinaryPrimitives; + +namespace PKHeX.Core; + +public static class DXT1 +{ + private const int bpp = 4; + public static int GetDecompressedSize(int width, int height) => bpp * width * height; + + public static byte[] Decompress(ReadOnlySpan data, int width, int height) + { + var result = new byte[GetDecompressedSize(width, height)]; + Decompress(data, width, height, result); + return result; + } + + public static void Decompress(ReadOnlySpan data, int width, int height, Span result) + { + int blockCountX = width / bpp; + int blockCountY = height / bpp; + Span colors = stackalloc Color[4]; + for (int y = 0; y < blockCountY; y++) + { + for (int x = 0; x < blockCountX; x++) + { + int blockOffset = ((y * blockCountX) + x) * 8; + var span = data.Slice(blockOffset, 8); + + var color0 = ReadUInt16LittleEndian(span); + var color1 = ReadUInt16LittleEndian(span[2..]); + var indices = ReadUInt32LittleEndian(span[4..]); + GetColors(colors, color0, color1); + + for (int pixelY = 0; pixelY < 4; pixelY++) + { + var baseIndex = (((4 * y) + pixelY) * width) + (x * 4); + var baseShift = (4 * pixelY); + for (int pixelX = 0; pixelX < 4; pixelX++) + { + int pixelIndex = baseIndex + pixelX; + var shift = (baseShift + pixelX) << 1; + var index = (indices >> shift) & 0x3; + var color = colors[(int)index]; + + var dest = result[(pixelIndex * 4)..]; + dest[0] = color.B; + dest[1] = color.G; + dest[2] = color.R; + dest[3] = color.A; + } + } + } + } + } + + private static void GetColors(Span colors, ushort color0, ushort color1) + { + colors[0] = RGB565ToColor(color0); + colors[1] = RGB565ToColor(color1); + + if (color0 > color1) + { + colors[2] = Lerp(colors[0], colors[1], 1f / 3f); + colors[3] = Lerp(colors[0], colors[1], 2f / 3f); + } + else + { + colors[2] = Lerp(colors[0], colors[1], 0.5f); + colors[3] = default; // 0 + } + } + + private static Color RGB565ToColor(ushort rgb565) + { + byte r = (byte)((rgb565 >> 11) & 0x1F); + byte g = (byte)((rgb565 >> 5) & 0x3F); + byte b = (byte)(rgb565 & 0x1F); + + r = (byte)(r << 3 | r >> 2); + g = (byte)(g << 2 | g >> 4); + b = (byte)(b << 3 | b >> 2); + return new(0xFF, r, g, b); + } + private static Color Lerp(Color c1, Color c2, float t) + { + int r = (int)(c1.R + ((c2.R - c1.R) * t)); + int g = (int)(c1.G + ((c2.G - c1.G) * t)); + int b = (int)(c1.B + ((c2.B - c1.B) * t)); + int aVal = (int)(c1.A + ((c2.A - c1.A) * t)); + + return new((byte)aVal, (byte)r, (byte)g, (byte)b); + } + + private readonly record struct Color(byte A, byte R, byte G, byte B); +} diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.Designer.cs index d953a2126..bbba85994 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.Designer.cs @@ -91,12 +91,12 @@ private void InitializeComponent() L_SinglesC = new System.Windows.Forms.Label(); TC_Editor = new System.Windows.Forms.TabControl(); Tab_Overview = new System.Windows.Forms.TabPage(); + trainerID1 = new Controls.TrainerID(); L_Started = new System.Windows.Forms.Label(); CAL_AdventureStartDate = new System.Windows.Forms.DateTimePicker(); MT_LP = new System.Windows.Forms.MaskedTextBox(); B_MaxLP = new System.Windows.Forms.Button(); L_LP = new System.Windows.Forms.Label(); - trainerID1 = new Controls.TrainerID(); Tab_MiscValues = new System.Windows.Forms.TabPage(); B_UnlockBikeUpgrades = new System.Windows.Forms.Button(); B_UnlockTMRecipes = new System.Windows.Forms.Button(); @@ -109,6 +109,10 @@ private void InitializeComponent() L_Y = new System.Windows.Forms.Label(); L_Z = new System.Windows.Forms.Label(); L_X = new System.Windows.Forms.Label(); + Tab_Images = new System.Windows.Forms.TabPage(); + P_InitialIcon = new System.Windows.Forms.PictureBox(); + P_CurrIcon = new System.Windows.Forms.PictureBox(); + P_CurrPhoto = new System.Windows.Forms.PictureBox(); TC_Editor.SuspendLayout(); Tab_Overview.SuspendLayout(); Tab_MiscValues.SuspendLayout(); @@ -116,15 +120,19 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)NUD_Z).BeginInit(); ((System.ComponentModel.ISupportInitialize)NUD_Y).BeginInit(); ((System.ComponentModel.ISupportInitialize)NUD_X).BeginInit(); + Tab_Images.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)P_InitialIcon).BeginInit(); + ((System.ComponentModel.ISupportInitialize)P_CurrIcon).BeginInit(); + ((System.ComponentModel.ISupportInitialize)P_CurrPhoto).BeginInit(); SuspendLayout(); // // B_Cancel // B_Cancel.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; - B_Cancel.Location = new System.Drawing.Point(277, 300); - B_Cancel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Cancel.Location = new System.Drawing.Point(345, 440); + B_Cancel.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); B_Cancel.Name = "B_Cancel"; - B_Cancel.Size = new System.Drawing.Size(88, 27); + B_Cancel.Size = new System.Drawing.Size(101, 36); B_Cancel.TabIndex = 0; B_Cancel.Text = "Cancel"; B_Cancel.UseVisualStyleBackColor = true; @@ -133,10 +141,10 @@ private void InitializeComponent() // B_Save // B_Save.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; - B_Save.Location = new System.Drawing.Point(372, 300); - B_Save.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Save.Location = new System.Drawing.Point(453, 440); + B_Save.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); B_Save.Name = "B_Save"; - B_Save.Size = new System.Drawing.Size(88, 27); + B_Save.Size = new System.Drawing.Size(101, 36); B_Save.TabIndex = 1; B_Save.Text = "Save"; B_Save.UseVisualStyleBackColor = true; @@ -145,11 +153,11 @@ private void InitializeComponent() // TB_OTName // TB_OTName.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - TB_OTName.Location = new System.Drawing.Point(132, 10); - TB_OTName.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + TB_OTName.Location = new System.Drawing.Point(197, 13); + TB_OTName.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); TB_OTName.MaxLength = 12; TB_OTName.Name = "TB_OTName"; - TB_OTName.Size = new System.Drawing.Size(120, 20); + TB_OTName.Size = new System.Drawing.Size(137, 20); TB_OTName.TabIndex = 2; TB_OTName.Text = "WWWWWWWWWWWW"; TB_OTName.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; @@ -157,31 +165,31 @@ private void InitializeComponent() // // L_TrainerName // - L_TrainerName.Location = new System.Drawing.Point(28, 9); - L_TrainerName.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_TrainerName.Location = new System.Drawing.Point(78, 12); + L_TrainerName.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); L_TrainerName.Name = "L_TrainerName"; - L_TrainerName.Size = new System.Drawing.Size(104, 24); + L_TrainerName.Size = new System.Drawing.Size(119, 32); L_TrainerName.TabIndex = 3; L_TrainerName.Text = "Trainer Name:"; L_TrainerName.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // MT_Money // - MT_Money.Location = new System.Drawing.Point(132, 62); - MT_Money.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MT_Money.Location = new System.Drawing.Point(197, 103); + MT_Money.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); MT_Money.Mask = "0000000"; MT_Money.Name = "MT_Money"; - MT_Money.Size = new System.Drawing.Size(67, 23); + MT_Money.Size = new System.Drawing.Size(76, 23); MT_Money.TabIndex = 4; MT_Money.Text = "1234567"; MT_Money.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // L_Money // - L_Money.Location = new System.Drawing.Point(94, 66); - L_Money.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_Money.Location = new System.Drawing.Point(153, 101); + L_Money.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); L_Money.Name = "L_Money"; - L_Money.Size = new System.Drawing.Size(37, 23); + L_Money.Size = new System.Drawing.Size(42, 31); L_Money.TabIndex = 5; L_Money.Text = "$:"; L_Money.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -258,82 +266,82 @@ private void InitializeComponent() // // L_Seconds // - L_Seconds.Location = new System.Drawing.Point(247, 168); + L_Seconds.Location = new System.Drawing.Point(328, 244); L_Seconds.Margin = new System.Windows.Forms.Padding(0); L_Seconds.Name = "L_Seconds"; - L_Seconds.Size = new System.Drawing.Size(41, 24); + L_Seconds.Size = new System.Drawing.Size(47, 32); L_Seconds.TabIndex = 30; L_Seconds.Text = "Sec:"; L_Seconds.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_Minutes // - L_Minutes.Location = new System.Drawing.Point(160, 168); + L_Minutes.Location = new System.Drawing.Point(227, 244); L_Minutes.Margin = new System.Windows.Forms.Padding(0); L_Minutes.Name = "L_Minutes"; - L_Minutes.Size = new System.Drawing.Size(67, 24); + L_Minutes.Size = new System.Drawing.Size(77, 32); L_Minutes.TabIndex = 29; L_Minutes.Text = "Min:"; L_Minutes.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // MT_Seconds // - MT_Seconds.Location = new System.Drawing.Point(288, 168); - MT_Seconds.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MT_Seconds.Location = new System.Drawing.Point(380, 247); + MT_Seconds.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); MT_Seconds.Mask = "00"; MT_Seconds.Name = "MT_Seconds"; - MT_Seconds.Size = new System.Drawing.Size(25, 23); + MT_Seconds.Size = new System.Drawing.Size(28, 23); MT_Seconds.TabIndex = 28; MT_Seconds.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; MT_Seconds.TextChanged += Change255; // // MT_Minutes // - MT_Minutes.Location = new System.Drawing.Point(227, 168); - MT_Minutes.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MT_Minutes.Location = new System.Drawing.Point(306, 247); + MT_Minutes.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); MT_Minutes.Mask = "00"; MT_Minutes.Name = "MT_Minutes"; - MT_Minutes.Size = new System.Drawing.Size(25, 23); + MT_Minutes.Size = new System.Drawing.Size(28, 23); MT_Minutes.TabIndex = 27; MT_Minutes.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; MT_Minutes.TextChanged += Change255; // // L_Hours // - L_Hours.Location = new System.Drawing.Point(62, 168); + L_Hours.Location = new System.Drawing.Point(117, 244); L_Hours.Margin = new System.Windows.Forms.Padding(0); L_Hours.Name = "L_Hours"; - L_Hours.Size = new System.Drawing.Size(70, 24); + L_Hours.Size = new System.Drawing.Size(80, 32); L_Hours.TabIndex = 26; L_Hours.Text = "Hrs:"; L_Hours.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // MT_Hours // - MT_Hours.Location = new System.Drawing.Point(132, 168); - MT_Hours.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MT_Hours.Location = new System.Drawing.Point(197, 245); + MT_Hours.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); MT_Hours.Mask = "00000"; MT_Hours.Name = "MT_Hours"; - MT_Hours.Size = new System.Drawing.Size(56, 23); + MT_Hours.Size = new System.Drawing.Size(63, 23); MT_Hours.TabIndex = 25; MT_Hours.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // L_Language // - L_Language.Location = new System.Drawing.Point(28, 141); - L_Language.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_Language.Location = new System.Drawing.Point(78, 206); + L_Language.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); L_Language.Name = "L_Language"; - L_Language.Size = new System.Drawing.Size(104, 24); + L_Language.Size = new System.Drawing.Size(119, 32); L_Language.TabIndex = 21; L_Language.Text = "Language:"; L_Language.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // B_MaxCash // - B_MaxCash.Location = new System.Drawing.Point(203, 62); + B_MaxCash.Location = new System.Drawing.Point(278, 101); B_MaxCash.Margin = new System.Windows.Forms.Padding(0); B_MaxCash.Name = "B_MaxCash"; - B_MaxCash.Size = new System.Drawing.Size(23, 23); + B_MaxCash.Size = new System.Drawing.Size(26, 31); B_MaxCash.TabIndex = 16; B_MaxCash.Text = "+"; B_MaxCash.UseVisualStyleBackColor = true; @@ -342,10 +350,10 @@ private void InitializeComponent() // CB_Language.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; CB_Language.FormattingEnabled = true; - CB_Language.Location = new System.Drawing.Point(132, 141); - CB_Language.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_Language.Location = new System.Drawing.Point(197, 209); + CB_Language.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); CB_Language.Name = "CB_Language"; - CB_Language.Size = new System.Drawing.Size(120, 23); + CB_Language.Size = new System.Drawing.Size(137, 23); CB_Language.TabIndex = 15; // // CB_Game @@ -353,10 +361,10 @@ private void InitializeComponent() CB_Game.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; CB_Game.FormattingEnabled = true; CB_Game.Items.AddRange(new object[] { "Scarlet", "Violet" }); - CB_Game.Location = new System.Drawing.Point(132, 115); - CB_Game.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_Game.Location = new System.Drawing.Point(197, 173); + CB_Game.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); CB_Game.Name = "CB_Game"; - CB_Game.Size = new System.Drawing.Size(120, 23); + CB_Game.Size = new System.Drawing.Size(137, 23); CB_Game.TabIndex = 24; // // CB_Gender @@ -364,10 +372,10 @@ private void InitializeComponent() CB_Gender.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; CB_Gender.FormattingEnabled = true; CB_Gender.Items.AddRange(new object[] { "♂", "♀" }); - CB_Gender.Location = new System.Drawing.Point(255, 115); - CB_Gender.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_Gender.Location = new System.Drawing.Point(338, 173); + CB_Gender.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); CB_Gender.Name = "CB_Gender"; - CB_Gender.Size = new System.Drawing.Size(33, 23); + CB_Gender.Size = new System.Drawing.Size(45, 23); CB_Gender.TabIndex = 22; // // TB_MBMS @@ -610,18 +618,20 @@ private void InitializeComponent() // // TC_Editor // - TC_Editor.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; TC_Editor.Controls.Add(Tab_Overview); TC_Editor.Controls.Add(Tab_MiscValues); - TC_Editor.Location = new System.Drawing.Point(14, 14); - TC_Editor.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + TC_Editor.Controls.Add(Tab_Images); + TC_Editor.Dock = System.Windows.Forms.DockStyle.Fill; + TC_Editor.Location = new System.Drawing.Point(0, 0); + TC_Editor.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); TC_Editor.Name = "TC_Editor"; TC_Editor.SelectedIndex = 0; - TC_Editor.Size = new System.Drawing.Size(445, 279); + TC_Editor.Size = new System.Drawing.Size(496, 361); TC_Editor.TabIndex = 54; // // Tab_Overview // + Tab_Overview.Controls.Add(trainerID1); Tab_Overview.Controls.Add(L_Started); Tab_Overview.Controls.Add(CAL_AdventureStartDate); Tab_Overview.Controls.Add(MT_LP); @@ -629,7 +639,6 @@ private void InitializeComponent() Tab_Overview.Controls.Add(B_MaxLP); Tab_Overview.Controls.Add(L_LP); Tab_Overview.Controls.Add(L_Hours); - Tab_Overview.Controls.Add(trainerID1); Tab_Overview.Controls.Add(MT_Minutes); Tab_Overview.Controls.Add(L_Minutes); Tab_Overview.Controls.Add(TB_OTName); @@ -644,20 +653,28 @@ private void InitializeComponent() Tab_Overview.Controls.Add(MT_Seconds); Tab_Overview.Controls.Add(L_Seconds); Tab_Overview.Location = new System.Drawing.Point(4, 24); - Tab_Overview.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Tab_Overview.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); Tab_Overview.Name = "Tab_Overview"; - Tab_Overview.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); - Tab_Overview.Size = new System.Drawing.Size(437, 251); + Tab_Overview.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); + Tab_Overview.Size = new System.Drawing.Size(488, 333); Tab_Overview.TabIndex = 0; Tab_Overview.Text = "Overview"; Tab_Overview.UseVisualStyleBackColor = true; // + // trainerID1 + // + trainerID1.Location = new System.Drawing.Point(160, 57); + trainerID1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + trainerID1.Name = "trainerID1"; + trainerID1.Size = new System.Drawing.Size(248, 41); + trainerID1.TabIndex = 77; + // // L_Started // - L_Started.Location = new System.Drawing.Point(8, 195); - L_Started.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_Started.Location = new System.Drawing.Point(55, 282); + L_Started.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); L_Started.Name = "L_Started"; - L_Started.Size = new System.Drawing.Size(124, 23); + L_Started.Size = new System.Drawing.Size(142, 31); L_Started.TabIndex = 73; L_Started.Text = "Game Started:"; L_Started.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -665,53 +682,45 @@ private void InitializeComponent() // CAL_AdventureStartDate // CAL_AdventureStartDate.Format = System.Windows.Forms.DateTimePickerFormat.Short; - CAL_AdventureStartDate.Location = new System.Drawing.Point(132, 194); - CAL_AdventureStartDate.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CAL_AdventureStartDate.Location = new System.Drawing.Point(197, 282); + CAL_AdventureStartDate.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); CAL_AdventureStartDate.MaxDate = new System.DateTime(2099, 12, 31, 0, 0, 0, 0); CAL_AdventureStartDate.MinDate = new System.DateTime(2000, 1, 1, 0, 0, 0, 0); CAL_AdventureStartDate.Name = "CAL_AdventureStartDate"; - CAL_AdventureStartDate.Size = new System.Drawing.Size(120, 23); + CAL_AdventureStartDate.Size = new System.Drawing.Size(137, 23); CAL_AdventureStartDate.TabIndex = 72; CAL_AdventureStartDate.Value = new System.DateTime(2000, 1, 1, 0, 0, 0, 0); // // MT_LP // - MT_LP.Location = new System.Drawing.Point(132, 88); - MT_LP.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MT_LP.Location = new System.Drawing.Point(197, 138); + MT_LP.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); MT_LP.Mask = "0000000"; MT_LP.Name = "MT_LP"; - MT_LP.Size = new System.Drawing.Size(67, 23); + MT_LP.Size = new System.Drawing.Size(76, 23); MT_LP.TabIndex = 70; MT_LP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // B_MaxLP // - B_MaxLP.Location = new System.Drawing.Point(203, 88); + B_MaxLP.Location = new System.Drawing.Point(278, 136); B_MaxLP.Margin = new System.Windows.Forms.Padding(0); B_MaxLP.Name = "B_MaxLP"; - B_MaxLP.Size = new System.Drawing.Size(23, 23); + B_MaxLP.Size = new System.Drawing.Size(26, 31); B_MaxLP.TabIndex = 71; B_MaxLP.Text = "+"; B_MaxLP.UseVisualStyleBackColor = true; // // L_LP // - L_LP.Location = new System.Drawing.Point(94, 89); - L_LP.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_LP.Location = new System.Drawing.Point(153, 136); + L_LP.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); L_LP.Name = "L_LP"; - L_LP.Size = new System.Drawing.Size(37, 23); + L_LP.Size = new System.Drawing.Size(42, 31); L_LP.TabIndex = 68; L_LP.Text = "LP:"; L_LP.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // trainerID1 - // - trainerID1.Location = new System.Drawing.Point(92, 35); - trainerID1.Margin = new System.Windows.Forms.Padding(0); - trainerID1.Name = "trainerID1"; - trainerID1.Size = new System.Drawing.Size(246, 23); - trainerID1.TabIndex = 66; - // // Tab_MiscValues // Tab_MiscValues.Controls.Add(B_UnlockBikeUpgrades); @@ -720,20 +729,20 @@ private void InitializeComponent() Tab_MiscValues.Controls.Add(B_UnlockFlyLocations); Tab_MiscValues.Controls.Add(GB_Map); Tab_MiscValues.Location = new System.Drawing.Point(4, 24); - Tab_MiscValues.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Tab_MiscValues.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); Tab_MiscValues.Name = "Tab_MiscValues"; - Tab_MiscValues.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); - Tab_MiscValues.Size = new System.Drawing.Size(437, 251); + Tab_MiscValues.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); + Tab_MiscValues.Size = new System.Drawing.Size(501, 360); Tab_MiscValues.TabIndex = 4; Tab_MiscValues.Text = "Misc"; Tab_MiscValues.UseVisualStyleBackColor = true; // // B_UnlockBikeUpgrades // - B_UnlockBikeUpgrades.Location = new System.Drawing.Point(262, 186); + B_UnlockBikeUpgrades.Location = new System.Drawing.Point(299, 248); B_UnlockBikeUpgrades.Margin = new System.Windows.Forms.Padding(0); B_UnlockBikeUpgrades.Name = "B_UnlockBikeUpgrades"; - B_UnlockBikeUpgrades.Size = new System.Drawing.Size(160, 48); + B_UnlockBikeUpgrades.Size = new System.Drawing.Size(183, 64); B_UnlockBikeUpgrades.TabIndex = 63; B_UnlockBikeUpgrades.Text = "Unlock All Bike Upgrades"; B_UnlockBikeUpgrades.UseVisualStyleBackColor = true; @@ -741,10 +750,10 @@ private void InitializeComponent() // // B_UnlockTMRecipes // - B_UnlockTMRecipes.Location = new System.Drawing.Point(262, 130); + B_UnlockTMRecipes.Location = new System.Drawing.Point(299, 173); B_UnlockTMRecipes.Margin = new System.Windows.Forms.Padding(0); B_UnlockTMRecipes.Name = "B_UnlockTMRecipes"; - B_UnlockTMRecipes.Size = new System.Drawing.Size(160, 48); + B_UnlockTMRecipes.Size = new System.Drawing.Size(183, 64); B_UnlockTMRecipes.TabIndex = 62; B_UnlockTMRecipes.Text = "Unlock All TM Recipes"; B_UnlockTMRecipes.UseVisualStyleBackColor = true; @@ -752,10 +761,10 @@ private void InitializeComponent() // // B_CollectAllStakes // - B_CollectAllStakes.Location = new System.Drawing.Point(262, 74); + B_CollectAllStakes.Location = new System.Drawing.Point(299, 99); B_CollectAllStakes.Margin = new System.Windows.Forms.Padding(0); B_CollectAllStakes.Name = "B_CollectAllStakes"; - B_CollectAllStakes.Size = new System.Drawing.Size(160, 48); + B_CollectAllStakes.Size = new System.Drawing.Size(183, 64); B_CollectAllStakes.TabIndex = 61; B_CollectAllStakes.Text = "Collect All Stakes"; B_CollectAllStakes.UseVisualStyleBackColor = true; @@ -763,10 +772,10 @@ private void InitializeComponent() // // B_UnlockFlyLocations // - B_UnlockFlyLocations.Location = new System.Drawing.Point(262, 18); + B_UnlockFlyLocations.Location = new System.Drawing.Point(299, 24); B_UnlockFlyLocations.Margin = new System.Windows.Forms.Padding(0); B_UnlockFlyLocations.Name = "B_UnlockFlyLocations"; - B_UnlockFlyLocations.Size = new System.Drawing.Size(160, 48); + B_UnlockFlyLocations.Size = new System.Drawing.Size(183, 64); B_UnlockFlyLocations.TabIndex = 60; B_UnlockFlyLocations.Text = "Unlock All Fly Locations"; B_UnlockFlyLocations.UseVisualStyleBackColor = true; @@ -780,11 +789,11 @@ private void InitializeComponent() GB_Map.Controls.Add(L_Y); GB_Map.Controls.Add(L_Z); GB_Map.Controls.Add(L_X); - GB_Map.Location = new System.Drawing.Point(14, 11); - GB_Map.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Map.Location = new System.Drawing.Point(16, 15); + GB_Map.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); GB_Map.Name = "GB_Map"; - GB_Map.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); - GB_Map.Size = new System.Drawing.Size(232, 96); + GB_Map.Padding = new System.Windows.Forms.Padding(5, 4, 5, 4); + GB_Map.Size = new System.Drawing.Size(265, 128); GB_Map.TabIndex = 59; GB_Map.TabStop = false; GB_Map.Text = "Map Position"; @@ -793,12 +802,12 @@ private void InitializeComponent() // NUD_Z.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; NUD_Z.DecimalPlaces = 5; - NUD_Z.Location = new System.Drawing.Point(108, 40); + NUD_Z.Location = new System.Drawing.Point(123, 53); NUD_Z.Margin = new System.Windows.Forms.Padding(0); NUD_Z.Maximum = new decimal(new int[] { 99999999, 0, 0, 0 }); NUD_Z.Minimum = new decimal(new int[] { 99999999, 0, 0, int.MinValue }); NUD_Z.Name = "NUD_Z"; - NUD_Z.Size = new System.Drawing.Size(112, 23); + NUD_Z.Size = new System.Drawing.Size(128, 23); NUD_Z.TabIndex = 53; NUD_Z.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; NUD_Z.ValueChanged += ChangeMapValue; @@ -807,12 +816,12 @@ private void InitializeComponent() // NUD_Y.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; NUD_Y.DecimalPlaces = 5; - NUD_Y.Location = new System.Drawing.Point(108, 64); + NUD_Y.Location = new System.Drawing.Point(123, 85); NUD_Y.Margin = new System.Windows.Forms.Padding(0); NUD_Y.Maximum = new decimal(new int[] { 99999999, 0, 0, 0 }); NUD_Y.Minimum = new decimal(new int[] { 99999999, 0, 0, int.MinValue }); NUD_Y.Name = "NUD_Y"; - NUD_Y.Size = new System.Drawing.Size(112, 23); + NUD_Y.Size = new System.Drawing.Size(128, 23); NUD_Y.TabIndex = 51; NUD_Y.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; NUD_Y.ValueChanged += ChangeMapValue; @@ -821,56 +830,104 @@ private void InitializeComponent() // NUD_X.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; NUD_X.DecimalPlaces = 5; - NUD_X.Location = new System.Drawing.Point(108, 16); + NUD_X.Location = new System.Drawing.Point(123, 21); NUD_X.Margin = new System.Windows.Forms.Padding(0); NUD_X.Maximum = new decimal(new int[] { 99999999, 0, 0, 0 }); NUD_X.Minimum = new decimal(new int[] { 99999999, 0, 0, int.MinValue }); NUD_X.Name = "NUD_X"; - NUD_X.Size = new System.Drawing.Size(112, 23); + NUD_X.Size = new System.Drawing.Size(128, 23); NUD_X.TabIndex = 50; NUD_X.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; NUD_X.ValueChanged += ChangeMapValue; // // L_Y // - L_Y.Location = new System.Drawing.Point(8, 64); + L_Y.Location = new System.Drawing.Point(9, 85); L_Y.Margin = new System.Windows.Forms.Padding(0); L_Y.Name = "L_Y"; - L_Y.Size = new System.Drawing.Size(96, 23); + L_Y.Size = new System.Drawing.Size(110, 31); L_Y.TabIndex = 49; L_Y.Text = "Y Coordinate:"; L_Y.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_Z // - L_Z.Location = new System.Drawing.Point(8, 40); + L_Z.Location = new System.Drawing.Point(9, 53); L_Z.Margin = new System.Windows.Forms.Padding(0); L_Z.Name = "L_Z"; - L_Z.Size = new System.Drawing.Size(96, 23); + L_Z.Size = new System.Drawing.Size(110, 31); L_Z.TabIndex = 48; L_Z.Text = "Z Coordinate:"; L_Z.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_X // - L_X.Location = new System.Drawing.Point(8, 16); + L_X.Location = new System.Drawing.Point(9, 21); L_X.Margin = new System.Windows.Forms.Padding(0); L_X.Name = "L_X"; - L_X.Size = new System.Drawing.Size(96, 23); + L_X.Size = new System.Drawing.Size(110, 31); L_X.TabIndex = 47; L_X.Text = "X Coordinate:"; L_X.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // + // Tab_Images + // + Tab_Images.Controls.Add(P_InitialIcon); + Tab_Images.Controls.Add(P_CurrIcon); + Tab_Images.Controls.Add(P_CurrPhoto); + Tab_Images.Location = new System.Drawing.Point(4, 24); + Tab_Images.Name = "Tab_Images"; + Tab_Images.Size = new System.Drawing.Size(501, 360); + Tab_Images.TabIndex = 5; + Tab_Images.Text = "Images"; + Tab_Images.UseVisualStyleBackColor = true; + // + // P_InitialIcon + // + P_InitialIcon.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + P_InitialIcon.Cursor = System.Windows.Forms.Cursors.Hand; + P_InitialIcon.Location = new System.Drawing.Point(410, 169); + P_InitialIcon.Name = "P_InitialIcon"; + P_InitialIcon.Size = new System.Drawing.Size(88, 88); + P_InitialIcon.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + P_InitialIcon.TabIndex = 79; + P_InitialIcon.TabStop = false; + P_InitialIcon.Click += P_InitialIcon_Click; + // + // P_CurrIcon + // + P_CurrIcon.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + P_CurrIcon.Cursor = System.Windows.Forms.Cursors.Hand; + P_CurrIcon.Location = new System.Drawing.Point(410, 37); + P_CurrIcon.Name = "P_CurrIcon"; + P_CurrIcon.Size = new System.Drawing.Size(88, 88); + P_CurrIcon.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + P_CurrIcon.TabIndex = 78; + P_CurrIcon.TabStop = false; + P_CurrIcon.Click += P_CurrIcon_Click; + // + // P_CurrPhoto + // + P_CurrPhoto.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + P_CurrPhoto.Cursor = System.Windows.Forms.Cursors.Hand; + P_CurrPhoto.Location = new System.Drawing.Point(3, 37); + P_CurrPhoto.Name = "P_CurrPhoto"; + P_CurrPhoto.Size = new System.Drawing.Size(320, 220); + P_CurrPhoto.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + P_CurrPhoto.TabIndex = 77; + P_CurrPhoto.TabStop = false; + P_CurrPhoto.Click += P_CurrPhoto_Click; + // // SAV_Trainer9 // AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; - ClientSize = new System.Drawing.Size(468, 337); + ClientSize = new System.Drawing.Size(496, 361); Controls.Add(TC_Editor); Controls.Add(B_Save); Controls.Add(B_Cancel); FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; Icon = Properties.Resources.Icon; - Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); MaximizeBox = false; MinimizeBox = false; Name = "SAV_Trainer9"; @@ -884,6 +941,10 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)NUD_Z).EndInit(); ((System.ComponentModel.ISupportInitialize)NUD_Y).EndInit(); ((System.ComponentModel.ISupportInitialize)NUD_X).EndInit(); + Tab_Images.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)P_InitialIcon).EndInit(); + ((System.ComponentModel.ISupportInitialize)P_CurrIcon).EndInit(); + ((System.ComponentModel.ISupportInitialize)P_CurrPhoto).EndInit(); ResumeLayout(false); } @@ -952,7 +1013,6 @@ private void InitializeComponent() private System.Windows.Forms.MaskedTextBox MT_Hours; private System.Windows.Forms.TabControl TC_Editor; private System.Windows.Forms.TabPage Tab_Overview; - private Controls.TrainerID trainerID1; private System.Windows.Forms.Label L_LP; private System.Windows.Forms.TabPage Tab_MiscValues; private System.Windows.Forms.GroupBox GB_Map; @@ -970,5 +1030,10 @@ private void InitializeComponent() private System.Windows.Forms.Button B_UnlockBikeUpgrades; private System.Windows.Forms.Label L_Started; private System.Windows.Forms.DateTimePicker CAL_AdventureStartDate; + private Controls.TrainerID trainerID1; + private System.Windows.Forms.TabPage Tab_Images; + private System.Windows.Forms.PictureBox P_InitialIcon; + private System.Windows.Forms.PictureBox P_CurrIcon; + private System.Windows.Forms.PictureBox P_CurrPhoto; } } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs index 692b09a48..0948f989d 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs @@ -1,7 +1,11 @@ using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; using System.Linq; using System.Windows.Forms; using PKHeX.Core; +using PKHeX.Drawing; using static PKHeX.Core.SaveBlockAccessor9SV; namespace PKHeX.WinForms; @@ -34,6 +38,7 @@ public SAV_Trainer9(SaveFile sav) CB_Gender.Items.Clear(); CB_Gender.Items.AddRange(Main.GenderSymbols.Take(2).ToArray()); // m/f depending on unicode selection + GetImages(); GetComboBoxes(); GetTextBoxes(); LoadMap(); @@ -41,6 +46,31 @@ public SAV_Trainer9(SaveFile sav) Loading = false; } + private void GetImages() + { + static Image GetImage(SCBlockAccessor blocks, uint kd, uint kw, uint kh) + { + var data = blocks.GetBlock(kd).Data; + var width = blocks.GetBlockValue(kw); + var height = blocks.GetBlockValue(kh); + var result = DXT1.Decompress(data, (int)width, (int)height); + return ImageUtil.GetBitmap(result, (int)width, (int)height, PixelFormat.Format32bppArgb); + } + + var blocks = SAV.Blocks; + P_CurrPhoto.Image = GetImage(blocks, KPictureProfileCurrent, KPictureProfileCurrentWidth, KPictureProfileCurrentHeight); + P_CurrIcon.Image = GetImage(blocks, KPictureIconCurrent, KPictureIconCurrentWidth, KPictureIconCurrentHeight); + P_InitialIcon.Image = GetImage(blocks, KPictureIconInitial, KPictureIconInitialWidth, KPictureIconInitialHeight); + P_CurrPhoto.Height = P_CurrPhoto.Image.Height / 4; + P_CurrPhoto.Width = P_CurrPhoto.Image.Width / 4; + P_CurrIcon.Height = P_CurrIcon.Image.Height / 4; + P_CurrIcon.Width = P_CurrIcon.Image.Width / 4; + P_InitialIcon.Height = P_InitialIcon.Image.Height / 4; + P_InitialIcon.Width = P_InitialIcon.Image.Width / 4; + P_CurrIcon.Location = P_CurrPhoto.Location with { X = P_CurrPhoto.Location.X + P_CurrPhoto.Width + 8 }; + P_InitialIcon.Location = P_CurrIcon.Location with { Y = P_CurrIcon.Location.Y + P_CurrIcon.Height + 8 }; + } + private readonly bool Loading; private bool MapUpdated; @@ -273,4 +303,29 @@ private void B_UnlockBikeUpgrades_Click(object sender, EventArgs e) accessor.GetBlock(block).ChangeBooleanType(SCTypeCode.Bool2); System.Media.SystemSounds.Asterisk.Play(); } + + private static void IMG_Save(Image image, string name) + { + var sfd = new SaveFileDialog + { + FileName = name, + Filter = "Images|*.png;*.bmp;*.jpg", + }; + if (sfd.ShowDialog() != DialogResult.OK) + return; + + var path = sfd.FileName; + var format = Path.GetExtension(path) switch + { + ".jpg" or ".jpeg" => ImageFormat.Jpeg, + ".bmp" => ImageFormat.Bmp, + _ => ImageFormat.Png, + }; + image.Save(path, format); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void P_CurrPhoto_Click(object sender, EventArgs e) => IMG_Save(P_CurrPhoto.Image, "current_photo"); + private void P_CurrIcon_Click(object sender, EventArgs e) => IMG_Save(P_CurrIcon.Image, "current_icon"); + private void P_InitialIcon_Click(object sender, EventArgs e) => IMG_Save(P_InitialIcon.Image, "initial_icon"); }