From 53b9c27ec9653df3bbc940b2361a4aaeada194ef Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 6 Oct 2024 14:50:17 -0500 Subject: [PATCH] Add Battle Test metadata properties Set the magic, set the flags to whatever, and refresh the checksum -> NPC recognizes you have DLC battle test ready and lets you challenge it immediately when starting a conversation with him. Of course, it crashes immediately because we don't know what the 0x000 - 0x5C1 region data should be, but hey, this is progress for unlocking unreleased content. --- .../Saves/Substructures/Gen5/BattleTest5.cs | 34 +++++++++++++++++++ .../Saves/Substructures/Gen5/MusicalShow5.cs | 1 + .../Subforms/Save Editors/Gen5/SAV_DLC5.cs | 17 ++++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/PKHeX.Core/Saves/Substructures/Gen5/BattleTest5.cs b/PKHeX.Core/Saves/Substructures/Gen5/BattleTest5.cs index 7d346bc0b..ac99155f2 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/BattleTest5.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/BattleTest5.cs @@ -1,4 +1,5 @@ using System; +using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -9,4 +10,37 @@ public class BattleTest5(Memory Raw) private Span Data => Raw.Span; public bool IsUninitialized => !Data.ContainsAnyExcept(0xFF, 0); + + public const ushort Sentinel = 0x0D68; + + // Should be equal to Sentinel otherwise the data is not valid. + public ushort Magic { get => ReadUInt16LittleEndian(Data[0x5C2..]); set => WriteUInt16LittleEndian(Data[0x5C2..], value); } + public ushort Flags { get => ReadUInt16LittleEndian(Data[0x5C4..]); set => WriteUInt16LittleEndian(Data[0x5C4..], value); } + public ushort Checksum { get => ReadUInt16LittleEndian(Data[0x5C6..]); set => WriteUInt16LittleEndian(Data[0x5C6..], value); } + + public bool IsDoubles + { + get => (Flags & 0x8000) != 0; + set + { + if (value) + Flags |= 0x8000; + else + Flags &= 0x7FFF; + } + } + + public ushort CalculateChecksum() => Checksums.CRC16_CCITT(Data[..0x5C6]); + public void RefreshChecksums() => Checksum = CalculateChecksum(); + + // Script command 0x1F2 in B2/W2 + public ushort GetScriptResultIsValid() + { + var chk = CalculateChecksum(); + if (chk != Checksum) + return 0; + if (Magic != Sentinel) + return 0; + return IsDoubles ? (ushort)2 : (ushort)1; + } } diff --git a/PKHeX.Core/Saves/Substructures/Gen5/MusicalShow5.cs b/PKHeX.Core/Saves/Substructures/Gen5/MusicalShow5.cs index 1a71efe18..c90defe1e 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/MusicalShow5.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/MusicalShow5.cs @@ -10,6 +10,7 @@ public sealed class MusicalShow5(Memory Raw) public const string Extension = "pms"; public Span Data => Raw.Span; + public bool IsUninitialized => !Data.ContainsAnyExcept(0xFF, 0); public int Length { diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_DLC5.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_DLC5.cs index 46016a167..65a224ba5 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_DLC5.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_DLC5.cs @@ -141,7 +141,7 @@ private void LoadPWT(SAV5B2W2 sav) LB_PWT.SelectedIndex = 0; } - private string? LastImportedFile = null; + private string? LastImportedFile; private bool ImportFile(string extension, string name, int expectSize, out byte[] data, string? initialName = null, int otherSize = -1) { @@ -349,9 +349,11 @@ private void B_MusicalImport_Click(object sender, EventArgs e) const int pporg = 0x17D78; if (!ImportFile(MusicalShow5.Extension, MusicalShowFileName, size, out var data, otherSize: pporg)) return; + + var musical = new MusicalShow5(data); SAV.SetMusical(data); if (LastImportedFile is { } name) - SAV.Musical.MusicalName = Path.GetFileNameWithoutExtension(name).Trim(); + SAV.Musical.MusicalName = musical.IsUninitialized ? "" : Path.GetFileNameWithoutExtension(name).Trim(); } private void B_MusicalExport_Click(object sender, EventArgs e) @@ -367,7 +369,8 @@ private void B_BattleVideoImport_Click(object sender, EventArgs e) bool decrypted = BattleVideo5.GetIsDecrypted(data); var bvid = new BattleVideo5(data) { IsDecrypted = decrypted }; bvid.Encrypt(); - bvid.RefreshChecksums(); + if (!bvid.IsUninitialized) + bvid.RefreshChecksums(); var index = LB_BattleVideo.SelectedIndex; SAV.SetBattleVideo(index, data); @@ -454,6 +457,14 @@ private void B_BattleTestImport_Click(object sender, EventArgs e) { if (!ImportFile(BattleTest5.Extension, BattleTestFileName, BattleTest5.SIZE, out var data)) return; + + // Ensure checksums are valid for user-fuzzed data. + var test = new BattleTest5(data); + if (!test.IsUninitialized) + { + test.Magic = BattleTest5.Sentinel; + test.RefreshChecksums(); + } SAV.SetBattleTest(data); } }