diff --git a/PKHeX.Core/Legality/Enums/CheckIdentifier.cs b/PKHeX.Core/Legality/Enums/CheckIdentifier.cs
index 548ba9c20..6df0c98be 100644
--- a/PKHeX.Core/Legality/Enums/CheckIdentifier.cs
+++ b/PKHeX.Core/Legality/Enums/CheckIdentifier.cs
@@ -148,5 +148,10 @@ public enum CheckIdentifier : byte
/// The pertains to the values.
///
GVs,
+
+ ///
+ /// The pertains to values.
+ ///
+ Marking,
}
}
diff --git a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs
index 86793d07f..0c355e4bc 100644
--- a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs
+++ b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs
@@ -288,6 +288,10 @@ public static class LegalityCheckStrings
public static string LLevelMetGiftFail { get; set; } = "Current Level below Mystery Gift level.";
public static string LLevelMetSane { get; set; } = "Current level is not below met level.";
+ public static string LMarkValueOutOfRange_0 { get; set; } = "Individual marking at index {0} is not within the allowed value range.";
+ public static string LMarkValueShouldBeZero { get; set; } = "Marking flags cannot be set.";
+ public static string LMarkValueUnusedBitsPresent { get; set; } = "Marking flags uses bits beyond the accessible range.";
+
public static string LMemoryArgBadCatch { get; set; } = "{0} Memory: {0} did not catch this.";
public static string LMemoryArgBadHatch { get; set; } = "{0} Memory: {0} did not hatch this.";
public static string LMemoryArgBadHT { get; set; } = "Memory: Can't have Handling Trainer Memory as Egg.";
diff --git a/PKHeX.Core/Legality/LegalityAnalysis.cs b/PKHeX.Core/Legality/LegalityAnalysis.cs
index 9bb44d1b8..64a2c5b2f 100644
--- a/PKHeX.Core/Legality/LegalityAnalysis.cs
+++ b/PKHeX.Core/Legality/LegalityAnalysis.cs
@@ -283,6 +283,7 @@ private void UpdateChecks()
GenderValues.Verify(this);
Item.Verify(this);
Contest.Verify(this);
+ Marking.Verify(this);
var format = pkm.Format;
if (format is 4 or 5 or 6) // Gen 6->7 transfer removes this property.
diff --git a/PKHeX.Core/Legality/LegalityAnalyzers.cs b/PKHeX.Core/Legality/LegalityAnalyzers.cs
index 23de0c7e6..7ea8a9153 100644
--- a/PKHeX.Core/Legality/LegalityAnalyzers.cs
+++ b/PKHeX.Core/Legality/LegalityAnalyzers.cs
@@ -25,6 +25,7 @@ internal static class LegalityAnalyzers
public static readonly MemoryVerifier Memory = new();
public static readonly HistoryVerifier History = new();
public static readonly ContestStatVerifier Contest = new();
+ public static readonly MarkingVerifier Marking = new();
public static readonly TrainerNameVerifier Trainer = new();
public static readonly TrainerIDVerifier TrainerID = new();
diff --git a/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs b/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs
index 7d32c55fb..e71b24521 100644
--- a/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs
@@ -13,8 +13,7 @@ public sealed class LegendsArceusVerifier : Verifier
public override void Verify(LegalityAnalysis data)
{
- var pk = data.pkm;
- if (pk is not PA8 pa)
+ if (data.pkm is not PA8 pa)
return;
if (pa.IsNoble)
@@ -38,7 +37,7 @@ private static void CheckGanbaru(LegalityAnalysis data, PA8 pa)
if (gv <= max)
continue;
- data.AddLine(GetInvalid(LGanbaruStatTooHigh, CheckIdentifier.EVs));
+ data.AddLine(GetInvalid(LGanbaruStatTooHigh, CheckIdentifier.GVs));
return;
}
}
diff --git a/PKHeX.Core/Legality/Verifiers/MarkingVerifier.cs b/PKHeX.Core/Legality/Verifiers/MarkingVerifier.cs
new file mode 100644
index 000000000..c42bcb456
--- /dev/null
+++ b/PKHeX.Core/Legality/Verifiers/MarkingVerifier.cs
@@ -0,0 +1,82 @@
+using static PKHeX.Core.LegalityCheckStrings;
+using static PKHeX.Core.CheckIdentifier;
+
+namespace PKHeX.Core;
+
+///
+/// Verifies the .
+///
+public sealed class MarkingVerifier : Verifier
+{
+ protected override CheckIdentifier Identifier => Marking;
+
+ public override void Verify(LegalityAnalysis data)
+ {
+ var pkm = data.pkm;
+ VerifyFavoriteMark(data, pkm);
+ VerifyMarkValue(data, pkm);
+ }
+
+ private void VerifyFavoriteMark(LegalityAnalysis data, PKM pkm)
+ {
+ // Can only be toggled on in LGP/E, and is retained via transfer to HOME and into other games.
+ if (pkm is IFavorite { Favorite: true } && !pkm.GG)
+ data.AddLine(GetInvalid(LFavoriteMarkingUnavailable));
+ }
+
+ private void VerifyMarkValue(LegalityAnalysis data, PKM pkm)
+ {
+ var mv = pkm.MarkValue;
+ if (mv == 0)
+ return;
+
+ // Eggs can have markings applied.
+ //if (pkm.IsEgg)
+ //{
+ // data.AddLine(GetInvalid(LMarkValueShouldBeZero));
+ // return;
+ //}
+
+ switch (pkm.Format)
+ {
+ case <= 2:
+ return;
+ case <= 6:
+ VerifyMarkValueSingle(data, pkm, mv);
+ return;
+ default:
+ VerifyMarkValueDual(data, pkm, mv);
+ return;
+ }
+ }
+
+ private const int Single4 = 0b_1111;
+ private const int Single6 = 0b_111111;
+ private const int Dual6 = 0b_1111_1111_1111;
+
+ private void VerifyMarkValueDual(LegalityAnalysis data, PKM pkm, int mv)
+ {
+ if (mv > Dual6)
+ data.AddLine(GetInvalid(LMarkValueUnusedBitsPresent));
+
+ var count = pkm.MarkingCount;
+ for (int i = 0; i < count; i++)
+ {
+ var value = pkm.GetMarking(i);
+ if (value is not (0 or 1 or 2))
+ data.AddLine(GetInvalid(string.Format(LMarkValueOutOfRange_0, i)));
+ }
+ }
+
+ private void VerifyMarkValueSingle(LegalityAnalysis data, PKM pkm, int mv)
+ {
+ if (!IsMarkValueValid3456(pkm, mv))
+ data.AddLine(GetInvalid(LMarkValueUnusedBitsPresent));
+ }
+
+ private static bool IsMarkValueValid3456(PKM pkm, int value)
+ {
+ var max = pkm.Format is 3 ? Single4 : Single6;
+ return value <= max;
+ }
+}
diff --git a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs
index feefbae95..c17f3018e 100644
--- a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs
@@ -499,9 +499,6 @@ private static void VerifyAbsoluteSizes(LegalityAnalysis data, IScaledSizeValue
private void VerifySWSHStats(LegalityAnalysis data, PK8 pk8)
{
- if (pk8.Favorite && !pk8.GG)
- data.AddLine(GetInvalid(LFavoriteMarkingUnavailable, Encounter));
-
var social = pk8.Sociability;
if (pk8.IsEgg)
{
@@ -562,10 +559,6 @@ private void VerifySWSHStats(LegalityAnalysis data, PK8 pk8)
private void VerifyPLAStats(LegalityAnalysis data, PA8 pa8)
{
VerifyAbsoluteSizes(data, pa8);
-
- if (pa8.Favorite && !pa8.GG)
- data.AddLine(GetInvalid(LFavoriteMarkingUnavailable, Encounter));
-
if (!pa8.HasVisitedSWSH(data.Info.EvoChainsAllGens.Gen8))
{
var affix = pa8.AffixedRibbon;
@@ -597,9 +590,6 @@ private void VerifyPLAStats(LegalityAnalysis data, PA8 pa8)
private void VerifyBDSPStats(LegalityAnalysis data, PB8 pb8)
{
- if (pb8.Favorite && !pb8.GG)
- data.AddLine(GetInvalid(LFavoriteMarkingUnavailable, Encounter));
-
if (!pb8.HasVisitedSWSH(data.Info.EvoChainsAllGens.Gen8))
{
var affix = pb8.AffixedRibbon;