private void GenerateSearchJob(DateTime testTime, int[] minIVs, int[] maxIVs, uint VCountMin, uint VCountMax, uint Timer0Min, uint Timer0Max, uint GxStatMin, uint GxStatMax, uint VFrameMin, uint VFrameMax, int secondsMin, int secondsMax, Version version, Language language, DSType dstype, int[] button, bool softReset, bool roamer, bool minMaxGxStat) { // offset the start by 2 for BW2 int offset = version == Version.Black2 || version == Version.White2 ? 2 : 0; uint buttonMashed = Functions.buttonMashed(button); var array = new uint[80]; uint[] h = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}; array[6] = (uint) (MAC_address & 0xFFFF); if (softReset) { array[6] = array[6] ^ 0x01000000; } var upperMAC = (uint) (MAC_address >> 16); // Get the version-unique part of the message Array.Copy(Nazos.Nazo(version, language, dstype), array, 5); array[10] = 0x00000000; array[11] = 0x00000000; array[12] = buttonMashed; array[13] = 0x80000000; array[14] = 0x00000000; array[15] = 0x000001A0; array[8] = Functions.seedDate(testTime); var GxStatList = new List<uint> {GxStatMin}; // build the GxStat ranges if (GxStatMin != GxStatMax) if (!minMaxGxStat) GxStatList.Add(GxStatMax); else for (uint i = GxStatMin + 1; i <= GxStatMax; ++i) GxStatList.Add(i); for (int cntSeconds = secondsMin; cntSeconds <= secondsMax; cntSeconds++) { array[9] = Functions.seedTime(testTime, dstype); for (uint cntVCount = VCountMin; cntVCount <= VCountMax; cntVCount++) { for (uint cntTimer0 = Timer0Min; cntTimer0 <= Timer0Max; cntTimer0++) { array[5] = cntVCount*0x10000 + cntTimer0; array[5] = Functions.Reorder(array[5]); foreach (uint GxStat in GxStatList) { for (uint cntVFrame = VFrameMin; cntVFrame <= VFrameMax; cntVFrame++) { uint a = h[0]; uint b = h[1]; uint c = h[2]; uint d = h[3]; uint e = h[4]; uint f = 0; uint k = 0; array[7] = (upperMAC ^ (cntVFrame*0x1000000) ^ GxStat); for (int i = 0; i < 80; i++) { if (i < 20) { f = (b & c) | ((~b) & d); k = 0x5A827999; } if (i < 40 && i >= 20) { f = b ^ c ^ d; k = 0x6ED9EBA1; } if (i < 60 && i >= 40) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; } if (i >= 60) { f = b ^ c ^ d; k = 0xCA62C1D6; } if (i > 15) { array[i] = Functions.RotateLeft( array[i - 3] ^ array[i - 8] ^ array[i - 14] ^ array[i - 16], 1); } uint temp = Functions.RotateLeft(a, 5) + f + e + k + array[i]; e = d; d = c; c = Functions.RotateRight(b, 2); b = a; a = temp; } uint part1 = Functions.Reorder(h[0] + a); uint part2 = Functions.Reorder(h[1] + b); ulong seed2 = (ulong) part1*0x6C078965; uint seed1 = part2*0x6C078965 + (uint) (seed2 >> 32); seed1 = seed1 + (part1*0x5D588B65); seed2 = (uint) (seed2 & 0xFFFFFFFF) + 0x269EC3; ulong seed = (ulong) (seed1*0x100000000) + seed2; var tempSeed = (uint) (seed >> 32); progressSearched++; if (!findDirectSeed) { var IVArray = new int[6]; MersenneTwisterFast mt; if (roamer) { mt = new MersenneTwisterFast(tempSeed, 7); mt.Nextuint(); IVArray[0] = (int) (mt.Nextuint() >> 27); IVArray[1] = (int) (mt.Nextuint() >> 27); IVArray[2] = (int) (mt.Nextuint() >> 27); IVArray[4] = (int) (mt.Nextuint() >> 27); IVArray[5] = (int) (mt.Nextuint() >> 27); IVArray[3] = (int) (mt.Nextuint() >> 27); } else { //advance for BW2 mt = new MersenneTwisterFast(tempSeed, 6 + offset); for (int i = 0; i < offset; ++i) mt.Nextuint(); IVArray[0] = (int) (mt.Nextuint() >> 27); IVArray[1] = (int) (mt.Nextuint() >> 27); IVArray[2] = (int) (mt.Nextuint() >> 27); IVArray[3] = (int) (mt.Nextuint() >> 27); IVArray[4] = (int) (mt.Nextuint() >> 27); IVArray[5] = (int) (mt.Nextuint() >> 27); } if ((IVArray[0] >= minIVs[0] && IVArray[0] <= maxIVs[0]) && (IVArray[1] >= minIVs[1] && IVArray[1] <= maxIVs[1]) && (IVArray[2] >= minIVs[2] && IVArray[2] <= maxIVs[2]) && (IVArray[3] >= minIVs[3] && IVArray[3] <= maxIVs[3]) && (IVArray[4] >= minIVs[4] && IVArray[4] <= maxIVs[4]) && (IVArray[5] >= minIVs[5] && IVArray[5] <= maxIVs[5])) { var dsParameterFound = new DSParameterCapture { ActualSeconds = testTime.Second, VCount = cntVCount, Timer0 = cntTimer0, GxStat = GxStat, VFrame = cntVFrame, Seed = seed }; dsParameters.Add(dsParameterFound); refreshQueue = true; progressFound++; } } else { if (checkBoxHalfSeed.Checked) { if (tempSeed == (int) directSeed) { var dsParameterFound = new DSParameterCapture { ActualSeconds = testTime.Second, VCount = cntVCount, Timer0 = cntTimer0, GxStat = GxStat, VFrame = cntVFrame, Seed = seed }; dsParameters.Add(dsParameterFound); refreshQueue = true; progressFound++; } } else { if (seed == directSeed) { var dsParameterFound = new DSParameterCapture { ActualSeconds = testTime.Second, VCount = cntVCount, Timer0 = cntTimer0, GxStat = GxStat, VFrame = cntVFrame, Seed = seed }; dsParameters.Add(dsParameterFound); refreshQueue = true; progressFound++; } } } } } } } testTime = testTime.AddSeconds(1); } }
private void Search(DateTime date, uint vcountMin, uint vcountMax, uint timer0Min, uint timer0Max, uint vframeMin, uint vframeMax, uint gxstatMin, uint gxstatMax, bool minmaxgxstat, int secondsMin, int secondsMax, bool softreset, Version version, Language language, DSType dstype, bool memorylink, ulong macaddress, uint buttons, uint[] pattern) { var array = new uint[80]; array[6] = (uint) (macaddress & 0xFFFF); if (softreset) { array[6] = array[6] ^ 0x01000000; } Array.Copy(Nazos.Nazo(version, language, dstype), array, 5); array[10] = 0x00000000; array[11] = 0x00000000; array[13] = 0x80000000; array[14] = 0x00000000; array[15] = 0x000001A0; array[12] = buttons; string yearMonth = String.Format("{0:00}", date.Year%2000) + String.Format("{0:00}", date.Month); string dateString = String.Format("{0:00}", (int) date.DayOfWeek); dateString = String.Format("{0:00}", date.Day) + dateString; dateString = yearMonth + dateString; array[8] = uint.Parse(dateString, NumberStyles.HexNumber); array[9] = 0x0; //uint[] alpha = Functions.alphaSHA1(array, 8); var upperMAC = (uint) (macaddress >> 16); for (uint vcount = vcountMin; vcount <= vcountMax; ++vcount) { for (uint timer0 = timer0Min; timer0 <= timer0Max; ++timer0) { array[5] = (vcount << 16) + timer0; array[5] = Functions.Reorder(array[5]); for (uint vframe = vframeMin; vframe <= vframeMax; ++vframe) { for (uint gxstat = gxstatMin; gxstat <= gxstatMax; ++gxstat) { array[7] = (upperMAC ^ (vframe*0x1000000) ^ gxstat); uint[] alpha = Functions.alphaSHA1(array, 8); array[16] = Functions.RotateLeft(array[13] ^ array[8] ^ array[2] ^ array[0], 1); array[18] = Functions.RotateLeft(array[15] ^ array[10] ^ array[4] ^ array[2], 1); array[19] = Functions.RotateLeft(array[16] ^ array[11] ^ array[5] ^ array[3], 1); array[21] = Functions.RotateLeft(array[18] ^ array[13] ^ array[7] ^ array[5], 1); array[22] = Functions.RotateLeft(array[19] ^ array[14] ^ array[8] ^ array[6], 1); array[24] = Functions.RotateLeft(array[21] ^ array[16] ^ array[10] ^ array[8], 1); array[27] = Functions.RotateLeft(array[24] ^ array[19] ^ array[13] ^ array[11], 1); for (int second = secondsMin; second <= secondsMax; ++second) { array[9] = Functions.seedSecond(second) | Functions.seedMinute(date.Minute) | Functions.seedHour(date.Hour, dstype); ulong seed = Functions.EncryptSeed(array, alpha, 9); // it appears to have the same initial seed as in the main game // pressing Unova link does the same probability table calls uint initial = Functions.initialPIDRNG(seed, version, memorylink); var rng = new BWRng(seed); for (uint i = 0; i < initial; ++i) rng.GetNext64BitNumber(); bool found = true; for (uint i = 0; i < pattern.Length; ++i) { if (pattern[i] != rng.GetNext32BitNumber(8)) { found = false; break; } // there's another RNG call here unreleated to the spinner rng.GetNext64BitNumber(); } progressSearched++; if (found) { var parameter = new DSParameterCapture { ActualSeconds = second, GxStat = gxstat, Seed = seed, Timer0 = timer0, VCount = vcount, VFrame = vframe }; dsParameters.Add(parameter); refreshQueue = true; progressFound++; } } if (minmaxgxstat && gxstatMax > gxstatMin) gxstat = gxstatMax - 1; } } } } }