mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-22 03:53:08 +00:00
Placeholder egg4 trash checks
This commit is contained in:
parent
14f4c7f271
commit
c3df0492e9
1 changed files with 125 additions and 31 deletions
|
@ -62,6 +62,19 @@ namespace PKHeX.Core
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enc is EncounterEgg { Generation: 4 } egg)
|
||||||
|
{
|
||||||
|
VerifyTrashNDS_EggNickname4(data, pkm, egg);
|
||||||
|
VerifyTrashNDS_OT(data, pkm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VerifyTrashNDS_Nickname(data, pkm);
|
||||||
|
VerifyTrashNDS_OT(data, pkm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VerifyTrashNDS_EggNickname4(LegalityAnalysis data, PKM pkm, IEncounterTemplate egg)
|
||||||
|
{
|
||||||
var trashNick = pkm.Nickname_Trash;
|
var trashNick = pkm.Nickname_Trash;
|
||||||
var trashNickIndex = FindTerminator(trashNick, 0xFF);
|
var trashNickIndex = FindTerminator(trashNick, 0xFF);
|
||||||
if (trashNickIndex == -1)
|
if (trashNickIndex == -1)
|
||||||
|
@ -70,23 +83,112 @@ namespace PKHeX.Core
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasFinalTerminator(trashNick) && trashNickIndex + 2 != trashNick.Length)
|
if (HasFinalTerminator(trashNick) || trashNickIndex + 2 == trashNick.Length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!IsValidGen4EggTrash(pkm, egg, trashNickIndex, trashNick))
|
||||||
|
data.AddLine(GetInvalid($"{nameof(PKM.Nickname_Trash)} should match egg trash details."));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsValidGen4EggTrash(ILangNick pkm, IVersion egg, int start, ReadOnlySpan<byte> trash)
|
||||||
|
{
|
||||||
|
var first = start;
|
||||||
|
var hatchLanguage = pkm.Language;
|
||||||
|
var maxTrashStart = (hatchLanguage is (int)LanguageID.Japanese or (int)LanguageID.Korean ? 10 : 20) + 2;
|
||||||
|
var version = egg.Version;
|
||||||
|
|
||||||
|
var isLittleEndian = pkm is not BK4;
|
||||||
|
for (int i = start + 2; i < trash.Length; i += 2)
|
||||||
{
|
{
|
||||||
// Allow nicknamed content to insert terminators and keyboard characters inside the mutable region.
|
if (i > maxTrashStart)
|
||||||
var littleEndian = pkm is not BK4;
|
break;
|
||||||
for (int i = trashNickIndex + 2; i < trashNick.Length; i+=2)
|
if (trash[i + 1] == 0xFF && trash[i] == 0xFF)
|
||||||
{
|
continue;
|
||||||
var character = littleEndian
|
|
||||||
? (trashNick[i] | (trashNick[i + 1] << 8))
|
var language = GetIsMatchUnderlayer(trash, i, hatchLanguage, version);
|
||||||
: (trashNick[i + 1] | (trashNick[i] << 8));
|
if (language == LanguageID.Hacked)
|
||||||
if (character is 0)
|
continue;
|
||||||
{
|
|
||||||
data.AddLine(GetInvalid($"{nameof(PKM.Nickname_Trash)} has empty trash between terminators."));
|
if (IsTrashOrTerminator4(trash, first, i, isLittleEndian, hatchLanguage))
|
||||||
return;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LanguageID GetIsMatchUnderlayer(ReadOnlySpan<byte> trash, int trashStart, int hatchLanguage, GameVersion version)
|
||||||
|
{
|
||||||
|
var startLanguage = hatchLanguage == (int)LanguageID.Korean ? LanguageID.Korean : LanguageID.Japanese;
|
||||||
|
for (var lang = startLanguage; lang <= LanguageID.Korean; lang++)
|
||||||
|
{
|
||||||
|
var eggTrash = GetEggTrash(lang, version);
|
||||||
|
if (HasUnderlayer(trash, eggTrash, trashStart))
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
return LanguageID.Hacked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlySpan<byte> GetEggTrash(LanguageID lang, GameVersion version)
|
||||||
|
{
|
||||||
|
return Array.Empty<byte>(); // todo
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsTrashOrTerminator4(ReadOnlySpan<byte> trash, int first, int last, bool isLittleEndian, int language)
|
||||||
|
{
|
||||||
|
for (int index = first + 2; index < last - 2; index += 2)
|
||||||
|
{
|
||||||
|
if (trash[index + 1] == 0xFF && trash[index] == 0xFF)
|
||||||
|
continue;
|
||||||
|
if (!IsValidKeyChar4(trash, isLittleEndian, index, language))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidKeyChar4(ReadOnlySpan<byte> trash, bool isLittleEndian, int index, int language)
|
||||||
|
{
|
||||||
|
var character = isLittleEndian
|
||||||
|
? (trash[index] | (trash[index + 1] << 8))
|
||||||
|
: (trash[index + 1] | (trash[index] << 8));
|
||||||
|
return IsValidKeyChar4(character, language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidKeyChar4(int character, int language)
|
||||||
|
{
|
||||||
|
return character is not 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VerifyTrashNDS_Nickname(LegalityAnalysis data, PKM pkm)
|
||||||
|
{
|
||||||
|
var trashNick = pkm.Nickname_Trash;
|
||||||
|
var trashNickIndex = FindTerminator(trashNick, 0xFF);
|
||||||
|
if (trashNickIndex == -1)
|
||||||
|
{
|
||||||
|
data.AddLine(GetInvalid($"{nameof(PKM.Nickname_Trash)} is missing a terminator."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasFinalTerminator(trashNick) || trashNickIndex + 2 == trashNick.Length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Allow nicknamed content to insert terminators and keyboard characters inside the mutable region.
|
||||||
|
var littleEndian = pkm is not BK4;
|
||||||
|
for (int i = trashNickIndex + 2; i < trashNick.Length; i += 2)
|
||||||
|
{
|
||||||
|
var character = littleEndian
|
||||||
|
? (trashNick[i] | (trashNick[i + 1] << 8))
|
||||||
|
: (trashNick[i + 1] | (trashNick[i] << 8));
|
||||||
|
|
||||||
|
if (character is not 0)
|
||||||
|
continue;
|
||||||
|
data.AddLine(GetInvalid($"{nameof(PKM.Nickname_Trash)} has empty trash between terminators."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VerifyTrashNDS_OT(LegalityAnalysis data, PKM pkm)
|
||||||
|
{
|
||||||
var trashOT = pkm.OT_Trash;
|
var trashOT = pkm.OT_Trash;
|
||||||
var trashOTIndex = FindTerminator(trashOT, 0xFF);
|
var trashOTIndex = FindTerminator(trashOT, 0xFF);
|
||||||
if (trashOTIndex == -1)
|
if (trashOTIndex == -1)
|
||||||
|
@ -95,24 +197,16 @@ namespace PKHeX.Core
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var littleEndian = pkm is not BK4;
|
||||||
|
for (int i = trashOTIndex + 2; i < trashOT.Length; i += 2)
|
||||||
{
|
{
|
||||||
var littleEndian = pkm is not BK4;
|
var character = littleEndian
|
||||||
for (int i = trashOTIndex + 2; i < trashOT.Length; i+=2)
|
? (trashOT[i] | (trashOT[i + 1] << 8))
|
||||||
{
|
: (trashOT[i + 1] | (trashOT[i] << 8));
|
||||||
var character = littleEndian
|
if (character is 0)
|
||||||
? (trashOT[i] | (trashOT[i + 1] << 8))
|
continue;
|
||||||
: (trashOT[i + 1] | (trashOT[i] << 8));
|
data.AddLine(GetInvalid($"{nameof(PKM.OT_Trash)} has nonzero trash after terminator."));
|
||||||
if (character is not 0)
|
return;
|
||||||
{
|
|
||||||
data.AddLine(GetInvalid($"{nameof(PKM.OT_Trash)} has nonzero trash after terminator."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!HasFinalTerminator(trashOT) && trashOTIndex + 2 != trashOT.Length)
|
|
||||||
{
|
|
||||||
data.AddLine(GetInvalid($"{nameof(PKM.OT_Trash)} detected at reserved terminator offset."));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue