Add daycare reader, show playtime in backup filename

This commit is contained in:
Kurt 2021-11-20 19:10:42 -08:00
parent d56d675868
commit 9d5cff5221
4 changed files with 86 additions and 5 deletions

View file

@ -207,9 +207,6 @@ namespace PKHeX.Core
{
return new()
{
new SlotInfoMisc(sav.Data, 0, 0x96080, true) { Type = StorageSlotType.Daycare },
new SlotInfoMisc(sav.Data, 1, 0x96080 + PokeCrypto.SIZE_8PARTY, true) { Type = StorageSlotType.Daycare },
new SlotInfoMisc(sav.Data, 0, 0x9A8E8 + (0 * PokeCrypto.SIZE_8PARTY), true) { Type = StorageSlotType.Misc },
new SlotInfoMisc(sav.Data, 1, 0x9A8E8 + (1 * PokeCrypto.SIZE_8PARTY), true) { Type = StorageSlotType.Misc },
new SlotInfoMisc(sav.Data, 2, 0x9A8E8 + (2 * PokeCrypto.SIZE_8PARTY), true) { Type = StorageSlotType.Misc },

View file

@ -7,7 +7,7 @@ namespace PKHeX.Core
public class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord
{
// Save Data Attributes
protected internal override string ShortSummary => $"{OT} ({Version})";
protected internal override string ShortSummary => $"{OT} ({Version}) - {Played.LastSavedTime}";
public override string Extension => string.Empty;
public override IReadOnlyList<string> PKMExtensions => Array.FindAll(PKM.Extensions, f =>
@ -30,8 +30,11 @@ namespace PKHeX.Core
// 0x7D3E0 - Trainer Battle Data (bool,bool)[707]
// 0x7E9F8 - Menu selections (TopMenuItemTypeInt32, bool IsNew)[8], TopMenuItemTypeInt32 LastSelected
// 0x7EA3C - _FIELDOBJ_SAVE Objects[1000] (sizeof (0x44, 17 int fields), total size 0x109A0
Records = new Record8b(this, 0x8F3DC);
Records = new Record8b(this, 0x8F3DC); // size: 0x78
// 0x8F454 - ENC_SV_DATA
Daycare = new Daycare8b(this, 0x96080); // 0x2C0
// 0x96340 - _DENDOU_SAVEDATA
Initialize();
}
@ -43,6 +46,7 @@ namespace PKHeX.Core
Party = PartyInfo.Offset;
PokeDex = Zukan.PokeDex;
BoxLayout.LoadBattleTeams();
DaycareOffset = Daycare.Offset;
}
public override bool HasEvents => true;
@ -146,6 +150,7 @@ namespace PKHeX.Core
// public Misc8 Misc { get; }
public Zukan8b Zukan { get; }
public Record8b Records { get; }
public Daycare8b Daycare { get; }
#endregion
public override GameVersion Version => Game switch
@ -260,5 +265,24 @@ namespace PKHeX.Core
public int GetRecordOffset(int recordID) => Records.GetRecordOffset(recordID);
public int GetRecordMax(int recordID) => Record8b.RecordMaxValue;
public void SetRecord(int recordID, int value) => Records.SetRecord(recordID, value);
#region Daycare
public override int DaycareSeedSize => 16; // 8byte
public override int GetDaycareSlotOffset(int loc, int slot) => Daycare.GetParentSlotOffset(slot);
public override uint? GetDaycareEXP(int loc, int slot) => (uint)Daycare.EggStepCount;
public override bool? IsDaycareOccupied(int loc, int slot) => Daycare.GetDaycareSlotOccupied(slot);
public override bool? IsDaycareHasEgg(int loc) => Daycare.IsEggAvailable;
public override void SetDaycareEXP(int loc, int slot, uint EXP) => Daycare.EggStepCount = (int)EXP;
public override void SetDaycareOccupied(int loc, int slot, bool occupied) { }
public override void SetDaycareHasEgg(int loc, bool hasEgg) => Daycare.IsEggAvailable = hasEgg;
public override string GetDaycareRNGSeed(int loc)
{
var data = BitConverter.GetBytes(Daycare.DaycareSeed);
Array.Reverse(data);
return BitConverter.ToString(data).Replace("-", string.Empty);
}
public override void SetDaycareRNGSeed(int loc, string seed) => Daycare.DaycareSeed = BitConverter.ToUInt64(Util.GetBytesFromHexString(seed), 0);
#endregion
}
}

View file

@ -0,0 +1,59 @@
using System;
using System.ComponentModel;
namespace PKHeX.Core
{
/// <summary>
/// Storage for the in-game daycare structure.
/// </summary>
/// <remarks>size: 0x2C0</remarks>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class Daycare8b : SaveBlock
{
public Daycare8b(SaveFile sav, int offset) : base(sav) => Offset = offset;
// BLOCK STRUCTURE
// PB8[2] Parents;
// bool32 eggExist;
// ulong eggSeed; -- setter puts only 32 bits!
// int32 eggStepCount;
private const int SlotCount = 2;
private const int ExtraDataOffset = PokeCrypto.SIZE_8PARTY * SlotCount;
public bool GetDaycareSlotOccupied(int slot) => GetSlot(slot).Species != 0;
public int GetParentSlotOffset(int slot)
{
if ((uint)slot >= SlotCount)
throw new IndexOutOfRangeException(nameof(slot));
return Offset + (slot * PokeCrypto.SIZE_8PARTY);
}
public PB8 GetSlot(int slot)
{
var offset = GetParentSlotOffset(slot);
var data = Data.AsSpan(offset, PokeCrypto.SIZE_8PARTY).ToArray();
return new PB8(data);
}
public bool IsEggAvailable
{
get => BitConverter.ToUInt32(Data, Offset + ExtraDataOffset) == 1;
set => BitConverter.GetBytes(value ? 1u : 0).CopyTo(Data, Offset + ExtraDataOffset);
}
public ulong DaycareSeed
{
get => BitConverter.ToUInt64(Data, Offset + ExtraDataOffset + 4);
set => SAV.SetData(Data, BitConverter.GetBytes(value), Offset + ExtraDataOffset + 4);
}
public int EggStepCount
{
get => BitConverter.ToInt32(Data, Offset + ExtraDataOffset + 4 + 8);
set => BitConverter.GetBytes(value).CopyTo(Data, Offset + ExtraDataOffset + 4 + 8);
}
}
}

View file

@ -19,5 +19,6 @@ namespace PKHeX.Core
public byte PlayedMinutes { get => Data[Offset + 2]; set => Data[Offset + 2] = value; }
public byte PlayedSeconds { get => Data[Offset + 3]; set => Data[Offset + 3] = value; }
public string LastSavedTime => $"{PlayedHours:0000}ː{PlayedMinutes:00}ː{PlayedSeconds:00}"; // not :
}
}