mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 12:33:06 +00:00
Split PokeCrypto from PKX
All logic in PokeCrypto is separate from the rest of the PKHeX.Core library; makes it easy to just rip this portion out and reuse in other projects without needing the entirety of PKHeX.Core logic optimize out the CheckEncrypted to the actual path, separate methods. Only usages of this method were with hardcoded Format values, so no impact
This commit is contained in:
parent
68e6644d40
commit
e21d108fb2
46 changed files with 528 additions and 534 deletions
|
@ -60,7 +60,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
if (_pk != null)
|
||||
return _pk;
|
||||
byte[] ekdata = new byte[PKX.SIZE_4PARTY];
|
||||
byte[] ekdata = new byte[PokeCrypto.SIZE_4PARTY];
|
||||
Array.Copy(Data, 8, ekdata, 0, ekdata.Length);
|
||||
return _pk = new PK4(ekdata);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace PKHeX.Core
|
|||
|
||||
var pkdata = value.Data.All(z => z == 0)
|
||||
? value.Data
|
||||
: PKX.EncryptArray45(value.Data);
|
||||
: PokeCrypto.EncryptArray45(value.Data);
|
||||
pkdata.CopyTo(Data, 8);
|
||||
}
|
||||
}
|
||||
|
@ -100,9 +100,9 @@ namespace PKHeX.Core
|
|||
|
||||
private void EncryptPK()
|
||||
{
|
||||
byte[] ekdata = new byte[PKX.SIZE_4PARTY];
|
||||
byte[] ekdata = new byte[PokeCrypto.SIZE_4PARTY];
|
||||
Array.Copy(Data, 8, ekdata, 0, ekdata.Length);
|
||||
ekdata = PKX.EncryptArray45(ekdata);
|
||||
ekdata = PokeCrypto.EncryptArray45(ekdata);
|
||||
ekdata.CopyTo(Data, 8);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override IReadOnlyList<ushort> ExtraBytes => Unused;
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_4STORED;
|
||||
public override int SIZE_STORED => PKX.SIZE_4STORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_4STORED;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_4STORED;
|
||||
public override int Format => 4;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.HGSS[Species];
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
Data = data;
|
||||
uint sv = ((PID & 0x3E000) >> 0xD) % 24;
|
||||
Data = PKX.ShuffleArray(Data, sv, PKX.SIZE_4BLOCK);
|
||||
Data = PokeCrypto.ShuffleArray(Data, sv, PokeCrypto.SIZE_4BLOCK);
|
||||
if (Sanity != 0 && Species <= MaxSpeciesID && !ChecksumValid) // We can only hope
|
||||
RefreshChecksum();
|
||||
if (Valid && Sanity == 0)
|
||||
|
@ -370,7 +370,7 @@ namespace PKHeX.Core
|
|||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
return PKX.ShuffleArray(Data, PKX.blockPositionInvert[((PID & 0x3E000) >> 0xD)%24], PKX.SIZE_4BLOCK);
|
||||
return PokeCrypto.ShuffleArray(Data, PokeCrypto.blockPositionInvert[((PID & 0x3E000) >> 0xD)%24], PokeCrypto.SIZE_4BLOCK);
|
||||
}
|
||||
|
||||
public PK4 ConvertToPK4()
|
||||
|
|
|
@ -17,8 +17,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override IReadOnlyList<ushort> ExtraBytes => Unused;
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_3CSTORED;
|
||||
public override int SIZE_STORED => PKX.SIZE_3CSTORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_3CSTORED;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_3CSTORED;
|
||||
public override int Format => 3;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.RS[Species];
|
||||
public override byte[] Data { get; }
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace PKHeX.Core
|
|||
|
||||
public PB7(byte[] data)
|
||||
{
|
||||
PKX.CheckEncrypted(ref data, 7);
|
||||
PokeCrypto.DecryptIfEncrypted67(ref data);
|
||||
if (data.Length != SIZE)
|
||||
Array.Resize(ref data, SIZE);
|
||||
Data = data;
|
||||
|
|
|
@ -10,13 +10,13 @@ namespace PKHeX.Core
|
|||
|
||||
public override bool Valid => Species <= 151 && (Data[0] == 0 || Species != 0);
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_1PARTY;
|
||||
public override int SIZE_STORED => PKX.SIZE_1STORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_1PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_1STORED;
|
||||
public override bool Korean => false;
|
||||
|
||||
public override int Format => 1;
|
||||
|
||||
public PK1(bool jp = false) : base(new byte[PKX.SIZE_1PARTY], jp) { }
|
||||
public PK1(bool jp = false) : base(new byte[PokeCrypto.SIZE_1PARTY], jp) { }
|
||||
public PK1(byte[] decryptedData, bool jp = false) : base(decryptedData, jp) { }
|
||||
|
||||
public override PKM Clone() => new PK1((byte[])Data.Clone(), Japanese)
|
||||
|
|
|
@ -9,13 +9,13 @@ namespace PKHeX.Core
|
|||
|
||||
public override bool Valid => Species <= 252;
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_2PARTY;
|
||||
public override int SIZE_STORED => PKX.SIZE_2STORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_2PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_2STORED;
|
||||
public override bool Korean => !Japanese && otname[0] <= 0xB;
|
||||
|
||||
public override int Format => 2;
|
||||
|
||||
public PK2(bool jp = false) : base(new byte[PKX.SIZE_2PARTY], jp) { }
|
||||
public PK2(bool jp = false) : base(new byte[PokeCrypto.SIZE_2PARTY], jp) { }
|
||||
public PK2(byte[] decryptedData, bool jp = false) : base(decryptedData, jp) { }
|
||||
|
||||
public override PKM Clone() => new PK2((byte[])Data.Clone(), Japanese)
|
||||
|
|
|
@ -11,27 +11,27 @@ namespace PKHeX.Core
|
|||
0x2A, 0x2B
|
||||
};
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_3PARTY;
|
||||
public override int SIZE_STORED => PKX.SIZE_3STORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_3PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_3STORED;
|
||||
public override int Format => 3;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.RS[Species];
|
||||
|
||||
public override IReadOnlyList<ushort> ExtraBytes => Unused;
|
||||
|
||||
public override byte[] Data { get; }
|
||||
public PK3() => Data = new byte[PKX.SIZE_3PARTY];
|
||||
public PK3() => Data = new byte[PokeCrypto.SIZE_3PARTY];
|
||||
|
||||
public PK3(byte[] data)
|
||||
{
|
||||
PKX.CheckEncrypted(ref data, Format);
|
||||
if (data.Length != PKX.SIZE_3PARTY)
|
||||
Array.Resize(ref data, PKX.SIZE_3PARTY);
|
||||
PokeCrypto.DecryptIfEncrypted3(ref data);
|
||||
if (data.Length != PokeCrypto.SIZE_3PARTY)
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_3PARTY);
|
||||
Data = data;
|
||||
}
|
||||
|
||||
public override PKM Clone()
|
||||
{
|
||||
// Don't use the byte[] constructor, the CheckEncrypted call is based on checksum.
|
||||
// Don't use the byte[] constructor, the DecryptIfEncrypted call is based on checksum.
|
||||
// An invalid checksum will shuffle the data; we already know it's un-shuffled. Set up manually.
|
||||
var pk = new PK3 {Identifier = Identifier};
|
||||
Data.CopyTo(pk.Data, 0);
|
||||
|
@ -196,7 +196,7 @@ namespace PKHeX.Core
|
|||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
return PKX.EncryptArray3(Data);
|
||||
return PokeCrypto.EncryptArray3(Data);
|
||||
}
|
||||
|
||||
public override void RefreshChecksum()
|
||||
|
|
|
@ -14,19 +14,19 @@ namespace PKHeX.Core
|
|||
|
||||
public override IReadOnlyList<ushort> ExtraBytes => Unused;
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_4PARTY;
|
||||
public override int SIZE_STORED => PKX.SIZE_4STORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_4PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_4STORED;
|
||||
public override int Format => 4;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.HGSS.GetFormeEntry(Species, AltForm);
|
||||
|
||||
public override byte[] Data { get; }
|
||||
public PK4() => Data = new byte[PKX.SIZE_4PARTY];
|
||||
public PK4() => Data = new byte[PokeCrypto.SIZE_4PARTY];
|
||||
|
||||
public PK4(byte[] data)
|
||||
{
|
||||
PKX.CheckEncrypted(ref data, Format);
|
||||
if (data.Length != PKX.SIZE_4PARTY)
|
||||
Array.Resize(ref data, PKX.SIZE_4PARTY);
|
||||
PokeCrypto.DecryptIfEncrypted45(ref data);
|
||||
if (data.Length != PokeCrypto.SIZE_4PARTY)
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_4PARTY);
|
||||
Data = data;
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,7 @@ namespace PKHeX.Core
|
|||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
return PKX.EncryptArray45(Data);
|
||||
return PokeCrypto.EncryptArray45(Data);
|
||||
}
|
||||
|
||||
// Synthetic Trading Logic
|
||||
|
|
|
@ -20,19 +20,19 @@ namespace PKHeX.Core
|
|||
|
||||
public override IReadOnlyList<ushort> ExtraBytes => Unused;
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_5PARTY;
|
||||
public override int SIZE_STORED => PKX.SIZE_5STORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_5PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_5STORED;
|
||||
public override int Format => 5;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.B2W2.GetFormeEntry(Species, AltForm);
|
||||
|
||||
public override byte[] Data { get; }
|
||||
public PK5() => Data = new byte[PKX.SIZE_5PARTY];
|
||||
public PK5() => Data = new byte[PokeCrypto.SIZE_5PARTY];
|
||||
|
||||
public PK5(byte[] data)
|
||||
{
|
||||
PKX.CheckEncrypted(ref data, Format);
|
||||
if (data.Length != PKX.SIZE_5PARTY)
|
||||
Array.Resize(ref data, PKX.SIZE_5PARTY);
|
||||
PokeCrypto.DecryptIfEncrypted45(ref data);
|
||||
if (data.Length != PokeCrypto.SIZE_5PARTY)
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_5PARTY);
|
||||
Data = data;
|
||||
}
|
||||
|
||||
|
@ -301,7 +301,7 @@ namespace PKHeX.Core
|
|||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
return PKX.EncryptArray45(Data);
|
||||
return PokeCrypto.EncryptArray45(Data);
|
||||
}
|
||||
|
||||
// Synthetic Trading Logic
|
||||
|
|
|
@ -16,15 +16,15 @@ namespace PKHeX.Core
|
|||
public override int Format => 6;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.AO.GetFormeEntry(Species, AltForm);
|
||||
|
||||
public PK6() => Data = new byte[PKX.SIZE_6PARTY];
|
||||
public PK6() => Data = new byte[PokeCrypto.SIZE_6PARTY];
|
||||
|
||||
public override byte[] Data { get; }
|
||||
|
||||
public PK6(byte[] data)
|
||||
{
|
||||
PKX.CheckEncrypted(ref data, Format);
|
||||
if (data.Length != PKX.SIZE_6PARTY)
|
||||
Array.Resize(ref data, PKX.SIZE_6PARTY);
|
||||
PokeCrypto.DecryptIfEncrypted67(ref data);
|
||||
if (data.Length != PokeCrypto.SIZE_6PARTY)
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_6PARTY);
|
||||
Data = data;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@ namespace PKHeX.Core
|
|||
|
||||
public override byte[] Data { get; }
|
||||
|
||||
public PK7() => Data = new byte[PKX.SIZE_6PARTY];
|
||||
public PK7() => Data = new byte[PokeCrypto.SIZE_6PARTY];
|
||||
|
||||
public PK7(byte[] data)
|
||||
{
|
||||
PKX.CheckEncrypted(ref data, Format);
|
||||
if (data.Length != PKX.SIZE_6PARTY)
|
||||
Array.Resize(ref data, PKX.SIZE_6PARTY);
|
||||
PokeCrypto.DecryptIfEncrypted67(ref data);
|
||||
if (data.Length != PokeCrypto.SIZE_6PARTY)
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_6PARTY);
|
||||
Data = data;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,14 +23,14 @@ namespace PKHeX.Core
|
|||
|
||||
public PK8()
|
||||
{
|
||||
Data = new byte[PKX.SIZE_8PARTY];
|
||||
Data = new byte[PokeCrypto.SIZE_8PARTY];
|
||||
AffixedRibbon = -1; // 00 would make it show Kalos Champion :)
|
||||
}
|
||||
|
||||
protected override ushort CalculateChecksum()
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < PKX.SIZE_8STORED; i += 2)
|
||||
for (int i = 8; i < PokeCrypto.SIZE_8STORED; i += 2)
|
||||
chk += BitConverter.ToUInt16(Data, i);
|
||||
return chk;
|
||||
}
|
||||
|
@ -50,9 +50,9 @@ namespace PKHeX.Core
|
|||
|
||||
public PK8(byte[] data)
|
||||
{
|
||||
PKX.CheckEncrypted(ref data, Format);
|
||||
if (data.Length != PKX.SIZE_8PARTY)
|
||||
Array.Resize(ref data, PKX.SIZE_8PARTY);
|
||||
PokeCrypto.DecryptIfEncrypted8(ref data);
|
||||
if (data.Length != PokeCrypto.SIZE_8PARTY)
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_8PARTY);
|
||||
Data = data;
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,8 @@ namespace PKHeX.Core
|
|||
private string GetString(int Offset, int Count) => StringConverter.GetString7(Data, Offset, Count);
|
||||
private byte[] SetString(string value, int maxLength, bool chinese = false) => StringConverter.SetString7(value, maxLength, Language, chinese: chinese);
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_8PARTY;
|
||||
public override int SIZE_STORED => PKX.SIZE_8STORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_8STORED;
|
||||
|
||||
// Trash Bytes
|
||||
public override byte[] Nickname_Trash { get => GetData(0x58, 24); set { if (value?.Length == 24) value.CopyTo(Data, 0x58); } }
|
||||
|
@ -104,7 +104,7 @@ namespace PKHeX.Core
|
|||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
return PKX.EncryptArray8(Data);
|
||||
return PokeCrypto.EncryptArray8(Data);
|
||||
}
|
||||
|
||||
public void FixRelearn()
|
||||
|
|
|
@ -5,8 +5,8 @@ namespace PKHeX.Core
|
|||
/// <summary> Generation 6 <see cref="PKM"/> format. </summary>
|
||||
public abstract class G6PKM : PKM
|
||||
{
|
||||
public override int SIZE_PARTY => PKX.SIZE_6PARTY;
|
||||
public override int SIZE_STORED => PKX.SIZE_6STORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_6PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_6STORED;
|
||||
|
||||
// Trash Bytes
|
||||
public override byte[] Nickname_Trash { get => GetData(0x40, 24); set { if (value?.Length == 24) value.CopyTo(Data, 0x40); } }
|
||||
|
@ -16,7 +16,7 @@ namespace PKHeX.Core
|
|||
protected override ushort CalculateChecksum()
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < PKX.SIZE_6STORED; i += 2) // don't use SIZE_STORED property; pb7 overrides stored size
|
||||
for (int i = 8; i < PokeCrypto.SIZE_6STORED; i += 2) // don't use SIZE_STORED property; pb7 overrides stored size
|
||||
chk += BitConverter.ToUInt16(Data, i);
|
||||
return chk;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ namespace PKHeX.Core
|
|||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
return PKX.EncryptArray6(Data);
|
||||
return PokeCrypto.EncryptArray6(Data);
|
||||
}
|
||||
|
||||
// General User-error Fixes
|
||||
|
|
|
@ -8,10 +8,10 @@ namespace PKHeX.Core
|
|||
|
||||
public PokeList1(byte[] d, PokeListType c = PokeListType.Single, bool jp = false) : base(d, c, jp) { }
|
||||
public PokeList1(PokeListType c = PokeListType.Single, bool jp = false) : base(c, jp) { }
|
||||
public PokeList1(byte[] d) : base(d, PokeListType.Single, d.Length == PKX.SIZE_1JLIST) { }
|
||||
public PokeList1(byte[] d) : base(d, PokeListType.Single, d.Length == PokeCrypto.SIZE_1JLIST) { }
|
||||
public PokeList1(PK1 pk) : base(pk) { }
|
||||
|
||||
private static int GetEntrySize(bool party) => party ? PKX.SIZE_1PARTY : PKX.SIZE_1STORED;
|
||||
private static int GetEntrySize(bool party) => party ? PokeCrypto.SIZE_1PARTY : PokeCrypto.SIZE_1STORED;
|
||||
public static int GetDataLength(PokeListType c, bool jp) => GetDataSize(c, jp, GetEntrySize(IsCapacityPartyFormat(c)));
|
||||
}
|
||||
}
|
|
@ -8,10 +8,10 @@ namespace PKHeX.Core
|
|||
|
||||
public PokeList2(byte[] d, PokeListType c = PokeListType.Single, bool jp = false) : base(d, c, jp) { }
|
||||
public PokeList2(PokeListType c = PokeListType.Single, bool jp = false) : base(c, jp) { }
|
||||
public PokeList2(byte[] d) : base(d, PokeListType.Single, d.Length == PKX.SIZE_2JLIST) { }
|
||||
public PokeList2(byte[] d) : base(d, PokeListType.Single, d.Length == PokeCrypto.SIZE_2JLIST) { }
|
||||
public PokeList2(PK2 pk) : base(pk) { }
|
||||
|
||||
private static int GetEntrySize(bool party) => party ? PKX.SIZE_2PARTY : PKX.SIZE_2STORED;
|
||||
private static int GetEntrySize(bool party) => party ? PokeCrypto.SIZE_2PARTY : PokeCrypto.SIZE_2STORED;
|
||||
public static int GetDataLength(PokeListType c, bool jp) => GetDataSize(c, jp, GetEntrySize(IsCapacityPartyFormat(c)));
|
||||
}
|
||||
}
|
|
@ -34,29 +34,29 @@ namespace PKHeX.Core
|
|||
|
||||
switch (data.Length)
|
||||
{
|
||||
case PKX.SIZE_1JLIST:
|
||||
case PKX.SIZE_1ULIST:
|
||||
case PokeCrypto.SIZE_1JLIST:
|
||||
case PokeCrypto.SIZE_1ULIST:
|
||||
return 1;
|
||||
case PKX.SIZE_2ULIST:
|
||||
case PKX.SIZE_2JLIST:
|
||||
case PokeCrypto.SIZE_2ULIST:
|
||||
case PokeCrypto.SIZE_2JLIST:
|
||||
return 2;
|
||||
case PKX.SIZE_3PARTY:
|
||||
case PKX.SIZE_3STORED:
|
||||
case PKX.SIZE_3CSTORED:
|
||||
case PKX.SIZE_3XSTORED:
|
||||
case PokeCrypto.SIZE_3PARTY:
|
||||
case PokeCrypto.SIZE_3STORED:
|
||||
case PokeCrypto.SIZE_3CSTORED:
|
||||
case PokeCrypto.SIZE_3XSTORED:
|
||||
return 3;
|
||||
case PKX.SIZE_4PARTY:
|
||||
case PKX.SIZE_4STORED:
|
||||
case PKX.SIZE_5PARTY:
|
||||
case PokeCrypto.SIZE_4PARTY:
|
||||
case PokeCrypto.SIZE_4STORED:
|
||||
case PokeCrypto.SIZE_5PARTY:
|
||||
if ((BitConverter.ToUInt16(data, 0x4) == 0) && (BitConverter.ToUInt16(data, 0x80) >= 0x3333 || data[0x5F] >= 0x10) && BitConverter.ToUInt16(data, 0x46) == 0) // PK5
|
||||
return 5;
|
||||
return 4;
|
||||
case PKX.SIZE_6STORED:
|
||||
case PokeCrypto.SIZE_6STORED:
|
||||
return 6;
|
||||
case PKX.SIZE_6PARTY: // collision with PGT, same size.
|
||||
case PokeCrypto.SIZE_6PARTY: // collision with PGT, same size.
|
||||
if (BitConverter.ToUInt16(data, 0x4) != 0) // Bad Sanity?
|
||||
return -1;
|
||||
if (BitConverter.ToUInt32(data, 0x06) == PKX.GetCHK(data))
|
||||
if (BitConverter.ToUInt32(data, 0x06) == PokeCrypto.GetCHK(data))
|
||||
return 6;
|
||||
if (BitConverter.ToUInt16(data, 0x58) != 0) // Encrypted?
|
||||
{
|
||||
|
@ -69,8 +69,8 @@ namespace PKHeX.Core
|
|||
return -1;
|
||||
}
|
||||
return 6;
|
||||
case PKX.SIZE_8PARTY:
|
||||
case PKX.SIZE_8STORED:
|
||||
case PokeCrypto.SIZE_8PARTY:
|
||||
case PokeCrypto.SIZE_8STORED:
|
||||
return 8;
|
||||
|
||||
default:
|
||||
|
@ -98,8 +98,8 @@ namespace PKHeX.Core
|
|||
case 3:
|
||||
return data.Length switch
|
||||
{
|
||||
PKX.SIZE_3CSTORED => new CK3(data),
|
||||
PKX.SIZE_3XSTORED => new XK3(data),
|
||||
PokeCrypto.SIZE_3CSTORED => new CK3(data),
|
||||
PokeCrypto.SIZE_3XSTORED => new XK3(data),
|
||||
_ => (PKM)new PK3(data)
|
||||
};
|
||||
case 4:
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -13,50 +11,16 @@ namespace PKHeX.Core
|
|||
internal static readonly PersonalTable Personal = PersonalTable.SWSH;
|
||||
public const int Generation = 8;
|
||||
|
||||
internal const int SIZE_1ULIST = 69;
|
||||
internal const int SIZE_1JLIST = 59;
|
||||
internal const int SIZE_1PARTY = 44;
|
||||
internal const int SIZE_1STORED = 33;
|
||||
|
||||
internal const int SIZE_2ULIST = 73;
|
||||
internal const int SIZE_2JLIST = 63;
|
||||
internal const int SIZE_2PARTY = 48;
|
||||
internal const int SIZE_2STORED = 32;
|
||||
|
||||
internal const int SIZE_3CSTORED = 312;
|
||||
internal const int SIZE_3XSTORED = 196;
|
||||
internal const int SIZE_3PARTY = 100;
|
||||
internal const int SIZE_3STORED = 80;
|
||||
internal const int SIZE_3BLOCK = 12;
|
||||
|
||||
internal const int SIZE_4PARTY = 236;
|
||||
internal const int SIZE_4STORED = 136;
|
||||
internal const int SIZE_4BLOCK = 32;
|
||||
|
||||
internal const int SIZE_5PARTY = 220;
|
||||
internal const int SIZE_5STORED = 136;
|
||||
internal const int SIZE_5BLOCK = 32;
|
||||
|
||||
internal const int SIZE_6PARTY = 0x104;
|
||||
internal const int SIZE_6STORED = 0xE8;
|
||||
internal const int SIZE_6BLOCK = 56;
|
||||
|
||||
// Gen7 Format is the same size as Gen6.
|
||||
|
||||
internal const int SIZE_8STORED = 8 + (4 * SIZE_8BLOCK); // 0x148
|
||||
internal const int SIZE_8PARTY = SIZE_8STORED + 0x10; // 0x158
|
||||
internal const int SIZE_8BLOCK = 80; // 0x50
|
||||
|
||||
private static readonly HashSet<int> Sizes = new HashSet<int>
|
||||
{
|
||||
SIZE_1JLIST, SIZE_1ULIST,
|
||||
SIZE_2ULIST, SIZE_2JLIST,
|
||||
SIZE_3STORED, SIZE_3PARTY,
|
||||
SIZE_3CSTORED, SIZE_3XSTORED,
|
||||
SIZE_4STORED, SIZE_4PARTY,
|
||||
SIZE_5PARTY,
|
||||
SIZE_6STORED, SIZE_6PARTY,
|
||||
SIZE_8STORED, SIZE_8PARTY,
|
||||
PokeCrypto.SIZE_1JLIST, PokeCrypto.SIZE_1ULIST,
|
||||
PokeCrypto.SIZE_2ULIST, PokeCrypto.SIZE_2JLIST,
|
||||
PokeCrypto.SIZE_3STORED, PokeCrypto.SIZE_3PARTY,
|
||||
PokeCrypto.SIZE_3CSTORED, PokeCrypto.SIZE_3XSTORED,
|
||||
PokeCrypto.SIZE_4STORED, PokeCrypto.SIZE_4PARTY,
|
||||
PokeCrypto.SIZE_5PARTY,
|
||||
PokeCrypto.SIZE_6STORED, PokeCrypto.SIZE_6PARTY,
|
||||
PokeCrypto.SIZE_8STORED, PokeCrypto.SIZE_8PARTY,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -140,236 +104,6 @@ namespace PKHeX.Core
|
|||
stats[decr] *= 9; stats[decr] /= 10;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Positions for shuffling.
|
||||
/// </summary>
|
||||
private static readonly byte[] BlockPosition =
|
||||
{
|
||||
0, 1, 2, 3,
|
||||
0, 1, 3, 2,
|
||||
0, 2, 1, 3,
|
||||
0, 3, 1, 2,
|
||||
0, 2, 3, 1,
|
||||
0, 3, 2, 1,
|
||||
1, 0, 2, 3,
|
||||
1, 0, 3, 2,
|
||||
2, 0, 1, 3,
|
||||
3, 0, 1, 2,
|
||||
2, 0, 3, 1,
|
||||
3, 0, 2, 1,
|
||||
1, 2, 0, 3,
|
||||
1, 3, 0, 2,
|
||||
2, 1, 0, 3,
|
||||
3, 1, 0, 2,
|
||||
2, 3, 0, 1,
|
||||
3, 2, 0, 1,
|
||||
1, 2, 3, 0,
|
||||
1, 3, 2, 0,
|
||||
2, 1, 3, 0,
|
||||
3, 1, 2, 0,
|
||||
2, 3, 1, 0,
|
||||
3, 2, 1, 0,
|
||||
|
||||
// duplicates of 0-7 to eliminate modulus
|
||||
0, 1, 2, 3,
|
||||
0, 1, 3, 2,
|
||||
0, 2, 1, 3,
|
||||
0, 3, 1, 2,
|
||||
0, 2, 3, 1,
|
||||
0, 3, 2, 1,
|
||||
1, 0, 2, 3,
|
||||
1, 0, 3, 2,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Positions for unshuffling.
|
||||
/// </summary>
|
||||
internal static readonly byte[] blockPositionInvert =
|
||||
{
|
||||
0, 1, 2, 4, 3, 5, 6, 7, 12, 18, 13, 19, 8, 10, 14, 20, 16, 22, 9, 11, 15, 21, 17, 23,
|
||||
0, 1, 2, 4, 3, 5, 6, 7, // duplicates of 0-7 to eliminate modulus
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles a 232 byte array containing <see cref="PKM"/> data.
|
||||
/// </summary>
|
||||
/// <param name="data">Data to shuffle</param>
|
||||
/// <param name="sv">Block Shuffle order</param>
|
||||
/// <param name="blockSize">Size of shuffling chunks</param>
|
||||
/// <returns>Shuffled byte array</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static byte[] ShuffleArray(byte[] data, uint sv, int blockSize)
|
||||
{
|
||||
byte[] sdata = (byte[])data.Clone();
|
||||
uint index = sv*4;
|
||||
for (int block = 0; block < 4; block++)
|
||||
{
|
||||
int ofs = BlockPosition[index + block];
|
||||
Array.Copy(data, 8 + (blockSize * ofs), sdata, 8 + (blockSize * block), blockSize);
|
||||
}
|
||||
return sdata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a Gen8 pkm byte array.
|
||||
/// </summary>
|
||||
/// <param name="ekm">Encrypted <see cref="PKM"/> data.</param>
|
||||
/// <returns>Decrypted <see cref="PKM"/> data.</returns>
|
||||
/// <returns>Encrypted <see cref="PKM"/> data.</returns>
|
||||
public static byte[] DecryptArray8(byte[] ekm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(ekm, 0);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
CryptPKM(ekm, pv, SIZE_8BLOCK);
|
||||
return ShuffleArray(ekm, sv, SIZE_8BLOCK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a Gen8 pkm byte array.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Decrypted <see cref="PKM"/> data.</param>
|
||||
public static byte[] EncryptArray8(byte[] pkm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(pkm, 0);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
byte[] ekm = ShuffleArray(pkm, blockPositionInvert[sv], SIZE_8BLOCK);
|
||||
CryptPKM(ekm, pv, SIZE_8BLOCK);
|
||||
return ekm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a 232 byte + party stat byte array.
|
||||
/// </summary>
|
||||
/// <param name="ekm">Encrypted <see cref="PKM"/> data.</param>
|
||||
/// <returns>Decrypted <see cref="PKM"/> data.</returns>
|
||||
/// <returns>Encrypted <see cref="PKM"/> data.</returns>
|
||||
public static byte[] DecryptArray6(byte[] ekm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(ekm, 0);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
CryptPKM(ekm, pv, SIZE_6BLOCK);
|
||||
return ShuffleArray(ekm, sv, SIZE_6BLOCK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a 232 byte + party stat byte array.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Decrypted <see cref="PKM"/> data.</param>
|
||||
public static byte[] EncryptArray6(byte[] pkm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(pkm, 0);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
byte[] ekm = ShuffleArray(pkm, blockPositionInvert[sv], SIZE_6BLOCK);
|
||||
CryptPKM(ekm, pv, SIZE_6BLOCK);
|
||||
return ekm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a 136 byte + party stat byte array.
|
||||
/// </summary>
|
||||
/// <param name="ekm">Encrypted <see cref="PKM"/> data.</param>
|
||||
/// <returns>Decrypted <see cref="PKM"/> data.</returns>
|
||||
public static byte[] DecryptArray45(byte[] ekm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(ekm, 0);
|
||||
uint chk = BitConverter.ToUInt16(ekm, 6);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
CryptPKM45(ekm, pv, chk, SIZE_4BLOCK);
|
||||
return ShuffleArray(ekm, sv, SIZE_4BLOCK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a 136 byte + party stat byte array.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Decrypted <see cref="PKM"/> data.</param>
|
||||
/// <returns>Encrypted <see cref="PKM"/> data.</returns>
|
||||
public static byte[] EncryptArray45(byte[] pkm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(pkm, 0);
|
||||
uint chk = BitConverter.ToUInt16(pkm, 6);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
byte[] ekm = ShuffleArray(pkm, blockPositionInvert[sv], SIZE_4BLOCK);
|
||||
CryptPKM45(ekm, pv, chk, SIZE_4BLOCK);
|
||||
return ekm;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void CryptPKM(byte[] data, uint pv, int blockSize)
|
||||
{
|
||||
const int start = 8;
|
||||
int end = (4 * blockSize) + start;
|
||||
CryptArray(data, pv, 8, end); // Blocks
|
||||
if (data.Length > end)
|
||||
CryptArray(data, pv, end, data.Length); // Party Stats
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void CryptPKM45(byte[] data, uint pv, uint chk, int blockSize)
|
||||
{
|
||||
const int start = 8;
|
||||
int end = (4 * blockSize) + start;
|
||||
CryptArray(data, chk, start, end); // Blocks
|
||||
if (data.Length > end)
|
||||
CryptArray(data, pv, end, data.Length); // Party Stats
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void CryptArray(byte[] data, uint seed, int start, int end)
|
||||
{
|
||||
int i = start;
|
||||
do // all block sizes are multiples of 4
|
||||
{
|
||||
Crypt(data, ref seed, i); i += 2;
|
||||
Crypt(data, ref seed, i); i += 2;
|
||||
}
|
||||
while (i < end);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void CryptArray(byte[] data, uint seed) => CryptArray(data, seed, 0, data.Length);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void Crypt(byte[] data, ref uint seed, int i)
|
||||
{
|
||||
seed = (0x41C64E6D * seed) + 0x00006073;
|
||||
data[i] ^= (byte)(seed >> 16);
|
||||
data[i + 1] ^= (byte)(seed >> 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the checksum of a 232 byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">Decrypted <see cref="PKM"/> data.</param>
|
||||
/// <returns></returns>
|
||||
public static ushort GetCHK(byte[] data)
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < SIZE_6STORED; i += 2)
|
||||
chk += BitConverter.ToUInt16(data, i);
|
||||
|
||||
return chk;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the checksum of a Generation 3 byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">Decrypted <see cref="PKM"/> data.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ushort GetCHK3(byte[] data)
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 0x20; i < SIZE_3STORED; i += 2)
|
||||
chk += BitConverter.ToUInt16(data, i);
|
||||
return chk;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random PID according to specifications.
|
||||
/// </summary>
|
||||
|
@ -454,109 +188,6 @@ namespace PKHeX.Core
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts an 80 byte format <see cref="PK3"/> byte array.
|
||||
/// </summary>
|
||||
/// <param name="ekm">Encrypted data.</param>
|
||||
/// <returns>Decrypted data.</returns>
|
||||
public static byte[] DecryptArray3(byte[] ekm)
|
||||
{
|
||||
Debug.Assert(ekm.Length == SIZE_3PARTY || ekm.Length == SIZE_3STORED);
|
||||
|
||||
uint PID = BitConverter.ToUInt32(ekm, 0);
|
||||
uint OID = BitConverter.ToUInt32(ekm, 4);
|
||||
uint seed = PID ^ OID;
|
||||
|
||||
byte[] xorkey = BitConverter.GetBytes(seed);
|
||||
for (int i = 32; i < 80; i++)
|
||||
ekm[i] ^= xorkey[i & 3];
|
||||
return ShuffleArray3(ekm, PID%24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles an 80 byte format <see cref="PK3"/> byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">Unshuffled data.</param>
|
||||
/// <param name="sv">Block order shuffle value</param>
|
||||
/// <returns></returns>
|
||||
private static byte[] ShuffleArray3(byte[] data, uint sv)
|
||||
{
|
||||
byte[] sdata = (byte[])data.Clone();
|
||||
uint index = sv * 4;
|
||||
for (int block = 0; block < 4; block++)
|
||||
{
|
||||
int ofs = BlockPosition[index + block];
|
||||
Array.Copy(data, 32 + (12 * ofs), sdata, 32 + (12 * block), 12);
|
||||
}
|
||||
|
||||
// Fill the Battle Stats back
|
||||
if (data.Length > SIZE_3STORED)
|
||||
Array.Copy(data, SIZE_3STORED, sdata, SIZE_3STORED, data.Length - SIZE_3STORED);
|
||||
|
||||
return sdata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts an 80 byte format <see cref="PK3"/> byte array.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Decrypted data.</param>
|
||||
/// <returns>Encrypted data.</returns>
|
||||
public static byte[] EncryptArray3(byte[] pkm)
|
||||
{
|
||||
Debug.Assert(pkm.Length == SIZE_3PARTY || pkm.Length == SIZE_3STORED);
|
||||
|
||||
uint PID = BitConverter.ToUInt32(pkm, 0);
|
||||
uint OID = BitConverter.ToUInt32(pkm, 4);
|
||||
uint seed = PID ^ OID;
|
||||
|
||||
byte[] ekm = ShuffleArray3(pkm, blockPositionInvert[PID%24]);
|
||||
byte[] xorkey = BitConverter.GetBytes(seed);
|
||||
for (int i = 32; i < SIZE_3STORED; i++)
|
||||
ekm[i] ^= xorkey[i & 3];
|
||||
return ekm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a PKM is encrypted; if encrypted, decrypts the PKM.
|
||||
/// </summary>
|
||||
/// <remarks>The input PKM object is decrypted; no new object is returned.</remarks>
|
||||
/// <param name="pkm">PKM to check encryption for (and decrypt if appropriate).</param>
|
||||
/// <param name="format">Format specific check selection</param>
|
||||
public static void CheckEncrypted(ref byte[] pkm, int format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 1:
|
||||
case 2: // no encryption
|
||||
return;
|
||||
case 3:
|
||||
if (pkm.Length > SIZE_3PARTY) // C/XD
|
||||
return; // no encryption
|
||||
ushort chk = GetCHK3(pkm);
|
||||
if (chk != BitConverter.ToUInt16(pkm, 0x1C))
|
||||
pkm = DecryptArray3(pkm);
|
||||
return;
|
||||
case 4:
|
||||
case 5:
|
||||
if (BitConverter.ToUInt16(pkm, 4) != 0) // BK4
|
||||
return;
|
||||
if (BitConverter.ToUInt32(pkm, 0x64) != 0)
|
||||
pkm = DecryptArray45(pkm);
|
||||
return;
|
||||
case 6:
|
||||
case 7:
|
||||
if (BitConverter.ToUInt16(pkm, 0xC8) != 0 && BitConverter.ToUInt16(pkm, 0x58) != 0)
|
||||
pkm = DecryptArray6(pkm);
|
||||
return;
|
||||
case 8:
|
||||
if (BitConverter.ToUInt16(pkm, 0x70) != 0 && BitConverter.ToUInt16(pkm, 0xC0) != 0)
|
||||
pkm = DecryptArray8(pkm);
|
||||
return;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(format));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of valid <see cref="PKM"/> file extensions.
|
||||
/// </summary>
|
||||
|
@ -631,7 +262,7 @@ namespace PKHeX.Core
|
|||
return IsPKMPresent;
|
||||
if (blank.Format <= 2)
|
||||
return IsPKMPresentGB;
|
||||
if (blank.Data.Length <= SIZE_3PARTY)
|
||||
if (blank.Data.Length <= PokeCrypto.SIZE_3PARTY)
|
||||
return IsPKMPresentGBA;
|
||||
return IsPKMPresentGC;
|
||||
}
|
||||
|
|
363
PKHeX.Core/PKM/Util/PokeCrypto.cs
Normal file
363
PKHeX.Core/PKM/Util/PokeCrypto.cs
Normal file
|
@ -0,0 +1,363 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Logic related to Encrypting and Decrypting Pokémon entity data.
|
||||
/// </summary>
|
||||
public static class PokeCrypto
|
||||
{
|
||||
internal const int SIZE_1ULIST = 69;
|
||||
internal const int SIZE_1JLIST = 59;
|
||||
internal const int SIZE_1PARTY = 44;
|
||||
internal const int SIZE_1STORED = 33;
|
||||
|
||||
internal const int SIZE_2ULIST = 73;
|
||||
internal const int SIZE_2JLIST = 63;
|
||||
internal const int SIZE_2PARTY = 48;
|
||||
internal const int SIZE_2STORED = 32;
|
||||
|
||||
internal const int SIZE_3CSTORED = 312;
|
||||
internal const int SIZE_3XSTORED = 196;
|
||||
internal const int SIZE_3PARTY = 100;
|
||||
internal const int SIZE_3STORED = 80;
|
||||
internal const int SIZE_3BLOCK = 12;
|
||||
|
||||
internal const int SIZE_4PARTY = 236;
|
||||
internal const int SIZE_4STORED = 136;
|
||||
internal const int SIZE_4BLOCK = 32;
|
||||
|
||||
internal const int SIZE_5PARTY = 220;
|
||||
internal const int SIZE_5STORED = 136;
|
||||
internal const int SIZE_5BLOCK = 32;
|
||||
|
||||
internal const int SIZE_6PARTY = 0x104;
|
||||
internal const int SIZE_6STORED = 0xE8;
|
||||
internal const int SIZE_6BLOCK = 56;
|
||||
|
||||
// Gen7 Format is the same size as Gen6.
|
||||
|
||||
internal const int SIZE_8STORED = 8 + (4 * SIZE_8BLOCK); // 0x148
|
||||
internal const int SIZE_8PARTY = SIZE_8STORED + 0x10; // 0x158
|
||||
internal const int SIZE_8BLOCK = 80; // 0x50
|
||||
|
||||
/// <summary>
|
||||
/// Positions for shuffling.
|
||||
/// </summary>
|
||||
private static readonly byte[] BlockPosition =
|
||||
{
|
||||
0, 1, 2, 3,
|
||||
0, 1, 3, 2,
|
||||
0, 2, 1, 3,
|
||||
0, 3, 1, 2,
|
||||
0, 2, 3, 1,
|
||||
0, 3, 2, 1,
|
||||
1, 0, 2, 3,
|
||||
1, 0, 3, 2,
|
||||
2, 0, 1, 3,
|
||||
3, 0, 1, 2,
|
||||
2, 0, 3, 1,
|
||||
3, 0, 2, 1,
|
||||
1, 2, 0, 3,
|
||||
1, 3, 0, 2,
|
||||
2, 1, 0, 3,
|
||||
3, 1, 0, 2,
|
||||
2, 3, 0, 1,
|
||||
3, 2, 0, 1,
|
||||
1, 2, 3, 0,
|
||||
1, 3, 2, 0,
|
||||
2, 1, 3, 0,
|
||||
3, 1, 2, 0,
|
||||
2, 3, 1, 0,
|
||||
3, 2, 1, 0,
|
||||
|
||||
// duplicates of 0-7 to eliminate modulus
|
||||
0, 1, 2, 3,
|
||||
0, 1, 3, 2,
|
||||
0, 2, 1, 3,
|
||||
0, 3, 1, 2,
|
||||
0, 2, 3, 1,
|
||||
0, 3, 2, 1,
|
||||
1, 0, 2, 3,
|
||||
1, 0, 3, 2,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Positions for unshuffling.
|
||||
/// </summary>
|
||||
internal static readonly byte[] blockPositionInvert =
|
||||
{
|
||||
0, 1, 2, 4, 3, 5, 6, 7, 12, 18, 13, 19, 8, 10, 14, 20, 16, 22, 9, 11, 15, 21, 17, 23,
|
||||
0, 1, 2, 4, 3, 5, 6, 7, // duplicates of 0-7 to eliminate modulus
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles a 232 byte array containing Pokémon data.
|
||||
/// </summary>
|
||||
/// <param name="data">Data to shuffle</param>
|
||||
/// <param name="sv">Block Shuffle order</param>
|
||||
/// <param name="blockSize">Size of shuffling chunks</param>
|
||||
/// <returns>Shuffled byte array</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static byte[] ShuffleArray(byte[] data, uint sv, int blockSize)
|
||||
{
|
||||
byte[] sdata = (byte[])data.Clone();
|
||||
uint index = sv * 4;
|
||||
for (int block = 0; block < 4; block++)
|
||||
{
|
||||
int ofs = BlockPosition[index + block];
|
||||
Array.Copy(data, 8 + (blockSize * ofs), sdata, 8 + (blockSize * block), blockSize);
|
||||
}
|
||||
return sdata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a Gen8 pkm byte array.
|
||||
/// </summary>
|
||||
/// <param name="ekm">Encrypted Pokémon data.</param>
|
||||
/// <returns>Decrypted Pokémon data.</returns>
|
||||
/// <returns>Encrypted Pokémon data.</returns>
|
||||
public static byte[] DecryptArray8(byte[] ekm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(ekm, 0);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
CryptPKM(ekm, pv, SIZE_8BLOCK);
|
||||
return ShuffleArray(ekm, sv, SIZE_8BLOCK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a Gen8 pkm byte array.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Decrypted Pokémon data.</param>
|
||||
public static byte[] EncryptArray8(byte[] pkm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(pkm, 0);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
byte[] ekm = ShuffleArray(pkm, blockPositionInvert[sv], SIZE_8BLOCK);
|
||||
CryptPKM(ekm, pv, SIZE_8BLOCK);
|
||||
return ekm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a 232 byte + party stat byte array.
|
||||
/// </summary>
|
||||
/// <param name="ekm">Encrypted Pokémon data.</param>
|
||||
/// <returns>Decrypted Pokémon data.</returns>
|
||||
/// <returns>Encrypted Pokémon data.</returns>
|
||||
public static byte[] DecryptArray6(byte[] ekm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(ekm, 0);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
CryptPKM(ekm, pv, SIZE_6BLOCK);
|
||||
return ShuffleArray(ekm, sv, SIZE_6BLOCK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a 232 byte + party stat byte array.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Decrypted Pokémon data.</param>
|
||||
public static byte[] EncryptArray6(byte[] pkm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(pkm, 0);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
byte[] ekm = ShuffleArray(pkm, blockPositionInvert[sv], SIZE_6BLOCK);
|
||||
CryptPKM(ekm, pv, SIZE_6BLOCK);
|
||||
return ekm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a 136 byte + party stat byte array.
|
||||
/// </summary>
|
||||
/// <param name="ekm">Encrypted Pokémon data.</param>
|
||||
/// <returns>Decrypted Pokémon data.</returns>
|
||||
public static byte[] DecryptArray45(byte[] ekm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(ekm, 0);
|
||||
uint chk = BitConverter.ToUInt16(ekm, 6);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
CryptPKM45(ekm, pv, chk, SIZE_4BLOCK);
|
||||
return ShuffleArray(ekm, sv, SIZE_4BLOCK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a 136 byte + party stat byte array.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Decrypted Pokémon data.</param>
|
||||
/// <returns>Encrypted Pokémon data.</returns>
|
||||
public static byte[] EncryptArray45(byte[] pkm)
|
||||
{
|
||||
uint pv = BitConverter.ToUInt32(pkm, 0);
|
||||
uint chk = BitConverter.ToUInt16(pkm, 6);
|
||||
uint sv = pv >> 13 & 31;
|
||||
|
||||
byte[] ekm = ShuffleArray(pkm, blockPositionInvert[sv], SIZE_4BLOCK);
|
||||
CryptPKM45(ekm, pv, chk, SIZE_4BLOCK);
|
||||
return ekm;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void CryptPKM(byte[] data, uint pv, int blockSize)
|
||||
{
|
||||
const int start = 8;
|
||||
int end = (4 * blockSize) + start;
|
||||
CryptArray(data, pv, 8, end); // Blocks
|
||||
if (data.Length > end)
|
||||
CryptArray(data, pv, end, data.Length); // Party Stats
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void CryptPKM45(byte[] data, uint pv, uint chk, int blockSize)
|
||||
{
|
||||
const int start = 8;
|
||||
int end = (4 * blockSize) + start;
|
||||
CryptArray(data, chk, start, end); // Blocks
|
||||
if (data.Length > end)
|
||||
CryptArray(data, pv, end, data.Length); // Party Stats
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void CryptArray(byte[] data, uint seed, int start, int end)
|
||||
{
|
||||
int i = start;
|
||||
do // all block sizes are multiples of 4
|
||||
{
|
||||
Crypt(data, ref seed, i); i += 2;
|
||||
Crypt(data, ref seed, i); i += 2;
|
||||
}
|
||||
while (i < end);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void CryptArray(byte[] data, uint seed) => CryptArray(data, seed, 0, data.Length);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void Crypt(in byte[] data, ref uint seed, in int i)
|
||||
{
|
||||
seed = (0x41C64E6D * seed) + 0x00006073;
|
||||
data[i] ^= (byte)(seed >> 16);
|
||||
data[i + 1] ^= (byte)(seed >> 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts an 80 byte format Generation 3 Pokémon byte array.
|
||||
/// </summary>
|
||||
/// <param name="ekm">Encrypted data.</param>
|
||||
/// <returns>Decrypted data.</returns>
|
||||
public static byte[] DecryptArray3(byte[] ekm)
|
||||
{
|
||||
Debug.Assert(ekm.Length == SIZE_3PARTY || ekm.Length == SIZE_3STORED);
|
||||
|
||||
uint PID = BitConverter.ToUInt32(ekm, 0);
|
||||
uint OID = BitConverter.ToUInt32(ekm, 4);
|
||||
uint seed = PID ^ OID;
|
||||
|
||||
byte[] xorkey = BitConverter.GetBytes(seed);
|
||||
for (int i = 32; i < 80; i++)
|
||||
ekm[i] ^= xorkey[i & 3];
|
||||
return ShuffleArray3(ekm, PID % 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles an 80 byte format Generation 3 Pokémon byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">Unshuffled data.</param>
|
||||
/// <param name="sv">Block order shuffle value</param>
|
||||
/// <returns>Unshuffled data.</returns>
|
||||
private static byte[] ShuffleArray3(byte[] data, uint sv)
|
||||
{
|
||||
byte[] sdata = (byte[])data.Clone();
|
||||
uint index = sv * 4;
|
||||
for (int block = 0; block < 4; block++)
|
||||
{
|
||||
int ofs = BlockPosition[index + block];
|
||||
Array.Copy(data, 32 + (12 * ofs), sdata, 32 + (12 * block), 12);
|
||||
}
|
||||
|
||||
// Fill the Battle Stats back
|
||||
if (data.Length > SIZE_3STORED)
|
||||
Array.Copy(data, SIZE_3STORED, sdata, SIZE_3STORED, data.Length - SIZE_3STORED);
|
||||
|
||||
return sdata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts an 80 byte format Generation 3 Pokémon byte array.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Decrypted data.</param>
|
||||
/// <returns>Encrypted data.</returns>
|
||||
public static byte[] EncryptArray3(byte[] pkm)
|
||||
{
|
||||
Debug.Assert(pkm.Length == SIZE_3PARTY || pkm.Length == SIZE_3STORED);
|
||||
|
||||
uint PID = BitConverter.ToUInt32(pkm, 0);
|
||||
uint OID = BitConverter.ToUInt32(pkm, 4);
|
||||
uint seed = PID ^ OID;
|
||||
|
||||
byte[] ekm = ShuffleArray3(pkm, blockPositionInvert[PID % 24]);
|
||||
byte[] xorkey = BitConverter.GetBytes(seed);
|
||||
for (int i = 32; i < SIZE_3STORED; i++)
|
||||
ekm[i] ^= xorkey[i & 3];
|
||||
return ekm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the checksum of a 232 byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">Decrypted Pokémon data.</param>
|
||||
public static ushort GetCHK(byte[] data)
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < SIZE_6STORED; i += 2)
|
||||
chk += BitConverter.ToUInt16(data, i);
|
||||
|
||||
return chk;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the checksum of a Generation 3 byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">Decrypted Pokémon data.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ushort GetCHK3(byte[] data)
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 0x20; i < SIZE_3STORED; i += 2)
|
||||
chk += BitConverter.ToUInt16(data, i);
|
||||
return chk;
|
||||
}
|
||||
|
||||
public static void DecryptIfEncrypted3(ref byte[] pkm)
|
||||
{
|
||||
ushort chk = GetCHK3(pkm);
|
||||
if (chk != BitConverter.ToUInt16(pkm, 0x1C))
|
||||
pkm = DecryptArray3(pkm);
|
||||
}
|
||||
|
||||
public static void DecryptIfEncrypted45(ref byte[] pkm)
|
||||
{
|
||||
if (BitConverter.ToUInt16(pkm, 4) != 0) // BK4
|
||||
return;
|
||||
if (BitConverter.ToUInt32(pkm, 0x64) != 0)
|
||||
pkm = DecryptArray45(pkm);
|
||||
}
|
||||
|
||||
public static void DecryptIfEncrypted67(ref byte[] pkm)
|
||||
{
|
||||
if (BitConverter.ToUInt16(pkm, 0xC8) != 0 && BitConverter.ToUInt16(pkm, 0x58) != 0)
|
||||
pkm = DecryptArray6(pkm);
|
||||
}
|
||||
|
||||
public static void DecryptIfEncrypted8(ref byte[] pkm)
|
||||
{
|
||||
if (BitConverter.ToUInt16(pkm, 0x70) != 0 && BitConverter.ToUInt16(pkm, 0xC0) != 0)
|
||||
pkm = DecryptArray8(pkm);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,8 +16,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override IReadOnlyList<ushort> ExtraBytes => Unused;
|
||||
|
||||
public override int SIZE_PARTY => PKX.SIZE_3XSTORED;
|
||||
public override int SIZE_STORED => PKX.SIZE_3XSTORED;
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_3XSTORED;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_3XSTORED;
|
||||
public override int Format => 3;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.RS[Species];
|
||||
public override byte[] Data { get; }
|
||||
|
|
|
@ -103,9 +103,9 @@ namespace PKHeX.Core
|
|||
Array.Copy(Data, Offsets.Daycare, rawDC, 0, rawDC.Length);
|
||||
byte[] TempDaycare = new byte[PokeList1.GetDataLength(PokeListType.Single, Japanese)];
|
||||
TempDaycare[0] = rawDC[0];
|
||||
Array.Copy(rawDC, 1, TempDaycare, 2 + 1 + PKX.SIZE_1PARTY + StringLength, StringLength);
|
||||
Array.Copy(rawDC, 1 + StringLength, TempDaycare, 2 + 1 + PKX.SIZE_1PARTY, StringLength);
|
||||
Array.Copy(rawDC, 1 + (2 * StringLength), TempDaycare, 2 + 1, PKX.SIZE_1STORED);
|
||||
Array.Copy(rawDC, 1, TempDaycare, 2 + 1 + PokeCrypto.SIZE_1PARTY + StringLength, StringLength);
|
||||
Array.Copy(rawDC, 1 + StringLength, TempDaycare, 2 + 1 + PokeCrypto.SIZE_1PARTY, StringLength);
|
||||
Array.Copy(rawDC, 1 + (2 * StringLength), TempDaycare, 2 + 1, PokeCrypto.SIZE_1STORED);
|
||||
PokeList1 daycareList = new PokeList1(TempDaycare, PokeListType.Single, Japanese);
|
||||
daycareList.Write().CopyTo(Data, GetPartyOffset(7));
|
||||
DaycareOffset = GetPartyOffset(7);
|
||||
|
@ -160,11 +160,11 @@ namespace PKHeX.Core
|
|||
|
||||
// Daycare is read-only, but in case it ever becomes editable, copy it back in.
|
||||
byte[] rawDC = GetData(GetDaycareSlotOffset(loc: 0, slot: 0), SIZE_STORED);
|
||||
byte[] dc = new byte[1 + (2 * StringLength) + PKX.SIZE_1STORED];
|
||||
byte[] dc = new byte[1 + (2 * StringLength) + PokeCrypto.SIZE_1STORED];
|
||||
dc[0] = rawDC[0];
|
||||
Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY + StringLength, dc, 1, StringLength);
|
||||
Array.Copy(rawDC, 2 + 1 + PKX.SIZE_1PARTY, dc, 1 + StringLength, StringLength);
|
||||
Array.Copy(rawDC, 2 + 1, dc, 1 + (2 * StringLength), PKX.SIZE_1STORED);
|
||||
Array.Copy(rawDC, 2 + 1 + PokeCrypto.SIZE_1PARTY + StringLength, dc, 1, StringLength);
|
||||
Array.Copy(rawDC, 2 + 1 + PokeCrypto.SIZE_1PARTY, dc, 1 + StringLength, StringLength);
|
||||
Array.Copy(rawDC, 2 + 1, dc, 1 + (2 * StringLength), PokeCrypto.SIZE_1STORED);
|
||||
dc.CopyTo(Data, Offsets.Daycare);
|
||||
|
||||
SetChecksums();
|
||||
|
@ -183,8 +183,8 @@ namespace PKHeX.Core
|
|||
// Configuration
|
||||
public override SaveFile Clone() => new SAV1(Write(), Version);
|
||||
|
||||
public override int SIZE_STORED => Japanese ? PKX.SIZE_1JLIST : PKX.SIZE_1ULIST;
|
||||
protected override int SIZE_PARTY => Japanese ? PKX.SIZE_1JLIST : PKX.SIZE_1ULIST;
|
||||
public override int SIZE_STORED => Japanese ? PokeCrypto.SIZE_1JLIST : PokeCrypto.SIZE_1ULIST;
|
||||
protected override int SIZE_PARTY => Japanese ? PokeCrypto.SIZE_1JLIST : PokeCrypto.SIZE_1ULIST;
|
||||
private int SIZE_BOX => BoxSlotCount*SIZE_STORED;
|
||||
private int SIZE_STOREDBOX => PokeList1.GetDataLength(Japanese ? PokeListType.StoredJP : PokeListType.Stored, Japanese);
|
||||
private int SIZE_STOREDPARTY => PokeList1.GetDataLength(PokeListType.Party, Japanese);
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace PKHeX.Core
|
|||
offset++;
|
||||
var pk2 = ReadPKMFromOffset(offset); // parent 2
|
||||
var daycare2 = new PokeList2(pk2);
|
||||
offset += (StringLength * 2) + PKX.SIZE_2STORED; // nick/ot/pkm
|
||||
offset += (StringLength * 2) + PokeCrypto.SIZE_2STORED; // nick/ot/pkm
|
||||
var pk3 = ReadPKMFromOffset(offset); // egg!
|
||||
pk3.IsEgg = true;
|
||||
var daycare3 = new PokeList2(pk3);
|
||||
|
@ -145,7 +145,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
byte[] nick = new byte[StringLength];
|
||||
byte[] ot = new byte[StringLength];
|
||||
byte[] pk = new byte[PKX.SIZE_2STORED];
|
||||
byte[] pk = new byte[PokeCrypto.SIZE_2STORED];
|
||||
|
||||
Array.Copy(Data, offset, nick, 0, nick.Length); offset += nick.Length;
|
||||
Array.Copy(Data, offset, ot, 0, ot.Length); offset += ot.Length;
|
||||
|
@ -246,8 +246,8 @@ namespace PKHeX.Core
|
|||
// Configuration
|
||||
public override SaveFile Clone() => new SAV2(Write());
|
||||
|
||||
public override int SIZE_STORED => Japanese ? PKX.SIZE_2JLIST : PKX.SIZE_2ULIST;
|
||||
protected override int SIZE_PARTY => Japanese ? PKX.SIZE_2JLIST : PKX.SIZE_2ULIST;
|
||||
public override int SIZE_STORED => Japanese ? PokeCrypto.SIZE_2JLIST : PokeCrypto.SIZE_2ULIST;
|
||||
protected override int SIZE_PARTY => Japanese ? PokeCrypto.SIZE_2JLIST : PokeCrypto.SIZE_2ULIST;
|
||||
public override PKM BlankPKM => new PK2(jp: Japanese);
|
||||
public override Type PKMType => typeof(PK2);
|
||||
|
||||
|
|
|
@ -281,8 +281,8 @@ namespace PKHeX.Core
|
|||
// Configuration
|
||||
public override SaveFile Clone() => new SAV3(Write(), Version);
|
||||
|
||||
public override int SIZE_STORED => PKX.SIZE_3STORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_3PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_3STORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_3PARTY;
|
||||
public override PKM BlankPKM => new PK3();
|
||||
public override Type PKMType => typeof(PK3);
|
||||
|
||||
|
@ -749,7 +749,7 @@ namespace PKHeX.Core
|
|||
|
||||
protected override byte[] DecryptPKM(byte[] data)
|
||||
{
|
||||
return PKX.DecryptArray3(data);
|
||||
return PokeCrypto.DecryptArray3(data);
|
||||
}
|
||||
|
||||
// Pokédex
|
||||
|
|
|
@ -134,8 +134,8 @@ namespace PKHeX.Core
|
|||
return sav;
|
||||
}
|
||||
|
||||
public override int SIZE_STORED => PKX.SIZE_3CSTORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_3CSTORED; // unused
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_3CSTORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_3CSTORED; // unused
|
||||
public override PKM BlankPKM => new CK3();
|
||||
public override Type PKMType => typeof(CK3);
|
||||
|
||||
|
|
|
@ -103,8 +103,8 @@ namespace PKHeX.Core
|
|||
return sav;
|
||||
}
|
||||
|
||||
public override int SIZE_STORED => PKX.SIZE_3STORED + 4;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_3PARTY; // unused
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_3STORED + 4;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_3PARTY; // unused
|
||||
public override PKM BlankPKM => new PK3();
|
||||
public override Type PKMType => typeof(PK3);
|
||||
|
||||
|
@ -177,16 +177,16 @@ namespace PKHeX.Core
|
|||
|
||||
protected override PKM GetPKM(byte[] data)
|
||||
{
|
||||
if (data.Length != PKX.SIZE_3STORED)
|
||||
Array.Resize(ref data, PKX.SIZE_3STORED);
|
||||
if (data.Length != PokeCrypto.SIZE_3STORED)
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_3STORED);
|
||||
return new PK3(data);
|
||||
}
|
||||
|
||||
protected override byte[] DecryptPKM(byte[] data)
|
||||
{
|
||||
if (data.Length != PKX.SIZE_3STORED)
|
||||
Array.Resize(ref data, PKX.SIZE_3STORED);
|
||||
return PKX.DecryptArray3(data);
|
||||
if (data.Length != PokeCrypto.SIZE_3STORED)
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_3STORED);
|
||||
return PokeCrypto.DecryptArray3(data);
|
||||
}
|
||||
|
||||
protected override void SetDex(PKM pkm) { /* No Pokedex for this game, do nothing */ }
|
||||
|
@ -194,8 +194,8 @@ namespace PKHeX.Core
|
|||
public override void WriteBoxSlot(PKM pkm, byte[] data, int offset)
|
||||
{
|
||||
base.WriteBoxSlot(pkm, data, offset);
|
||||
BitConverter.GetBytes((ushort)pkm.TID).CopyTo(data, offset + PKX.SIZE_3STORED + 0);
|
||||
BitConverter.GetBytes((ushort)pkm.SID).CopyTo(data, offset + PKX.SIZE_3STORED + 2);
|
||||
BitConverter.GetBytes((ushort)pkm.TID).CopyTo(data, offset + PokeCrypto.SIZE_3STORED + 0);
|
||||
BitConverter.GetBytes((ushort)pkm.SID).CopyTo(data, offset + PokeCrypto.SIZE_3STORED + 2);
|
||||
}
|
||||
|
||||
public override string GetString(byte[] data, int offset, int length) => StringConverter3.GetString3(data, offset, length, Japanese);
|
||||
|
|
|
@ -158,8 +158,8 @@ namespace PKHeX.Core
|
|||
return sav;
|
||||
}
|
||||
|
||||
public override int SIZE_STORED => PKX.SIZE_3XSTORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_3XSTORED; // unused
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_3XSTORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_3XSTORED; // unused
|
||||
public override PKM BlankPKM => new XK3();
|
||||
public override Type PKMType => typeof(XK3);
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ namespace PKHeX.Core
|
|||
SetData(Storage, s4.Storage, 0);
|
||||
}
|
||||
|
||||
public override int SIZE_STORED => PKX.SIZE_4STORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_4PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_4STORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_4PARTY;
|
||||
public override PKM BlankPKM => new PK4();
|
||||
public override Type PKMType => typeof(PK4);
|
||||
|
||||
|
@ -426,7 +426,7 @@ namespace PKHeX.Core
|
|||
public override uint SecondsToFame { get => BitConverter.ToUInt32(General, AdventureInfo + 0x3C); set => BitConverter.GetBytes(value).CopyTo(General, AdventureInfo + 0x3C); }
|
||||
|
||||
protected override PKM GetPKM(byte[] data) => new PK4(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray45(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray45(data);
|
||||
|
||||
protected override void SetPKM(PKM pkm)
|
||||
{
|
||||
|
|
|
@ -88,8 +88,8 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
public override int SIZE_STORED => PKX.SIZE_4STORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_4STORED + 4;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_4STORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_4STORED + 4;
|
||||
public override PKM BlankPKM => new BK4();
|
||||
public override Type PKMType => typeof(BK4);
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace PKHeX.Core
|
|||
private const int BOX_SLOTS = 30;
|
||||
private const int BOX_NAME_LEN = 40; // 20 characters
|
||||
|
||||
private const int BOX_DATA_LEN = (BOX_SLOTS * PKX.SIZE_4STORED) + 0x10; // 0xFF0, each box chunk is padded to nearest 0x100
|
||||
private const int BOX_DATA_LEN = (BOX_SLOTS * PokeCrypto.SIZE_4STORED) + 0x10; // 0xFF0, each box chunk is padded to nearest 0x100
|
||||
private const int BOX_END = BOX_COUNT * BOX_DATA_LEN; // 18 * 0x1000
|
||||
private const int BOX_NAME = 0x12008; // after current & counter
|
||||
private const int BOX_WP = BOX_NAME + (BOX_COUNT * BOX_NAME_LEN); // 0x122D8;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace PKHeX.Core
|
|||
private const int BOX_SLOTS = 30;
|
||||
private const int BOX_NAME_LEN = 40; // 20 characters
|
||||
|
||||
private const int BOX_DATA_LEN = (BOX_SLOTS * PKX.SIZE_4STORED); // 0xFF0, no padding between boxes (to nearest 0x100)
|
||||
private const int BOX_DATA_LEN = (BOX_SLOTS * PokeCrypto.SIZE_4STORED); // 0xFF0, no padding between boxes (to nearest 0x100)
|
||||
private const int BOX_END = BOX_COUNT * BOX_DATA_LEN; // 18 * 0xFF0
|
||||
private const int BOX_NAME = 4 + BOX_END; // after box data
|
||||
private const int BOX_WP = BOX_NAME + (BOX_COUNT * BOX_NAME_LEN); // 0x121B4;
|
||||
|
|
|
@ -9,15 +9,15 @@ namespace PKHeX.Core
|
|||
public abstract class SAV5 : SaveFile, ISaveBlock5BW
|
||||
{
|
||||
protected override PKM GetPKM(byte[] data) => new PK5(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray45(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray45(data);
|
||||
|
||||
protected override string BAKText => $"{OT} ({(GameVersion)Game}) - {PlayTimeString}";
|
||||
public override string Filter => (Footer.Length != 0 ? "DeSmuME DSV|*.dsv|" : string.Empty) + "SAV File|*.sav|All Files|*.*";
|
||||
public override string Extension => ".sav";
|
||||
|
||||
public override IReadOnlyList<ushort> HeldItems => Legal.HeldItems_BW;
|
||||
public override int SIZE_STORED => PKX.SIZE_5STORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_5PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_5STORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_5PARTY;
|
||||
public override PKM BlankPKM => new PK5();
|
||||
public override Type PKMType => typeof(PK5);
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ namespace PKHeX.Core
|
|||
protected SAV6(int size, int biOffset) : base(size, biOffset) { }
|
||||
|
||||
// Configuration
|
||||
public override int SIZE_STORED => PKX.SIZE_6STORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_6PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_6STORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_6PARTY;
|
||||
public override PKM BlankPKM => new PK6();
|
||||
public override Type PKMType => typeof(PK6);
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace PKHeX.Core
|
|||
public override int MaxGameID => Legal.MaxGameID_6; // OR
|
||||
|
||||
protected override PKM GetPKM(byte[] data) => new PK6(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray6(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray6(data);
|
||||
|
||||
protected int WondercardFlags { get; set; } = int.MinValue;
|
||||
protected int JPEG { get; set; } = int.MinValue;
|
||||
|
|
|
@ -64,8 +64,8 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
|
||||
// Configuration
|
||||
public override int SIZE_STORED => PKX.SIZE_6STORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_6PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_6STORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_6PARTY;
|
||||
public override PKM BlankPKM => new PK7();
|
||||
public override Type PKMType => typeof(PK7);
|
||||
|
||||
|
@ -81,7 +81,7 @@ namespace PKHeX.Core
|
|||
public override int MaxBallID => Legal.MaxBallID_7; // 26
|
||||
public override int MaxGameID => Legal.MaxGameID_7;
|
||||
protected override PKM GetPKM(byte[] data) => new PK7(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray6(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray6(data);
|
||||
|
||||
// Feature Overrides
|
||||
|
||||
|
@ -251,7 +251,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
if ((uint)slot >= FusedCount)
|
||||
return -1;
|
||||
return AllBlocks[08].Offset + (PKX.SIZE_6PARTY * slot); // 0x104*slot
|
||||
return AllBlocks[08].Offset + (PokeCrypto.SIZE_6PARTY * slot); // 0x104*slot
|
||||
}
|
||||
|
||||
public override int DaycareSeedSize => Daycare7.DaycareSeedSize; // 128 bits
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace PKHeX.Core
|
|||
public override bool GetSeen(int species) => Blocks.Zukan.GetSeen(species);
|
||||
|
||||
protected override PKM GetPKM(byte[] data) => new PB7(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray6(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray6(data);
|
||||
public override int GetBoxOffset(int box) => Box + (box * BoxSlotCount * SIZE_STORED);
|
||||
protected override IList<int>[] SlotPointers => new[] { Blocks.Storage.PokeListInfo };
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ namespace PKHeX.Core
|
|||
protected SAV8() { }
|
||||
|
||||
// Configuration
|
||||
public override int SIZE_STORED => PKX.SIZE_8STORED;
|
||||
protected override int SIZE_PARTY => PKX.SIZE_8PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_8STORED;
|
||||
protected override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY;
|
||||
public override PKM BlankPKM => new PK8();
|
||||
public override Type PKMType => typeof(PK8);
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace PKHeX.Core
|
|||
public override int OTLength => 12;
|
||||
public override int NickLength => 12;
|
||||
protected override PKM GetPKM(byte[] data) => new PK8(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray8(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray8(data);
|
||||
|
||||
#region Blocks
|
||||
public abstract Box8 BoxInfo { get; }
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace PKHeX.Core
|
|||
public override string Filter { get; } = "Ranch G4 Storage|*.bin*";
|
||||
|
||||
protected override PKM GetPKM(byte[] data) => new PK4(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray45(data);
|
||||
protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray45(data);
|
||||
public override StorageSlotFlag GetSlotFlags(int index) => index >= SlotCount ? StorageSlotFlag.Locked : StorageSlotFlag.None;
|
||||
protected override bool IsSlotSwapProtected(int box, int slot) => IsSlotOverwriteProtected(box, slot);
|
||||
|
||||
|
|
|
@ -83,9 +83,9 @@ namespace PKHeX.Core
|
|||
Teams[t] = new PKM[6];
|
||||
for (int p = 0; p < 6; p++)
|
||||
{
|
||||
int offset = start + (PKX.SIZE_6PARTY*((t * 6) + p));
|
||||
int offset = start + (PokeCrypto.SIZE_6PARTY*((t * 6) + p));
|
||||
offset += 8*(((t * 6) + p)/6); // 8 bytes padding between teams
|
||||
Teams[t][p] = new PK6(Data.Slice(offset, PKX.SIZE_6PARTY)) {Identifier = $"Team {t}, Slot {p}"};
|
||||
Teams[t][p] = new PK6(Data.Slice(offset, PokeCrypto.SIZE_6PARTY)) {Identifier = $"Team {t}, Slot {p}"};
|
||||
}
|
||||
}
|
||||
return Teams;
|
||||
|
@ -98,7 +98,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
for (int p = 0; p < 6; p++)
|
||||
{
|
||||
int offset = start + (PKX.SIZE_6PARTY*((t * 6) + p));
|
||||
int offset = start + (PokeCrypto.SIZE_6PARTY*((t * 6) + p));
|
||||
offset += 8*(((t * 6) + p)/6); // 8 bytes padding between teams
|
||||
Teams[t][p].EncryptedPartyData.CopyTo(Data, offset);
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ namespace PKHeX.Core
|
|||
Teams[t] = new PKM[6];
|
||||
for (int p = 0; p < 6; p++)
|
||||
{
|
||||
int offset = offsets[t] + (PKX.SIZE_6PARTY * p);
|
||||
Teams[t][p] = new PK7(Data.Slice(offset, PKX.SIZE_6STORED)) {Identifier = $"Team {t}, Slot {p}"};
|
||||
int offset = offsets[t] + (PokeCrypto.SIZE_6PARTY * p);
|
||||
Teams[t][p] = new PK7(Data.Slice(offset, PokeCrypto.SIZE_6STORED)) {Identifier = $"Team {t}, Slot {p}"};
|
||||
}
|
||||
}
|
||||
return Teams;
|
||||
|
@ -47,7 +47,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
for (int p = 0; p < 6; p++)
|
||||
{
|
||||
int offset = offsets[t] + (PKX.SIZE_6PARTY * p);
|
||||
int offset = offsets[t] + (PokeCrypto.SIZE_6PARTY * p);
|
||||
Teams[t][p].EncryptedPartyData.CopyTo(Data, offset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core
|
|||
// bool32 occupied
|
||||
// pk5party pkm
|
||||
// u32 expGained
|
||||
private const int SlotSize = 4 + PKX.SIZE_5PARTY + 4; // occupied u32 flag, pk5, exp
|
||||
private const int SlotSize = 4 + PokeCrypto.SIZE_5PARTY + 4; // occupied u32 flag, pk5, exp
|
||||
|
||||
// struct daycare
|
||||
// daycareSlot[2]
|
||||
|
@ -35,7 +35,7 @@ namespace PKHeX.Core
|
|||
|
||||
private int GetDaycareSlotOffset(int slot) => Offset + (SlotSize * slot);
|
||||
public int GetPKMOffset(int slot) => GetDaycareSlotOffset(slot) + 4;
|
||||
private int GetDaycareEXPOffset(int slot) => GetDaycareSlotOffset(slot) + 4 + PKX.SIZE_5PARTY;
|
||||
private int GetDaycareEXPOffset(int slot) => GetDaycareSlotOffset(slot) + 4 + PokeCrypto.SIZE_5PARTY;
|
||||
|
||||
public bool? IsOccupied(int slot) => BitConverter.ToUInt32(Data, GetDaycareSlotOffset(slot)) == 1;
|
||||
public void SetOccupied(int slot, bool occupied) => SAV.SetData(BitConverter.GetBytes((uint)(occupied ? 1 : 0)), GetDaycareSlotOffset(slot));
|
||||
|
|
|
@ -31,13 +31,13 @@ namespace PKHeX.Core
|
|||
public EntreeForest(byte[] data)
|
||||
{
|
||||
Data = data;
|
||||
PKX.CryptArray(data, EncryptionSeed, 0, EncryptionSeedOffset);
|
||||
PokeCrypto.CryptArray(data, EncryptionSeed, 0, EncryptionSeedOffset);
|
||||
}
|
||||
|
||||
public byte[] Write()
|
||||
{
|
||||
byte[] data = (byte[])Data.Clone();
|
||||
PKX.CryptArray(data, EncryptionSeed, 0, EncryptionSeedOffset);
|
||||
PokeCrypto.CryptArray(data, EncryptionSeed, 0, EncryptionSeedOffset);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace PKHeX.Core
|
|||
|
||||
private static EncryptedMysteryGiftAlbum GetAlbum(uint seed, byte[] wcData)
|
||||
{
|
||||
PKX.CryptArray(wcData, seed);
|
||||
PokeCrypto.CryptArray(wcData, seed);
|
||||
|
||||
var flags = new bool[MaxReceivedFlag];
|
||||
var gifts = new DataMysteryGift[MaxCardsPresent];
|
||||
|
@ -71,7 +71,7 @@ namespace PKHeX.Core
|
|||
value.Gifts[i].Data.CopyTo(wcData, CardStart + (i * PGF.Size));
|
||||
|
||||
// Decrypted, Encrypt
|
||||
PKX.CryptArray(wcData, value.Seed);
|
||||
PokeCrypto.CryptArray(wcData, value.Seed);
|
||||
return wcData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
public BattleBox6(SaveFile SAV, int offset) : base(SAV) => Offset = offset;
|
||||
|
||||
private int LockedFlagOffset => Offset + (6 * PKX.SIZE_6STORED);
|
||||
private int LockedFlagOffset => Offset + (6 * PokeCrypto.SIZE_6STORED);
|
||||
|
||||
public bool Locked
|
||||
{
|
||||
|
|
|
@ -9,17 +9,17 @@
|
|||
|
||||
public bool GetIsOccupied(int slot)
|
||||
{
|
||||
return Data[Offset + ((PKX.SIZE_6STORED + 1) * slot)] != 0;
|
||||
return Data[Offset + ((PokeCrypto.SIZE_6STORED + 1) * slot)] != 0;
|
||||
}
|
||||
|
||||
public void SetOccupied(int slot, bool occupied)
|
||||
{
|
||||
Data[Offset + ((PKX.SIZE_6STORED + 1) * slot)] = (byte)(occupied ? 1 : 0);
|
||||
Data[Offset + ((PokeCrypto.SIZE_6STORED + 1) * slot)] = (byte)(occupied ? 1 : 0);
|
||||
}
|
||||
|
||||
public int GetDaycareSlotOffset(int slot)
|
||||
{
|
||||
return Offset + 1 + (slot * (PKX.SIZE_6STORED + 1));
|
||||
return Offset + 1 + (slot * (PokeCrypto.SIZE_6STORED + 1));
|
||||
}
|
||||
|
||||
public bool HasEgg
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core
|
|||
public ResortSave7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
|
||||
|
||||
public const int ResortCount = 93;
|
||||
public int GetResortSlotOffset(int slot) => Offset + 0x16 + (slot * PKX.SIZE_6STORED);
|
||||
public int GetResortSlotOffset(int slot) => Offset + 0x16 + (slot * PokeCrypto.SIZE_6STORED);
|
||||
|
||||
public PKM[] ResortPKM
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ namespace PKHeX.Core
|
|||
PKM[] data = new PKM[ResortCount];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var bytes = SAV.GetData(GetResortSlotOffset(i), PKX.SIZE_6STORED);
|
||||
var bytes = SAV.GetData(GetResortSlotOffset(i), PokeCrypto.SIZE_6STORED);
|
||||
data[i] = new PK7(bytes) { Identifier = $"Resort Slot {i}" };
|
||||
}
|
||||
return data;
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Size of each PKM data stored (bool, pk8)
|
||||
/// </summary>
|
||||
private const int STRUCT_SIZE = 1 + PKX.SIZE_8STORED;
|
||||
private const int STRUCT_SIZE = 1 + PokeCrypto.SIZE_8STORED;
|
||||
|
||||
/// <summary>
|
||||
/// Size of each daycare (both entries & metadata)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
{
|
||||
if ((uint)slot >= 3)
|
||||
return -1;
|
||||
return PKX.SIZE_8PARTY * slot;
|
||||
return PokeCrypto.SIZE_8PARTY * slot;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
public int PartyCount
|
||||
{
|
||||
get => Data[6 * PKX.SIZE_8PARTY];
|
||||
set => Data[6 * PKX.SIZE_8PARTY] = (byte)value;
|
||||
get => Data[6 * PokeCrypto.SIZE_8PARTY];
|
||||
set => Data[6 * PokeCrypto.SIZE_8PARTY] = (byte)value;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue