small optimizations

Add ccitt method to checksum an existing array
reduce linq usage (faster save retrieval)

misc4 line endings?
This commit is contained in:
Kurt 2017-06-11 00:23:04 -07:00
parent 43838a5f24
commit 21ab0296f3
6 changed files with 38 additions and 26 deletions

View file

@ -172,11 +172,15 @@ namespace PKHeX.Core
}
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)
{
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) { }

View file

@ -86,8 +86,8 @@ namespace PKHeX.Core
if (c == null)
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(getData(c[1][0] + SBO, c[1][1] - c[1][0]))).CopyTo(Data, c[1][2] + SBO);
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(Data, c[1][0] + SBO, c[1][1] - c[1][0])).CopyTo(Data, c[1][2] + SBO);
}
public override bool ChecksumsValid
{
@ -97,9 +97,9 @@ namespace PKHeX.Core
if (c == null)
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
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 true;
@ -114,9 +114,9 @@ namespace PKHeX.Core
return "Unable to check Save File.";
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;
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;
return r.Length == 0 ? "Checksums valid." : r.TrimEnd();

View file

@ -229,20 +229,21 @@ namespace PKHeX.Core
if (!new[] { SIZE_G3BOX, SIZE_G3BOXGCI }.Contains(data.Length))
return GameVersion.Invalid;
byte[] sav = data.Skip(data.Length - SIZE_G3BOX).Take(SIZE_G3BOX).ToArray();
byte[] sav = data;
// Verify first checksum
uint chk = 0; // initial value
var ofs = data.Length - SIZE_G3BOX + 0x2000;
for (int j = 0x4; j < 0x1FFC; j += 2)
{
chk += (ushort)(sav[0x2000 + j] << 8);
chk += sav[0x2000 + j + 1];
chk += (ushort)(sav[ofs + j] << 8);
chk += sav[ofs + j + 1];
}
ushort chkA = (ushort)chk;
ushort chkB = (ushort)(0xF004 - chkA);
ushort CHK_A = (ushort)((sav[0x2000] << 8) | sav[0x2001]);
ushort CHK_B = (ushort)((sav[0x2002] << 8) | sav[0x2003]);
ushort CHK_A = (ushort)((sav[ofs + 0] << 8) | sav[ofs + 1]);
ushort CHK_B = (ushort)((sav[ofs + 2] << 8) | sav[ofs + 3]);
return CHK_A == chkA && CHK_B == chkB ? GameVersion.RSBOX : GameVersion.Invalid;
}
@ -295,11 +296,11 @@ namespace PKHeX.Core
return GameVersion.Invalid;
// 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;
if (BitConverter.ToUInt16(data, 0xCF2A) == ccitt16(data.Take(0xCF18).ToArray()))
if (BitConverter.ToUInt16(data, 0xCF2A) == ccitt16(data, 0, 0xCF18))
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;
// General Block Checksum is invalid, check for block identifiers
@ -346,11 +347,11 @@ namespace PKHeX.Core
return GameVersion.Invalid;
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)
return GameVersion.BW;
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)
return GameVersion.B2W2;
return GameVersion.Invalid;
@ -590,15 +591,19 @@ namespace PKHeX.Core
// SAV Manipulation
/// <summary>Calculates the CRC16-CCITT checksum over an input byte array.</summary>
/// <param name="data">Input byte array</param>
/// <param name="start">Starting point for checksum</param>
/// <param name="length"></param>
/// <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 poly = 0x1021;
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);
for (int j = 0; j < 8; j++)
{
@ -611,6 +616,11 @@ namespace PKHeX.Core
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 =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,

View file

@ -491,7 +491,8 @@ namespace PKHeX.WinForms
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));
}
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()

View file

@ -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 + 0x100);
byte[] skinchkdata = SAV.Data.Skip(SAV.CGearDataOffset + bgdata.Length + 0x100).Take(4).ToArray();
ushort skinchkval = SaveUtil.ccitt16(skinchkdata);
ushort skinchkval = SaveUtil.ccitt16(SAV.Data, bgdata.Length + 0x100, 4);
BitConverter.GetBytes(skinchkval).CopyTo(SAV.Data, SAV.CGearDataOffset + bgdata.Length + 0x112);
// Indicate in the save file that data is present
BitConverter.GetBytes((ushort)0xC21E).CopyTo(SAV.Data, 0x19438);
SAV.Data[SAV.CGearInfoOffset + 0x26] = 1; // data present
BitConverter.GetBytes(chk).CopyTo(SAV.Data, SAV.CGearInfoOffset + 0x24);

View file

@ -40,7 +40,7 @@ namespace PKHeX.WinForms
Array.Copy(LinkInfo.Data, 0, data, 0x1FF, LinkInfo.Data.Length);
// 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);
SAV.LinkBlock = data;