diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs index 2452fbc07..8ca4bf14d 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs @@ -137,13 +137,6 @@ public sealed record EncounterSlot8GO : EncounterSlotGO, IFixedOTFriendship public void GetInitialMoves(int level, Span moves) => MoveLevelUp.GetEncounterMoves(moves, Species, Form, level, OriginGroup); - public ReadOnlySpan GetInitialMoves(int level) - { - var result = new ushort[4]; - GetInitialMoves(level, result); - return result; - } - public override EncounterMatchRating GetMatchRating(PKM pk) { if (IsMatchPartial(pk)) diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterLearn.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterLearn.cs index 4bf32dd7a..25b9d0e62 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterLearn.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterLearn.cs @@ -54,13 +54,16 @@ public static class EncounterLearn if (speciesID <= 0) return Array.Empty(); - var moveIDs = StringUtil.GetIndexes(str.movelist, moves.ToList()); - if (Array.Exists(moveIDs, static z => z <= 0)) - return Array.Empty(); - - var span = new ushort[moveIDs.Length]; - for (int i = 0; i < moveIDs.Length; i++) - span[i] = (ushort)moveIDs[i]; + var allMoves = moves.ToList(); + var span = new ushort[allMoves.Count]; + for (int i = 0; i < span.Length; i++) + { + var move = allMoves[i]; + var index = StringUtil.FindIndexIgnoreCase(str.movelist, move); + if (index <= 0) + return Array.Empty(); + span[i] = (ushort)index; + } return GetLearn((ushort)speciesID, span, form); } diff --git a/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversal.cs b/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversal.cs index 7f44b213b..fe2b641d1 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversal.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversal.cs @@ -115,7 +115,7 @@ public static class LCRNGReversal for (uint i = 0; i <= 255; i++, search1 -= k2, search2 -= k2) { - uint val = (ushort)(search1 >> 16); + ushort val = (ushort)(search1 >> 16); if (flags[val]) { // Verify PID calls line up diff --git a/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversalSkip.cs b/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversalSkip.cs index cf975cb03..a6f054e63 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversalSkip.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversalSkip.cs @@ -114,7 +114,7 @@ public static class LCRNGReversalSkip for (uint i = 0; i <= 255; i++, search1 -= k2, search3 -= k2) { - uint val = (ushort)(search1 >> 16); + ushort val = (ushort)(search1 >> 16); if (flags[val]) { // Verify PID calls line up diff --git a/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs b/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs index cef1bdc7f..3f5e00eb1 100644 --- a/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs +++ b/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs @@ -336,14 +336,14 @@ public static class FrameFinder return false; // init natures - uint[] natures = new uint[25]; - for (uint i = 0; i < 25; i++) + Span natures = stackalloc byte[25]; + for (byte i = 0; i < 25; i++) natures[i] = i; // shuffle nature list - for (uint i = 0; i < 25; i++) + for (int i = 0; i < 25; i++) { - for (uint j = 1 + i; j < 25; j++) + for (int j = 1 + i; j < 25; j++) { var s = stack.Pop(); if (((s >> 16) & 1) == 0) diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs index 6961b3fb2..aec380127 100644 --- a/PKHeX.Core/Saves/SAV4.cs +++ b/PKHeX.Core/Saves/SAV4.cs @@ -303,9 +303,8 @@ public abstract class SAV4 : SaveFile, IEventFlag37 return false; } - private byte[] MatchMysteryGifts(DataMysteryGift[] value) + private bool MatchMysteryGifts(DataMysteryGift[] value, Span indexes) { - byte[] cardMatch = new byte[8]; for (int i = 0; i < 8; i++) { if (value[i] is not PGT pgt) @@ -313,11 +312,11 @@ public abstract class SAV4 : SaveFile, IEventFlag37 if (pgt.CardType == 0) // empty { - cardMatch[i] = pgt.Slot = 0; + indexes[i] = pgt.Slot = 0; continue; } - cardMatch[i] = pgt.Slot = 3; + indexes[i] = pgt.Slot = 3; for (byte j = 0; j < 3; j++) { if (value[8 + j] is not PCD pcd) @@ -329,11 +328,11 @@ public abstract class SAV4 : SaveFile, IEventFlag37 if (this is SAV4HGSS) j++; // hgss 0,1,2; dppt 1,2,3 - cardMatch[i] = pgt.Slot = j; + indexes[i] = pgt.Slot = j; break; } } - return cardMatch; + return true; } public override MysteryGiftAlbum GiftAlbum @@ -406,8 +405,9 @@ public abstract class SAV4 : SaveFile, IEventFlag37 } set { - var Matches = MatchMysteryGifts(value); // automatically applied - if (Matches.Length == 0) + Span indexes = stackalloc byte[8]; + bool matchAny = MatchMysteryGifts(value, indexes); // automatically applied + if (!matchAny) return; for (int i = 0; i < 8; i++) // 8 PGT diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs index 98834a837..f7196a880 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs @@ -80,7 +80,9 @@ public sealed class Zukan4 : ZukanBase return formNames; } - public int[] GetForms(ushort species) + public const byte FORM_NONE = byte.MaxValue; + + public byte[] GetForms(ushort species) { const int brSize = 0x40; if (species == (int)Species.Deoxys) @@ -101,14 +103,10 @@ public sealed class Zukan4 : ZukanBase case (int)Species.Wormadam: // Wormadam return GetDexFormValues(Data[FormOffset1 + 3], 2, 3); case (int)Species.Unown: // Unown - int[] result = new int[0x1C]; - var slice = Data.AsSpan(FormOffset1 + 4); - for (int i = 0; i < result.Length; i++) - result[i] = slice[i]; - return result; + return Data.AsSpan(FormOffset1 + 4, 0x1C).ToArray(); } if (DP) - return Array.Empty(); + return Array.Empty(); int PokeDexLanguageFlags = FormOffset1 + (HGSS ? 0x3C : 0x20); int FormOffset2 = PokeDexLanguageFlags + 0x1F4; @@ -118,11 +116,11 @@ public sealed class Zukan4 : ZukanBase (int)Species.Shaymin => GetDexFormValues(Data[FormOffset2 + 4], 1, 2), (int)Species.Giratina => GetDexFormValues(Data[FormOffset2 + 5], 1, 2), (int)Species.Pichu when HGSS => GetDexFormValues(Data[FormOffset2 + 6], 2, 3), - _ => Array.Empty(), + _ => Array.Empty(), }; } - public void SetForms(ushort species, ReadOnlySpan forms) + public void SetForms(ushort species, ReadOnlySpan forms) { const int brSize = 0x40; switch (species) @@ -150,14 +148,10 @@ public sealed class Zukan4 : ZukanBase Data[FormOffset1 + 3] = (byte)SetDexFormValues(forms, 2, 3); return; case (int)Species.Unown: // Unown - int ofs = FormOffset1 + 4; - int len = forms.Length; - Span unown = stackalloc byte[0x1C]; - for (int i = 0; i < len; i++) - unown[i] = (byte)forms[i]; - for (int i = len; i < forms.Length; i++) - unown[i] = 0xFF; - unown.CopyTo(Data.AsSpan(ofs)); + var unown = Data.AsSpan(FormOffset1 + 4, 0x1C); + forms.CopyTo(unown); + if (forms.Length != unown.Length) + unown[forms.Length..].Fill(FORM_NONE); return; } @@ -184,27 +178,27 @@ public sealed class Zukan4 : ZukanBase } } - private static int[] GetDexFormValues(uint Value, int BitsPerForm, int readCt) + private static byte[] GetDexFormValues(uint Value, int BitsPerForm, int readCt) { - int[] Forms = new int[readCt]; + byte[] Forms = new byte[readCt]; int n1 = 0xFF >> (8 - BitsPerForm); for (int i = 0; i < Forms.Length; i++) { int val = (int)(Value >> (i * BitsPerForm)) & n1; if (n1 == val && BitsPerForm > 1) - Forms[i] = -1; + Forms[i] = byte.MaxValue; else - Forms[i] = val; + Forms[i] = (byte)val; } // (BitsPerForm > 1) was already handled, handle (BitsPerForm == 1) if (BitsPerForm == 1 && Forms[0] == Forms[1] && Forms[0] == 1) - Forms[0] = Forms[1] = -1; + Forms[0] = Forms[1] = byte.MaxValue; return Forms; } - private static uint SetDexFormValues(ReadOnlySpan Forms, int BitsPerForm, int readCt) + private static uint SetDexFormValues(ReadOnlySpan Forms, int BitsPerForm, int readCt) { int n1 = 0xFF >> (8 - BitsPerForm); uint Value = 0xFFFFFFFF << (readCt * BitsPerForm); @@ -221,13 +215,13 @@ public sealed class Zukan4 : ZukanBase return Value; } - private static bool TryInsertForm(Span forms, byte form) + private static bool TryInsertForm(Span forms, byte form) { if (forms.IndexOf(form) >= 0) return false; // already in list // insert at first empty - var index = forms.IndexOf(-1); + var index = forms.IndexOf(FORM_NONE); if (index < 0) return false; // no free slots? @@ -245,7 +239,7 @@ public sealed class Zukan4 : ZukanBase byte val = Data[ofs + i]; if (val == form) return i; - if (val == 0xFF) // end of populated indexes + if (val == FORM_NONE) // end of populated indexes return UnownEmpty; } return UnownEmpty; @@ -259,7 +253,7 @@ public sealed class Zukan4 : ZukanBase byte val = Data[ofs + i]; if (val == form) return i; - if (val == 0xFF) + if (val == FORM_NONE) return i; } @@ -270,7 +264,7 @@ public sealed class Zukan4 : ZukanBase { var ofs = Offset + OFS_FORM1 + 4; for (int i = 0; i < 0x1C; i++) - Data[ofs + i] = 0xFF; + Data[ofs + i] = FORM_NONE; } public bool GetUnownForm(byte form) => GetUnownFormIndex(form) != UnownEmpty; @@ -336,7 +330,7 @@ public sealed class Zukan4 : ZukanBase return; } - Span forms = GetForms(species); + var forms = GetForms(species); if (forms.Length == 0) return; @@ -466,8 +460,8 @@ public sealed class Zukan4 : ZukanBase if (forms.Length <= 1) return; - Span values = stackalloc int[forms.Length]; - for (int i = 1; i < values.Length; i++) + Span values = stackalloc byte[forms.Length]; + for (byte i = 1; i < values.Length; i++) values[i] = i; SetForms(species, values); } @@ -493,7 +487,7 @@ public sealed class Zukan4 : ZukanBase SetSeen(species, false); SetSeenGenderNeither(species); - SetForms(species, Array.Empty()); + SetForms(species, ReadOnlySpan.Empty); ClearLanguages(species); } diff --git a/PKHeX.Core/Util/StringUtil.cs b/PKHeX.Core/Util/StringUtil.cs index c5d76590c..92d43be4e 100644 --- a/PKHeX.Core/Util/StringUtil.cs +++ b/PKHeX.Core/Util/StringUtil.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Globalization; namespace PKHeX.Core; @@ -19,32 +18,6 @@ public static class StringUtil /// Index within public static int FindIndexIgnoreCase(string[] arr, string value) => Array.FindIndex(arr, z => IsMatchIgnoreCase(z, value)); - /// - /// Gets the indexes by calling for all . - /// - /// Array of strings to search in - /// Items to search for - /// Index within - public static int[] GetIndexes(string[] arr, IReadOnlyList items) => GetIndexes(arr, items, 0, items.Count); - - /// - /// Gets the indexes by calling for all . - /// - /// Array of strings to search in - /// Items to search for - /// Starting index within - /// Amount to convert within - /// Index within - public static int[] GetIndexes(string[] arr, IReadOnlyList items, int start, int length) - { - if (length < 0) - length = items.Count - start; - var result = new int[length]; - for (int i = 0; i < result.Length; i++) - result[i] = FindIndexIgnoreCase(arr, items[start + i]); - return result; - } - public static bool IsMatchIgnoreCase(string string1, string string2) { if (string1.Length != string2.Length) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs index 0c9751c89..9e0bebcd7 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs @@ -831,7 +831,7 @@ public partial class SAV_Misc4 : Form private void SaveWalker(SAV4HGSS s) { - bool[] courses = new bool[32]; + Span courses = stackalloc bool[32]; for (int i = 0; i < CLB_WalkerCourses.Items.Count; i++) courses[i] = CLB_WalkerCourses.GetItemChecked(i); s.SetPokewalkerCoursesUnlocked(courses); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs index de349ee2b..25dac5ced 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs @@ -121,7 +121,7 @@ public partial class SAV_Pokedex4 : Form string[] formNames = GetFormNames4Dex(species); - var seen = forms.Where(z => z >= 0 && z < forms.Length).Distinct().Select((_, i) => formNames[forms[i]]).ToArray(); + var seen = forms.Where(z => z != FORM_NONE && z < forms.Length).Distinct().Select((_, i) => formNames[forms[i]]).ToArray(); var not = formNames.Except(seen).ToArray(); LB_Form.Items.AddRange(seen); @@ -184,10 +184,11 @@ public partial class SAV_Pokedex4 : Form var forms = SAV.Dex.GetForms(species); if (forms.Length > 0) { - int[] arr = new int[LB_Form.Items.Count]; + var items = LB_Form.Items; + Span arr = stackalloc byte[items.Count]; string[] formNames = GetFormNames4Dex(species); - for (int i = 0; i < LB_Form.Items.Count; i++) - arr[i] = Array.IndexOf(formNames, (string)LB_Form.Items[i]); + for (int i = 0; i < items.Count; i++) + arr[i] = (byte)Array.IndexOf(formNames, (string)items[i]); // shouldn't ever fail SAV.Dex.SetForms(species, arr); } }