Minor tweaks

Less alloc
This commit is contained in:
Kurt 2022-09-04 22:23:35 -07:00
parent 6a61b0e449
commit 06196e0440
10 changed files with 56 additions and 92 deletions

View file

@ -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))

View file

@ -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))
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>();
var span = new ushort[moveIDs.Length];
for (int i = 0; i < moveIDs.Length; i++)
span[i] = (ushort)moveIDs[i];
span[i] = (ushort)index;
}
return GetLearn((ushort)speciesID, span, form);
}

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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);
}

View file

@ -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)

View file

@ -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);

View file

@ -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);
}
}