mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-26 22:10:21 +00:00
Minor tweaks
Less alloc
This commit is contained in:
parent
6a61b0e449
commit
06196e0440
10 changed files with 56 additions and 92 deletions
|
@ -137,13 +137,6 @@ public sealed record EncounterSlot8GO : EncounterSlotGO, IFixedOTFriendship
|
|||
|
||||
public void GetInitialMoves(int level, Span<ushort> moves) => MoveLevelUp.GetEncounterMoves(moves, Species, Form, level, OriginGroup);
|
||||
|
||||
public ReadOnlySpan<ushort> GetInitialMoves(int level)
|
||||
{
|
||||
var result = new ushort[4];
|
||||
GetInitialMoves(level, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override EncounterMatchRating GetMatchRating(PKM pk)
|
||||
{
|
||||
if (IsMatchPartial(pk))
|
||||
|
|
|
@ -54,13 +54,16 @@ public static class EncounterLearn
|
|||
if (speciesID <= 0)
|
||||
return Array.Empty<IEncounterable>();
|
||||
|
||||
var moveIDs = StringUtil.GetIndexes(str.movelist, moves.ToList());
|
||||
if (Array.Exists(moveIDs, static z => z <= 0))
|
||||
return Array.Empty<IEncounterable>();
|
||||
|
||||
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<IEncounterable>();
|
||||
span[i] = (ushort)index;
|
||||
}
|
||||
|
||||
return GetLearn((ushort)speciesID, span, form);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<byte> 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)
|
||||
|
|
|
@ -303,9 +303,8 @@ public abstract class SAV4 : SaveFile, IEventFlag37
|
|||
return false;
|
||||
}
|
||||
|
||||
private byte[] MatchMysteryGifts(DataMysteryGift[] value)
|
||||
private bool MatchMysteryGifts(DataMysteryGift[] value, Span<byte> 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<byte> indexes = stackalloc byte[8];
|
||||
bool matchAny = MatchMysteryGifts(value, indexes); // automatically applied
|
||||
if (!matchAny)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 8; i++) // 8 PGT
|
||||
|
|
|
@ -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<int>();
|
||||
return Array.Empty<byte>();
|
||||
|
||||
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<int>(),
|
||||
_ => Array.Empty<byte>(),
|
||||
};
|
||||
}
|
||||
|
||||
public void SetForms(ushort species, ReadOnlySpan<int> forms)
|
||||
public void SetForms(ushort species, ReadOnlySpan<byte> 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<byte> 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<int> Forms, int BitsPerForm, int readCt)
|
||||
private static uint SetDexFormValues(ReadOnlySpan<byte> 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<int> forms, byte form)
|
||||
private static bool TryInsertForm(Span<byte> 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<int> 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<int> values = stackalloc int[forms.Length];
|
||||
for (int i = 1; i < values.Length; i++)
|
||||
Span<byte> 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<int>());
|
||||
SetForms(species, ReadOnlySpan<byte>.Empty);
|
||||
ClearLanguages(species);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
@ -19,32 +18,6 @@ public static class StringUtil
|
|||
/// <returns>Index within <see cref="arr"/></returns>
|
||||
public static int FindIndexIgnoreCase(string[] arr, string value) => Array.FindIndex(arr, z => IsMatchIgnoreCase(z, value));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the indexes by calling <see cref="FindIndexIgnoreCase"/> for all <see cref="items"/>.
|
||||
/// </summary>
|
||||
/// <param name="arr">Array of strings to search in</param>
|
||||
/// <param name="items">Items to search for</param>
|
||||
/// <returns>Index within <see cref="arr"/></returns>
|
||||
public static int[] GetIndexes(string[] arr, IReadOnlyList<string> items) => GetIndexes(arr, items, 0, items.Count);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the indexes by calling <see cref="FindIndexIgnoreCase"/> for all <see cref="items"/>.
|
||||
/// </summary>
|
||||
/// <param name="arr">Array of strings to search in</param>
|
||||
/// <param name="items">Items to search for</param>
|
||||
/// <param name="start">Starting index within <see cref="items"/></param>
|
||||
/// <param name="length">Amount to convert within <see cref="items"/></param>
|
||||
/// <returns>Index within <see cref="arr"/></returns>
|
||||
public static int[] GetIndexes(string[] arr, IReadOnlyList<string> 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)
|
||||
|
|
|
@ -831,7 +831,7 @@ public partial class SAV_Misc4 : Form
|
|||
|
||||
private void SaveWalker(SAV4HGSS s)
|
||||
{
|
||||
bool[] courses = new bool[32];
|
||||
Span<bool> courses = stackalloc bool[32];
|
||||
for (int i = 0; i < CLB_WalkerCourses.Items.Count; i++)
|
||||
courses[i] = CLB_WalkerCourses.GetItemChecked(i);
|
||||
s.SetPokewalkerCoursesUnlocked(courses);
|
||||
|
|
|
@ -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<byte> 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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue