mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 12:33:06 +00:00
small optimizations
Add ccitt method to checksum an existing array reduce linq usage (faster save retrieval) misc4 line endings?
This commit is contained in:
parent
43838a5f24
commit
21ab0296f3
6 changed files with 38 additions and 26 deletions
|
@ -172,11 +172,15 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
public override PKM getPKM(byte[] data)
|
public override PKM getPKM(byte[] data)
|
||||||
{
|
{
|
||||||
return new PK3(data.Take(PKX.SIZE_3STORED).ToArray());
|
if (data.Length != PKX.SIZE_3STORED)
|
||||||
|
Array.Resize(ref data, PKX.SIZE_3STORED);
|
||||||
|
return new PK3(data);
|
||||||
}
|
}
|
||||||
public override byte[] decryptPKM(byte[] data)
|
public override byte[] decryptPKM(byte[] data)
|
||||||
{
|
{
|
||||||
return PKX.decryptArray3(data.Take(PKX.SIZE_3STORED).ToArray());
|
if (data.Length != PKX.SIZE_3STORED)
|
||||||
|
Array.Resize(ref data, PKX.SIZE_3STORED);
|
||||||
|
return PKX.decryptArray3(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void setDex(PKM pkm) { }
|
protected override void setDex(PKM pkm) { }
|
||||||
|
|
|
@ -86,8 +86,8 @@ namespace PKHeX.Core
|
||||||
if (c == null)
|
if (c == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BitConverter.GetBytes(SaveUtil.ccitt16(getData(c[0][0] + GBO, c[0][1] - c[0][0]))).CopyTo(Data, c[0][2] + GBO);
|
BitConverter.GetBytes(SaveUtil.ccitt16(Data, c[0][0] + GBO, c[0][1] - c[0][0])).CopyTo(Data, c[0][2] + GBO);
|
||||||
BitConverter.GetBytes(SaveUtil.ccitt16(getData(c[1][0] + SBO, c[1][1] - c[1][0]))).CopyTo(Data, c[1][2] + SBO);
|
BitConverter.GetBytes(SaveUtil.ccitt16(Data, c[1][0] + SBO, c[1][1] - c[1][0])).CopyTo(Data, c[1][2] + SBO);
|
||||||
}
|
}
|
||||||
public override bool ChecksumsValid
|
public override bool ChecksumsValid
|
||||||
{
|
{
|
||||||
|
@ -97,9 +97,9 @@ namespace PKHeX.Core
|
||||||
if (c == null)
|
if (c == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (SaveUtil.ccitt16(getData(c[0][0] + GBO, c[0][1] - c[0][0])) != BitConverter.ToUInt16(Data, c[0][2] + GBO))
|
if (SaveUtil.ccitt16(Data, c[0][0] + GBO, c[0][1] - c[0][0]) != BitConverter.ToUInt16(Data, c[0][2] + GBO))
|
||||||
return false; // Small Fail
|
return false; // Small Fail
|
||||||
if (SaveUtil.ccitt16(getData(c[1][0] + SBO, c[1][1] - c[1][0])) != BitConverter.ToUInt16(Data, c[1][2] + SBO))
|
if (SaveUtil.ccitt16(Data, c[1][0] + SBO, c[1][1] - c[1][0]) != BitConverter.ToUInt16(Data, c[1][2] + SBO))
|
||||||
return false; // Large Fail
|
return false; // Large Fail
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -114,9 +114,9 @@ namespace PKHeX.Core
|
||||||
return "Unable to check Save File.";
|
return "Unable to check Save File.";
|
||||||
|
|
||||||
string r = "";
|
string r = "";
|
||||||
if (SaveUtil.ccitt16(getData(c[0][0] + GBO, c[0][1] - c[0][0])) != BitConverter.ToUInt16(Data, c[0][2] + GBO))
|
if (SaveUtil.ccitt16(Data, c[0][0] + GBO, c[0][1] - c[0][0]) != BitConverter.ToUInt16(Data, c[0][2] + GBO))
|
||||||
r += "Small block checksum is invalid" + Environment.NewLine;
|
r += "Small block checksum is invalid" + Environment.NewLine;
|
||||||
if (SaveUtil.ccitt16(getData(c[1][0] + SBO, c[1][1] - c[1][0])) != BitConverter.ToUInt16(Data, c[1][2] + SBO))
|
if (SaveUtil.ccitt16(Data, c[1][0] + SBO, c[1][1] - c[1][0]) != BitConverter.ToUInt16(Data, c[1][2] + SBO))
|
||||||
r += "Large block checksum is invalid" + Environment.NewLine;
|
r += "Large block checksum is invalid" + Environment.NewLine;
|
||||||
|
|
||||||
return r.Length == 0 ? "Checksums valid." : r.TrimEnd();
|
return r.Length == 0 ? "Checksums valid." : r.TrimEnd();
|
||||||
|
|
|
@ -229,20 +229,21 @@ namespace PKHeX.Core
|
||||||
if (!new[] { SIZE_G3BOX, SIZE_G3BOXGCI }.Contains(data.Length))
|
if (!new[] { SIZE_G3BOX, SIZE_G3BOXGCI }.Contains(data.Length))
|
||||||
return GameVersion.Invalid;
|
return GameVersion.Invalid;
|
||||||
|
|
||||||
byte[] sav = data.Skip(data.Length - SIZE_G3BOX).Take(SIZE_G3BOX).ToArray();
|
byte[] sav = data;
|
||||||
|
|
||||||
// Verify first checksum
|
// Verify first checksum
|
||||||
uint chk = 0; // initial value
|
uint chk = 0; // initial value
|
||||||
|
var ofs = data.Length - SIZE_G3BOX + 0x2000;
|
||||||
for (int j = 0x4; j < 0x1FFC; j += 2)
|
for (int j = 0x4; j < 0x1FFC; j += 2)
|
||||||
{
|
{
|
||||||
chk += (ushort)(sav[0x2000 + j] << 8);
|
chk += (ushort)(sav[ofs + j] << 8);
|
||||||
chk += sav[0x2000 + j + 1];
|
chk += sav[ofs + j + 1];
|
||||||
}
|
}
|
||||||
ushort chkA = (ushort)chk;
|
ushort chkA = (ushort)chk;
|
||||||
ushort chkB = (ushort)(0xF004 - chkA);
|
ushort chkB = (ushort)(0xF004 - chkA);
|
||||||
|
|
||||||
ushort CHK_A = (ushort)((sav[0x2000] << 8) | sav[0x2001]);
|
ushort CHK_A = (ushort)((sav[ofs + 0] << 8) | sav[ofs + 1]);
|
||||||
ushort CHK_B = (ushort)((sav[0x2002] << 8) | sav[0x2003]);
|
ushort CHK_B = (ushort)((sav[ofs + 2] << 8) | sav[ofs + 3]);
|
||||||
|
|
||||||
return CHK_A == chkA && CHK_B == chkB ? GameVersion.RSBOX : GameVersion.Invalid;
|
return CHK_A == chkA && CHK_B == chkB ? GameVersion.RSBOX : GameVersion.Invalid;
|
||||||
}
|
}
|
||||||
|
@ -295,11 +296,11 @@ namespace PKHeX.Core
|
||||||
return GameVersion.Invalid;
|
return GameVersion.Invalid;
|
||||||
|
|
||||||
// General Block Checksum
|
// General Block Checksum
|
||||||
if (BitConverter.ToUInt16(data, 0xC0FE) == ccitt16(data.Take(0xC0EC).ToArray()))
|
if (BitConverter.ToUInt16(data, 0xC0FE) == ccitt16(data, 0, 0xC0EC))
|
||||||
return GameVersion.DP;
|
return GameVersion.DP;
|
||||||
if (BitConverter.ToUInt16(data, 0xCF2A) == ccitt16(data.Take(0xCF18).ToArray()))
|
if (BitConverter.ToUInt16(data, 0xCF2A) == ccitt16(data, 0, 0xCF18))
|
||||||
return GameVersion.Pt;
|
return GameVersion.Pt;
|
||||||
if (BitConverter.ToUInt16(data, 0xF626) == ccitt16(data.Take(0xF618).ToArray()))
|
if (BitConverter.ToUInt16(data, 0xF626) == ccitt16(data, 0, 0xF618))
|
||||||
return GameVersion.HGSS;
|
return GameVersion.HGSS;
|
||||||
|
|
||||||
// General Block Checksum is invalid, check for block identifiers
|
// General Block Checksum is invalid, check for block identifiers
|
||||||
|
@ -346,11 +347,11 @@ namespace PKHeX.Core
|
||||||
return GameVersion.Invalid;
|
return GameVersion.Invalid;
|
||||||
|
|
||||||
ushort chk1 = BitConverter.ToUInt16(data, SIZE_G5BW - 0x100 + 0x8C + 0xE);
|
ushort chk1 = BitConverter.ToUInt16(data, SIZE_G5BW - 0x100 + 0x8C + 0xE);
|
||||||
ushort actual1 = ccitt16(data.Skip(SIZE_G5BW - 0x100).Take(0x8C).ToArray());
|
ushort actual1 = ccitt16(data, SIZE_G5BW - 0x100, 0x8C);
|
||||||
if (chk1 == actual1)
|
if (chk1 == actual1)
|
||||||
return GameVersion.BW;
|
return GameVersion.BW;
|
||||||
ushort chk2 = BitConverter.ToUInt16(data, SIZE_G5B2W2 - 0x100 + 0x94 + 0xE);
|
ushort chk2 = BitConverter.ToUInt16(data, SIZE_G5B2W2 - 0x100 + 0x94 + 0xE);
|
||||||
ushort actual2 = ccitt16(data.Skip(SIZE_G5B2W2 - 0x100).Take(0x94).ToArray());
|
ushort actual2 = ccitt16(data, SIZE_G5B2W2 - 0x100, 0x94);
|
||||||
if (chk2 == actual2)
|
if (chk2 == actual2)
|
||||||
return GameVersion.B2W2;
|
return GameVersion.B2W2;
|
||||||
return GameVersion.Invalid;
|
return GameVersion.Invalid;
|
||||||
|
@ -590,15 +591,19 @@ namespace PKHeX.Core
|
||||||
// SAV Manipulation
|
// SAV Manipulation
|
||||||
/// <summary>Calculates the CRC16-CCITT checksum over an input byte array.</summary>
|
/// <summary>Calculates the CRC16-CCITT checksum over an input byte array.</summary>
|
||||||
/// <param name="data">Input byte array</param>
|
/// <param name="data">Input byte array</param>
|
||||||
|
/// <param name="start">Starting point for checksum</param>
|
||||||
|
/// <param name="length"></param>
|
||||||
/// <returns>Checksum</returns>
|
/// <returns>Checksum</returns>
|
||||||
public static ushort ccitt16(byte[] data)
|
public static ushort ccitt16(byte[] data, int start, int length)
|
||||||
{
|
{
|
||||||
const ushort init = 0xFFFF;
|
const ushort init = 0xFFFF;
|
||||||
const ushort poly = 0x1021;
|
const ushort poly = 0x1021;
|
||||||
|
|
||||||
ushort crc = init;
|
ushort crc = init;
|
||||||
foreach (byte b in data)
|
int end = start + length;
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
{
|
{
|
||||||
|
byte b = data[i];
|
||||||
crc ^= (ushort)(b << 8);
|
crc ^= (ushort)(b << 8);
|
||||||
for (int j = 0; j < 8; j++)
|
for (int j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
|
@ -611,6 +616,11 @@ namespace PKHeX.Core
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Calculates the CRC16-CCITT checksum over an input byte array.</summary>
|
||||||
|
/// <param name="data">Input byte array</param>
|
||||||
|
/// <returns>Checksum</returns>
|
||||||
|
public static ushort ccitt16(byte[] data) => ccitt16(data, 0, data.Length);
|
||||||
|
|
||||||
private static readonly ushort[] crc16 =
|
private static readonly ushort[] crc16 =
|
||||||
{
|
{
|
||||||
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
||||||
|
|
|
@ -491,7 +491,8 @@ namespace PKHeX.WinForms
|
||||||
if (Prints[i] == 1 + Math.Sign((BitConverter.ToUInt16(SAV.Data, ofsPrints + (i << 1)) >> 1) - 1)) continue;
|
if (Prints[i] == 1 + Math.Sign((BitConverter.ToUInt16(SAV.Data, ofsPrints + (i << 1)) >> 1) - 1)) continue;
|
||||||
BitConverter.GetBytes(Prints[i] << 1).CopyTo(SAV.Data, ofsPrints + (i << 1));
|
BitConverter.GetBytes(Prints[i] << 1).CopyTo(SAV.Data, ofsPrints + (i << 1));
|
||||||
}
|
}
|
||||||
if (HallStatUpdated) BitConverter.GetBytes(SaveUtil.ccitt16(SAV.Data.Skip(ofsHallStat).Take(0xBAE).ToArray())).CopyTo(SAV.Data, ofsHallStat + 0xBAE);
|
if (HallStatUpdated)
|
||||||
|
BitConverter.GetBytes(SaveUtil.ccitt16(SAV.Data, ofsHallStat, 0xBAE)).CopyTo(SAV.Data, ofsHallStat + 0xBAE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPrints()
|
private void setPrints()
|
||||||
|
|
|
@ -122,15 +122,12 @@ namespace PKHeX.WinForms
|
||||||
BitConverter.GetBytes(chk).CopyTo(SAV.Data, SAV.CGearDataOffset + bgdata.Length + 2);
|
BitConverter.GetBytes(chk).CopyTo(SAV.Data, SAV.CGearDataOffset + bgdata.Length + 2);
|
||||||
BitConverter.GetBytes(chk).CopyTo(SAV.Data, SAV.CGearDataOffset + bgdata.Length + 0x100);
|
BitConverter.GetBytes(chk).CopyTo(SAV.Data, SAV.CGearDataOffset + bgdata.Length + 0x100);
|
||||||
|
|
||||||
byte[] skinchkdata = SAV.Data.Skip(SAV.CGearDataOffset + bgdata.Length + 0x100).Take(4).ToArray();
|
ushort skinchkval = SaveUtil.ccitt16(SAV.Data, bgdata.Length + 0x100, 4);
|
||||||
ushort skinchkval = SaveUtil.ccitt16(skinchkdata);
|
|
||||||
BitConverter.GetBytes(skinchkval).CopyTo(SAV.Data, SAV.CGearDataOffset + bgdata.Length + 0x112);
|
BitConverter.GetBytes(skinchkval).CopyTo(SAV.Data, SAV.CGearDataOffset + bgdata.Length + 0x112);
|
||||||
|
|
||||||
// Indicate in the save file that data is present
|
// Indicate in the save file that data is present
|
||||||
BitConverter.GetBytes((ushort)0xC21E).CopyTo(SAV.Data, 0x19438);
|
BitConverter.GetBytes((ushort)0xC21E).CopyTo(SAV.Data, 0x19438);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SAV.Data[SAV.CGearInfoOffset + 0x26] = 1; // data present
|
SAV.Data[SAV.CGearInfoOffset + 0x26] = 1; // data present
|
||||||
BitConverter.GetBytes(chk).CopyTo(SAV.Data, SAV.CGearInfoOffset + 0x24);
|
BitConverter.GetBytes(chk).CopyTo(SAV.Data, SAV.CGearInfoOffset + 0x24);
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace PKHeX.WinForms
|
||||||
Array.Copy(LinkInfo.Data, 0, data, 0x1FF, LinkInfo.Data.Length);
|
Array.Copy(LinkInfo.Data, 0, data, 0x1FF, LinkInfo.Data.Length);
|
||||||
|
|
||||||
// Fix Checksum just in case.
|
// Fix Checksum just in case.
|
||||||
ushort ccitt = SaveUtil.ccitt16(data.Skip(0x200).Take(data.Length - 4 - 0x200).ToArray()); // [app,chk)
|
ushort ccitt = SaveUtil.ccitt16(data, 0x200, data.Length - 4 - 0x200); // [app,chk)
|
||||||
BitConverter.GetBytes(ccitt).CopyTo(data, data.Length - 4);
|
BitConverter.GetBytes(ccitt).CopyTo(data, data.Length - 4);
|
||||||
|
|
||||||
SAV.LinkBlock = data;
|
SAV.LinkBlock = data;
|
||||||
|
|
Loading…
Reference in a new issue