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) 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) { }

View file

@ -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();

View file

@ -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,

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; 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()

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 + 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);

View file

@ -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;