diff --git a/PKHeX.Core/Legality/LearnSource/MoveResult.cs b/PKHeX.Core/Legality/LearnSource/MoveResult.cs
index 6b5187679..df106a6fb 100644
--- a/PKHeX.Core/Legality/LearnSource/MoveResult.cs
+++ b/PKHeX.Core/Legality/LearnSource/MoveResult.cs
@@ -69,6 +69,9 @@ public readonly record struct MoveResult(MoveLearnInfo Info, byte EvoStage = 0,
public static MoveResult Unobtainable(ushort expect) => new(LearnMethod.UnobtainableExpect) { Expect = expect };
public static MoveResult Unobtainable() => new(LearnMethod.Unobtainable);
+ ///
+ /// Checks if all s in the span are .
+ ///
public static bool AllValid(ReadOnlySpan span)
{
foreach (var result in span)
@@ -79,6 +82,9 @@ public readonly record struct MoveResult(MoveLearnInfo Info, byte EvoStage = 0,
return true;
}
+ ///
+ /// Checks if all s in the span are .
+ ///
public static bool AllParsed(ReadOnlySpan span)
{
foreach (var result in span)
diff --git a/PKHeX.Core/Legality/RNG/CXD/LockFinder.cs b/PKHeX.Core/Legality/RNG/CXD/LockFinder.cs
index e4bec3be6..34a763db7 100644
--- a/PKHeX.Core/Legality/RNG/CXD/LockFinder.cs
+++ b/PKHeX.Core/Legality/RNG/CXD/LockFinder.cs
@@ -52,10 +52,13 @@ public static class LockFinder
/// True if the starter ID correlation is correct
public static bool IsXDStarterValid(uint seed, uint TID16, uint SID16)
{
- // pidiv reversed 2x yields SID16, 3x yields TID16. shift by 7 if another PKM is generated prior
- var SIDf = XDRNG.Prev2(seed);
- var TIDf = XDRNG.Prev(SIDf);
- return SIDf >> 16 == SID16 && TIDf >> 16 == TID16;
+ // pidiv is right before the IV calls; need to unroll 2x for fake calls, then unroll for the TID/SID.
+ // reversed 2x yields SID16, 3x yields TID16.
+ var TIDf = XDRNG.Prev3(seed);
+ if (TIDf >> 16 != TID16)
+ return false;
+ var SIDf = XDRNG.Next(TIDf);
+ return SIDf >> 16 == SID16;
}
///
diff --git a/PKHeX.Core/PKM/Strings/StringConverter12.cs b/PKHeX.Core/PKM/Strings/StringConverter12.cs
index f7351ab32..5543468d1 100644
--- a/PKHeX.Core/PKM/Strings/StringConverter12.cs
+++ b/PKHeX.Core/PKM/Strings/StringConverter12.cs
@@ -101,6 +101,8 @@ public static class StringConverter12
/// Character count loaded.
public static int LoadString(ReadOnlySpan data, Span result, bool jp)
{
+ if (data.Length == 0)
+ return 0;
if (data[0] == G1TradeOTCode) // In-game Trade
{
result[0] = G1TradeOT;
@@ -139,7 +141,9 @@ public static class StringConverter12
else if (option is StringConverterOption.Clear7F)
destBuffer.Fill(G1SpaceCode);
- if (value.Length != 0 && value[0] == G1TradeOT) // Handle "[TRAINER]"
+ if (value.Length == 0)
+ return 0;
+ if (value[0] == G1TradeOT) // Handle "[TRAINER]"
{
destBuffer[0] = G1TradeOTCode;
destBuffer[1] = G1TerminatorCode;
@@ -149,7 +153,7 @@ public static class StringConverter12
if (value.Length > maxLength)
value = value[..maxLength]; // Hard cap
- var dict = jp ? TableEN : TableJP;
+ var dict = jp ? TableJP : TableEN;
int i = 0;
for (; i < value.Length; i++)
{
@@ -213,7 +217,7 @@ public static class StringConverter12
'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ホ', 'マ', 'ミ', 'ム', // 90-9F
'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'ル', 'レ', 'ロ', 'ワ', 'ヲ', 'ン', 'ッ', 'ャ', 'ュ', 'ョ', // A0-AF
'ィ', 'あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ', 'さ', 'し', 'す', 'せ', 'そ', // B0-BF
- 'た', 'ち', 'つ', 'て', 'と', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ひ', 'ふ', 'ヘ', 'ほ', 'ま', // C0-CF
+ 'た', 'ち', 'つ', 'て', 'と', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ひ', 'ふ', 'へ', 'ほ', 'ま', // C0-CF
'み', 'む', 'め', 'も', 'や', 'ゆ', 'よ', 'ら', 'リ', 'る', 'れ', 'ろ', 'わ', 'を', 'ん', 'っ', // D0-DF
'ゃ', 'ゅ', 'ょ', 'ー', '゚', '゙', '?', '!', '。', 'ァ', 'ゥ', 'ェ', NUL, NUL, NUL, '♂', // E0-EF
MNY, NUL, '.', '/', 'ォ', '♀', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', // F0-FF
diff --git a/PKHeX.Core/PKM/Strings/StringConverter2KOR.cs b/PKHeX.Core/PKM/Strings/StringConverter2KOR.cs
index ebbc8be16..6e279cba7 100644
--- a/PKHeX.Core/PKM/Strings/StringConverter2KOR.cs
+++ b/PKHeX.Core/PKM/Strings/StringConverter2KOR.cs
@@ -40,6 +40,8 @@ public static class StringConverter2KOR
/// Character count loaded.
public static int LoadString(ReadOnlySpan data, Span result)
{
+ if (data.Length == 0)
+ return 0;
if (data[0] == G1TradeOTCode) // In-game Trade
{
result[0] = G1TradeOT;
@@ -91,7 +93,10 @@ public static class StringConverter2KOR
else if (option is StringConverterOption.Clear50)
destBuffer.Fill(G1TerminatorCode);
- if (value.Length != 0 && value[0] == G1TradeOT) // Handle "[TRAINER]"
+ if (value.Length == 0)
+ return 0;
+ // Can't get Gen1 In-Game trades with this char, but handle it anyways since the game can handle it.
+ if (value[0] == G1TradeOT) // Handle "[TRAINER]"
{
destBuffer[0] = G1TradeOTCode;
destBuffer[1] = G1TerminatorCode;
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/ItemInfo6.cs b/PKHeX.Core/Saves/Substructures/Gen6/ItemInfo6.cs
index df42f7a99..23412d54b 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/ItemInfo6.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/ItemInfo6.cs
@@ -10,16 +10,16 @@ public sealed class ItemInfo6 : SaveBlock
private const int BoundItemCount = 4;
private const int RecentItemCount = 12;
- public int[] SelectItems
+ public ushort[] SelectItems
{
// UP,RIGHT,DOWN,LEFT
get
{
var span = Data.AsSpan(Offset + 10);
- int[] list = new int[BoundItemCount];
- for (int i = 0; i < list.Length; i++)
- list[i] = ReadUInt16LittleEndian(span[(2 * i)..]);
- return list;
+ var result = new ushort[BoundItemCount];
+ for (int i = 0; i < result.Length; i++)
+ result[i] = ReadUInt16LittleEndian(span[(2 * i)..]);
+ return result;
}
set
{
@@ -27,20 +27,20 @@ public sealed class ItemInfo6 : SaveBlock
throw new ArgumentException(nameof(value));
var span = Data.AsSpan(Offset + 10);
for (int i = 0; i < value.Length; i++)
- WriteUInt16LittleEndian(span[(2 * i)..], (ushort)value[i]);
+ WriteUInt16LittleEndian(span[(2 * i)..], value[i]);
}
}
- public int[] RecentItems
+ public ushort[] RecentItems
{
// Items recently interacted with (Give, Use)
get
{
var span = Data.AsSpan(Offset + 20);
- int[] list = new int[RecentItemCount];
- for (int i = 0; i < list.Length; i++)
- list[i] = ReadUInt16LittleEndian(span[(2 * i)..]);
- return list;
+ var result = new ushort[RecentItemCount];
+ for (int i = 0; i < result.Length; i++)
+ result[i] = ReadUInt16LittleEndian(span[(2 * i)..]);
+ return result;
}
set
{
@@ -48,7 +48,7 @@ public sealed class ItemInfo6 : SaveBlock
throw new ArgumentException(nameof(value));
var span = Data.AsSpan(Offset + 20);
for (int i = 0; i < value.Length; i++)
- WriteUInt16LittleEndian(span[(2 * i)..], (ushort)value[i]);
+ WriteUInt16LittleEndian(span[(2 * i)..], value[i]);
}
}
}
diff --git a/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs b/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs
index 5eb40e049..98629e23a 100644
--- a/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs
+++ b/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs
@@ -99,8 +99,8 @@ public class LegalityTest
var info = legality.Info;
foreach (var m in info.Moves.Where(z => !z.Valid))
- yield return m.Summary(legality.Info.Entity, legality.Info.EvoChainsAllGens);
+ yield return m.Summary(info.Entity, info.EvoChainsAllGens);
foreach (var r in info.Relearn.Where(z => !z.Valid))
- yield return r.Summary(legality.Info.Entity, legality.Info.EvoChainsAllGens);
+ yield return r.Summary(info.Entity, info.EvoChainsAllGens);
}
}