diff --git a/PKHeX/PKHeX.csproj b/PKHeX/PKHeX.csproj index 4ac51cb68..807cdf50f 100644 --- a/PKHeX/PKHeX.csproj +++ b/PKHeX/PKHeX.csproj @@ -375,6 +375,7 @@ SplashScreen.cs + diff --git a/PKHeX/Saves/SAV3Colosseum.cs b/PKHeX/Saves/SAV3Colosseum.cs index 77d7c4306..5b6285da1 100644 --- a/PKHeX/Saves/SAV3Colosseum.cs +++ b/PKHeX/Saves/SAV3Colosseum.cs @@ -325,7 +325,6 @@ namespace PKHeX } } - // Daycare Structure: // 0x00 -- Occupied // 0x01 -- Deposited Level @@ -338,64 +337,4 @@ namespace PKHeX public override void setDaycareEXP(int loc, int slot, uint EXP) { } public override void setDaycareOccupied(int loc, int slot, bool occupied) { } } - internal static class BigEndian - { - internal static uint ToUInt32(byte[] data, int offset) - { - int val = 0; - val |= data[offset + 0] << 24; - val |= data[offset + 1] << 16; - val |= data[offset + 2] << 8; - val |= data[offset + 3] << 0; - return (uint)val; - } - internal static ushort ToUInt16(byte[] data, int offset) - { - int val = 0; - val |= data[offset + 0] << 8; - val |= data[offset + 1] << 0; - return (ushort)val; - } - internal static int ToInt32(byte[] data, int offset) - { - int val = 0; - val |= data[offset + 0] << 24; - val |= data[offset + 1] << 16; - val |= data[offset + 2] << 8; - val |= data[offset + 3] << 0; - return val; - } - internal static short ToInt16(byte[] data, int offset) - { - int val = 0; - val |= data[offset + 0] << 8; - val |= data[offset + 1] << 0; - return (short)val; - } - internal static byte[] GetBytes(int value) - { - return Invert(BitConverter.GetBytes(value)); - } - internal static byte[] GetBytes(short value) - { - return Invert(BitConverter.GetBytes(value)); - } - internal static byte[] GetBytes(uint value) - { - return Invert(BitConverter.GetBytes(value)); - } - internal static byte[] GetBytes(ushort value) - { - return Invert(BitConverter.GetBytes(value)); - } - private static byte[] Invert(byte[] data) - { - byte[] result = new byte[data.Length]; - int o = 0; - int i = data.Length; - while (o != data.Length) - result[--i] = data[o++]; - return result; - } - } } diff --git a/PKHeX/Saves/SAV4BR.cs b/PKHeX/Saves/SAV4BR.cs index bf209512d..ab448441f 100644 --- a/PKHeX/Saves/SAV4BR.cs +++ b/PKHeX/Saves/SAV4BR.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Text; @@ -12,6 +11,7 @@ namespace PKHeX public override string Filter => "PbrSaveData|*"; public override string Extension => ""; + private const int SAVE_COUNT = 4; public SAV4BR(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G4BR] : (byte[])data.Clone(); @@ -24,8 +24,7 @@ namespace PKHeX Data = DecryptPBRSaveData(data); // Detect active save - if (Util.SwapEndianness(BitConverter.ToUInt32(Data, 0x1C004C)) > - Util.SwapEndianness(BitConverter.ToUInt32(Data, 0x4C))) + if (BigEndian.ToUInt32(Data, 0x1C004C) > BigEndian.ToUInt32(Data, 0x4C)) { byte[] tempData = new byte[0x1C0000]; Array.Copy(Data, 0, tempData, 0, 0x1C0000); @@ -34,8 +33,8 @@ namespace PKHeX } SaveSlots = new List(); - SaveNames = new string[4]; - for (int i = 0; i < 4; i++) + SaveNames = new string[SAVE_COUNT]; + for (int i = 0; i < SAVE_COUNT; i++) { if (BitConverter.ToUInt16(Data, 0x390 + 0x6FF00*i) != 0) { @@ -53,20 +52,20 @@ namespace PKHeX resetBoxes(); } - private readonly int SaveCount; - public override byte[] Write(bool dsv = false) + private readonly int SaveCount; // TODO : unique save identification + public override byte[] Write(bool DSV) { setChecksums(); return EncryptPBRSaveData(Data); } // Configuration - public override SaveFile Clone() { return new SAV4BR(Write()); } + public override SaveFile Clone() { return new SAV4BR(Write(DSV: false)); } - public List SaveSlots; - public string[] SaveNames; + public readonly List SaveSlots; + public readonly string[] SaveNames; public int CurrentSlot; - protected override int Box { + protected override int Box { // 4 save slots, data reading depends on current slot get { return 0x978 + 0x6FF00*CurrentSlot; } set { } } @@ -111,19 +110,13 @@ namespace PKHeX return valid; } } - public override string ChecksumInfo - { - get - { - return $"Checksums valid: {ChecksumsValid}."; - } - } + public override string ChecksumInfo => $"Checksums valid: {ChecksumsValid}."; // Trainer Info public override GameVersion Version { get { return GameVersion.BATREV; } protected set { } } // Storage - public override int getPartyOffset(int slot) + public override int getPartyOffset(int slot) // TODO { return -1; } @@ -131,23 +124,13 @@ namespace PKHeX { return Box + SIZE_STORED * box * 30; } - public override int CurrentBox - { - get { return 0; } - set { /* This isn't a real field. */ } - } - public override int getBoxWallpaper(int box) - { - return 0; - } - public override string getBoxName(int box) - { - return $"BOX {box + 1}"; - } - public override void setBoxName(int box, string value) - { - /* No custom box names here. */ - } + + // Save file does not have Box Name / Wallpaper info + public override int CurrentBox { get { return 0; } set { } } + public override int getBoxWallpaper(int box) { return box; } + public override string getBoxName(int box) { return $"BOX {box + 1}"; } + public override void setBoxName(int box, string value) { } + public override PKM getPKM(byte[] data) { byte[] pkm = data.Take(SIZE_STORED).ToArray(); @@ -161,40 +144,24 @@ namespace PKHeX protected override void setDex(PKM pkm) { } - public override void setStoredSlot(PKM pkm, int offset, bool? trade = null, bool? dex = null) - { - if (pkm == null) return; - if (pkm.GetType() != PKMType) - throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a Battle Revolution Save File."); - if (trade ?? SetUpdatePKM) - setPKM(pkm); - if (dex ?? SetUpdateDex) - setDex(pkm); - byte[] data = pkm.EncryptedBoxData; - setData(data, offset); - - Edited = true; - } - public static byte[] DecryptPBRSaveData(byte[] input) { byte[] output = new byte[input.Length]; for (int base_ofs = 0; base_ofs < SaveUtil.SIZE_G4BR; base_ofs += 0x1C0000) { - Array.Copy(input, base_ofs, output, base_ofs, 8); ushort[] keys = new ushort[4]; for (int i = 0; i < keys.Length; i++) - keys[i] = Util.SwapEndianness(BitConverter.ToUInt16(input, base_ofs + i * 2)); + keys[i] = BigEndian.ToUInt16(input, base_ofs + i * 2); for (int ofs = base_ofs + 8; ofs < base_ofs + 0x1C0000; ofs += 8) { for (int i = 0; i < keys.Length; i++) { - ushort val = Util.SwapEndianness(BitConverter.ToUInt16(input, ofs + i*2)); + ushort val = BigEndian.ToUInt16(input, ofs + i*2); val -= keys[i]; - BitConverter.GetBytes(Util.SwapEndianness(val)).CopyTo(output, ofs + i*2); + BigEndian.GetBytes(val).CopyTo(output, ofs + i*2); } ushort[] oldKeys = (ushort[])keys.Clone(); oldKeys[0] += 0x43; @@ -210,25 +177,24 @@ namespace PKHeX return output; } - public static byte[] EncryptPBRSaveData(byte[] input) + private static byte[] EncryptPBRSaveData(byte[] input) { byte[] output = new byte[input.Length]; for (int base_ofs = 0; base_ofs < SaveUtil.SIZE_G4BR; base_ofs += 0x1C0000) { - Array.Copy(input, base_ofs, output, base_ofs, 8); ushort[] keys = new ushort[4]; for (int i = 0; i < keys.Length; i++) - keys[i] = Util.SwapEndianness(BitConverter.ToUInt16(input, base_ofs + i * 2)); + keys[i] = BigEndian.ToUInt16(input, base_ofs + i * 2); for (int ofs = base_ofs + 8; ofs < base_ofs + 0x1C0000; ofs += 8) { for (int i = 0; i < keys.Length; i++) { - ushort val = Util.SwapEndianness(BitConverter.ToUInt16(input, ofs + i * 2)); + ushort val = BigEndian.ToUInt16(input, ofs + i * 2); val += keys[i]; - BitConverter.GetBytes(Util.SwapEndianness(val)).CopyTo(output, ofs + i * 2); + BigEndian.GetBytes(val).CopyTo(output, ofs + i * 2); } ushort[] oldKeys = (ushort[])keys.Clone(); oldKeys[0] += 0x43; @@ -249,15 +215,15 @@ namespace PKHeX uint[] storedChecksums = new uint[16]; for (int i = 0; i < storedChecksums.Length; i++) { - storedChecksums[i] = Util.SwapEndianness(BitConverter.ToUInt32(input, checksum_offset + i*4)); - BitConverter.GetBytes((uint) 0).CopyTo(input, checksum_offset + i*4); + storedChecksums[i] = BigEndian.ToUInt32(input, checksum_offset + i*4); + BitConverter.GetBytes((uint)0).CopyTo(input, checksum_offset + i*4); } uint[] checksums = new uint[16]; for (int i = 0; i < len; i += 2) { - ushort val = Util.SwapEndianness(BitConverter.ToUInt16(input, offset + i)); + ushort val = BigEndian.ToUInt16(input, offset + i); for (int j = 0; j < 16; j++) { checksums[j] += (uint)((val >> j) & 1); @@ -266,7 +232,7 @@ namespace PKHeX for (int i = 0; i < storedChecksums.Length; i++) { - BitConverter.GetBytes(Util.SwapEndianness(storedChecksums[i])).CopyTo(input, checksum_offset + i*4); + BigEndian.GetBytes(storedChecksums[i]).CopyTo(input, checksum_offset + i*4); } return checksums.SequenceEqual(storedChecksums); @@ -277,7 +243,7 @@ namespace PKHeX uint[] storedChecksums = new uint[16]; for (int i = 0; i < storedChecksums.Length; i++) { - storedChecksums[i] = Util.SwapEndianness(BitConverter.ToUInt32(input, checksum_offset + i * 4)); + storedChecksums[i] = BigEndian.ToUInt32(input, checksum_offset + i * 4); BitConverter.GetBytes((uint)0).CopyTo(input, checksum_offset + i * 4); } @@ -285,7 +251,7 @@ namespace PKHeX for (int i = 0; i < len; i += 2) { - ushort val = Util.SwapEndianness(BitConverter.ToUInt16(input, offset + i)); + ushort val = BigEndian.ToUInt16(input, offset + i); for (int j = 0; j < 16; j++) { checksums[j] += (uint)((val >> j) & 1); @@ -294,13 +260,8 @@ namespace PKHeX for (int i = 0; i < checksums.Length; i++) { - BitConverter.GetBytes(Util.SwapEndianness(checksums[i])).CopyTo(input, checksum_offset + i * 4); + BigEndian.GetBytes(checksums[i]).CopyTo(input, checksum_offset + i * 4); } } - - private void SwapBytes(byte[] input, int offset, int num_bytes) - { - input.Skip(offset).Take(num_bytes).Reverse().ToArray().CopyTo(input, offset); - } } } diff --git a/PKHeX/Saves/SaveFile.cs b/PKHeX/Saves/SaveFile.cs index 0dc4f42da..4431602bb 100644 --- a/PKHeX/Saves/SaveFile.cs +++ b/PKHeX/Saves/SaveFile.cs @@ -373,7 +373,7 @@ namespace PKHeX { if (pkm == null) return; if (pkm.GetType() != PKMType) - throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a Gen{Generation} Save File."); + throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a {GetType().Name.Last()} Save File."); if (trade ?? SetUpdatePKM) setPKM(pkm); if (dex ?? SetUpdateDex) diff --git a/PKHeX/Util/BigEndian.cs b/PKHeX/Util/BigEndian.cs new file mode 100644 index 000000000..35258012e --- /dev/null +++ b/PKHeX/Util/BigEndian.cs @@ -0,0 +1,67 @@ +using System; + +namespace PKHeX +{ + internal static class BigEndian + { + internal static uint ToUInt32(byte[] data, int offset) + { + int val = 0; + val |= data[offset + 0] << 24; + val |= data[offset + 1] << 16; + val |= data[offset + 2] << 8; + val |= data[offset + 3] << 0; + return (uint)val; + } + internal static ushort ToUInt16(byte[] data, int offset) + { + int val = 0; + val |= data[offset + 0] << 8; + val |= data[offset + 1] << 0; + return (ushort)val; + } + internal static int ToInt32(byte[] data, int offset) + { + int val = 0; + val |= data[offset + 0] << 24; + val |= data[offset + 1] << 16; + val |= data[offset + 2] << 8; + val |= data[offset + 3] << 0; + return val; + } + internal static short ToInt16(byte[] data, int offset) + { + int val = 0; + val |= data[offset + 0] << 8; + val |= data[offset + 1] << 0; + return (short)val; + } + + internal static byte[] GetBytes(int value) + { + return Invert(BitConverter.GetBytes(value)); + } + internal static byte[] GetBytes(short value) + { + return Invert(BitConverter.GetBytes(value)); + } + internal static byte[] GetBytes(uint value) + { + return Invert(BitConverter.GetBytes(value)); + } + internal static byte[] GetBytes(ushort value) + { + return Invert(BitConverter.GetBytes(value)); + } + + private static byte[] Invert(byte[] data) + { + byte[] result = new byte[data.Length]; + int o = 0; + int i = data.Length; + while (o != data.Length) + result[--i] = data[o++]; + return result; + } + } +}