/* * * Uncipher 64 bits of the KDBG with 3 keys * * @param data data to uncipher * @param KiWaitNever one key * @param KiWaitAlways one key * @param KdpDataBlockEncoded one key * @return data data unciphered */ __inline uint64_t uncipherData(uint64_t Data, uint64_t KiWaitNever, uint64_t KiWaitAlways, uint64_t KdpDataBlockEncoded) { Data = Data^KiWaitNever; Data = _rotl64(Data, KiWaitNever & 0xFF); Data = Data^KdpDataBlockEncoded; Data = _byteswap_uint64(Data); Data = Data^KiWaitAlways; return Data; }
KDPC* TransTimerDpcEx( IN PKTIMER InTimer, IN ULONGLONG InKiWaitNever, IN ULONGLONG InKiWaitAlways) { ULONGLONG RDX = (ULONGLONG)InTimer->Dpc; RDX ^= InKiWaitNever; RDX = _rotl64(RDX, (UCHAR)(InKiWaitNever & 0xFF)); RDX ^= (ULONGLONG)InTimer; RDX = _byteswap_uint64(RDX); RDX ^= InKiWaitAlways; return (KDPC*)RDX; }
// This is the 128-bit variant of the MurmurHash3 hash function that is targeted for 64-bit // platforms (MurmurHash3_x64_128). It was taken from: // https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out) { const u8* data = (const u8*)key; const size_t nblocks = len / 16; u64 h1 = seed; u64 h2 = seed; const u64 c1 = 0x87c37b91114253d5llu; const u64 c2 = 0x4cf5ad432745937fllu; // Body const u64* blocks = (const u64*)(data); for (size_t i = 0; i < nblocks; i++) { u64 k1 = getblock64(blocks, i * 2 + 0); u64 k2 = getblock64(blocks, i * 2 + 1); k1 *= c1; k1 = _rotl64(k1, 31); k1 *= c2; h1 ^= k1; h1 = _rotl64(h1, 27); h1 += h2; h1 = h1 * 5 + 0x52dce729; k2 *= c2; k2 = _rotl64(k2, 33); k2 *= c1; h2 ^= k2; h2 = _rotl64(h2, 31); h2 += h1; h2 = h2 * 5 + 0x38495ab5; } // Tail const u8* tail = (const u8*)(data + nblocks * 16); u64 k1 = 0; u64 k2 = 0; switch (len & 15) { case 15: k2 ^= ((u64)tail[14]) << 48; case 14: k2 ^= ((u64)tail[13]) << 40; case 13: k2 ^= ((u64)tail[12]) << 32; case 12: k2 ^= ((u64)tail[11]) << 24; case 11: k2 ^= ((u64)tail[10]) << 16; case 10: k2 ^= ((u64)tail[9]) << 8; case 9: k2 ^= ((u64)tail[8]) << 0; k2 *= c2; k2 = _rotl64(k2, 33); k2 *= c1; h2 ^= k2; case 8: k1 ^= ((u64)tail[7]) << 56; case 7: k1 ^= ((u64)tail[6]) << 48; case 6: k1 ^= ((u64)tail[5]) << 40; case 5: k1 ^= ((u64)tail[4]) << 32; case 4: k1 ^= ((u64)tail[3]) << 24; case 3: k1 ^= ((u64)tail[2]) << 16; case 2: k1 ^= ((u64)tail[1]) << 8; case 1: k1 ^= ((u64)tail[0]) << 0; k1 *= c1; k1 = _rotl64(k1, 31); k1 *= c2; h1 ^= k1; }; // Finalization h1 ^= len; h2 ^= len; h1 += h2; h2 += h1; h1 = fmix64(h1); h2 = fmix64(h2); h1 += h2; h2 += h1; ((u64*)out)[0] = h1; ((u64*)out)[1] = h2; }
void tidySolutions(int attack, int knightNumber, int coverage, int counter) { FILE* inFile = mkSolDir(attack, coverage, knightNumber, maximisedFile, true, false, counter); FILE* duplicatesOutFile = NULL; FILE* tidiedOutFile = NULL; solution sol; solutionTree = (solutionLeaf *)malloc(sizeof(solutionLeaf) * MAX_SOLUTIONS); solutionLeaf* slot = solutionTree; unsigned long long count = 0; bool error = false; initialiseXYs(); int pos = knightsYX[attack][1] > knightsYX[attack][0] ? knightsYX[attack][1] : knightsYX[attack][0]; if (pos + HASH_BORDER >= MAX_GRID) { printf("Cannot hash more than %d rows", (MAX_GRID - HASH_BORDER)); return; } long long currentPosition = _ftelli64(inFile); size_t loop = readSolution(&sol, inFile); unsigned long long mask = _rotr64(MASK, pos); while (loop) { int offset = 0; int multiplierIndex = 0; unsigned long long rowHash = 0; unsigned long long hash = 0; for (int row = 0; row < pos; row++) { unsigned long long part = (sol.coverage[row] & mask); if (offset < pos) { part = _rotl64(part, pos - offset); } else if (offset > pos) { part = _rotr64(part, offset - pos); } rowHash |= part; offset += HASH_BORDER; if (offset > MAX_GRID) { offset -= MAX_GRID; if (multiplierIndex == 0) { hash |= rowHash; } else { hash |= (rowHash + 1) * multiplier[multiplierIndex]; multiplierIndex++; } } } for (int row = pos; row < pos + HASH_BORDER; row++) { hash |= (_rotr64(sol.coverage[row], MAX_GRID - HASH_BORDER - pos) + 1) * multiplier[multiplierIndex]; multiplierIndex++; } slot->hash = hash; slot->bigger = NULL; slot->equal = NULL; slot->lesser = NULL; slot->solutionOffset = currentPosition; if (count > 0) { solutionLeaf* root = solutionTree; while (true) { if (hash == root->hash) { if (root->equal == NULL) { root->equal = slot; break; } else { root = root->equal; } } else if (hash > root->hash) { if (root->bigger == NULL) { root->bigger = slot; break; } else { root = root->bigger; } } else if (hash < root->hash) { if (root->lesser == NULL) { root->lesser = slot; break; } else { root = root->lesser; } } } } slot++; count++; currentPosition = _ftelli64(inFile); loop = readSolution(&sol, inFile); if ((count == MAX_SOLUTIONS) && loop) { printf("Too many solutions to manage."); error = true; break; } } fclose(inFile); if (error) { return; } inFile = mkSolDir(attack, coverage, knightNumber, maximisedFile, true, false, counter); tidiedOutFile = mkSolDir(attack, coverage, knightNumber, tidiedFile, false, false, 0); slot = solutionTree; readSolution(&sol, inFile); solution compare; while (count) { if (slot->equal == NULL) { //Could be in a maximised file less than counter! writeSolution(&sol, tidiedOutFile); slot++; } else { solutionLeaf* test = slot->equal; int state = STATE_KEEP; while (test != NULL) { _fseeki64(inFile, test->solutionOffset, SEEK_SET); readSolution(&compare, inFile); int cmp = memcmp(sol.coverage, compare.coverage, sizeof(unsigned long long) * MAX_GRID); if (cmp == 0) { cmp = memcmp(sol.knights, compare.knights, sizeof(unsigned long long) * MAX_GRID); if (cmp == 0) { state = STATE_SCRAP; break; } else { state = STATE_DUPLICATE; } } test = test->equal; } if (state == STATE_KEEP) { writeSolution(&sol, tidiedOutFile); } else if (state == STATE_DUPLICATE) { if (duplicatesOutFile == NULL) { duplicatesOutFile = mkSolDir(attack, coverage, knightNumber, duplicatesFile, false, false, 0); } writeSolution(&sol, duplicatesOutFile); } slot++; _fseeki64(inFile, slot->solutionOffset, SEEK_SET); } readSolution(&sol, inFile); count--; } fclose(inFile); fclose(tidiedOutFile); if (duplicatesOutFile != NULL) { fclose(duplicatesOutFile); } }