From ca85fba061ae679a43b081ee90a27e650514a7f6 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 13 May 2024 19:39:37 -0500 Subject: [PATCH] Force writeback on addition to uninitialized data Adding an entity to an uninitialized save's box data will force all data to be flushed unless the final destination was (initially zeroed and has no slots to set). --- PKHeX.Core/PKM/Shared/PokeList1.cs | 2 +- PKHeX.Core/Saves/SAV1.cs | 41 ++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/PKHeX.Core/PKM/Shared/PokeList1.cs b/PKHeX.Core/PKM/Shared/PokeList1.cs index 3ba95c7ad..7c90d3428 100644 --- a/PKHeX.Core/PKM/Shared/PokeList1.cs +++ b/PKHeX.Core/PKM/Shared/PokeList1.cs @@ -45,7 +45,7 @@ public static class PokeList1 /// List header /// Count of slots allowed in the list /// Offset jump between slot indexes; used to parse multi-single lists instead of a multi-list. - private static int CountPresent(ReadOnlySpan input, int capacity, int lerp = 0) + public static int CountPresent(ReadOnlySpan input, int capacity, int lerp = 0) { var count = 0; for (int i = 0; i < capacity; i++) diff --git a/PKHeX.Core/Saves/SAV1.cs b/PKHeX.Core/Saves/SAV1.cs index f8a12188b..c0c5e77d4 100644 --- a/PKHeX.Core/Saves/SAV1.cs +++ b/PKHeX.Core/Saves/SAV1.cs @@ -144,23 +144,28 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo protected override byte[] GetFinalData() { - bool anyBoxPresent = false; int boxListLength = SIZE_BOX_LIST; var boxSlotCount = BoxSlotCount; bool boxInitialized = BoxesInitialized; + var current = CurrentBox; + if (!boxInitialized) + { + // Check if any box has content in it. + bool newContent = AnyBoxSlotSpeciesPresent(current, boxSlotCount); + if (newContent) + BoxesInitialized = boxInitialized = true; + } + for (int i = 0; i < BoxCount; i++) { int ofs = GetBoxRawDataOffset(i); var dest = Data.AsSpan(ofs, boxListLength); - var src = BoxBuffer.Slice(i * SIZE_BOX_AS_SINGLES, SIZE_BOX_AS_SINGLES); + var src = GetUnpackedBoxSpan(i); bool written = PokeList1.MergeSingles(src, dest, StringLength, boxSlotCount, false, boxInitialized); if (written && i == CurrentBox) dest.CopyTo(Data.AsSpan(Offsets.CurrentBox)); - anyBoxPresent |= written; } - if (anyBoxPresent) - BoxesInitialized = true; // box data has been flushed at least once // Write Party { @@ -184,6 +189,32 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo return Data; } + private Span GetUnpackedBoxSpan(int box) + { + var size = SIZE_BOX_AS_SINGLES; + return BoxBuffer.Slice(box * size, size); + } + + private bool AnyBoxSlotSpeciesPresent(int current, int boxSlotCount) + { + bool newContent = false; + for (int i = 0; i < BoxCount; i++) + { + if (i == current) // Exclude current box in the check. + continue; + + var src = GetUnpackedBoxSpan(i); + int count = PokeList1.CountPresent(src, boxSlotCount); + if (count == 0) + continue; + + newContent = true; + break; + } + + return newContent; + } + private int GetBoxRawDataOffset(int box) { if (box < BoxCount / 2)