From 934757eac19ed55df92848bfcd1ce6414f095472 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 24 Feb 2018 13:03:32 -0800 Subject: [PATCH] Add Bank7 r/w --- PKHeX.Core/Saves/SaveUtil.cs | 14 ++++- PKHeX.Core/Saves/Storage/Bank7.cs | 51 +++++++++++++++++++ PKHeX.Core/Saves/Storage/BulkStorage.cs | 8 ++- .../Controls/SAV Editor/SAVEditor.cs | 13 +++-- 4 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 PKHeX.Core/Saves/Storage/Bank7.cs diff --git a/PKHeX.Core/Saves/SaveUtil.cs b/PKHeX.Core/Saves/SaveUtil.cs index b70175f9a..5f628ebc3 100644 --- a/PKHeX.Core/Saves/SaveUtil.cs +++ b/PKHeX.Core/Saves/SaveUtil.cs @@ -41,6 +41,9 @@ public static class SaveUtil public const int SIZE_G2EMU_J = 0x10030; public const int SIZE_G1RAW = 0x8000; public const int SIZE_G1BAT = 0x802C; + + // Bank Binaries + public const int SIZE_G7BANK = 0xACA48; private static readonly HashSet SIZES_2 = new HashSet { SIZE_G2RAW_U, SIZE_G2VC_U, SIZE_G2BAT_U, SIZE_G2EMU_U, SIZE_G2RAW_J, SIZE_G2BAT_J, SIZE_G2EMU_J, SIZE_G2VC_J, @@ -53,7 +56,9 @@ public static class SaveUtil SIZE_G4BR, SIZE_G4RAW, SIZE_G3BOX, SIZE_G3BOXGCI, SIZE_G3COLO, SIZE_G3COLOGCI, SIZE_G3XD, SIZE_G3XDGCI, SIZE_G3RAW, SIZE_G3RAWHALF, // SIZES_2 covers gen2 sizes since there's so many - SIZE_G1RAW, SIZE_G1BAT + SIZE_G1RAW, SIZE_G1BAT, + + SIZE_G7BANK, }; private static readonly int[] mainSizes = { SIZE_G6XY, SIZE_G6ORAS, SIZE_G7SM, SIZE_G7USUM }; @@ -91,6 +96,9 @@ private static GameVersion GetSAVGeneration(byte[] data) if (GetIsG4BRSAV(data) != GameVersion.Invalid) return GameVersion.BATREV; + if (GetIsBank7(data)) + return GameVersion.USUM; + return GameVersion.Invalid; } /// @@ -406,6 +414,7 @@ private static GameVersion GetIsG7SAV(byte[] data) return GameVersion.Invalid; } + private static bool GetIsBank7(byte[] data) => data.Length == SIZE_G7BANK && data[0] != 0; /// Creates an instance of a SaveFile using the given save data. /// Save data from which to create a SaveFile. @@ -433,6 +442,9 @@ public static SaveFile GetVariantSAV(byte[] data) case GameVersion.XD: sav = new SAV3XD(data); break; case GameVersion.RSBOX: sav = new SAV3RSBox(data); break; case GameVersion.BATREV: sav = new SAV4BR(data); break; + + // Bulk Storage + case GameVersion.USUM: sav = Bank7.GetBank7(data); break; // No pattern matched default: return null; diff --git a/PKHeX.Core/Saves/Storage/Bank7.cs b/PKHeX.Core/Saves/Storage/Bank7.cs new file mode 100644 index 000000000..c04893003 --- /dev/null +++ b/PKHeX.Core/Saves/Storage/Bank7.cs @@ -0,0 +1,51 @@ +using System; + +namespace PKHeX.Core +{ + public sealed class Bank7 : BulkStorage + { + public Bank7(byte[] data, Type t, int start, int slotsPerBox = 30) : base(data, t, start, slotsPerBox) + { + Personal = PersonalTable.USUM; + Version = GameVersion.USUM; + HeldItems = Legal.HeldItems_USUM; + } + + protected override string PlayTimeString => $"{Year:00}{Month:00}{Day:00}_{Hours:00}ː{Minutes:00}"; + public override string BAKName => $"{FileName} [{PlayTimeString}].bak"; + private const int GroupNameSize = 0x20; + private const int BankNameSize = 0x24; + private const int GroupNameSpacing = GroupNameSize + 2; + private const int BankNameSpacing = BankNameSize + 2; + + public ulong UID => BitConverter.ToUInt64(Data, 0); + public string GetGroupName(int group) + { + if (group < 0 || group > 10) + throw new ArgumentException($"{nameof(group)} must be 1-10."); + int offset = 0x8 + GroupNameSpacing * group + 2; // skip over " " + return GetString(offset, GroupNameSize / 2); + } + + public override int BoxCount => BankCount; + private int BankCount + { + get => Data[0x15E]; + set => Data[0x15E] = (byte)value; + } + private int Year => BitConverter.ToUInt16(Data, 0x160); + private int Month => Data[0x162]; + private int Day => Data[0x163]; + private int Hours => Data[0x164]; + private int Minutes => Data[0x165]; + + private int BoxDataSize => 30 * SIZE_STORED + BankNameSpacing; + public override int GetBoxOffset(int box) => Box + BoxDataSize * box; + public override string GetBoxName(int box) => GetString(GetBoxNameOffset(box), BankNameSize / 2); + public int GetBoxNameOffset(int box) => GetBoxOffset(box) + 30 * SIZE_STORED; + public int GetBoxIndex(int box) => BitConverter.ToUInt16(Data, GetBoxNameOffset(box) + BankNameSize); + + private const int BoxStart = 0x17C; + public static Bank7 GetBank7(byte[] data) => new Bank7(data, typeof(PK7), BoxStart); + } +} diff --git a/PKHeX.Core/Saves/Storage/BulkStorage.cs b/PKHeX.Core/Saves/Storage/BulkStorage.cs index 7af0c8f69..8d0e99c33 100644 --- a/PKHeX.Core/Saves/Storage/BulkStorage.cs +++ b/PKHeX.Core/Saves/Storage/BulkStorage.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace PKHeX.Core { @@ -7,7 +8,7 @@ namespace PKHeX.Core /// public class BulkStorage : SaveFile { - public BulkStorage(byte[] data, Type t, int start, int slotsPerBox = 30) + protected BulkStorage(byte[] data, Type t, int start, int slotsPerBox = 30) { Box = start; Data = data; @@ -16,11 +17,14 @@ public BulkStorage(byte[] data, Type t, int start, int slotsPerBox = 30) blank = PKMConverter.GetBlank(t); var slots = (Data.Length - Box) / blank.SIZE_STORED; BoxCount = slots / SlotsPerBox; + + Exportable = !Data.All(z => z == 0); + BAK = (byte[])Data.Clone(); } private readonly int SlotsPerBox; - public override string BAKName => $"{FileName} [{SaveUtil.CRC16(Data, Box, Data.Length - Box)}].bak"; + public override string BAKName => $"{FileName} [{SaveUtil.CRC16(Data, Box, Data.Length - Box):X4}].bak"; public override SaveFile Clone() => new BulkStorage((byte[])Data.Clone(), PKMType, Box, SlotsPerBox); public override string Filter { get; } = "All Files|*.*"; public override string Extension { get; } = ".bin"; diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs index 1c80322e9..0e4cdce20 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs @@ -986,7 +986,14 @@ private bool ToggleViewDaycare(SaveFile sav, int BoxTab, int PartyTab) } private void ToggleViewSubEditors(SaveFile sav) { - if (sav.Exportable) // Actual save file + if (!sav.Exportable || sav is BulkStorage) + { + GB_SAVtools.Visible = false; + B_JPEG.Visible = false; + SL_Extra.HideAllSlots(); + return; + } + { PAN_BattleBox.Visible = L_BattleBox.Visible = L_ReadOnlyPBB.Visible = sav.HasBattleBox; GB_Daycare.Visible = sav.HasDaycare; @@ -1023,10 +1030,6 @@ private void ToggleViewSubEditors(SaveFile sav) var slots = SL_Extra.Initialize(sav.GetExtraSlots(HaX), InitializeDragDrop); Box.SlotPictureBoxes.AddRange(slots); } - else - { - SL_Extra.HideAllSlots(); - } GB_SAVtools.Visible = sav.Exportable && FLP_SAVtools.Controls.Cast().Any(c => c.Enabled); foreach (Control c in FLP_SAVtools.Controls.Cast()) c.Visible = c.Enabled;