Rename battle video classes, allow bv4 recognition

This commit is contained in:
Kurt 2024-03-07 00:34:21 -06:00
parent 802974a42c
commit df7c25d43f
9 changed files with 46 additions and 37 deletions

View file

@ -280,10 +280,10 @@ public sealed class SAV3E : SAV3, IGen3Hoenn, IGen3Joyful, IGen3Wonder, IDaycare
private const int OFS_BV = 31 * 0x1000; // last sector of the save
public bool HasBattleVideo => Data.Length > SaveUtil.SIZE_G3RAWHALF && ReadUInt32LittleEndian(Data.AsSpan(OFS_BV)) == EXTRADATA_SENTINEL;
private Span<byte> BattleVideoData => Data.AsSpan(OFS_BV + 4, BV3.SIZE);
public BV3 BattleVideo
private Span<byte> BattleVideoData => Data.AsSpan(OFS_BV + 4, BattleVideo3.SIZE);
public BattleVideo3 BattleVideo
{
get => HasBattleVideo ? new BV3(BattleVideoData.ToArray()) : new BV3();
get => HasBattleVideo ? new BattleVideo3(BattleVideoData.ToArray()) : new BattleVideo3();
set => SetData(BattleVideoData, value.Data);
}
}

View file

@ -1,33 +1,31 @@
using System;
using System.Collections.Generic;
using System;
namespace PKHeX.Core;
public abstract class BattleVideo : IPokeGroup
public static class BattleVideo
{
public abstract IReadOnlyList<PKM> BattlePKMs { get; }
public abstract byte Generation { get; }
public IEnumerable<PKM> Contents => BattlePKMs;
public static BattleVideo? GetVariantBattleVideo(byte[] data)
public static IBattleVideo? GetVariantBattleVideo(byte[] data)
{
if (BV6.IsValid(data))
return new BV6(data);
if (BV7.IsValid(data))
return new BV7(data);
if (BV3.IsValid(data))
return new BV3(data);
if (BattleVideo6.IsValid(data))
return new BattleVideo6(data);
if (BattleVideo7.IsValid(data))
return new BattleVideo7(data);
if (BattleVideo4.IsValid(data))
return new BattleVideo4(data);
if (BattleVideo3.IsValid(data))
return new BattleVideo3(data);
return null;
}
public static bool IsValid(ReadOnlySpan<byte> data)
{
if (BV6.IsValid(data))
if (BattleVideo6.IsValid(data))
return true;
if (BV7.IsValid(data))
if (BattleVideo7.IsValid(data))
return true;
if (BV3.IsValid(data))
if (BattleVideo4.IsValid(data))
return true;
if (BattleVideo3.IsValid(data))
return true;
return false;
}

View file

@ -5,18 +5,18 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class BV3(byte[] Data) : BattleVideo
public sealed class BattleVideo3(byte[] Data) : IBattleVideo
{
public BV3() : this(new byte[SIZE]) { }
public BattleVideo3() : this(new byte[SIZE]) { }
public readonly byte[] Data = (byte[])Data.Clone();
internal const int SIZE = 0xF80;
public override byte Generation => 3;
public byte Generation => 3;
public override IReadOnlyList<PK3> BattlePKMs => PlayerTeams.SelectMany(z => z).ToArray();
public IEnumerable<PKM> Contents => PlayerTeams.SelectMany(z => z);
internal new static bool IsValid(ReadOnlySpan<byte> data)
public static bool IsValid(ReadOnlySpan<byte> data)
{
if (data.Length != SIZE)
return false;

View file

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
@ -7,7 +9,7 @@ namespace PKHeX.Core;
/// Extra-data block for Hall of Fame records.
/// </summary>
/// <param name="Raw">Chunk of memory storing the structure.</param>
public sealed class BattleVideo4(Memory<byte> Raw)
public sealed class BattleVideo4(Memory<byte> Raw) : IBattleVideo
{
private const int SIZE = 0x1D50;
private const int SIZE_FOOTER = 0x10;
@ -21,6 +23,10 @@ public sealed class BattleVideo4(Memory<byte> Raw)
private const int CryptoEnd = 0x1D4C;
private Span<byte> CryptoData => Data[CryptoStart..CryptoEnd];
public byte Generation => 4;
public IEnumerable<PKM> Contents => GetTeam(0).Concat(GetTeam(1)); // don't bother with multi-battles
public static bool IsValid(ReadOnlySpan<byte> data) => data.Length == SIZE_USED && ReadUInt32LittleEndian(data[^8..]) == SIZE;
// Structure:
// 0x00: u32 Key
// 0x04... ???
@ -65,7 +71,6 @@ public sealed class BattleVideo4(Memory<byte> Raw)
#region Footer
public bool SizeValid => BlockSize == SIZE;
public bool ChecksumValid => Checksum == GetChecksum();
public bool IsValid => SizeValid && ChecksumValid;
public uint Magic { get => ReadUInt32LittleEndian(Footer); set => WriteUInt32LittleEndian(Footer, value); }
public uint Revision { get => ReadUInt32LittleEndian(Footer[0x4..]); set => WriteUInt32LittleEndian(Footer[0x4..], value); }

View file

@ -6,7 +6,7 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class BV6(byte[] Data) : BattleVideo
public sealed class BattleVideo6(byte[] Data) : IBattleVideo
{
private readonly byte[] Data = (byte[])Data.Clone();
@ -14,10 +14,10 @@ public sealed class BV6(byte[] Data) : BattleVideo
private const string NPC = "NPC";
private const int PlayerCount = 4;
public override IReadOnlyList<PK6> BattlePKMs => PlayerTeams.SelectMany(t => t).ToArray();
public override byte Generation => 6;
public IEnumerable<PKM> Contents => PlayerTeams.SelectMany(t => t);
public byte Generation => 6;
internal new static bool IsValid(ReadOnlySpan<byte> data)
public static bool IsValid(ReadOnlySpan<byte> data)
{
if (data.Length != SIZE)
return false;

View file

@ -5,17 +5,17 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class BV7(byte[] data) : BattleVideo
public sealed class BattleVideo7(byte[] data) : IBattleVideo
{
public const int SIZE = 0x2BC0;
private const string NPC = "NPC";
private const int PlayerCount = 4;
public override byte Generation => 7;
public byte Generation => 7;
private readonly byte[] Data = (byte[])data.Clone();
public override IReadOnlyList<PK7> BattlePKMs => PlayerTeams.SelectMany(t => t).ToArray();
internal new static bool IsValid(ReadOnlySpan<byte> data) => data.Length == SIZE;
public IEnumerable<PKM> Contents => PlayerTeams.SelectMany(t => t);
public static bool IsValid(ReadOnlySpan<byte> data) => data.Length == SIZE;
private static ReadOnlySpan<ushort> TeamOffsets => [0xE41, 0x145E, 0x1A7B, 0x2098];

View file

@ -0,0 +1,3 @@
namespace PKHeX.Core;
public interface IBattleVideo : IPokeGroup, IGeneration;

View file

@ -254,7 +254,7 @@ public static class FileUtil
/// <param name="data">Binary data</param>
/// <param name="bv">Output result</param>
/// <returns>True if file object reference is valid, false if none found.</returns>
public static bool TryGetBattleVideo(byte[] data, [NotNullWhen(true)] out BattleVideo? bv)
public static bool TryGetBattleVideo(byte[] data, [NotNullWhen(true)] out IBattleVideo? bv)
{
bv = BattleVideo.GetVariantBattleVideo(data);
return bv != null;

View file

@ -190,6 +190,9 @@ public partial class SAV_PokedexSM : Form
bool isSpeciesEntry = species <= SAV.MaxSpeciesID;
editing = true;
CHK_P1.Enabled = isSpeciesEntry;
CHK_P1.Checked = Dex.GetCaught(species);
var gt = Dex.GetBaseSpeciesGenderValue(index);
var canBeMale = gt != PersonalInfo.RatioMagicFemale;
var canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless);