From 84185dc6c9a1f8ebd7caf8e30598d2e290c282ce Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 5 Aug 2018 12:39:06 -0700 Subject: [PATCH] misc improvements add records class for managing info for trainer records add more b2w2 block docs --- PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs | 36 +++++----- PKHeX.Core/Saves/SAV7.cs | 70 ++----------------- PKHeX.Core/Saves/Substructures/Records.cs | 85 +++++++++++++++++++++++ 3 files changed, 109 insertions(+), 82 deletions(-) create mode 100644 PKHeX.Core/Saves/Substructures/Records.cs diff --git a/PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs b/PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs index 576cc5e0b..5af7c1ed7 100644 --- a/PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs +++ b/PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs @@ -147,33 +147,33 @@ protected override void SetChecksum(byte[] data) new BlockInfoNDS(0x19600, 0x1338, 0x1A93A, 0x25F3A), // Unity Tower and survey stuff new BlockInfoNDS(0x1AA00, 0x07c4, 0x1B1C6, 0x25F3C), // Pal Pad Player Data (30d) new BlockInfoNDS(0x1B200, 0x0d54, 0x1BF56, 0x25F3E), // Pal Pad Friend Data - new BlockInfoNDS(0x1C000, 0x0094, 0x1C096, 0x25F40), // Skin Info - new BlockInfoNDS(0x1C100, 0x0658, 0x1C75A, 0x25F42), // Card Signature Block & ???? + new BlockInfoNDS(0x1C000, 0x0094, 0x1C096, 0x25F40), // Options / Skin Info + new BlockInfoNDS(0x1C100, 0x0658, 0x1C75A, 0x25F42), // Trainer Card new BlockInfoNDS(0x1C800, 0x0a94, 0x1D296, 0x25F44), // Mystery Gift new BlockInfoNDS(0x1D300, 0x01ac, 0x1D4AE, 0x25F46), // Dream World Stuff (Catalog) new BlockInfoNDS(0x1D500, 0x03ec, 0x1D8EE, 0x25F48), // Chatter new BlockInfoNDS(0x1D900, 0x005c, 0x1D95E, 0x25F4A), // Adventure data - new BlockInfoNDS(0x1DA00, 0x01e0, 0x1DBE2, 0x25F4C), // Trainer Card Records + new BlockInfoNDS(0x1DA00, 0x01e0, 0x1DBE2, 0x25F4C), // Record new BlockInfoNDS(0x1DC00, 0x00a8, 0x1DCAA, 0x25F4E), // ??? - new BlockInfoNDS(0x1DD00, 0x0460, 0x1E162, 0x25F50), // (40d) + new BlockInfoNDS(0x1DD00, 0x0460, 0x1E162, 0x25F50), // Mail (40d) new BlockInfoNDS(0x1E200, 0x1400, 0x1F602, 0x25F52), // ??? - new BlockInfoNDS(0x1F700, 0x02a4, 0x1F9A6, 0x25F54), // Contains flags and references for downloaded data (Musical) + new BlockInfoNDS(0x1F700, 0x02a4, 0x1F9A6, 0x25F54), // Musical new BlockInfoNDS(0x1FA00, 0x00e0, 0x1FAE2, 0x25F56), // Fused Reshiram/Zekrom Storage - new BlockInfoNDS(0x1FB00, 0x034c, 0x1FE4E, 0x25F58), // ??? - new BlockInfoNDS(0x1FF00, 0x04e0, 0x203E2, 0x25F5A), // Const Data Block and Event Flag Block (0x35E is the split) + new BlockInfoNDS(0x1FB00, 0x034c, 0x1FE4E, 0x25F58), // IR + new BlockInfoNDS(0x1FF00, 0x04e0, 0x203E2, 0x25F5A), // EventWork new BlockInfoNDS(0x20400, 0x00f8, 0x204FA, 0x25F5C), // ??? - new BlockInfoNDS(0x20500, 0x02fc, 0x207FE, 0x25F5E), // Tournament Block - new BlockInfoNDS(0x20800, 0x0094, 0x20896, 0x25F60), // ??? - new BlockInfoNDS(0x20900, 0x035c, 0x20C5E, 0x25F62), // Battle Box Block - new BlockInfoNDS(0x20D00, 0x01d4, 0x20ED6, 0x25F64), // Daycare Block (50d) + new BlockInfoNDS(0x20500, 0x02fc, 0x207FE, 0x25F5E), // Regulation + new BlockInfoNDS(0x20800, 0x0094, 0x20896, 0x25F60), // Gimmick + new BlockInfoNDS(0x20900, 0x035c, 0x20C5E, 0x25F62), // Battle Box + new BlockInfoNDS(0x20D00, 0x01d4, 0x20ED6, 0x25F64), // Daycare (50d) new BlockInfoNDS(0x20F00, 0x01e0, 0x210E2, 0x25F66), // Strength Boulder Status Block - new BlockInfoNDS(0x21100, 0x00f0, 0x211F2, 0x25F68), // Badge Flags, Money, Trainer Sayings + new BlockInfoNDS(0x21100, 0x00f0, 0x211F2, 0x25F68), // Misc (Badge Flags, Money, Trainer Sayings) new BlockInfoNDS(0x21200, 0x01b4, 0x213B6, 0x25F6A), // Entralink (Level & Powers etc) new BlockInfoNDS(0x21400, 0x04dc, 0x218DE, 0x25F6C), // Pokedex - new BlockInfoNDS(0x21900, 0x0034, 0x21936, 0x25F6E), // Swarm and other overworld info - 2C - swarm, 2D - repel steps, 2E repel type - new BlockInfoNDS(0x21A00, 0x003c, 0x21A3E, 0x25F70), // ??? - new BlockInfoNDS(0x21B00, 0x01ac, 0x21CAE, 0x25F72), // Battle Subway - new BlockInfoNDS(0x21D00, 0x0b90, 0x22892, 0x25F74), // ??? + new BlockInfoNDS(0x21900, 0x0034, 0x21936, 0x25F6E), // Encount (Swarm and other overworld info - 2C - swarm, 2D - repel steps, 2E repel type) + new BlockInfoNDS(0x21A00, 0x003c, 0x21A3E, 0x25F70), // Battle Subway Play Info + new BlockInfoNDS(0x21B00, 0x01ac, 0x21CAE, 0x25F72), // Battle Subway Score Info + new BlockInfoNDS(0x21D00, 0x0b90, 0x22892, 0x25F74), // Battle Subway WiFI Info new BlockInfoNDS(0x22900, 0x00ac, 0x229AE, 0x25F76), // Online Records new BlockInfoNDS(0x22A00, 0x0850, 0x23252, 0x25F78), // Entralink Forest pokémon data (60d) new BlockInfoNDS(0x23300, 0x0284, 0x23586, 0x25F7A), // ??? @@ -183,9 +183,9 @@ protected override void SetChecksum(byte[] data) new BlockInfoNDS(0x23A00, 0x0080, 0x23A82, 0x25F82), // ??? new BlockInfoNDS(0x23B00, 0x00fc, 0x23BFE, 0x25F84), // Hollow/Rival Block new BlockInfoNDS(0x23C00, 0x16a8, 0x252AA, 0x25F86), // Join Avenue Block - new BlockInfoNDS(0x25300, 0x0498, 0x2579A, 0x25F88), // Medal data + new BlockInfoNDS(0x25300, 0x0498, 0x2579A, 0x25F88), // Medal new BlockInfoNDS(0x25800, 0x0060, 0x25862, 0x25F8A), // Key-related data - new BlockInfoNDS(0x25900, 0x00fc, 0x259FE, 0x25F8C), // (70d) + new BlockInfoNDS(0x25900, 0x00fc, 0x259FE, 0x25F8C), // Festa Missions (70d) new BlockInfoNDS(0x25A00, 0x03e4, 0x25DE6, 0x25F8E), // ??? new BlockInfoNDS(0x25E00, 0x00f0, 0x25EF2, 0x25F90), // ??? new BlockInfoNDS(0x25F00, 0x0094, 0x25FA2, 0x25FA2), // Checksum Block (73d) diff --git a/PKHeX.Core/Saves/SAV7.cs b/PKHeX.Core/Saves/SAV7.cs index ccbcd34db..602c2042e 100644 --- a/PKHeX.Core/Saves/SAV7.cs +++ b/PKHeX.Core/Saves/SAV7.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; @@ -702,7 +701,7 @@ public override int PlayedSeconds public int RecordCount => 200; public int GetRecord(int recordID) { - int ofs = GetRecordOffset(recordID); + int ofs = Records.GetOffset(Record, recordID); if (recordID < 100) return BitConverter.ToInt32(Data, ofs); if (recordID < 200) @@ -711,9 +710,9 @@ public int GetRecord(int recordID) } public void SetRecord(int recordID, int value) { - int ofs = GetRecordOffset(recordID); - var maxes = USUM ? RecordMaxType_USUM: RecordMaxType_SM; - int max = GetRecordMax(recordID, maxes); + int ofs = Records.GetOffset(Record, recordID); + var maxes = USUM ? Records.MaxType_USUM: Records.MaxType_SM; + int max = Records.GetMax(recordID, maxes); if (value > max) value = max; if (recordID < 100) @@ -721,65 +720,8 @@ public void SetRecord(int recordID, int value) if (recordID < 200) BitConverter.GetBytes((ushort)value).CopyTo(Data, ofs); } - public int GetRecordOffset(int recordID) - { - if (recordID < 100) - return Record + recordID*4; - if (recordID < 200) - return Record + recordID*2 + 200; // first 100 are 4bytes, so bias the difference - return -1; - } - public int GetRecordMax(int recordID) => GetRecordMax(recordID, USUM ? RecordMaxType_USUM : RecordMaxType_SM); - private static int GetRecordMax(int recordID, IReadOnlyList maxes) => recordID < 200 ? RecordMax[maxes[recordID]] : 0; - private static readonly int[] RecordMax = {999999999, 9999999, 999999, 99999, 65535, 9999, 999}; - private static readonly int[] RecordMaxType_SM = - { - 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - }; - private static readonly int[] RecordMaxType_USUM = - { - 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, - 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 4, 4, 4, 5, 5, 4, 5, 5 - }; + public int GetRecordMax(int recordID) => Records.GetMax(recordID, USUM ? Records.MaxType_USUM : Records.MaxType_SM); + public int GetRecordOffset(int recordID) => Records.GetOffset(Record, recordID); public ushort PokeFinderCameraVersion { diff --git a/PKHeX.Core/Saves/Substructures/Records.cs b/PKHeX.Core/Saves/Substructures/Records.cs new file mode 100644 index 000000000..a47d1d834 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Records.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; + +namespace PKHeX.Core +{ + public static class Records + { + private const int LargeRecordCount = 100; + private const int SmallRecordCount = 100; + private const int Count = LargeRecordCount + SmallRecordCount; + + /// + /// Gets the maximum value for the specified record using the provided maximum list. + /// + /// Record ID to retrieve the maximum for + /// Maximum enum values for each record + /// Maximum the record can be + public static int GetMax(int recordID, IReadOnlyList maxes) + { + if (recordID >= Count) + return 0; + return MaxByType[maxes[recordID]]; + } + + public static int GetOffset(int baseOfs, int recordID) + { + if (recordID < LargeRecordCount) + return baseOfs + (recordID * 4); + if (recordID < Count) + return baseOfs + (recordID * 2) + 200; // first 100 are 4bytes, so bias the difference + return -1; + } + + private static readonly int[] MaxByType = { 999999999, 9999999, 999999, 99999, 65535, 9999, 999 }; + + public static readonly IReadOnlyList MaxType_SM = new[] + { + 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + }; + + public static readonly IReadOnlyList MaxType_USUM = new[] + { + 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 4, 4, 4, 5, 5, 4, 5, 5 + }; + } +}