mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-22 12:03:10 +00:00
Reduce alloc for ot/nick by raw trash reads
Legality check now catches buffer overflow mons. Now that I have each type exposing a trash length & charcount, should be easy to have some reusable trash byte measuring methods (see the old branch)
This commit is contained in:
parent
08ed482555
commit
7b6abc0520
70 changed files with 286 additions and 138 deletions
|
@ -18,7 +18,7 @@ public sealed class FakeSaveFile : SaveFile
|
||||||
public override int MaxEV => 0;
|
public override int MaxEV => 0;
|
||||||
public override ReadOnlySpan<ushort> HeldItems => Legal.HeldItems_RS;
|
public override ReadOnlySpan<ushort> HeldItems => Legal.HeldItems_RS;
|
||||||
public override int GetBoxOffset(int box) => -1;
|
public override int GetBoxOffset(int box) => -1;
|
||||||
public override int MaxStringLengthOT => 5;
|
public override int MaxStringLengthTrainer => 5;
|
||||||
public override int MaxStringLengthNickname => 5;
|
public override int MaxStringLengthNickname => 5;
|
||||||
public override ushort MaxMoveID => 5;
|
public override ushort MaxMoveID => 5;
|
||||||
public override ushort MaxSpeciesID => 1;
|
public override ushort MaxSpeciesID => 1;
|
||||||
|
|
|
@ -202,25 +202,39 @@ public sealed record EncounterGift1 : IEncounterable, IEncounterMatch, IEncounte
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsTrainerNameValid(PKM pk) => Trainer switch
|
private bool IsTrainerNameValid(PKM pk)
|
||||||
{
|
{
|
||||||
Recipient => true,
|
if (Trainer == Recipient)
|
||||||
VirtualConsoleMew => pk.OriginalTrainerName == (pk.Language == 1 ? VirtualConsoleMewJPN : VirtualConsoleMewINT),
|
return true;
|
||||||
Stadium => pk.Language switch
|
|
||||||
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
if (Trainer == EuropeTour)
|
||||||
|
return IsTourOT(trainer);
|
||||||
|
|
||||||
|
var language = pk.Language;
|
||||||
|
if (Trainer == VirtualConsoleMew)
|
||||||
|
return trainer.SequenceEqual(language == 1 ? VirtualConsoleMewJPN : VirtualConsoleMewINT);
|
||||||
|
|
||||||
|
if (Trainer == Stadium)
|
||||||
{
|
{
|
||||||
(int)Japanese => pk.OriginalTrainerName == StadiumJPN,
|
return language switch
|
||||||
_ => pk.OriginalTrainerName switch
|
|
||||||
{
|
{
|
||||||
StadiumENG => true,
|
(int)Japanese => trainer.SequenceEqual(StadiumJPN),
|
||||||
StadiumFRE => true,
|
_ => trainer switch
|
||||||
StadiumITA => true,
|
{
|
||||||
StadiumSPA => true,
|
StadiumENG => true,
|
||||||
_ => false,
|
StadiumFRE => true,
|
||||||
},
|
StadiumITA => true,
|
||||||
},
|
StadiumSPA => true,
|
||||||
EuropeTour => IsTourOT(pk.OriginalTrainerName),
|
_ => false,
|
||||||
_ => true,
|
},
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsTrainerIDValid(PKM pk) => Trainer switch
|
private bool IsTrainerIDValid(PKM pk) => Trainer switch
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,7 +75,12 @@ public sealed record EncounterTrade1 : IEncounterable, IEncounterMatch, IFixedTr
|
||||||
return pk.OriginalTrainerTrash is [StringConverter1.TradeOTCode, StringConverter1.TerminatorCode, ..];
|
return pk.OriginalTrainerTrash is [StringConverter1.TradeOTCode, StringConverter1.TerminatorCode, ..];
|
||||||
var lang = pk.Language;
|
var lang = pk.Language;
|
||||||
var expect = StringConverter12Transporter.GetTradeNameGen1(lang);
|
var expect = StringConverter12Transporter.GetTradeNameGen1(lang);
|
||||||
return pk.OriginalTrainerName == expect;
|
|
||||||
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
return trainer.SequenceEqual(expect);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetNicknameIndex(ReadOnlySpan<char> nickname) => GetIndex(nickname, Nicknames);
|
private int GetNicknameIndex(ReadOnlySpan<char> nickname) => GetIndex(nickname, Nicknames);
|
||||||
|
|
|
@ -131,10 +131,19 @@ public sealed record EncounterTrade2 : IEncounterable, IEncounterMatch, IFixedTr
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsTrainerNicknameCorrect(PKM pk)
|
private bool IsTrainerNicknameCorrect(PKM pk)
|
||||||
{
|
{
|
||||||
// Italian and English share the same OT name for Spearow, but different nicknames. Others are like this, so we need to check both.
|
// Italian and English share the same OT name for Spearow, but different nicknames. Others are like this, so we need to check both.
|
||||||
var lang = DetectLanguage(pk, pk.OriginalTrainerName, pk.Nickname);
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
Span<char> nickname = stackalloc char[pk.TrashCharCountNickname];
|
||||||
|
len = pk.LoadString(pk.NicknameTrash, nickname);
|
||||||
|
nickname = nickname[..len];
|
||||||
|
|
||||||
|
var lang = DetectLanguage(pk, trainer, nickname);
|
||||||
return lang != -1;
|
return lang != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +253,9 @@ public sealed record EncounterTrade2 : IEncounterable, IEncounterMatch, IFixedTr
|
||||||
public bool IsNicknameMatch(PKM pk, ReadOnlySpan<char> nickname, int _)
|
public bool IsNicknameMatch(PKM pk, ReadOnlySpan<char> nickname, int _)
|
||||||
{
|
{
|
||||||
// Match both.
|
// Match both.
|
||||||
ReadOnlySpan<char> trainer = pk.OriginalTrainerName;
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
var lang = DetectLanguage(pk, trainer, nickname);
|
var lang = DetectLanguage(pk, trainer, nickname);
|
||||||
if (lang != -1)
|
if (lang != -1)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -243,15 +243,18 @@ public sealed record EncounterTrade4PID
|
||||||
return lang;
|
return lang;
|
||||||
|
|
||||||
// Since two locales (JPN/ENG) can have the same LanguageID, check which we should be validating with.
|
// Since two locales (JPN/ENG) can have the same LanguageID, check which we should be validating with.
|
||||||
ReadOnlySpan<char> ot = pk.OriginalTrainerName;
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
var len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
var expect = TrainerNames[1];
|
var expect = TrainerNames[1];
|
||||||
var match = ot.SequenceEqual(expect);
|
var match = trainer.SequenceEqual(expect);
|
||||||
if (!match)
|
if (!match)
|
||||||
return 2; // verify strings with English locale instead.
|
return 2; // verify strings with English locale instead.
|
||||||
return lang;
|
return lang;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int DetectTradeLanguageG4MeisterMagikarp(PKM pk,int currentLanguageID)
|
private int DetectTradeLanguageG4MeisterMagikarp(PKM pk, int currentLanguageID)
|
||||||
{
|
{
|
||||||
if (currentLanguageID == (int)LanguageID.English)
|
if (currentLanguageID == (int)LanguageID.English)
|
||||||
return (int)LanguageID.German;
|
return (int)LanguageID.German;
|
||||||
|
@ -259,7 +262,13 @@ public sealed record EncounterTrade4PID
|
||||||
// All have German, regardless of origin version.
|
// All have German, regardless of origin version.
|
||||||
var lang = DetectTradeLanguage(pk.OriginalTrainerName, currentLanguageID);
|
var lang = DetectTradeLanguage(pk.OriginalTrainerName, currentLanguageID);
|
||||||
if (lang == (int)LanguageID.English) // possible collision with FR/ES/DE. Check nickname
|
if (lang == (int)LanguageID.English) // possible collision with FR/ES/DE. Check nickname
|
||||||
return pk.Nickname == Nicknames[(int)LanguageID.French] ? (int)LanguageID.French : (int)LanguageID.Spanish; // Spanish is same as English
|
{
|
||||||
|
Span<char> nickname = stackalloc char[pk.TrashCharCountNickname];
|
||||||
|
var len = pk.LoadString(pk.NicknameTrash, nickname);
|
||||||
|
nickname = nickname[..len];
|
||||||
|
|
||||||
|
return nickname.SequenceEqual(Nicknames[(int)LanguageID.French]) ? (int)LanguageID.French : (int)LanguageID.Spanish; // Spanish is same as English
|
||||||
|
}
|
||||||
|
|
||||||
return lang;
|
return lang;
|
||||||
}
|
}
|
||||||
|
@ -271,8 +280,14 @@ public sealed record EncounterTrade4PID
|
||||||
|
|
||||||
// All have English, regardless of origin version.
|
// All have English, regardless of origin version.
|
||||||
var lang = DetectTradeLanguage(pk.OriginalTrainerName, currentLanguageID);
|
var lang = DetectTradeLanguage(pk.OriginalTrainerName, currentLanguageID);
|
||||||
if (lang == 2) // possible collision with ES/IT. Check nickname
|
if (lang == (int)LanguageID.English) // possible collision with ES/IT. Check nickname
|
||||||
return pk.Nickname == Nicknames[(int)LanguageID.Italian] ? (int)LanguageID.Italian : (int)LanguageID.Spanish;
|
{
|
||||||
|
Span<char> nickname = stackalloc char[pk.TrashCharCountNickname];
|
||||||
|
var len = pk.LoadString(pk.NicknameTrash, nickname);
|
||||||
|
nickname = nickname[..len];
|
||||||
|
|
||||||
|
return nickname.SequenceEqual(Nicknames[(int)LanguageID.Italian]) ? (int)LanguageID.Italian : (int)LanguageID.Spanish;
|
||||||
|
}
|
||||||
|
|
||||||
return lang;
|
return lang;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,12 @@ public static class MysteryGiftVerifier
|
||||||
return false; // no data
|
return false; // no data
|
||||||
if (!val.HasFlag(MysteryGiftRestriction.OTReplacedOnTrade))
|
if (!val.HasFlag(MysteryGiftRestriction.OTReplacedOnTrade))
|
||||||
return false;
|
return false;
|
||||||
return CurrentOTMatchesReplaced(g.Generation, pk.OriginalTrainerName);
|
|
||||||
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
return CurrentOTMatchesReplaced(g.Generation, trainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CanVersionReceiveGift(byte generation, int version4bit, GameVersion version)
|
private static bool CanVersionReceiveGift(byte generation, int version4bit, GameVersion version)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#define SUPPRESS
|
//#define SUPPRESS
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -16,12 +16,15 @@ public sealed class NicknameVerifier : Verifier
|
||||||
var pk = data.Entity;
|
var pk = data.Entity;
|
||||||
|
|
||||||
// If the Pokémon is not nicknamed, it should match one of the language strings.
|
// If the Pokémon is not nicknamed, it should match one of the language strings.
|
||||||
var nickname = pk.Nickname;
|
Span<char> nickname = stackalloc char[pk.TrashCharCountNickname];
|
||||||
if (nickname.Length == 0)
|
int len = pk.LoadString(pk.NicknameTrash, nickname);
|
||||||
|
if (len == 0)
|
||||||
{
|
{
|
||||||
data.AddLine(GetInvalid(LNickLengthShort));
|
data.AddLine(GetInvalid(LNickLengthShort));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
nickname = nickname[..len];
|
||||||
|
|
||||||
if (pk.Species > SpeciesName.MaxSpeciesID)
|
if (pk.Species > SpeciesName.MaxSpeciesID)
|
||||||
{
|
{
|
||||||
data.AddLine(Get(LNickLengthShort, Severity.Invalid));
|
data.AddLine(Get(LNickLengthShort, Severity.Invalid));
|
||||||
|
@ -65,7 +68,7 @@ public sealed class NicknameVerifier : Verifier
|
||||||
// Non-nicknamed strings have already been checked.
|
// Non-nicknamed strings have already been checked.
|
||||||
if (ParseSettings.Settings.WordFilter.IsEnabled(pk.Format) && pk.IsNicknamed)
|
if (ParseSettings.Settings.WordFilter.IsEnabled(pk.Format) && pk.IsNicknamed)
|
||||||
{
|
{
|
||||||
if (WordFilter.IsFiltered(nickname, out var badPattern))
|
if (WordFilter.IsFiltered(nickname.ToString(), out var badPattern))
|
||||||
data.AddLine(GetInvalid($"Word Filter: {badPattern}"));
|
data.AddLine(GetInvalid($"Word Filter: {badPattern}"));
|
||||||
if (TrainerNameVerifier.ContainsTooManyNumbers(nickname, data.Info.Generation))
|
if (TrainerNameVerifier.ContainsTooManyNumbers(nickname, data.Info.Generation))
|
||||||
data.AddLine(GetInvalid("Word Filter: Too many numbers."));
|
data.AddLine(GetInvalid("Word Filter: Too many numbers."));
|
||||||
|
@ -261,16 +264,40 @@ public sealed class NicknameVerifier : Verifier
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format == 5 && enc.Generation != 5) // transfer
|
if (format == 5 && enc.Generation != 5) // transfer
|
||||||
{
|
return IsMatch45(nickname, species, expect, language, canHaveAnyLanguage);
|
||||||
if (canHaveAnyLanguage)
|
|
||||||
return !SpeciesName.IsNicknamedAnyLanguage(species, nickname, 4);
|
|
||||||
expect = SpeciesName.GetSpeciesNameGeneration(species, language, 4);
|
|
||||||
return nickname.SequenceEqual(expect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsMatch45(ReadOnlySpan<char> nickname, ushort species, string expect, int language, bool canHaveAnyLanguage)
|
||||||
|
{
|
||||||
|
if (species is (int)Species.Farfetchd)
|
||||||
|
{
|
||||||
|
if (nickname.Length == expect.Length)
|
||||||
|
{
|
||||||
|
// Compare as upper -- different apostrophe than Gen4 encoding.
|
||||||
|
if (IsMatchUpper45(nickname, expect))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (SpeciesName.IsApostropheFarfetchdLanguage(language))
|
||||||
|
return false; // must have matched above
|
||||||
|
}
|
||||||
|
if (canHaveAnyLanguage)
|
||||||
|
return !SpeciesName.IsNicknamedAnyLanguage(species, nickname, 4);
|
||||||
|
expect = SpeciesName.GetSpeciesNameGeneration(species, language, 4);
|
||||||
|
return nickname.SequenceEqual(expect);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsMatchUpper45(ReadOnlySpan<char> nickname, string expect)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < expect.Length; i++)
|
||||||
|
{
|
||||||
|
if (nickname[i] != char.ToUpperInvariant(expect[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static void VerifyNicknameEgg(LegalityAnalysis data)
|
private static void VerifyNicknameEgg(LegalityAnalysis data)
|
||||||
{
|
{
|
||||||
var Info = data.Info;
|
var Info = data.Info;
|
||||||
|
@ -280,7 +307,7 @@ public sealed class NicknameVerifier : Verifier
|
||||||
if (pk.IsNicknamed != flagState)
|
if (pk.IsNicknamed != flagState)
|
||||||
data.AddLine(GetInvalid(flagState ? LNickFlagEggYes : LNickFlagEggNo, CheckIdentifier.Egg));
|
data.AddLine(GetInvalid(flagState ? LNickFlagEggYes : LNickFlagEggNo, CheckIdentifier.Egg));
|
||||||
|
|
||||||
Span<char> nickname = stackalloc char[pk.MaxStringLengthNickname];
|
Span<char> nickname = stackalloc char[pk.TrashCharCountNickname];
|
||||||
int len = pk.LoadString(pk.NicknameTrash, nickname);
|
int len = pk.LoadString(pk.NicknameTrash, nickname);
|
||||||
nickname = nickname[..len];
|
nickname = nickname[..len];
|
||||||
|
|
||||||
|
@ -351,7 +378,15 @@ public sealed class NicknameVerifier : Verifier
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lang = t.DetectMeisterMagikarpLanguage(pk.Nickname, pk.OriginalTrainerName, lang);
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
Span<char> nickname = stackalloc char[pk.TrashCharCountNickname];
|
||||||
|
len = pk.LoadString(pk.NicknameTrash, nickname);
|
||||||
|
nickname = nickname[..len];
|
||||||
|
|
||||||
|
lang = t.DetectMeisterMagikarpLanguage(nickname, trainer, lang);
|
||||||
if (lang == -1) // err
|
if (lang == -1) // err
|
||||||
data.AddLine(GetInvalid(string.Format(LOTLanguage, $"{Japanese}/{German}", $"{(LanguageID)pk.Language}"), CheckIdentifier.Language));
|
data.AddLine(GetInvalid(string.Format(LOTLanguage, $"{Japanese}/{German}", $"{(LanguageID)pk.Language}"), CheckIdentifier.Language));
|
||||||
}
|
}
|
||||||
|
@ -388,7 +423,12 @@ public sealed class NicknameVerifier : Verifier
|
||||||
if (pk.IsNicknamed && (pk.Format < 8 || pk.FatefulEncounter))
|
if (pk.IsNicknamed && (pk.Format < 8 || pk.FatefulEncounter))
|
||||||
return GetInvalid(LEncTradeChangedNickname, CheckIdentifier.Nickname);
|
return GetInvalid(LEncTradeChangedNickname, CheckIdentifier.Nickname);
|
||||||
int lang = pk.Language;
|
int lang = pk.Language;
|
||||||
if (!t.IsTrainerMatch(pk, pk.OriginalTrainerName, lang))
|
|
||||||
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
if (!t.IsTrainerMatch(pk, trainer, lang))
|
||||||
return GetInvalid(LEncTradeIndexBad, CheckIdentifier.Trainer);
|
return GetInvalid(LEncTradeIndexBad, CheckIdentifier.Trainer);
|
||||||
return GetValid(LEncTradeUnchanged, CheckIdentifier.Nickname);
|
return GetValid(LEncTradeUnchanged, CheckIdentifier.Nickname);
|
||||||
}
|
}
|
||||||
|
@ -413,7 +453,11 @@ public sealed class NicknameVerifier : Verifier
|
||||||
private static void VerifyTrainerName(LegalityAnalysis data, IFixedTrainer ft, int language)
|
private static void VerifyTrainerName(LegalityAnalysis data, IFixedTrainer ft, int language)
|
||||||
{
|
{
|
||||||
var pk = data.Entity;
|
var pk = data.Entity;
|
||||||
if (!ft.IsTrainerMatch(pk, pk.OriginalTrainerName, language))
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
if (!ft.IsTrainerMatch(pk, trainer, language))
|
||||||
data.AddLine(GetInvalid(LEncTradeChangedOT, CheckIdentifier.Trainer));
|
data.AddLine(GetInvalid(LEncTradeChangedOT, CheckIdentifier.Trainer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ using static PKHeX.Core.LegalityCheckStrings;
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifies the <see cref="PKM.OriginalTrainerName"/>.
|
/// Verifies the <see cref="PKM.ID32"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class TrainerIDVerifier : Verifier
|
public sealed class TrainerIDVerifier : Verifier
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,11 +23,16 @@ public sealed class TrainerNameVerifier : Verifier
|
||||||
if (!IsPlayerOriginalTrainer(enc))
|
if (!IsPlayerOriginalTrainer(enc))
|
||||||
return; // already verified
|
return; // already verified
|
||||||
|
|
||||||
var ot = pk.OriginalTrainerName;
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
if (ot.Length == 0)
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
data.AddLine(GetInvalid(LOTShort));
|
data.AddLine(GetInvalid(LOTShort));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
if (IsOTNameSuspicious(ot))
|
if (IsOTNameSuspicious(trainer))
|
||||||
{
|
{
|
||||||
data.AddLine(Get(LOTSuspicious, Severity.Fishy));
|
data.AddLine(Get(LOTSuspicious, Severity.Fishy));
|
||||||
}
|
}
|
||||||
|
@ -36,17 +41,17 @@ public sealed class TrainerNameVerifier : Verifier
|
||||||
{
|
{
|
||||||
VerifyOTGB(data);
|
VerifyOTGB(data);
|
||||||
}
|
}
|
||||||
else if (ot.Length > Legal.GetMaxLengthOT(data.Info.Generation, (LanguageID)pk.Language))
|
else if (trainer.Length > Legal.GetMaxLengthOT(data.Info.Generation, (LanguageID)pk.Language))
|
||||||
{
|
{
|
||||||
if (!IsEdgeCaseLength(pk, data.EncounterOriginal, ot))
|
if (!IsEdgeCaseLength(pk, data.EncounterOriginal, trainer))
|
||||||
data.AddLine(Get(LOTLong, Severity.Invalid));
|
data.AddLine(Get(LOTLong, Severity.Invalid));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ParseSettings.Settings.WordFilter.IsEnabled(pk.Format))
|
if (ParseSettings.Settings.WordFilter.IsEnabled(pk.Format))
|
||||||
{
|
{
|
||||||
if (WordFilter.IsFiltered(ot, out var badPattern))
|
if (WordFilter.IsFiltered(trainer.ToString(), out var badPattern))
|
||||||
data.AddLine(GetInvalid($"Word Filter: {badPattern}"));
|
data.AddLine(GetInvalid($"Word Filter: {badPattern}"));
|
||||||
if (ContainsTooManyNumbers(ot, data.Info.Generation))
|
if (ContainsTooManyNumbers(trainer, data.Info.Generation))
|
||||||
data.AddLine(GetInvalid("Word Filter: Too many numbers."));
|
data.AddLine(GetInvalid("Word Filter: Too many numbers."));
|
||||||
|
|
||||||
if (WordFilter.IsFiltered(pk.HandlingTrainerName, out badPattern))
|
if (WordFilter.IsFiltered(pk.HandlingTrainerName, out badPattern))
|
||||||
|
@ -101,8 +106,11 @@ public sealed class TrainerNameVerifier : Verifier
|
||||||
if (enc is IFixedTrainer { IsFixedTrainer: true })
|
if (enc is IFixedTrainer { IsFixedTrainer: true })
|
||||||
return; // already verified
|
return; // already verified
|
||||||
|
|
||||||
string tr = pk.OriginalTrainerName;
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
if (tr.Length == 0)
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
if (trainer.Length == 0)
|
||||||
{
|
{
|
||||||
if (pk is SK2 {TID16: 0, IsRental: true})
|
if (pk is SK2 {TID16: 0, IsRental: true})
|
||||||
{
|
{
|
||||||
|
@ -114,7 +122,7 @@ public sealed class TrainerNameVerifier : Verifier
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VerifyGBOTWithinBounds(data, tr);
|
VerifyGBOTWithinBounds(data, trainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VerifyGBOTWithinBounds(LegalityAnalysis data, ReadOnlySpan<char> str)
|
private void VerifyGBOTWithinBounds(LegalityAnalysis data, ReadOnlySpan<char> str)
|
||||||
|
|
|
@ -28,6 +28,8 @@ public sealed class CK3(byte[] Data) : G3PKM(Data), IShadowCapture
|
||||||
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x18, 22);
|
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x18, 22);
|
||||||
public override Span<byte> NicknameTrash => Data.AsSpan(0x2E, 22);
|
public override Span<byte> NicknameTrash => Data.AsSpan(0x2E, 22);
|
||||||
public Span<byte> NicknameCopy_Trash => Data.AsSpan(0x44, 22);
|
public Span<byte> NicknameCopy_Trash => Data.AsSpan(0x44, 22);
|
||||||
|
public override int TrashCharCountTrainer => 11;
|
||||||
|
public override int TrashCharCountNickname => 11;
|
||||||
|
|
||||||
// Future Attributes
|
// Future Attributes
|
||||||
public override ushort SpeciesInternal { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access
|
public override ushort SpeciesInternal { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access
|
||||||
|
|
|
@ -81,6 +81,8 @@ public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBat
|
||||||
public override Span<byte> NicknameTrash => Core.NicknameTrash;
|
public override Span<byte> NicknameTrash => Core.NicknameTrash;
|
||||||
public override Span<byte> OriginalTrainerTrash => Core.OriginalTrainerTrash;
|
public override Span<byte> OriginalTrainerTrash => Core.OriginalTrainerTrash;
|
||||||
public override Span<byte> HandlingTrainerTrash => Core.HandlingTrainerTrash;
|
public override Span<byte> HandlingTrainerTrash => Core.HandlingTrainerTrash;
|
||||||
|
public override int TrashCharCountTrainer => 13;
|
||||||
|
public override int TrashCharCountNickname => 13;
|
||||||
public override bool IsUntraded => ReadUInt16LittleEndian(HandlingTrainerTrash) == 0; // immediately terminated HandlingTrainerName data (\0)
|
public override bool IsUntraded => ReadUInt16LittleEndian(HandlingTrainerTrash) == 0; // immediately terminated HandlingTrainerName data (\0)
|
||||||
|
|
||||||
#region Core
|
#region Core
|
||||||
|
@ -233,7 +235,7 @@ public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBat
|
||||||
|
|
||||||
public override int MaxIV => 31;
|
public override int MaxIV => 31;
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
public override ushort MaxMoveID => Legal.MaxMoveID_8a;
|
public override ushort MaxMoveID => Legal.MaxMoveID_8a;
|
||||||
public override ushort MaxSpeciesID => Legal.MaxSpeciesID_8a;
|
public override ushort MaxSpeciesID => Legal.MaxSpeciesID_8a;
|
||||||
|
|
|
@ -53,7 +53,7 @@ public interface IGameValueLimit
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum length of a string field for a Trainer Name.
|
/// Maximum length of a string field for a Trainer Name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int MaxStringLengthOT { get; }
|
int MaxStringLengthTrainer { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum length of a string field for a Pokémon Nickname.
|
/// Maximum length of a string field for a Pokémon Nickname.
|
||||||
|
|
|
@ -65,11 +65,13 @@ public sealed class PA8 : PKM, ISanityChecksum,
|
||||||
public override Span<byte> NicknameTrash => Data.AsSpan(0x60, 26);
|
public override Span<byte> NicknameTrash => Data.AsSpan(0x60, 26);
|
||||||
public override Span<byte> HandlingTrainerTrash => Data.AsSpan(0xB8, 26);
|
public override Span<byte> HandlingTrainerTrash => Data.AsSpan(0xB8, 26);
|
||||||
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x110, 26);
|
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x110, 26);
|
||||||
|
public override int TrashCharCountTrainer => 13;
|
||||||
|
public override int TrashCharCountNickname => 13;
|
||||||
|
|
||||||
// Maximums
|
// Maximums
|
||||||
public override int MaxIV => 31;
|
public override int MaxIV => 31;
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
|
|
||||||
public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4;
|
public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4;
|
||||||
|
|
|
@ -252,7 +252,7 @@ public sealed class PK1 : GBPKML, IPersonalType
|
||||||
=> StringConverter1.GetString(data, Japanese);
|
=> StringConverter1.GetString(data, Japanese);
|
||||||
public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
public override int LoadString(ReadOnlySpan<byte> data, Span<char> destBuffer)
|
||||||
=> StringConverter1.LoadString(data, destBuffer, Japanese);
|
=> StringConverter1.LoadString(data, destBuffer, Japanese);
|
||||||
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option = StringConverterOption.None)
|
public override int SetString(Span<byte> destBuffer, ReadOnlySpan<char> value, int maxLength, StringConverterOption option)
|
||||||
=> StringConverter1.SetString(destBuffer, value, maxLength, Japanese, option);
|
=> StringConverter1.SetString(destBuffer, value, maxLength, Japanese, option);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -38,6 +38,8 @@ public sealed class PK3 : G3PKM, ISanityChecksum
|
||||||
// Trash Bytes
|
// Trash Bytes
|
||||||
public override Span<byte> NicknameTrash => Data.AsSpan(0x08, 10); // no inaccessible terminator
|
public override Span<byte> NicknameTrash => Data.AsSpan(0x08, 10); // no inaccessible terminator
|
||||||
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x14, 7); // no inaccessible terminator
|
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x14, 7); // no inaccessible terminator
|
||||||
|
public override int TrashCharCountTrainer => 7;
|
||||||
|
public override int TrashCharCountNickname => 10;
|
||||||
|
|
||||||
// At top for System.Reflection execution order hack
|
// At top for System.Reflection execution order hack
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ public sealed class PK5 : PKM, ISanityChecksum,
|
||||||
// Trash Bytes
|
// Trash Bytes
|
||||||
public override Span<byte> NicknameTrash => Data.AsSpan(0x48, 22);
|
public override Span<byte> NicknameTrash => Data.AsSpan(0x48, 22);
|
||||||
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x68, 16);
|
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x68, 16);
|
||||||
|
public override int TrashCharCountNickname => 11;
|
||||||
|
public override int TrashCharCountTrainer => 8;
|
||||||
|
|
||||||
// Future Attributes
|
// Future Attributes
|
||||||
public override uint EncryptionConstant { get => PID; set { } }
|
public override uint EncryptionConstant { get => PID; set { } }
|
||||||
|
@ -297,7 +299,7 @@ public sealed class PK5 : PKM, ISanityChecksum,
|
||||||
public override GameVersion MaxGameID => Legal.MaxGameID_5; // B2
|
public override GameVersion MaxGameID => Legal.MaxGameID_5; // B2
|
||||||
public override int MaxIV => 31;
|
public override int MaxIV => 31;
|
||||||
public override int MaxEV => EffortValues.Max255;
|
public override int MaxEV => EffortValues.Max255;
|
||||||
public override int MaxStringLengthOT => 7;
|
public override int MaxStringLengthTrainer => 7;
|
||||||
public override int MaxStringLengthNickname => 10;
|
public override int MaxStringLengthNickname => 10;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
|
|
@ -65,11 +65,13 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, ITechRecord, IObedien
|
||||||
public override Span<byte> NicknameTrash => Data.AsSpan(0x58, 26);
|
public override Span<byte> NicknameTrash => Data.AsSpan(0x58, 26);
|
||||||
public override Span<byte> HandlingTrainerTrash => Data.AsSpan(0xA8, 26);
|
public override Span<byte> HandlingTrainerTrash => Data.AsSpan(0xA8, 26);
|
||||||
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0xF8, 26);
|
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0xF8, 26);
|
||||||
|
public override int TrashCharCountTrainer => 13;
|
||||||
|
public override int TrashCharCountNickname => 13;
|
||||||
|
|
||||||
// Maximums
|
// Maximums
|
||||||
public override int MaxIV => 31;
|
public override int MaxIV => 31;
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
|
|
||||||
public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4;
|
public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4;
|
||||||
|
|
|
@ -252,8 +252,15 @@ public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILa
|
||||||
public virtual GameVersion MinGameID => 0;
|
public virtual GameVersion MinGameID => 0;
|
||||||
public abstract int MaxIV { get; }
|
public abstract int MaxIV { get; }
|
||||||
public abstract int MaxEV { get; }
|
public abstract int MaxEV { get; }
|
||||||
public abstract int MaxStringLengthOT { get; }
|
|
||||||
|
/// <summary> Maximum length a Trainer Name can be represented as. </summary>
|
||||||
|
public abstract int MaxStringLengthTrainer { get; }
|
||||||
|
/// <summary> Maximum length a Nickname can be represented as. </summary>
|
||||||
public abstract int MaxStringLengthNickname { get; }
|
public abstract int MaxStringLengthNickname { get; }
|
||||||
|
/// <summary> Total characters allocated for holding a Trainer Name. </summary>
|
||||||
|
public abstract int TrashCharCountTrainer { get; }
|
||||||
|
/// <summary> Total characters allocated for holding a Nickname. </summary>
|
||||||
|
public abstract int TrashCharCountNickname { get; }
|
||||||
|
|
||||||
// Derived
|
// Derived
|
||||||
public virtual int SpriteItem => HeldItem;
|
public virtual int SpriteItem => HeldItem;
|
||||||
|
|
|
@ -18,7 +18,7 @@ public sealed class SK2 : GBPKM, ICaughtData2
|
||||||
private const int StringLength = 12;
|
private const int StringLength = 12;
|
||||||
|
|
||||||
public override EntityContext Context => EntityContext.Gen2;
|
public override EntityContext Context => EntityContext.Gen2;
|
||||||
public override int MaxStringLengthOT => StringLength;
|
public override int MaxStringLengthTrainer => StringLength;
|
||||||
public override int MaxStringLengthNickname => StringLength;
|
public override int MaxStringLengthNickname => StringLength;
|
||||||
|
|
||||||
public SK2(bool jp = false) : base(PokeCrypto.SIZE_2STADIUM) => IsEncodingJapanese = jp;
|
public SK2(bool jp = false) : base(PokeCrypto.SIZE_2STADIUM) => IsEncodingJapanese = jp;
|
||||||
|
@ -114,6 +114,8 @@ public sealed class SK2 : GBPKM, ICaughtData2
|
||||||
|
|
||||||
public override Span<byte> NicknameTrash => Data.AsSpan(0x24, StringLength);
|
public override Span<byte> NicknameTrash => Data.AsSpan(0x24, StringLength);
|
||||||
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x30, StringLength);
|
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x30, StringLength);
|
||||||
|
public override int TrashCharCountTrainer => StringLength;
|
||||||
|
public override int TrashCharCountNickname => StringLength;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS
|
||||||
public sealed override GameVersion MaxGameID => Legal.MaxGameID_3;
|
public sealed override GameVersion MaxGameID => Legal.MaxGameID_3;
|
||||||
public sealed override int MaxIV => 31;
|
public sealed override int MaxIV => 31;
|
||||||
public sealed override int MaxEV => EffortValues.Max255;
|
public sealed override int MaxEV => EffortValues.Max255;
|
||||||
public sealed override int MaxStringLengthOT => 7;
|
public sealed override int MaxStringLengthTrainer => 7;
|
||||||
public sealed override int MaxStringLengthNickname => 10;
|
public sealed override int MaxStringLengthNickname => 10;
|
||||||
|
|
||||||
// Generated Attributes
|
// Generated Attributes
|
||||||
|
|
|
@ -21,7 +21,7 @@ public abstract class G4PKM : PKM, IHandlerUpdate,
|
||||||
public sealed override GameVersion MaxGameID => Legal.MaxGameID_4;
|
public sealed override GameVersion MaxGameID => Legal.MaxGameID_4;
|
||||||
public sealed override int MaxIV => 31;
|
public sealed override int MaxIV => 31;
|
||||||
public sealed override int MaxEV => EffortValues.Max255;
|
public sealed override int MaxEV => EffortValues.Max255;
|
||||||
public sealed override int MaxStringLengthOT => 7;
|
public sealed override int MaxStringLengthTrainer => 7;
|
||||||
public sealed override int MaxStringLengthNickname => 10;
|
public sealed override int MaxStringLengthNickname => 10;
|
||||||
|
|
||||||
public sealed override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 3;
|
public sealed override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 3;
|
||||||
|
@ -41,6 +41,8 @@ public abstract class G4PKM : PKM, IHandlerUpdate,
|
||||||
// Trash Bytes
|
// Trash Bytes
|
||||||
public sealed override Span<byte> NicknameTrash => Data.AsSpan(0x48, 22);
|
public sealed override Span<byte> NicknameTrash => Data.AsSpan(0x48, 22);
|
||||||
public sealed override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x68, 16);
|
public sealed override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x68, 16);
|
||||||
|
public override int TrashCharCountNickname => 11;
|
||||||
|
public override int TrashCharCountTrainer => 8;
|
||||||
|
|
||||||
// Future Attributes
|
// Future Attributes
|
||||||
public sealed override uint EncryptionConstant { get => PID; set { } }
|
public sealed override uint EncryptionConstant { get => PID; set { } }
|
||||||
|
|
|
@ -15,6 +15,8 @@ public abstract class G6PKM : PKM, ISanityChecksum, IHandlerUpdate
|
||||||
public sealed override Span<byte> NicknameTrash => Data.AsSpan(0x40, 26);
|
public sealed override Span<byte> NicknameTrash => Data.AsSpan(0x40, 26);
|
||||||
public sealed override Span<byte> HandlingTrainerTrash => Data.AsSpan(0x78, 26);
|
public sealed override Span<byte> HandlingTrainerTrash => Data.AsSpan(0x78, 26);
|
||||||
public sealed override Span<byte> OriginalTrainerTrash => Data.AsSpan(0xB0, 26);
|
public sealed override Span<byte> OriginalTrainerTrash => Data.AsSpan(0xB0, 26);
|
||||||
|
public override int TrashCharCountTrainer => 13;
|
||||||
|
public override int TrashCharCountNickname => 13;
|
||||||
|
|
||||||
public abstract ushort Sanity { get; set; }
|
public abstract ushort Sanity { get; set; }
|
||||||
public abstract ushort Checksum { get; set; }
|
public abstract ushort Checksum { get; set; }
|
||||||
|
@ -122,7 +124,7 @@ public abstract class G6PKM : PKM, ISanityChecksum, IHandlerUpdate
|
||||||
// Maximums
|
// Maximums
|
||||||
public sealed override int MaxIV => 31;
|
public sealed override int MaxIV => 31;
|
||||||
public sealed override int MaxEV => EffortValues.Max252;
|
public sealed override int MaxEV => EffortValues.Max252;
|
||||||
public sealed override int MaxStringLengthOT => 12;
|
public sealed override int MaxStringLengthTrainer => 12;
|
||||||
public sealed override int MaxStringLengthNickname => 12;
|
public sealed override int MaxStringLengthNickname => 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,13 @@ public abstract class G8PKM : PKM, ISanityChecksum,
|
||||||
public override Span<byte> NicknameTrash => Data.AsSpan(0x58, 26);
|
public override Span<byte> NicknameTrash => Data.AsSpan(0x58, 26);
|
||||||
public override Span<byte> HandlingTrainerTrash => Data.AsSpan(0xA8, 26);
|
public override Span<byte> HandlingTrainerTrash => Data.AsSpan(0xA8, 26);
|
||||||
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0xF8, 26);
|
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0xF8, 26);
|
||||||
|
public override int TrashCharCountTrainer => 13;
|
||||||
|
public override int TrashCharCountNickname => 13;
|
||||||
|
|
||||||
// Maximums
|
// Maximums
|
||||||
public override int MaxIV => 31;
|
public override int MaxIV => 31;
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
|
|
||||||
public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4;
|
public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4;
|
||||||
|
|
|
@ -77,9 +77,9 @@ public abstract class GBPKM : PKM
|
||||||
if (StringConverter1.IsG12German(OriginalTrainerTrash))
|
if (StringConverter1.IsG12German(OriginalTrainerTrash))
|
||||||
return (int)LanguageID.German; // german
|
return (int)LanguageID.German; // german
|
||||||
|
|
||||||
Span<char> nick = stackalloc char[11];
|
Span<char> nickname = stackalloc char[TrashCharCountNickname];
|
||||||
int len = StringConverter1.LoadString(NicknameTrash, nick, false);
|
int len = StringConverter1.LoadString(NicknameTrash, nickname, false);
|
||||||
int lang = SpeciesName.GetSpeciesNameLanguage(Species, nick[..len], Format);
|
int lang = SpeciesName.GetSpeciesNameLanguage(Species, nickname[..len], Format);
|
||||||
if (lang > 0)
|
if (lang > 0)
|
||||||
return lang;
|
return lang;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -255,8 +255,14 @@ public abstract class GBPKM : PKM
|
||||||
|
|
||||||
internal void ImportFromFuture(PKM pk)
|
internal void ImportFromFuture(PKM pk)
|
||||||
{
|
{
|
||||||
Nickname = pk.Nickname;
|
Span<char> nickname = stackalloc char[pk.TrashCharCountNickname];
|
||||||
OriginalTrainerName = pk.OriginalTrainerName;
|
pk.LoadString(pk.NicknameTrash, nickname);
|
||||||
|
SetString(NicknameTrash, nickname, MaxStringLengthNickname, StringConverterOption.Clear50);
|
||||||
|
|
||||||
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
SetString(OriginalTrainerTrash, nickname, MaxStringLengthTrainer, StringConverterOption.Clear50);
|
||||||
|
|
||||||
IV_ATK = pk.IV_ATK / 2;
|
IV_ATK = pk.IV_ATK / 2;
|
||||||
IV_DEF = pk.IV_DEF / 2;
|
IV_DEF = pk.IV_DEF / 2;
|
||||||
IV_SPC = pk.IV_SPA / 2;
|
IV_SPC = pk.IV_SPA / 2;
|
||||||
|
|
|
@ -11,7 +11,7 @@ public abstract class GBPKML : GBPKM
|
||||||
{
|
{
|
||||||
internal const int StringLengthJapanese = 6;
|
internal const int StringLengthJapanese = 6;
|
||||||
internal const int StringLengthNotJapan = 11;
|
internal const int StringLengthNotJapan = 11;
|
||||||
public sealed override int MaxStringLengthOT => Japanese ? 5 : 7;
|
public sealed override int MaxStringLengthTrainer => Japanese ? 5 : 7;
|
||||||
public sealed override int MaxStringLengthNickname => Japanese ? 5 : 10;
|
public sealed override int MaxStringLengthNickname => Japanese ? 5 : 10;
|
||||||
public sealed override bool Japanese => RawOT.Length == StringLengthJapanese;
|
public sealed override bool Japanese => RawOT.Length == StringLengthJapanese;
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ public abstract class GBPKML : GBPKM
|
||||||
// Trash Bytes
|
// Trash Bytes
|
||||||
public sealed override Span<byte> NicknameTrash => RawNickname;
|
public sealed override Span<byte> NicknameTrash => RawNickname;
|
||||||
public sealed override Span<byte> OriginalTrainerTrash => RawOT;
|
public sealed override Span<byte> OriginalTrainerTrash => RawOT;
|
||||||
|
public override int TrashCharCountTrainer => RawOT.Length;
|
||||||
|
public override int TrashCharCountNickname => RawNickname.Length;
|
||||||
|
|
||||||
protected GBPKML([ConstantExpected] int size, bool jp = false) : base(size)
|
protected GBPKML([ConstantExpected] int size, bool jp = false) : base(size)
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,9 +98,10 @@ public static class StringConverter345
|
||||||
{
|
{
|
||||||
for (int i = 0; i < input.Length; i++)
|
for (int i = 0; i < input.Length; i++)
|
||||||
{
|
{
|
||||||
if (IsInvalid45(input[i]))
|
var c = input[i];
|
||||||
|
if (IsInvalid45(c))
|
||||||
input[i] = '?';
|
input[i] = '?';
|
||||||
if (input[i] == '’') // Farfetch’d and CH’DING nicknames
|
else if (c == '’') // Farfetch’d and CH’DING nicknames
|
||||||
input[i] = '\''; // Wrong apostrophe, nice. Only is corrected when converted to Gen6.
|
input[i] = '\''; // Wrong apostrophe, nice. Only is corrected when converted to Gen6.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,8 +255,11 @@ public static class EntityConverter
|
||||||
if (pk.Nickname.Length > limit.MaxStringLengthNickname)
|
if (pk.Nickname.Length > limit.MaxStringLengthNickname)
|
||||||
pk.Nickname = pk.Nickname[..pk.MaxStringLengthNickname];
|
pk.Nickname = pk.Nickname[..pk.MaxStringLengthNickname];
|
||||||
|
|
||||||
if (pk.OriginalTrainerName.Length > limit.MaxStringLengthOT)
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
pk.OriginalTrainerName = pk.OriginalTrainerName[..pk.MaxStringLengthOT];
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
var max = limit.MaxStringLengthTrainer;
|
||||||
|
if (len > max)
|
||||||
|
pk.SetString(pk.OriginalTrainerTrash, trainer[..max], max, StringConverterOption.None);
|
||||||
|
|
||||||
if (pk.Move1 > limit.MaxMoveID || pk.Move2 > limit.MaxMoveID || pk.Move3 > limit.MaxMoveID || pk.Move4 > limit.MaxMoveID)
|
if (pk.Move1 > limit.MaxMoveID || pk.Move2 > limit.MaxMoveID || pk.Move3 > limit.MaxMoveID || pk.Move4 > limit.MaxMoveID)
|
||||||
pk.ClearInvalidMoves();
|
pk.ClearInvalidMoves();
|
||||||
|
|
|
@ -224,21 +224,26 @@ public static class EntitySorting
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets if the current handler is the original trainer.
|
/// Gets if the current handler is the original trainer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="trainer">The <see cref="ITrainerInfo"/> requesting the check.</param>
|
/// <param name="tr">The <see cref="ITrainerInfo"/> requesting the check.</param>
|
||||||
/// <param name="pk">Pokémon data</param>
|
/// <param name="pk">Pokémon data</param>
|
||||||
/// <param name="checkGame">Toggle to check the game's version or not</param>
|
/// <param name="checkGame">Toggle to check the game's version or not</param>
|
||||||
/// <returns>True if OT, false if not OT.</returns>
|
/// <returns>True if OT, false if not OT.</returns>
|
||||||
public static bool IsOriginalHandler(this ITrainerInfo trainer, PKM pk, bool checkGame)
|
public static bool IsOriginalHandler(this ITrainerInfo tr, PKM pk, bool checkGame)
|
||||||
{
|
{
|
||||||
if (pk.Format >= 6)
|
if (pk.Format >= 6)
|
||||||
return pk.CurrentHandler != 1;
|
return pk.CurrentHandler != 1;
|
||||||
if (checkGame && trainer.Version != pk.Version)
|
if (checkGame && tr.Version != pk.Version)
|
||||||
return false;
|
return false;
|
||||||
if (trainer.TID16 != pk.TID16 || trainer.SID16 != pk.SID16)
|
if (tr.TID16 != pk.TID16 || tr.SID16 != pk.SID16)
|
||||||
return false;
|
return false;
|
||||||
if (trainer.Gender != pk.OriginalTrainerGender)
|
if (tr.Gender != pk.OriginalTrainerGender)
|
||||||
return false;
|
return false;
|
||||||
return trainer.OT == pk.OriginalTrainerName;
|
|
||||||
|
Span<char> trainer = stackalloc char[pk.TrashCharCountTrainer];
|
||||||
|
int len = pk.LoadString(pk.OriginalTrainerTrash, trainer);
|
||||||
|
trainer = trainer[..len];
|
||||||
|
|
||||||
|
return trainer.SequenceEqual(tr.OT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -97,7 +97,7 @@ public static class SpeciesName
|
||||||
return arr[species];
|
return arr[species];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsApostropheFarfetchdLanguage(int language) => language is 2 or 4 or 7;
|
public static bool IsApostropheFarfetchdLanguage(int language) => language is 2 or 4 or 7;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Pokémon's default name for the desired language ID and generation.
|
/// Gets a Pokémon's default name for the desired language ID and generation.
|
||||||
|
|
|
@ -28,6 +28,8 @@ public sealed class XK3 : G3PKM, IShadowCapture
|
||||||
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x38, 22);
|
public override Span<byte> OriginalTrainerTrash => Data.AsSpan(0x38, 22);
|
||||||
public override Span<byte> NicknameTrash => Data.AsSpan(0x4E, 22);
|
public override Span<byte> NicknameTrash => Data.AsSpan(0x4E, 22);
|
||||||
public Span<byte> NicknameCopy_Trash => Data.AsSpan(0x64, 22);
|
public Span<byte> NicknameCopy_Trash => Data.AsSpan(0x64, 22);
|
||||||
|
public override int TrashCharCountTrainer => 11;
|
||||||
|
public override int TrashCharCountNickname => 11;
|
||||||
|
|
||||||
public override ushort SpeciesInternal { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access
|
public override ushort SpeciesInternal { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access
|
||||||
public override ushort Species { get => SpeciesConverter.GetNational3(SpeciesInternal); set => SpeciesInternal = SpeciesConverter.GetInternal3(value); }
|
public override ushort Species { get => SpeciesConverter.GetNational3(SpeciesInternal); set => SpeciesInternal = SpeciesConverter.GetInternal3(value); }
|
||||||
|
|
|
@ -205,7 +205,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo
|
||||||
public override int MaxIV => 15;
|
public override int MaxIV => 15;
|
||||||
public override byte Generation => 1;
|
public override byte Generation => 1;
|
||||||
public override EntityContext Context => EntityContext.Gen1;
|
public override EntityContext Context => EntityContext.Gen1;
|
||||||
public override int MaxStringLengthOT => Japanese ? 5 : 7;
|
public override int MaxStringLengthTrainer => Japanese ? 5 : 7;
|
||||||
public override int MaxStringLengthNickname => Japanese ? 5 : 10;
|
public override int MaxStringLengthNickname => Japanese ? 5 : 10;
|
||||||
public override int BoxSlotCount => Japanese ? 30 : 20;
|
public override int BoxSlotCount => Japanese ? 30 : 20;
|
||||||
|
|
||||||
|
@ -233,8 +233,8 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo
|
||||||
|
|
||||||
public override string OT
|
public override string OT
|
||||||
{
|
{
|
||||||
get => GetString(Data.AsSpan(Offsets.OT, MaxStringLengthOT));
|
get => GetString(Data.AsSpan(Offsets.OT, MaxStringLengthTrainer));
|
||||||
set => SetString(Data.AsSpan(Offsets.OT, MaxStringLengthOT + 1), value, MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SetString(Data.AsSpan(Offsets.OT, MaxStringLengthTrainer + 1), value, MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<byte> OriginalTrainerTrash { get => Data.AsSpan(Offsets.OT, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.OT)); } }
|
public Span<byte> OriginalTrainerTrash { get => Data.AsSpan(Offsets.OT, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.OT)); } }
|
||||||
|
@ -261,8 +261,8 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo
|
||||||
|
|
||||||
public string Rival
|
public string Rival
|
||||||
{
|
{
|
||||||
get => GetString(Data.AsSpan(Offsets.Rival, MaxStringLengthOT));
|
get => GetString(Data.AsSpan(Offsets.Rival, MaxStringLengthTrainer));
|
||||||
set => SetString(Data.AsSpan(Offsets.Rival, MaxStringLengthOT), value, MaxStringLengthOT, StringConverterOption.Clear50);
|
set => SetString(Data.AsSpan(Offsets.Rival, MaxStringLengthTrainer), value, MaxStringLengthTrainer, StringConverterOption.Clear50);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<byte> Rival_Trash { get => Data.AsSpan(Offsets.Rival, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.Rival)); } }
|
public Span<byte> Rival_Trash { get => Data.AsSpan(Offsets.Rival, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.Rival)); } }
|
||||||
|
|
|
@ -24,7 +24,7 @@ public sealed class SAV1Stadium : SAV_STADIUM
|
||||||
private int StringLength => Japanese ? StringLengthJ : StringLengthU;
|
private int StringLength => Japanese ? StringLengthJ : StringLengthU;
|
||||||
private const int StringLengthJ = 6;
|
private const int StringLengthJ = 6;
|
||||||
private const int StringLengthU = 11;
|
private const int StringLengthU = 11;
|
||||||
public override int MaxStringLengthOT => StringLength;
|
public override int MaxStringLengthTrainer => StringLength;
|
||||||
public override int MaxStringLengthNickname => StringLength;
|
public override int MaxStringLengthNickname => StringLength;
|
||||||
public override int BoxCount => Japanese ? 8 : 12;
|
public override int BoxCount => Japanese ? 8 : 12;
|
||||||
public override int BoxSlotCount => Japanese ? 30 : 20;
|
public override int BoxSlotCount => Japanese ? 30 : 20;
|
||||||
|
|
|
@ -22,7 +22,7 @@ public sealed class SAV1StadiumJ : SAV_STADIUM
|
||||||
public override byte Generation => 1;
|
public override byte Generation => 1;
|
||||||
public override EntityContext Context => EntityContext.Gen1;
|
public override EntityContext Context => EntityContext.Gen1;
|
||||||
private const int StringLength = 6; // Japanese Only
|
private const int StringLength = 6; // Japanese Only
|
||||||
public override int MaxStringLengthOT => StringLength;
|
public override int MaxStringLengthTrainer => StringLength;
|
||||||
public override int MaxStringLengthNickname => StringLength;
|
public override int MaxStringLengthNickname => StringLength;
|
||||||
public override int BoxCount => 4; // 8 boxes stored sequentially; latter 4 are backups
|
public override int BoxCount => 4; // 8 boxes stored sequentially; latter 4 are backups
|
||||||
public override int BoxSlotCount => 30;
|
public override int BoxSlotCount => 30;
|
||||||
|
|
|
@ -258,7 +258,7 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo
|
||||||
public override int MaxIV => 15;
|
public override int MaxIV => 15;
|
||||||
public override byte Generation => 2;
|
public override byte Generation => 2;
|
||||||
public override EntityContext Context => EntityContext.Gen2;
|
public override EntityContext Context => EntityContext.Gen2;
|
||||||
public override int MaxStringLengthOT => Japanese || Korean ? 5 : 7;
|
public override int MaxStringLengthTrainer => Japanese || Korean ? 5 : 7;
|
||||||
public override int MaxStringLengthNickname => Japanese || Korean ? 5 : 10;
|
public override int MaxStringLengthNickname => Japanese || Korean ? 5 : 10;
|
||||||
public override int BoxSlotCount => Japanese ? 30 : 20;
|
public override int BoxSlotCount => Japanese ? 30 : 20;
|
||||||
|
|
||||||
|
@ -303,8 +303,8 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo
|
||||||
|
|
||||||
public override string OT
|
public override string OT
|
||||||
{
|
{
|
||||||
get => GetString(Data.AsSpan(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * MaxStringLengthOT));
|
get => GetString(Data.AsSpan(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * MaxStringLengthTrainer));
|
||||||
set => SetString(Data.AsSpan(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * MaxStringLengthOT), value, 8, StringConverterOption.Clear50);
|
set => SetString(Data.AsSpan(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * MaxStringLengthTrainer), value, 8, StringConverterOption.Clear50);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<byte> OriginalTrainerTrash
|
public Span<byte> OriginalTrainerTrash
|
||||||
|
@ -315,8 +315,8 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo
|
||||||
|
|
||||||
public string Rival
|
public string Rival
|
||||||
{
|
{
|
||||||
get => GetString(Data.AsSpan(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthOT));
|
get => GetString(Data.AsSpan(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthTrainer));
|
||||||
set => SetString(Data.AsSpan(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthOT), value, 8, StringConverterOption.Clear50);
|
set => SetString(Data.AsSpan(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthTrainer), value, 8, StringConverterOption.Clear50);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<byte> Rival_Trash
|
public Span<byte> Rival_Trash
|
||||||
|
|
|
@ -21,7 +21,7 @@ public sealed class SAV2Stadium : SAV_STADIUM, IBoxDetailName
|
||||||
public override byte Generation => 2;
|
public override byte Generation => 2;
|
||||||
public override EntityContext Context => EntityContext.Gen2;
|
public override EntityContext Context => EntityContext.Gen2;
|
||||||
private const int StringLength = 12;
|
private const int StringLength = 12;
|
||||||
public override int MaxStringLengthOT => StringLength;
|
public override int MaxStringLengthTrainer => StringLength;
|
||||||
public override int MaxStringLengthNickname => StringLength;
|
public override int MaxStringLengthNickname => StringLength;
|
||||||
public override int BoxCount => Japanese ? 9 : 14;
|
public override int BoxCount => Japanese ? 9 : 14;
|
||||||
public override int BoxSlotCount => Japanese ? 30 : 20;
|
public override int BoxSlotCount => Japanese ? 30 : 20;
|
||||||
|
|
|
@ -191,7 +191,7 @@ public abstract class SAV3 : SaveFile, ILangDeviantSave, IEventFlag37, IBoxDetai
|
||||||
public sealed override int MaxEV => EffortValues.Max255;
|
public sealed override int MaxEV => EffortValues.Max255;
|
||||||
public sealed override byte Generation => 3;
|
public sealed override byte Generation => 3;
|
||||||
public sealed override EntityContext Context => EntityContext.Gen3;
|
public sealed override EntityContext Context => EntityContext.Gen3;
|
||||||
public sealed override int MaxStringLengthOT => 7;
|
public sealed override int MaxStringLengthTrainer => 7;
|
||||||
public sealed override int MaxStringLengthNickname => 10;
|
public sealed override int MaxStringLengthNickname => 10;
|
||||||
public sealed override int MaxMoney => 999999;
|
public sealed override int MaxMoney => 999999;
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ public abstract class SAV3 : SaveFile, ILangDeviantSave, IEventFlag37, IBoxDetai
|
||||||
get => GetString(OriginalTrainerTrash);
|
get => GetString(OriginalTrainerTrash);
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
int len = Japanese ? 5 : MaxStringLengthOT;
|
int len = Japanese ? 5 : MaxStringLengthTrainer;
|
||||||
SetString(OriginalTrainerTrash[..len], value, len, StringConverterOption.ClearFF); // match the game-init FF terminating pattern
|
SetString(OriginalTrainerTrash[..len], value, len, StringConverterOption.ClearFF); // match the game-init FF terminating pattern
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile, IBoxDetailName, IDayc
|
||||||
public override int MaxEV => EffortValues.Max255;
|
public override int MaxEV => EffortValues.Max255;
|
||||||
public override byte Generation => 3;
|
public override byte Generation => 3;
|
||||||
public override EntityContext Context => EntityContext.Gen3;
|
public override EntityContext Context => EntityContext.Gen3;
|
||||||
public override int MaxStringLengthOT => 10; // as evident by Mattle Ho-Oh
|
public override int MaxStringLengthTrainer => 10; // as evident by Mattle Ho-Oh
|
||||||
public override int MaxStringLengthNickname => 10;
|
public override int MaxStringLengthNickname => 10;
|
||||||
public override int MaxMoney => 9999999;
|
public override int MaxMoney => 9999999;
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ public sealed class SAV3RSBox : SaveFile, IGCSaveFile, IBoxDetailName, IBoxDetai
|
||||||
public override int MaxEV => EffortValues.Max255;
|
public override int MaxEV => EffortValues.Max255;
|
||||||
public override byte Generation => 3;
|
public override byte Generation => 3;
|
||||||
public override EntityContext Context => EntityContext.Gen3;
|
public override EntityContext Context => EntityContext.Gen3;
|
||||||
public override int MaxStringLengthOT => 7;
|
public override int MaxStringLengthTrainer => 7;
|
||||||
public override int MaxStringLengthNickname => 10;
|
public override int MaxStringLengthNickname => 10;
|
||||||
public override int MaxMoney => 999999;
|
public override int MaxMoney => 999999;
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile, IBoxDetailName, IDaycareStor
|
||||||
public override int MaxEV => EffortValues.Max255;
|
public override int MaxEV => EffortValues.Max255;
|
||||||
public override byte Generation => 3;
|
public override byte Generation => 3;
|
||||||
public override EntityContext Context => EntityContext.Gen3;
|
public override EntityContext Context => EntityContext.Gen3;
|
||||||
public override int MaxStringLengthOT => 7;
|
public override int MaxStringLengthTrainer => 7;
|
||||||
public override int MaxStringLengthNickname => 10;
|
public override int MaxStringLengthNickname => 10;
|
||||||
public override int MaxMoney => 9999999;
|
public override int MaxMoney => 9999999;
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37, IDaycareStorage, IDaycareRa
|
||||||
public sealed override EntityContext Context => EntityContext.Gen4;
|
public sealed override EntityContext Context => EntityContext.Gen4;
|
||||||
public int EventFlagCount => 0xB60; // 2912
|
public int EventFlagCount => 0xB60; // 2912
|
||||||
public int EventWorkCount => (EventFlag - EventWork) >> 1;
|
public int EventWorkCount => (EventFlag - EventWork) >> 1;
|
||||||
public sealed override int MaxStringLengthOT => 7;
|
public sealed override int MaxStringLengthTrainer => 7;
|
||||||
public sealed override int MaxStringLengthNickname => 10;
|
public sealed override int MaxStringLengthNickname => 10;
|
||||||
public sealed override int MaxMoney => 999999;
|
public sealed override int MaxMoney => 999999;
|
||||||
public sealed override int MaxCoins => 50_000;
|
public sealed override int MaxCoins => 50_000;
|
||||||
|
@ -243,7 +243,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37, IDaycareStorage, IDaycareRa
|
||||||
public override string OT
|
public override string OT
|
||||||
{
|
{
|
||||||
get => GetString(General.Slice(Trainer1, 16));
|
get => GetString(General.Slice(Trainer1, 16));
|
||||||
set => SetString(General.Slice(Trainer1, 16), value, MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SetString(General.Slice(Trainer1, 16), value, MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override uint ID32
|
public override uint ID32
|
||||||
|
@ -325,7 +325,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37, IDaycareStorage, IDaycareRa
|
||||||
public string Rival
|
public string Rival
|
||||||
{
|
{
|
||||||
get => GetString(Rival_Trash);
|
get => GetString(Rival_Trash);
|
||||||
set => SetString(Rival_Trash, value, MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SetString(Rival_Trash, value, MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Span<byte> Rival_Trash { get; set; }
|
public abstract Span<byte> Rival_Trash { get; set; }
|
||||||
|
|
|
@ -107,7 +107,7 @@ public sealed class SAV4BR : SaveFile, IBoxDetailName
|
||||||
public override int MaxEV => EffortValues.Max255;
|
public override int MaxEV => EffortValues.Max255;
|
||||||
public override byte Generation => 4;
|
public override byte Generation => 4;
|
||||||
public override EntityContext Context => EntityContext.Gen4;
|
public override EntityContext Context => EntityContext.Gen4;
|
||||||
public override int MaxStringLengthOT => 7;
|
public override int MaxStringLengthTrainer => 7;
|
||||||
public override int MaxStringLengthNickname => 10;
|
public override int MaxStringLengthNickname => 10;
|
||||||
public override int MaxMoney => 999999;
|
public override int MaxMoney => 999999;
|
||||||
public override int Language => (int)LanguageID.English; // prevent KOR from inhabiting
|
public override int Language => (int)LanguageID.English; // prevent KOR from inhabiting
|
||||||
|
|
|
@ -116,8 +116,8 @@ public sealed class SAV4DP : SAV4Sinnoh
|
||||||
|
|
||||||
public override Span<byte> Rival_Trash
|
public override Span<byte> Rival_Trash
|
||||||
{
|
{
|
||||||
get => General.Slice(0x25A8, MaxStringLengthOT * 2);
|
get => General.Slice(0x25A8, MaxStringLengthTrainer * 2);
|
||||||
set { if (value.Length == MaxStringLengthOT * 2) value.CopyTo(General[0x25A8..]); }
|
set { if (value.Length == MaxStringLengthTrainer * 2) value.CopyTo(General[0x25A8..]); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int X2 { get => ReadUInt16LittleEndian(General[0x25FA..]); set => WriteUInt16LittleEndian(General[0x25FA..], (ushort)value); }
|
public override int X2 { get => ReadUInt16LittleEndian(General[0x25FA..]); set => WriteUInt16LittleEndian(General[0x25FA..], (ushort)value); }
|
||||||
|
|
|
@ -190,10 +190,10 @@ public sealed class SAV4HGSS : SAV4, IBoxDetailName, IBoxDetailWallpaper
|
||||||
public override Span<byte> Rival_Trash
|
public override Span<byte> Rival_Trash
|
||||||
{
|
{
|
||||||
get => RivalSpan;
|
get => RivalSpan;
|
||||||
set { if (value.Length == MaxStringLengthOT * 2) value.CopyTo(RivalSpan); }
|
set { if (value.Length == MaxStringLengthTrainer * 2) value.CopyTo(RivalSpan); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private Span<byte> RivalSpan => General.Slice(0x22D4, MaxStringLengthOT * 2);
|
private Span<byte> RivalSpan => General.Slice(0x22D4, MaxStringLengthTrainer * 2);
|
||||||
|
|
||||||
public override int X2 { get => ReadUInt16LittleEndian(General[0x236E..]); set => WriteUInt16LittleEndian(General[0x236E..], (ushort)value); }
|
public override int X2 { get => ReadUInt16LittleEndian(General[0x236E..]); set => WriteUInt16LittleEndian(General[0x236E..], (ushort)value); }
|
||||||
public override int Y2 { get => ReadUInt16LittleEndian(General[0x2372..]); set => WriteUInt16LittleEndian(General[0x2372..], (ushort)value); }
|
public override int Y2 { get => ReadUInt16LittleEndian(General[0x2372..]); set => WriteUInt16LittleEndian(General[0x2372..], (ushort)value); }
|
||||||
|
|
|
@ -161,10 +161,10 @@ public sealed class SAV4Pt : SAV4Sinnoh
|
||||||
public override Span<byte> Rival_Trash
|
public override Span<byte> Rival_Trash
|
||||||
{
|
{
|
||||||
get => RivalSpan;
|
get => RivalSpan;
|
||||||
set { if (value.Length == MaxStringLengthOT * 2) value.CopyTo(RivalSpan); }
|
set { if (value.Length == MaxStringLengthTrainer * 2) value.CopyTo(RivalSpan); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private Span<byte> RivalSpan => General.Slice(0x27E8, MaxStringLengthOT * 2);
|
private Span<byte> RivalSpan => General.Slice(0x27E8, MaxStringLengthTrainer * 2);
|
||||||
|
|
||||||
public override int X2 { get => ReadUInt16LittleEndian(General[0x287E..]); set => WriteUInt16LittleEndian(General[0x287E..], (ushort)value); }
|
public override int X2 { get => ReadUInt16LittleEndian(General[0x287E..]); set => WriteUInt16LittleEndian(General[0x287E..], (ushort)value); }
|
||||||
public override int Y2 { get => ReadUInt16LittleEndian(General[0x2882..]); set => WriteUInt16LittleEndian(General[0x2882..], (ushort)value); }
|
public override int Y2 { get => ReadUInt16LittleEndian(General[0x2882..]); set => WriteUInt16LittleEndian(General[0x2882..], (ushort)value); }
|
||||||
|
|
|
@ -26,7 +26,7 @@ public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlagProvider37, IBox
|
||||||
public override int MaxEV => EffortValues.Max255;
|
public override int MaxEV => EffortValues.Max255;
|
||||||
public override byte Generation => 5;
|
public override byte Generation => 5;
|
||||||
public override EntityContext Context => EntityContext.Gen5;
|
public override EntityContext Context => EntityContext.Gen5;
|
||||||
public override int MaxStringLengthOT => 7;
|
public override int MaxStringLengthTrainer => 7;
|
||||||
public override int MaxStringLengthNickname => 10;
|
public override int MaxStringLengthNickname => 10;
|
||||||
|
|
||||||
public override ushort MaxMoveID => Legal.MaxMoveID_5;
|
public override ushort MaxMoveID => Legal.MaxMoveID_5;
|
||||||
|
|
|
@ -65,13 +65,13 @@ public sealed class SAV5B2W2 : SAV5, ISaveBlock5B2W2
|
||||||
public string Rival
|
public string Rival
|
||||||
{
|
{
|
||||||
get => GetString(Rival_Trash);
|
get => GetString(Rival_Trash);
|
||||||
set => SetString(Rival_Trash, value, MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SetString(Rival_Trash, value, MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<byte> Rival_Trash
|
public Span<byte> Rival_Trash
|
||||||
{
|
{
|
||||||
get => Data.AsSpan(0x23BA4, MaxStringLengthOT * 2);
|
get => Data.AsSpan(0x23BA4, MaxStringLengthTrainer * 2);
|
||||||
set { if (value.Length == MaxStringLengthOT * 2) value.CopyTo(Data.AsSpan(0x23BA4)); }
|
set { if (value.Length == MaxStringLengthTrainer * 2) value.CopyTo(Data.AsSpan(0x23BA4)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Memory<byte> BattleVideoNative => Data.AsMemory(0x4C000, BattleVideo5.SIZE_USED);
|
public override Memory<byte> BattleVideoNative => Data.AsMemory(0x4C000, BattleVideo5.SIZE_USED);
|
||||||
|
|
|
@ -26,7 +26,7 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg
|
||||||
public sealed override int MaxEV => EffortValues.Max252;
|
public sealed override int MaxEV => EffortValues.Max252;
|
||||||
public sealed override byte Generation => 6;
|
public sealed override byte Generation => 6;
|
||||||
public sealed override EntityContext Context => EntityContext.Gen6;
|
public sealed override EntityContext Context => EntityContext.Gen6;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
|
|
||||||
public override ushort MaxSpeciesID => Legal.MaxSpeciesID_6;
|
public override ushort MaxSpeciesID => Legal.MaxSpeciesID_6;
|
||||||
|
|
|
@ -75,7 +75,7 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IReg
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override byte Generation => 7;
|
public override byte Generation => 7;
|
||||||
public override EntityContext Context => EntityContext.Gen7;
|
public override EntityContext Context => EntityContext.Gen7;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
|
|
||||||
public override int MaxBallID => Legal.MaxBallID_7; // 26
|
public override int MaxBallID => Legal.MaxBallID_7; // 26
|
||||||
|
|
|
@ -80,7 +80,7 @@ public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync, IMysteryGiftStora
|
||||||
|
|
||||||
public override int MaxIV => 31;
|
public override int MaxIV => 31;
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
|
|
||||||
public override bool HasParty => false; // handled via team slots
|
public override bool HasParty => false; // handled via team slots
|
||||||
|
|
|
@ -119,7 +119,7 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE
|
||||||
public override byte Generation => 8;
|
public override byte Generation => 8;
|
||||||
public override EntityContext Context => EntityContext.Gen8b;
|
public override EntityContext Context => EntityContext.Gen8b;
|
||||||
public override PersonalTable8BDSP Personal => PersonalTable.BDSP;
|
public override PersonalTable8BDSP Personal => PersonalTable.BDSP;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
public override ushort MaxMoveID => Legal.MaxMoveID_8b;
|
public override ushort MaxMoveID => Legal.MaxMoveID_8b;
|
||||||
public override ushort MaxSpeciesID => Legal.MaxSpeciesID_8b;
|
public override ushort MaxSpeciesID => Legal.MaxSpeciesID_8b;
|
||||||
|
@ -283,7 +283,7 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE
|
||||||
public string Rival
|
public string Rival
|
||||||
{
|
{
|
||||||
get => GetString(Data.AsSpan(0x55F4, 0x1A));
|
get => GetString(Data.AsSpan(0x55F4, 0x1A));
|
||||||
set => SetString(Data.AsSpan(0x55F4, 0x1A), value, MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SetString(Data.AsSpan(0x55F4, 0x1A), value, MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public short ZoneID // map
|
public short ZoneID // map
|
||||||
|
|
|
@ -67,7 +67,7 @@ public sealed class SAV8LA : SaveFile, ISaveBlock8LA, ISCBlockArray, ISaveFileRe
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override byte Generation => 8;
|
public override byte Generation => 8;
|
||||||
public override EntityContext Context => EntityContext.Gen8a;
|
public override EntityContext Context => EntityContext.Gen8a;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
|
|
||||||
public override bool ChecksumsValid => true;
|
public override bool ChecksumsValid => true;
|
||||||
|
|
|
@ -151,7 +151,7 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override byte Generation => 8;
|
public override byte Generation => 8;
|
||||||
public override EntityContext Context => EntityContext.Gen8;
|
public override EntityContext Context => EntityContext.Gen8;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
protected override PK8 GetPKM(byte[] data) => new(data);
|
protected override PK8 GetPKM(byte[] data) => new(data);
|
||||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray8(data);
|
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray8(data);
|
||||||
|
|
|
@ -157,7 +157,7 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile
|
||||||
public override int MaxEV => EffortValues.Max252;
|
public override int MaxEV => EffortValues.Max252;
|
||||||
public override byte Generation => 9;
|
public override byte Generation => 9;
|
||||||
public override EntityContext Context => EntityContext.Gen9;
|
public override EntityContext Context => EntityContext.Gen9;
|
||||||
public override int MaxStringLengthOT => 12;
|
public override int MaxStringLengthTrainer => 12;
|
||||||
public override int MaxStringLengthNickname => 12;
|
public override int MaxStringLengthNickname => 12;
|
||||||
protected override PK9 GetPKM(byte[] data) => new(data);
|
protected override PK9 GetPKM(byte[] data) => new(data);
|
||||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray9(data);
|
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray9(data);
|
||||||
|
|
|
@ -88,7 +88,7 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IGeneration, IVe
|
||||||
|
|
||||||
#region Stored PKM Limits
|
#region Stored PKM Limits
|
||||||
public abstract IPersonalTable Personal { get; }
|
public abstract IPersonalTable Personal { get; }
|
||||||
public abstract int MaxStringLengthOT { get; }
|
public abstract int MaxStringLengthTrainer { get; }
|
||||||
public abstract int MaxStringLengthNickname { get; }
|
public abstract int MaxStringLengthNickname { get; }
|
||||||
public abstract ushort MaxMoveID { get; }
|
public abstract ushort MaxMoveID { get; }
|
||||||
public abstract ushort MaxSpeciesID { get; }
|
public abstract ushort MaxSpeciesID { get; }
|
||||||
|
|
|
@ -42,7 +42,7 @@ public abstract class BulkStorage : SaveFile
|
||||||
public sealed override int MaxItemID => blank.MaxItemID;
|
public sealed override int MaxItemID => blank.MaxItemID;
|
||||||
public sealed override int MaxBallID => blank.MaxBallID;
|
public sealed override int MaxBallID => blank.MaxBallID;
|
||||||
public sealed override GameVersion MaxGameID => blank.MaxGameID;
|
public sealed override GameVersion MaxGameID => blank.MaxGameID;
|
||||||
public sealed override int MaxStringLengthOT => blank.MaxStringLengthOT;
|
public sealed override int MaxStringLengthTrainer => blank.MaxStringLengthTrainer;
|
||||||
public sealed override int MaxStringLengthNickname => blank.MaxStringLengthNickname;
|
public sealed override int MaxStringLengthNickname => blank.MaxStringLengthNickname;
|
||||||
public bool IsBigEndian => blank is BK4 or XK3 or CK3;
|
public bool IsBigEndian => blank is BK4 or XK3 or CK3;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ public sealed class PlayerData5(SAV5 sav, Memory<byte> raw) : SaveBlock<SAV5>(sa
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ID32
|
public uint ID32
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class MyStatus6(SAV6 sav, Memory<byte> raw) : SaveBlock<SAV6>(sav, raw),
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Span<byte> GetSayingSpan(int say) => Data.Slice(GetSayingOffset(say), SAV6.LongStringLength);
|
private Span<byte> GetSayingSpan(int say) => Data.Slice(GetSayingOffset(say), SAV6.LongStringLength);
|
||||||
|
|
|
@ -18,7 +18,7 @@ public sealed class FieldMenu7(SAV7 sav, Memory<byte> raw) : SaveBlock<SAV7>(sav
|
||||||
public string RotomOT
|
public string RotomOT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(RotomNameSpan);
|
get => SAV.GetString(RotomNameSpan);
|
||||||
set => SAV.SetString(RotomNameSpan, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(RotomNameSpan, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Span<byte> RotomNameSpan => Data.Slice(0x30, 0x1A);
|
private Span<byte> RotomNameSpan => Data.Slice(0x30, 0x1A);
|
||||||
|
|
|
@ -16,6 +16,6 @@ public sealed class Misc7b(SAV7b sav, Memory<byte> raw) : SaveBlock<SAV7b>(sav,
|
||||||
public string Rival
|
public string Rival
|
||||||
{
|
{
|
||||||
get => SAV.GetString(Rival_Trash);
|
get => SAV.GetString(Rival_Trash);
|
||||||
set => SAV.SetString(Rival_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(Rival_Trash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ public sealed class MyStatus7b(SAV7b sav, Memory<byte> raw) : SaveBlock<SAV7b>(s
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The value here corresponds to a Trainer Class string (ranging from 000 to 383, use pkNX to get a full list).
|
// The value here corresponds to a Trainer Class string (ranging from 000 to 383, use pkNX to get a full list).
|
||||||
|
|
|
@ -98,7 +98,7 @@ public sealed class MyStatus7(SAV7 sav, Memory<byte> raw) : SaveBlock<SAV7>(sav,
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int DressUpSkinColor
|
public int DressUpSkinColor
|
||||||
|
|
|
@ -19,7 +19,7 @@ public sealed class MyStatus8b(SAV8BS sav, Memory<byte> raw) : SaveBlock<SAV8BS>
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ID32
|
public uint ID32
|
||||||
|
|
|
@ -62,7 +62,7 @@ public sealed class MyStatus8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sa
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte Unk_0x50
|
public byte Unk_0x50
|
||||||
|
|
|
@ -170,7 +170,7 @@ public sealed class MyStatus8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
// D0
|
// D0
|
||||||
|
|
|
@ -12,7 +12,7 @@ public sealed class TrainerCard8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SW
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte Language
|
public byte Language
|
||||||
|
|
|
@ -83,7 +83,7 @@ public sealed class MyStatus9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav
|
||||||
public string OT
|
public string OT
|
||||||
{
|
{
|
||||||
get => SAV.GetString(OriginalTrainerTrash);
|
get => SAV.GetString(OriginalTrainerTrash);
|
||||||
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero);
|
set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthTrainer, StringConverterOption.ClearZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte BirthMonth { get => Data[0x5A]; set => Data[0x5A] = value; }
|
public byte BirthMonth { get => Data[0x5A]; set => Data[0x5A] = value; }
|
||||||
|
|
|
@ -1997,8 +1997,8 @@ public sealed partial class PKMEditor : UserControl, IMainEditor
|
||||||
PopulateFields(Entity);
|
PopulateFields(Entity);
|
||||||
|
|
||||||
// Save File Specific Limits
|
// Save File Specific Limits
|
||||||
TB_OT.MaxLength = Entity.MaxStringLengthOT;
|
TB_OT.MaxLength = Entity.MaxStringLengthTrainer;
|
||||||
TB_HT.MaxLength = Entity.MaxStringLengthOT;
|
TB_HT.MaxLength = Entity.MaxStringLengthTrainer;
|
||||||
TB_Nickname.MaxLength = Entity.MaxStringLengthNickname;
|
TB_Nickname.MaxLength = Entity.MaxStringLengthNickname;
|
||||||
|
|
||||||
// Hide Unused Tabs
|
// Hide Unused Tabs
|
||||||
|
|
|
@ -131,7 +131,7 @@ public partial class PokePreview : Form
|
||||||
display.Visible = true;
|
display.Visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Size MeasureSize(string text, Font font)
|
public static Size MeasureSize(ReadOnlySpan<char> text, Font font)
|
||||||
{
|
{
|
||||||
const TextFormatFlags flags = TextFormatFlags.LeftAndRightPadding | TextFormatFlags.VerticalCenter;
|
const TextFormatFlags flags = TextFormatFlags.LeftAndRightPadding | TextFormatFlags.VerticalCenter;
|
||||||
return TextRenderer.MeasureText(text, font, new Size(), flags);
|
return TextRenderer.MeasureText(text, font, new Size(), flags);
|
||||||
|
|
|
@ -18,7 +18,7 @@ public partial class SAV_SimpleTrainer : Form
|
||||||
Loading = true;
|
Loading = true;
|
||||||
|
|
||||||
cba = [CHK_1, CHK_2, CHK_3, CHK_4, CHK_5, CHK_6, CHK_7, CHK_8];
|
cba = [CHK_1, CHK_2, CHK_3, CHK_4, CHK_5, CHK_6, CHK_7, CHK_8];
|
||||||
TB_OTName.MaxLength = SAV.MaxStringLengthOT;
|
TB_OTName.MaxLength = SAV.MaxStringLengthTrainer;
|
||||||
B_MaxCash.Click += (sender, e) => MT_Money.Text = SAV.MaxMoney.ToString();
|
B_MaxCash.Click += (sender, e) => MT_Money.Text = SAV.MaxMoney.ToString();
|
||||||
B_MaxCoins.Click += (sender, e) => MT_Coins.Text = SAV.MaxCoins.ToString();
|
B_MaxCoins.Click += (sender, e) => MT_Coins.Text = SAV.MaxCoins.ToString();
|
||||||
MT_Money.Mask = "".PadRight((int)Math.Floor(Math.Log10(SAV.MaxMoney) + 1), '0');
|
MT_Money.Mask = "".PadRight((int)Math.Floor(Math.Log10(SAV.MaxMoney) + 1), '0');
|
||||||
|
|
Loading…
Reference in a new issue