From 7ab42e7cc2196b755bfdf92d0d752bff17ac2f6a Mon Sep 17 00:00:00 2001 From: Kurt Date: Fri, 4 Jan 2019 00:07:37 -0800 Subject: [PATCH] Misc improvements remove alloc on gc key advancement; advance keys in place make g6 sizes an explicit comparison instead of new[].Contains replace Any/Count with Array.Find calls (removes linq dependency from savetype detection!) --- PKHeX.Core/Saves/SAV4BR.cs | 4 +-- PKHeX.Core/Saves/Util/SaveUtil.cs | 58 +++++++++++++++++-------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/PKHeX.Core/Saves/SAV4BR.cs b/PKHeX.Core/Saves/SAV4BR.cs index 184748ce3..ee688b008 100644 --- a/PKHeX.Core/Saves/SAV4BR.cs +++ b/PKHeX.Core/Saves/SAV4BR.cs @@ -243,7 +243,7 @@ public static byte[] DecryptPBRSaveData(byte[] input) output[ofs + (i * 2)] = (byte)(val >> 8); output[ofs + (i * 2) + 1] = (byte)val; } - keys = SaveUtil.AdvanceGCKeys(keys); + SaveUtil.AdvanceGCKeys(keys); } } return output; @@ -268,7 +268,7 @@ private static byte[] EncryptPBRSaveData(byte[] input) output[ofs + (i * 2)] = (byte)(val >> 8); output[ofs + (i * 2) + 1] = (byte)val; } - keys = SaveUtil.AdvanceGCKeys(keys); + SaveUtil.AdvanceGCKeys(keys); } } return output; diff --git a/PKHeX.Core/Saves/Util/SaveUtil.cs b/PKHeX.Core/Saves/Util/SaveUtil.cs index 5b8498939..e5298b7ea 100644 --- a/PKHeX.Core/Saves/Util/SaveUtil.cs +++ b/PKHeX.Core/Saves/Util/SaveUtil.cs @@ -227,25 +227,26 @@ internal static GameVersion GetIsG3SAV(byte[] data) int count = data.Length/SIZE_G3RAWHALF; for (int s = 0; s < count; s++) { - int ofs = 0xE000*s; - int[] BlockOrder = new int[14]; - for (int i = 0; i < 14; i++) - BlockOrder[i] = BitConverter.ToInt16(data, (i * 0x1000) + 0xFF4 + ofs); + const int blockcount = 14; + const int blocksize = 0x1000; + int ofs = blockcount * blocksize * s; + int[] BlockOrder = new int[blockcount]; + for (int i = 0; i < BlockOrder.Length; i++) + BlockOrder[i] = BitConverter.ToUInt16(data, (i * blocksize) + 0xFF4 + ofs); - if (BlockOrder.Any(i => i > 0xD || i < 0)) + if (Array.FindIndex(BlockOrder, i => i > 0xD) >= 0) // invalid block ID continue; - // Detect RS/E/FRLG - // Section 0 stores Game Code @ 0x00AC; 0 for RS, 1 for FRLG, else for Emerald int Block0 = Array.IndexOf(BlockOrder, 0); // Sometimes not all blocks are present (start of game), yielding multiple block0's. // Real 0th block comes before block1. if (BlockOrder[0] == 1 && Block0 != BlockOrder.Length - 1) continue; - if (BlockOrder.Count(v => v == 0) == BlockOrder.Length) + if (Array.FindIndex(BlockOrder, v => v != 0) < 0) // all blocks are 0 continue; - return SAV3.GetVersion(data, (0x1000 * Block0) + ofs); + // Detect RS/E/FRLG + return SAV3.GetVersion(data, (blocksize * Block0) + ofs); } return GameVersion.Invalid; } @@ -330,9 +331,9 @@ bool validSequence(int offset) return false; var sdk = BitConverter.ToUInt32(data, offset - 0x8); - const int SDK_INT = 0x20060623; - const int SDK_KO = 0x20070903; - return sdk == SDK_INT || sdk == SDK_KO; + const int DATE_INT = 0x20060623; + const int DATE_KO = 0x20070903; + return sdk == DATE_INT || sdk == DATE_KO; } // Check the other save -- first save is done to the latter half of the binary. @@ -367,6 +368,7 @@ internal static GameVersion GetIsG5SAV(byte[] data) if (data.Length != SIZE_G5RAW) return GameVersion.Invalid; + // check the checksum block validity; nobody would normally modify this region ushort chk1 = BitConverter.ToUInt16(data, SIZE_G5BW - 0x100 + 0x8C + 0xE); ushort actual1 = CRC16_CCITT(data, SIZE_G5BW - 0x100, 0x8C); if (chk1 == actual1) @@ -383,7 +385,7 @@ internal static GameVersion GetIsG5SAV(byte[] data) /// Version Identifier or Invalid if type cannot be determined. private static GameVersion GetIsG6SAV(byte[] data) { - if (!new []{SIZE_G6XY, SIZE_G6ORAS, SIZE_G6ORASDEMO}.Contains(data.Length)) + if (data.Length != SIZE_G6XY && data.Length != SIZE_G6ORAS && data.Length != SIZE_G6ORASDEMO) return GameVersion.Invalid; if (BitConverter.ToUInt32(data, data.Length - 0x1F0) != BEEF) @@ -1102,7 +1104,7 @@ public static byte[] DecryptGC(byte[] input, int start, int end, ushort[] keys) output[index] = (byte)(val >> 8); output[index + 1] = (byte)val; } - keys = AdvanceGCKeys(keys); + AdvanceGCKeys(keys); } return output; } @@ -1120,25 +1122,27 @@ public static byte[] EncryptGC(byte[] input, int start, int end, ushort[] keys) output[index] = (byte)(val >> 8); output[index + 1] = (byte)val; } - keys = AdvanceGCKeys(keys); + AdvanceGCKeys(keys); } return output; } - public static ushort[] AdvanceGCKeys(ushort[] oldKeys) + public static void AdvanceGCKeys(ushort[] keys) { - oldKeys[0] += 0x43; - oldKeys[1] += 0x29; - oldKeys[2] += 0x17; - oldKeys[3] += 0x13; + keys[0] += 0x43; + keys[1] += 0x29; + keys[2] += 0x17; + keys[3] += 0x13; - return new[] - { - (ushort)((oldKeys[0] >> 00 & 0xf) | (oldKeys[1] << 4 & 0xf0) | (oldKeys[2] << 8 & 0xf00) | (oldKeys[3] << 12 & 0xf000)), - (ushort)((oldKeys[0] >> 04 & 0xf) | (oldKeys[1] << 0 & 0xf0) | (oldKeys[2] << 4 & 0xf00) | (oldKeys[3] << 08 & 0xf000)), - (ushort)((oldKeys[0] >> 08 & 0xf) | (oldKeys[1] >> 4 & 0xf0) | (oldKeys[2] >> 0 & 0xf00) | (oldKeys[3] << 04 & 0xf000)), - (ushort)((oldKeys[0] >> 12 & 0xf) | (oldKeys[1] >> 8 & 0xf0) | (oldKeys[2] >> 4 & 0xf00) | (oldKeys[3] << 00 & 0xf000)), - }; + var _0 = (ushort)((keys[0] >> 00 & 0xf) | (keys[1] << 4 & 0xf0) | (keys[2] << 8 & 0xf00) | (keys[3] << 12 & 0xf000)); + var _1 = (ushort)((keys[0] >> 04 & 0xf) | (keys[1] << 0 & 0xf0) | (keys[2] << 4 & 0xf00) | (keys[3] << 08 & 0xf000)); + var _2 = (ushort)((keys[0] >> 08 & 0xf) | (keys[1] >> 4 & 0xf0) | (keys[2] >> 0 & 0xf00) | (keys[3] << 04 & 0xf000)); + var _3 = (ushort)((keys[0] >> 12 & 0xf) | (keys[1] >> 8 & 0xf0) | (keys[2] >> 4 & 0xf00) | (keys[3] << 00 & 0xf000)); + + keys[0] = _0; + keys[1] = _1; + keys[2] = _2; + keys[3] = _3; } ///