public static ulong StrToU64(string input, out bool valid) { var chk = Pull(0, 4) >> 4; // first four chars are checksum bits var result = Pull(4, input.Length); // next 12 chars are the 70 value bits var actual = SaveUtil.CRC16_CCITT(BitConverter.GetBytes(result)); valid = chk == actual; return(result); ulong Pull(int start, int count) { ulong val = 0; for (int i = start; i < count; i++) { var c = input[i]; if (c == '-') { continue; } val <<= 5; val |= Get5BitFromChar(c) & 0b11111; } return(val); } }
protected override void SetChecksums() { int[][] c = GetChecksumOffsets(Version); if (c == null) { return; } BitConverter.GetBytes(SaveUtil.CRC16_CCITT(Data, c[0][0] + GBO, c[0][1] - c[0][0])).CopyTo(Data, c[0][2] + GBO); BitConverter.GetBytes(SaveUtil.CRC16_CCITT(Data, c[1][0] + SBO, c[1][1] - c[1][0])).CopyTo(Data, c[1][2] + SBO); }
private static ulong StringToUInt64(string s) { // First 4 characters act as the checksum ulong v1 = 0; ulong v2 = 0; for (int i = 0; i < 4; i++) { var c = CharToU16(s[i]); if (c == INVALID) { return(INVALID); } v2 = (uint)(((v1 | c) >> 27) | (v2 << 5)); v1 = (uint)((v1 | c) << 5); } var crc = ((v1 >> 5) | (uint)(v2 << 27)) >> 4; crc |= (v2 >> 5) << 28 | (v2 >> 9) << 32; // Last 12 characters act as the file ID (returned value) ulong val = 0; for (int i = 4; i < 16; i++) { var c = CharToU16(s[i]); if (c == INVALID) { return(INVALID); } var v14 = val | c; val = (val & 0xFFFFFFFF00000000) | (uint)(val | c); if (i == 0xF) { continue; } val = (uint)((val >> 32) << 5) << 32 | (uint)val | (v14 >> 27); val = (val & 0xFFFFFFFF00000000) | (uint)(v14 << 5); } if (SaveUtil.CRC16_CCITT(BitConverter.GetBytes(val)) != crc) { return(uint.MaxValue); } return(val); }
protected override void SetChecksums() { // Check for invalid block lengths if (Blocks.Length < 3) // arbitrary... { Debug.WriteLine("Not enough blocks ({0}), aborting SetChecksums", Blocks.Length); return; } // Apply checksums foreach (BlockInfo b in Blocks) { byte[] array = Data.Skip(b.Offset).Take(b.Length).ToArray(); ushort chk = SaveUtil.CRC16_CCITT(array); BitConverter.GetBytes(chk).CopyTo(Data, b.ChecksumOffset); BitConverter.GetBytes(chk).CopyTo(Data, b.ChecksumMirror); } }
protected override void SetChecksums() { // Check for invalid block lengths if (Blocks.Length < 3) // arbitrary... { Debug.WriteLine("Not enough blocks ({0}), aborting SetChecksums", Blocks.Length); return; } // Apply checksums for (int i = 0; i < Blocks.Length; i++) { if (Blocks[i].Length + Blocks[i].Offset > Data.Length) { Debug.WriteLine("Block {0} has invalid offset/length value.", i); return; } byte[] array = new byte[Blocks[i].Length]; Array.Copy(Data, Blocks[i].Offset, array, 0, array.Length); BitConverter.GetBytes(SaveUtil.CRC16_CCITT(array)).CopyTo(Data, BlockInfoOffset + 6 + i * 8); } }
public static string U64ToStr(ulong input, bool insertDash) { uint chk = SaveUtil.CRC16_CCITT(BitConverter.GetBytes(input)); var buff = new char[16]; int ctr = 15; Push(input, 12); // store value bits Push(chk << 4, 4); // store checksum bits return(!insertDash?string.Concat(buff) : GetStringWithDashesEvery(buff, 4)); void Push(ulong v, int count) { for (int i = 0; i < count; i++) { buff[ctr--] = Set5BitToChar((char)(v & 0b11111)); v >>= 5; } } }
private ushort GetChecksum(byte[] data) => SaveUtil.CRC16_CCITT(data, Offset, Length);