mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-09-10 18:35:58 -05:00
Fix daycare slot read
Closes #4279 adds writeback for daycare in gen2 as well
This commit is contained in:
@@ -271,4 +271,46 @@ public static byte[] WrapSingle(PK1 pk)
|
||||
/// <param name="pk">Entity to wrap</param>
|
||||
/// <param name="output">Destination to write the single-slot list</param>
|
||||
public static void WrapSingle(PK1 pk, Span<byte> output) => WriteToList(output, pk);
|
||||
|
||||
public static void UnpackNOB(ReadOnlySpan<byte> input, Span<byte> output, int stringLength, bool isParty = false)
|
||||
{
|
||||
// Nickname, OT, Data
|
||||
var lengthBody = GetBodyLength(isParty);
|
||||
var lengthParty = GetBodyLength(true);
|
||||
var nick = input[..stringLength];
|
||||
var trainer = input.Slice(stringLength, stringLength);
|
||||
var box = input.Slice(stringLength * 2, lengthBody);
|
||||
|
||||
var marker = box[0];
|
||||
if (marker is 0) // Ensure deleted (zeroed) slots act as an Empty (FF) slot.
|
||||
marker = SlotEmpty;
|
||||
|
||||
output[0] = 1;
|
||||
output[1] = marker;
|
||||
output = output[3..];
|
||||
|
||||
// Data, OT, Nickname
|
||||
box.CopyTo(output);
|
||||
output = output[lengthParty..];
|
||||
trainer.CopyTo(output);
|
||||
output = output[stringLength..];
|
||||
nick.CopyTo(output);
|
||||
}
|
||||
|
||||
public static void PackNOB(ReadOnlySpan<byte> input, Span<byte> output, int stringLength, bool isParty = false)
|
||||
{
|
||||
var lengthBody = GetBodyLength(isParty);
|
||||
var lengthParty = GetBodyLength(true);
|
||||
|
||||
input = input[3..]; // Skip header.
|
||||
var box = input[..lengthBody];
|
||||
var trainer = input.Slice(lengthParty, stringLength);
|
||||
var nick = input.Slice(lengthParty + stringLength, stringLength);
|
||||
|
||||
nick.CopyTo(output);
|
||||
output = output[stringLength..];
|
||||
trainer.CopyTo(output);
|
||||
output = output[stringLength..];
|
||||
box.CopyTo(output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,4 +274,46 @@ public static byte[] WrapSingle(PK2 pk)
|
||||
/// <param name="pk">Entity to wrap</param>
|
||||
/// <param name="output">Destination to write the single-slot list</param>
|
||||
public static void WrapSingle(PK2 pk, Span<byte> output) => WriteToList(output, pk);
|
||||
|
||||
public static void UnpackNOB(ReadOnlySpan<byte> input, Span<byte> output, int stringLength, bool isParty = false)
|
||||
{
|
||||
// Nickname, OT, Data
|
||||
var lengthBody = GetBodyLength(isParty);
|
||||
var lengthParty = GetBodyLength(true);
|
||||
var nick = input[..stringLength];
|
||||
var trainer = input.Slice(stringLength, stringLength);
|
||||
var box = input.Slice(stringLength * 2, lengthBody);
|
||||
|
||||
var marker = box[0];
|
||||
if (marker is 0) // Ensure deleted (zeroed) slots act as an Empty (FF) slot.
|
||||
marker = SlotEmpty;
|
||||
|
||||
output[0] = 1;
|
||||
output[1] = marker;
|
||||
output = output[3..];
|
||||
|
||||
// Data, OT, Nickname
|
||||
box.CopyTo(output);
|
||||
output = output[lengthParty..];
|
||||
trainer.CopyTo(output);
|
||||
output = output[stringLength..];
|
||||
nick.CopyTo(output);
|
||||
}
|
||||
|
||||
public static void PackNOB(ReadOnlySpan<byte> input, Span<byte> output, int stringLength, bool isParty = false)
|
||||
{
|
||||
var lengthBody = GetBodyLength(isParty);
|
||||
var lengthParty = GetBodyLength(true);
|
||||
|
||||
input = input[3..]; // Skip header.
|
||||
var box = input[..lengthBody];
|
||||
var trainer = input.Slice(lengthParty, stringLength);
|
||||
var nick = input.Slice(lengthParty + stringLength, stringLength);
|
||||
|
||||
nick.CopyTo(output);
|
||||
output = output[stringLength..];
|
||||
trainer.CopyTo(output);
|
||||
output = output[stringLength..];
|
||||
box.CopyTo(output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,20 +105,11 @@ private void Initialize(GameVersion versionOverride)
|
||||
PokeList1.Unpack(src, dest, StringLength, 6, true);
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> rawDC = Data.AsSpan(Offsets.Daycare, 0x38);
|
||||
var daycareOffset = DaycareOffset = GetPartyOffset(6);
|
||||
var TempDaycare = BoxBuffer[daycareOffset..];
|
||||
TempDaycare[0] = rawDC[0];
|
||||
|
||||
var dcDest = TempDaycare[3..];
|
||||
|
||||
// OT, Nickname, and Core data (rather than the reverse...)
|
||||
rawDC.Slice(1, StringLength).CopyTo(dcDest[(PokeCrypto.SIZE_1PARTY + StringLength)..]);
|
||||
rawDC.Slice(1 + StringLength, StringLength).CopyTo(dcDest[PokeCrypto.SIZE_1PARTY..]);
|
||||
rawDC.Slice(1 + (2 * StringLength), PokeCrypto.SIZE_1STORED).CopyTo(dcDest);
|
||||
var dc = Data.AsSpan(Offsets.Daycare, 0x38);
|
||||
PokeList1.UnpackNOB(dc[1..], PartyBuffer[DaycareOffset..], StringLength);
|
||||
}
|
||||
|
||||
private int DaycareOffset = -1;
|
||||
private int DaycareOffset => GetPartyOffset(6);
|
||||
public override bool HasPokeDex => true;
|
||||
|
||||
// Event Flags
|
||||
@@ -177,12 +168,7 @@ protected override byte[] GetFinalData()
|
||||
}
|
||||
|
||||
// Daycare is read-only, but in case it ever becomes editable, copy it back in.
|
||||
Span<byte> rawDC = Data.AsSpan(Offsets.Daycare, 0x38);
|
||||
var TempDaycare = BoxBuffer[DaycareOffset..];
|
||||
var dcDest = TempDaycare[3..];
|
||||
dcDest.Slice(2 + 1 + PokeCrypto.SIZE_1PARTY + StringLength, StringLength).CopyTo(rawDC[1..]);
|
||||
dcDest.Slice(2 + 1 + PokeCrypto.SIZE_1PARTY, StringLength).CopyTo(rawDC[(1 + StringLength)..]);
|
||||
dcDest.Slice(2 + 1, PokeCrypto.SIZE_1STORED).CopyTo(rawDC[(1 + (2 * StringLength))..]);
|
||||
PokeList1.PackNOB(PartyBuffer[DaycareOffset..], Data.AsSpan(Offsets.Daycare, 0x38)[1..], StringLength);
|
||||
|
||||
SetChecksums();
|
||||
return Data;
|
||||
|
||||
@@ -104,48 +104,43 @@ private void Initialize()
|
||||
|
||||
if (Offsets.Daycare >= 0)
|
||||
{
|
||||
int offset = Offsets.Daycare;
|
||||
var dc0 = PartyBuffer[GetDaycareSlotOffset(0)..];
|
||||
PokeList2.UnpackNOB(Data.AsSpan(GetRawDaycareSlotOffset(0)), dc0, StringLength);
|
||||
|
||||
offset++;
|
||||
var pk1 = ReadPKMFromOffset(offset); // parent 1
|
||||
offset += (StringLength * 2) + 0x20; // nick/ot/pk
|
||||
offset++;
|
||||
//byte steps = Data[offset];
|
||||
offset++;
|
||||
//byte BreedMotherOrNonDitto = Data[offset];
|
||||
offset++;
|
||||
var pk2 = ReadPKMFromOffset(offset); // parent 2
|
||||
offset += (StringLength * 2) + PokeCrypto.SIZE_2STORED; // nick/ot/pk
|
||||
var pk3 = ReadPKMFromOffset(offset); // egg!
|
||||
pk3.IsEgg = true;
|
||||
var dc1 = PartyBuffer[GetDaycareSlotOffset(1)..];
|
||||
PokeList2.UnpackNOB(Data.AsSpan(GetRawDaycareSlotOffset(1)), dc1, StringLength);
|
||||
|
||||
PokeList2.WriteToList(PartyBuffer[GetPartyOffset(6 + (0 * 2))..], pk1, 1, true);
|
||||
PokeList2.WriteToList(PartyBuffer[GetPartyOffset(6 + (1 * 2))..], pk2, 1, true);
|
||||
PokeList2.WriteToList(PartyBuffer[GetPartyOffset(6 + (2 * 2))..], pk3, 1, true);
|
||||
var egg = PartyBuffer[GetDaycareSlotOffset(2)..];
|
||||
PokeList2.UnpackNOB(Data.AsSpan(GetRawDaycareSlotOffset(2)), egg, StringLength);
|
||||
if (egg[2] != PokeList2.SlotEmpty)
|
||||
egg[1] = PokeList2.SlotEgg;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetRawDaycareSlotOffset(int index)
|
||||
{
|
||||
int offset = Offsets.Daycare;
|
||||
|
||||
offset++; // Breeding Status flags
|
||||
if (index == 0)
|
||||
return offset;
|
||||
|
||||
offset += (StringLength * 2) + PokeCrypto.SIZE_2STORED; // nick/ot/pk
|
||||
offset++; // Lady Status flags
|
||||
offset++; // Steps until Egg
|
||||
offset++; // Ditto Parent state
|
||||
if (index == 1)
|
||||
return offset;
|
||||
|
||||
offset += (StringLength * 2) + PokeCrypto.SIZE_2STORED; // nick/ot/pk
|
||||
return offset;
|
||||
}
|
||||
|
||||
public override bool HasPokeDex => true;
|
||||
|
||||
private int EventFlag => Offsets.EventFlag;
|
||||
private int EventWork => Offsets.EventWork;
|
||||
|
||||
private PK2 ReadPKMFromOffset(int offset)
|
||||
{
|
||||
var stringLength = StringLength;
|
||||
var span = Data.AsSpan(offset);
|
||||
|
||||
var pkData = span.Slice(stringLength * 2, PokeCrypto.SIZE_2STORED).ToArray();
|
||||
var pk = new PK2(pkData, jp: Japanese);
|
||||
|
||||
var nick = span[..stringLength];
|
||||
var ot = span.Slice(stringLength, stringLength);
|
||||
nick.CopyTo(pk.NicknameTrash);
|
||||
ot.CopyTo(pk.OriginalTrainerTrash);
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
||||
private int GetBoxRawDataOffset(int i, int splitAtIndex)
|
||||
{
|
||||
if (i < splitAtIndex)
|
||||
@@ -178,6 +173,20 @@ protected override byte[] GetFinalData()
|
||||
PokeList2.MergeSingles(src, dest, StringLength, 6, true);
|
||||
}
|
||||
|
||||
// Write Daycare
|
||||
|
||||
if (Offsets.Daycare >= 0)
|
||||
{
|
||||
var dc0 = PartyBuffer[GetDaycareSlotOffset(0)..];
|
||||
PokeList2.PackNOB(dc0, Data.AsSpan(GetRawDaycareSlotOffset(0)), StringLength);
|
||||
|
||||
var dc1 = PartyBuffer[GetDaycareSlotOffset(1)..];
|
||||
PokeList2.PackNOB(dc1, Data.AsSpan(GetRawDaycareSlotOffset(1)), StringLength);
|
||||
|
||||
var egg = PartyBuffer[GetDaycareSlotOffset(2)..];
|
||||
PokeList2.PackNOB(egg, Data.AsSpan(GetRawDaycareSlotOffset(2)), StringLength);
|
||||
}
|
||||
|
||||
SetChecksums();
|
||||
if (Japanese)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user