diff --git a/3rdparty/sharpcompress-0.11/LinqBridge.dll b/3rdparty/sharpcompress-0.11/LinqBridge.dll new file mode 100644 index 0000000..b7955c0 Binary files /dev/null and b/3rdparty/sharpcompress-0.11/LinqBridge.dll differ diff --git a/3rdparty/sharpcompress-0.11/README.md b/3rdparty/sharpcompress-0.11/README.md new file mode 100644 index 0000000..0a2a20a --- /dev/null +++ b/3rdparty/sharpcompress-0.11/README.md @@ -0,0 +1 @@ +libraries are built against this [tag version](https://github.com/adamhathcock/sharpcompress/tree/0.11) \ No newline at end of file diff --git a/3rdparty/sharpcompress-0.11/SharpCompress.dll b/3rdparty/sharpcompress-0.11/SharpCompress.dll new file mode 100644 index 0000000..b351b03 Binary files /dev/null and b/3rdparty/sharpcompress-0.11/SharpCompress.dll differ diff --git a/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.cpp b/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.cpp index 72735ec..50eec1a 100644 --- a/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.cpp +++ b/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.cpp @@ -57,46 +57,52 @@ bool AMDOpenCLDeviceDetection::QueryDevices() { else { for (auto i_pId = 0u; i_pId < platforms.size(); ++i_pId) { string platformName = StringnNullTerminatorFix(platforms[i_pId].getInfo()); - _platformNumbers.emplace(make_pair(platformName, i_pId)); - // not the best way but it should work - bool isAMD = platformName.find("AMD", 0) != string::npos; - vector platformDevs; - auto clDevs = getDevices(platforms, i_pId); - for (auto i_devId = 0u; i_devId < clDevs.size(); ++i_devId) { - OpenCLDevice curDevice; - curDevice.DeviceID = i_devId; - curDevice._CL_DEVICE_NAME = StringnNullTerminatorFix(clDevs[i_devId].getInfo()); - switch (clDevs[i_devId].getInfo()) { - case CL_DEVICE_TYPE_CPU: - curDevice._CL_DEVICE_TYPE = "CPU"; - break; - case CL_DEVICE_TYPE_GPU: - curDevice._CL_DEVICE_TYPE = "GPU"; - break; - case CL_DEVICE_TYPE_ACCELERATOR: - curDevice._CL_DEVICE_TYPE = "ACCELERATOR"; - break; - default: - curDevice._CL_DEVICE_TYPE = "DEFAULT"; - break; - } - - curDevice._CL_DEVICE_GLOBAL_MEM_SIZE = clDevs[i_devId].getInfo(); - curDevice._CL_DEVICE_VENDOR = StringnNullTerminatorFix(clDevs[i_devId].getInfo()); - curDevice._CL_DEVICE_VERSION = StringnNullTerminatorFix(clDevs[i_devId].getInfo()); - curDevice._CL_DRIVER_VERSION = StringnNullTerminatorFix(clDevs[i_devId].getInfo()); + if (std::find(_platformNames.begin(), _platformNames.end(), platformName) == _platformNames.end()) { + JsonLog current; + _platformNames.push_back(platformName); + // new + current.PlatformName = platformName; + current.PlatformNum = i_pId; + + // not the best way but it should work + bool isAMD = platformName.find("AMD", 0) != string::npos; + auto clDevs = getDevices(platforms, i_pId); + for (auto i_devId = 0u; i_devId < clDevs.size(); ++i_devId) { + OpenCLDevice curDevice; + curDevice.DeviceID = i_devId; + curDevice._CL_DEVICE_NAME = StringnNullTerminatorFix(clDevs[i_devId].getInfo()); + switch (clDevs[i_devId].getInfo()) { + case CL_DEVICE_TYPE_CPU: + curDevice._CL_DEVICE_TYPE = "CPU"; + break; + case CL_DEVICE_TYPE_GPU: + curDevice._CL_DEVICE_TYPE = "GPU"; + break; + case CL_DEVICE_TYPE_ACCELERATOR: + curDevice._CL_DEVICE_TYPE = "ACCELERATOR"; + break; + default: + curDevice._CL_DEVICE_TYPE = "DEFAULT"; + break; + } - // AMD topology get Bus No - if (isAMD) { - cl_device_topology_amd topology = clDevs[i_devId].getInfo(); - if (topology.raw.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) { - curDevice.AMD_BUS_ID = (int)topology.pcie.bus; + curDevice._CL_DEVICE_GLOBAL_MEM_SIZE = clDevs[i_devId].getInfo(); + curDevice._CL_DEVICE_VENDOR = StringnNullTerminatorFix(clDevs[i_devId].getInfo()); + curDevice._CL_DEVICE_VERSION = StringnNullTerminatorFix(clDevs[i_devId].getInfo()); + curDevice._CL_DRIVER_VERSION = StringnNullTerminatorFix(clDevs[i_devId].getInfo()); + + // AMD topology get Bus No + if (isAMD) { + cl_device_topology_amd topology = clDevs[i_devId].getInfo(); + if (topology.raw.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) { + curDevice.AMD_BUS_ID = (int)topology.pcie.bus; + } } - } - platformDevs.push_back(curDevice); + current.Devices.push_back(curDevice); + } + _devicesPlatformsDevices.push_back(current); } - _devicesPerPlatform.emplace(make_pair(platformName, platformDevs)); } } } @@ -113,28 +119,18 @@ bool AMDOpenCLDeviceDetection::QueryDevices() { // this function is hardcoded and horrable void AMDOpenCLDeviceDetection::PrintDevicesJson() { - cout << "{" << endl; + cout << "[" << endl; - // platforms array scope { - cout << "\t\"OCLPlatforms\" : {" << endl; - int platformsComma = _platformNumbers.size(); - for (const auto &plat_name_num : _platformNumbers) { - cout << "\t\t\"" + plat_name_num.first + "\" : " - << plat_name_num.second << COMMA(platformsComma) - << endl; - } - cout << "\t}," << endl; - } - // device per platform array scope - { - int devPlatformsComma = _devicesPerPlatform.size(); - cout << "\t\"OCLPlatformDevices\" : {" << endl; - for (const auto &plat_name_devs : _devicesPerPlatform) { - cout << "\t\t\"" + plat_name_devs.first + "\" : [" << endl; + int devPlatformsComma = _devicesPlatformsDevices.size(); + for (const auto &jsonLog : _devicesPlatformsDevices) { + cout << "\t{" << endl; + cout << "\t\t\"PlatformName\": \"" << jsonLog.PlatformName << "\"" << "," << endl; + cout << "\t\t\"PlatformNum\": " << jsonLog.PlatformNum << "," << endl; + cout << "\t\t\"Devices\" : [" << endl; // device print - int devComma = plat_name_devs.second.size(); - for (const auto &dev : plat_name_devs.second) { + int devComma = jsonLog.Devices.size(); + for (const auto &dev : jsonLog.Devices) { cout << "\t\t\t{" << endl; cout << "\t\t\t\t\"" << "DeviceID" << "\" : " << dev.DeviceID << "," << endl; // num cout << "\t\t\t\t\"" << "AMD_BUS_ID" << "\" : " << dev.AMD_BUS_ID << "," << endl; // num @@ -146,10 +142,43 @@ void AMDOpenCLDeviceDetection::PrintDevicesJson() { cout << "\t\t\t\t\"" << "_CL_DRIVER_VERSION" << "\" : \"" << dev._CL_DRIVER_VERSION << "\"" << endl; cout << "\t\t\t}" << COMMA(devComma) << endl; } - cout << "\t\t]" << COMMA(devPlatformsComma) << endl; + cout << "\t\t]" << endl; + cout << "\t}" << COMMA(devPlatformsComma) << endl; } - cout << "\t}" << endl; } - cout << "}" << endl; -} \ No newline at end of file + cout << "]" << endl; +} + + +void AMDOpenCLDeviceDetection::PrintDevicesJsonDirty() { + cout << "["; + + { + int devPlatformsComma = _devicesPlatformsDevices.size(); + for (const auto &jsonLog : _devicesPlatformsDevices) { + cout << "{"; + cout << "\"PlatformName\": \"" << jsonLog.PlatformName << "\"" << ","; + cout << "\"PlatformNum\": " << jsonLog.PlatformNum << ","; + cout << "\"Devices\" : ["; + // device print + int devComma = jsonLog.Devices.size(); + for (const auto &dev : jsonLog.Devices) { + cout << "{"; + cout << "\"" << "DeviceID" << "\" : " << dev.DeviceID << ","; // num + cout << "\"" << "AMD_BUS_ID" << "\" : " << dev.AMD_BUS_ID << ","; // num + cout << "\"" << "_CL_DEVICE_NAME" << "\" : \"" << dev._CL_DEVICE_NAME << "\","; + cout << "\"" << "_CL_DEVICE_TYPE" << "\" : \"" << dev._CL_DEVICE_TYPE << "\","; + cout << "\"" << "_CL_DEVICE_GLOBAL_MEM_SIZE" << "\" : " << dev._CL_DEVICE_GLOBAL_MEM_SIZE << ","; // num + cout << "\"" << "_CL_DEVICE_VENDOR" << "\" : \"" << dev._CL_DEVICE_VENDOR << "\","; + cout << "\"" << "_CL_DEVICE_VERSION" << "\" : \"" << dev._CL_DEVICE_VERSION << "\","; + cout << "\"" << "_CL_DRIVER_VERSION" << "\" : \"" << dev._CL_DRIVER_VERSION << "\""; + cout << "}" << COMMA(devComma); + } + cout << "]"; + cout << "}" << COMMA(devPlatformsComma); + } + } + + cout << "]" << endl; +} diff --git a/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.h b/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.h index 961479b..8708fbb 100644 --- a/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.h +++ b/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.h @@ -2,6 +2,8 @@ #define __CL_ENABLE_EXCEPTIONS #define CL_USE_DEPRECATED_OPENCL_2_0_APIS +#define CL_VERSION_1_2 +//#define CL_USE_DEPRECATED_OPENCL_1_1_APIS #include "cl_ext.hpp" @@ -12,6 +14,12 @@ #include "OpenCLDevice.h" +struct JsonLog { + std::string PlatformName; + int PlatformNum; + std::vector Devices; +}; + class AMDOpenCLDeviceDetection { public: AMDOpenCLDeviceDetection(); @@ -19,14 +27,15 @@ class AMDOpenCLDeviceDetection { bool QueryDevices(); void PrintDevicesJson(); + void PrintDevicesJsonDirty(); private: static std::vector getDevices(std::vector const& _platforms, unsigned _platformId); static std::vector getPlatforms(); - std::map> _devicesPerPlatform; - std::map _platformNumbers; + std::vector _platformNames; + std::vector _devicesPlatformsDevices; static std::string StringnNullTerminatorFix(const std::string& str); }; diff --git a/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.vcxproj b/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.vcxproj index 6aca6fc..1554203 100644 --- a/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.vcxproj +++ b/AMDOpenCLDeviceDetection/AMDOpenCLDeviceDetection.vcxproj @@ -1,10 +1,18 @@  + + Debug + Win32 + Debug x64 + + Release + Win32 + Release x64 @@ -22,6 +30,12 @@ v120 Unicode + + Application + true + v120 + Unicode + Application false @@ -29,24 +43,43 @@ true Unicode + + Application + false + v120 + true + Unicode + + + + + + + true $(SolutionDir)$(Configuration)\ + + true + false $(SolutionDir)$(Configuration)\ + + false + @@ -67,6 +100,29 @@ copy /Y "$(AMDAPPSDKROOT)\bin\x86_64\OpenCL.dll" "$(SolutionDir)$(Configuration)\OpenCL.dll" REM the path is absolute maybe fix copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT\msvcp120.dll" "$(SolutionDir)$(Configuration)\msvcp120.dll" +copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT\msvcr120.dll" "$(SolutionDir)$(Configuration)\msvcr120.dll" + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + .;$(AMDAPPSDKROOT)\include\;%(AdditionalIncludeDirectories) + + + Console + true + OpenCL.lib;%(AdditionalDependencies) + $(AMDAPPSDKROOT)\lib\x86\ + + + copy /Y "$(AMDAPPSDKROOT)\bin\x86_64\OpenCL.dll" "$(SolutionDir)$(Configuration)\OpenCL.dll" +REM the path is absolute maybe fix +copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT\msvcp120.dll" "$(SolutionDir)$(Configuration)\msvcp120.dll" copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT\msvcr120.dll" "$(SolutionDir)$(Configuration)\msvcr120.dll" @@ -94,6 +150,33 @@ copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Micro copy /Y "$(AMDAPPSDKROOT)\bin\x86_64\OpenCL.dll" "$(SolutionDir)$(Configuration)\OpenCL.dll" REM the path is absolute maybe fix copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT\msvcp120.dll" "$(SolutionDir)$(Configuration)\msvcp120.dll" +copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT\msvcr120.dll" "$(SolutionDir)$(Configuration)\msvcr120.dll" + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + .;$(AMDAPPSDKROOT)\include\;%(AdditionalIncludeDirectories) + + + Console + true + true + true + $(AMDAPPSDKROOT)\lib\x86\ + OpenCL.lib;%(AdditionalDependencies) + + + copy /Y "$(AMDAPPSDKROOT)\bin\x86_64\OpenCL.dll" "$(SolutionDir)$(Configuration)\OpenCL.dll" +REM the path is absolute maybe fix +copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT\msvcp120.dll" "$(SolutionDir)$(Configuration)\msvcp120.dll" copy /Y "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT\msvcr120.dll" "$(SolutionDir)$(Configuration)\msvcr120.dll" diff --git a/AMDOpenCLDeviceDetection/main.cpp b/AMDOpenCLDeviceDetection/main.cpp index 79f367f..b387304 100644 --- a/AMDOpenCLDeviceDetection/main.cpp +++ b/AMDOpenCLDeviceDetection/main.cpp @@ -1,9 +1,14 @@ #include "AMDOpenCLDeviceDetection.h" -int main() { +int main(int argc, char* argv[]) { AMDOpenCLDeviceDetection AMDOpenCLDeviceDetection; if (AMDOpenCLDeviceDetection.QueryDevices()) { - AMDOpenCLDeviceDetection.PrintDevicesJson(); + if (argc < 2) { + AMDOpenCLDeviceDetection.PrintDevicesJsonDirty(); + } + else { + AMDOpenCLDeviceDetection.PrintDevicesJson(); + } } return 0; } diff --git a/CudaDeviceDetection/CudaDetection.cpp b/CudaDeviceDetection/CudaDetection.cpp index df83dbc..f0d2559 100644 --- a/CudaDeviceDetection/CudaDetection.cpp +++ b/CudaDeviceDetection/CudaDetection.cpp @@ -8,6 +8,8 @@ using namespace std; CudaDetection::CudaDetection() { } CudaDetection::~CudaDetection() { } +#define PCI_BUS_LEN 64 + bool CudaDetection::QueryDevices() { const unsigned int UUID_SIZE = 128; try { @@ -19,11 +21,15 @@ bool CudaDetection::QueryDevices() { cudaDeviceProp props; CUDA_SAFE_CALL(cudaGetDeviceProperties(&props, i)); + char pciBusID[PCI_BUS_LEN]; + CUDA_SAFE_CALL(cudaDeviceGetPCIBusId(pciBusID, PCI_BUS_LEN, i)); + // serial stuff nvmlPciInfo_t pciInfo; nvmlDevice_t device_t; char uuid[UUID_SIZE]; - NVML_SAFE_CALL(nvmlDeviceGetHandleByIndex(i, &device_t)); + //NVML_SAFE_CALL(nvmlDeviceGetHandleByIndex(i, &device_t)); // this is wrong + NVML_SAFE_CALL(nvmlDeviceGetHandleByPciBusId(pciBusID, &device_t)); // use pciBusID to get the right version NVML_SAFE_CALL(nvmlDeviceGetPciInfo(device_t, &pciInfo)); NVML_SAFE_CALL(nvmlDeviceGetUUID(device_t, uuid, UUID_SIZE)); @@ -98,15 +104,15 @@ void CudaDetection::PrintDevicesJson() { cout << endl << "]" << endl; } -void CudaDetection::print(CudaDevice &dev) { - cout << "DeviceID : " << dev.DeviceID << endl; - cout << "DeviceName : " << dev.DeviceName << endl; - cout << "SMVersionString : " << dev.SMVersionString << endl; - cout << "UUID : " << dev.UUID << endl; - cout << "DeviceGlobalMemory : " << dev.DeviceGlobalMemory << endl; - cout << "pciDeviceId : " << dev.pciDeviceId << endl; - cout << "pciSubSystemId : " << dev.pciSubSystemId << endl << endl; -} +//void CudaDetection::print(CudaDevice &dev) { +// cout << "DeviceID : " << dev.DeviceID << endl; +// cout << "DeviceName : " << dev.DeviceName << endl; +// cout << "SMVersionString : " << dev.SMVersionString << endl; +// cout << "UUID : " << dev.UUID << endl; +// cout << "DeviceGlobalMemory : " << dev.DeviceGlobalMemory << endl; +// cout << "pciDeviceId : " << dev.pciDeviceId << endl; +// cout << "pciSubSystemId : " << dev.pciSubSystemId << endl << endl; +//} void CudaDetection::json_print(CudaDevice &dev) { cout << "\t{" << endl; @@ -123,4 +129,42 @@ void CudaDetection::json_print(CudaDevice &dev) { cout << "\t\t\"pciSubSystemId\" : " << dev.pciSubSystemId << "," << endl; // num cout << "\t\t\"SMX\" : " << dev.SMX << endl; // num cout << "\t}"; +} + +// non human readable print +void CudaDetection::PrintDevicesJson_d() { + cout << "["; + for (int i = 0; i < _cudaDevices.size() - 1; ++i) { + json_print_d(_cudaDevices[i]); + cout << ","; + } + json_print_d(_cudaDevices[_cudaDevices.size() - 1]); + cout << "]" << endl; +} + +//void CudaDetection::print_d(CudaDevice &dev) { +// cout << "DeviceID : " << dev.DeviceID ; +// cout << "DeviceName : " << dev.DeviceName ; +// cout << "SMVersionString : " << dev.SMVersionString ; +// cout << "UUID : " << dev.UUID ; +// cout << "DeviceGlobalMemory : " << dev.DeviceGlobalMemory ; +// cout << "pciDeviceId : " << dev.pciDeviceId ; +// cout << "pciSubSystemId : " << dev.pciSubSystemId ; +//} + +void CudaDetection::json_print_d(CudaDevice &dev) { + cout << "{"; + cout << "\"DeviceID\" : " << dev.DeviceID << ","; // num + cout << "\"VendorID\" : " << dev.VendorID << ","; // num + cout << "\"VendorName\" : \"" << dev.VendorName << "\","; // string + cout << "\"DeviceName\" : \"" << dev.DeviceName << "\","; // string + cout << "\"SMVersionString\" : \"" << dev.SMVersionString << "\","; // string + cout << "\"SM_major\" : " << dev.SM_major << ","; // num + cout << "\"SM_minor\" : " << dev.SM_minor << ","; // num + cout << "\"UUID\" : \"" << dev.UUID << "\","; // string + cout << "\"DeviceGlobalMemory\" : " << dev.DeviceGlobalMemory << ","; // num + cout << "\"pciDeviceId\" : " << dev.pciDeviceId << ","; // num + cout << "\"pciSubSystemId\" : " << dev.pciSubSystemId << ","; // num + cout << "\"SMX\" : " << dev.SMX; // num + cout << "}"; } \ No newline at end of file diff --git a/CudaDeviceDetection/CudaDetection.h b/CudaDeviceDetection/CudaDetection.h index 7cbebc1..045463b 100644 --- a/CudaDeviceDetection/CudaDetection.h +++ b/CudaDeviceDetection/CudaDetection.h @@ -17,12 +17,16 @@ class CudaDetection bool QueryDevices(); void PrintDevicesJson(); + void PrintDevicesJson_d(); private: - void print(CudaDevice &dev); + //void print(CudaDevice &dev); void json_print(CudaDevice &dev); + //void print_d(CudaDevice &dev); + void json_print_d(CudaDevice &dev); + std::vector _errorMsgs; std::vector _cudaDevices; diff --git a/CudaDeviceDetection/main.cpp b/CudaDeviceDetection/main.cpp index ad3b163..3a8a576 100644 --- a/CudaDeviceDetection/main.cpp +++ b/CudaDeviceDetection/main.cpp @@ -3,10 +3,15 @@ // TODO maybe add nvml.dll check //#include -int main() { +int main(int argc, char* argv[]) { CudaDetection detection; if (detection.QueryDevices()) { - detection.PrintDevicesJson(); + if (argc < 2) { + detection.PrintDevicesJson_d(); + } + else { + detection.PrintDevicesJson(); + } } return 0; } diff --git a/MessageBoxManager/MessageBoxManager.csproj b/MessageBoxManager/MessageBoxManager.csproj index f481f1c..9679e34 100644 --- a/MessageBoxManager/MessageBoxManager.csproj +++ b/MessageBoxManager/MessageBoxManager.csproj @@ -16,6 +16,7 @@ 2.0 + true @@ -25,6 +26,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -33,6 +35,7 @@ TRACE prompt 4 + false diff --git a/NiceHashMiner.sln b/NiceHashMiner.sln index d9526ef..abe500e 100644 --- a/NiceHashMiner.sln +++ b/NiceHashMiner.sln @@ -116,7 +116,7 @@ Global {36DC07F9-A4A6-4877-A146-1B960083CF6F}.Release|Win32.Build.0 = Release|x64 {36DC07F9-A4A6-4877-A146-1B960083CF6F}.Release|x64.ActiveCfg = Release|x64 {36DC07F9-A4A6-4877-A146-1B960083CF6F}.Release|x64.Build.0 = Release|x64 - {F4D88D6A-2321-4431-AFD1-8B6A1760358B}.Debug|Any CPU.ActiveCfg = Debug|x64 + {F4D88D6A-2321-4431-AFD1-8B6A1760358B}.Debug|Any CPU.ActiveCfg = Debug|Win32 {F4D88D6A-2321-4431-AFD1-8B6A1760358B}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 {F4D88D6A-2321-4431-AFD1-8B6A1760358B}.Debug|Mixed Platforms.Build.0 = Debug|x64 {F4D88D6A-2321-4431-AFD1-8B6A1760358B}.Debug|Win32.ActiveCfg = Debug|x64 diff --git a/NiceHashMiner/3rdParty/ADL.cs b/NiceHashMiner/3rdParty/ADL.cs index 28ac0cb..df31492 100644 --- a/NiceHashMiner/3rdParty/ADL.cs +++ b/NiceHashMiner/3rdParty/ADL.cs @@ -214,7 +214,7 @@ private static class ADLImport { #endregion Internal Constant #region DLLImport - [DllImport(Kernel32_FileName, CallingConvention = CallingConvention.Cdecl)] + [DllImport(Kernel32_FileName, CallingConvention = CallingConvention.StdCall)] internal static extern HMODULE GetModuleHandle(string moduleName); [DllImport(Atiadlxx_FileName, CallingConvention = CallingConvention.Cdecl)] diff --git a/NiceHashMiner/Algorithm.cs b/NiceHashMiner/Algorithm.cs index 66de48e..6982821 100644 --- a/NiceHashMiner/Algorithm.cs +++ b/NiceHashMiner/Algorithm.cs @@ -5,35 +5,49 @@ using System.Text; namespace NiceHashMiner { - [Serializable] public class Algorithm { - readonly public AlgorithmType NiceHashID; - // ignore the dictionary atribute shows the name - [JsonIgnore] - readonly public string NiceHashName; + + public readonly string AlgorithmName; + public readonly string MinerBaseTypeName; + public readonly AlgorithmType NiceHashID; + public readonly MinerBaseType MinerBaseType; + public readonly string AlgorithmStringID; // Miner name is used for miner ALGO flag parameter - readonly public string MinerName; + public readonly string MinerName; public double BenchmarkSpeed { get; set; } public string ExtraLaunchParameters { get; set; } + public bool Enabled { get; set; } - // not all miners, GPU sgminer and most ccminers - public double Intensity { get; set; } // CPU miners only setting public int LessThreads { get; set; } - public bool Skip { get; set; } + // avarage speed of same devices to increase mining stability + public double AvaragedSpeed { get; set; } + // based on device and settings here we set the miner path + public string MinerBinaryPath = ""; + // these are changing (logging reasons) + public double CurrentProfit = 0; + public double CurNhmSMADataVal = 0; + + public Algorithm(MinerBaseType minerBaseType, AlgorithmType niceHashID, string minerName) { + this.AlgorithmName = AlgorithmNiceHashNames.GetName(niceHashID); + this.MinerBaseTypeName = Enum.GetName(typeof(MinerBaseType), minerBaseType); + this.AlgorithmStringID = this.MinerBaseTypeName + "_" + this.AlgorithmName; - public static readonly string PasswordDefault = "x"; + MinerBaseType = minerBaseType; + NiceHashID = niceHashID; + MinerName = minerName; - [JsonIgnore] - public double CurrentProfit { get; set; } + BenchmarkSpeed = 0.0d; + ExtraLaunchParameters = ""; + LessThreads = 0; + Enabled = true; + BenchmarkStatus = ""; + } // benchmark info - [JsonIgnore] public string BenchmarkStatus { get; set; } - [JsonIgnore] public bool IsBenchmarkPending { get; private set; } - [JsonIgnore] public string CurPayingRatio { get { string ratio = International.GetText("BenchmarkRatioRateN_A"); @@ -43,7 +57,6 @@ public string CurPayingRatio { return ratio; } } - [JsonIgnore] public string CurPayingRate { get { string rate = International.GetText("BenchmarkRatioRateN_A"); @@ -54,33 +67,40 @@ public string CurPayingRate { } } - public Algorithm(AlgorithmType niceHashID, string minerName) { - NiceHashID = niceHashID; - NiceHashName = AlgorithmNiceHashNames.GetName(niceHashID); - MinerName = minerName; - - BenchmarkSpeed = 0.0d; - ExtraLaunchParameters = ""; - Intensity = 0.0d; // 0.0d is default - LessThreads = 0; - Skip = false; - BenchmarkStatus = ""; - } - public void SetBenchmarkPending() { IsBenchmarkPending = true; BenchmarkStatus = International.GetText("Algorithm_Waiting_Benchmark"); } + public void SetBenchmarkPendingNoMsg() { + IsBenchmarkPending = true; + } + + private bool IsPendingString() { + return BenchmarkStatus == International.GetText("Algorithm_Waiting_Benchmark") + || BenchmarkStatus == "." + || BenchmarkStatus == ".." + || BenchmarkStatus == "..."; + } + public void ClearBenchmarkPending() { + IsBenchmarkPending = false; + if (IsPendingString()) { + BenchmarkStatus = ""; + } + } + + public void ClearBenchmarkPendingFirst() { IsBenchmarkPending = false; BenchmarkStatus = ""; } public string BenchmarkSpeedString() { - if (!Skip && IsBenchmarkPending && !string.IsNullOrEmpty(BenchmarkStatus)) { + if (Enabled && IsBenchmarkPending && !string.IsNullOrEmpty(BenchmarkStatus)) { return BenchmarkStatus; } else if (BenchmarkSpeed > 0) { return Helpers.FormatSpeedOutput(BenchmarkSpeed); + } else if (!IsPendingString() && !string.IsNullOrEmpty(BenchmarkStatus)) { + return BenchmarkStatus; } return International.GetText("BenchmarkSpeedStringNone"); } diff --git a/NiceHashMiner/AlgorithmNiceHashNames.cs b/NiceHashMiner/AlgorithmNiceHashNames.cs deleted file mode 100644 index 38bdccc..0000000 --- a/NiceHashMiner/AlgorithmNiceHashNames.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using NiceHashMiner.Enums; - -namespace NiceHashMiner -{ - /// - /// AlgorithmNiceHashNames class is just a data container for mapping NiceHash JSON API names to algo type - /// - public static class AlgorithmNiceHashNames - { - readonly static private Dictionary _names = new Dictionary() - { - { AlgorithmType.INVALID , "INVALID" }, - { AlgorithmType.NONE , "NONE" }, - //{ AlgorithmType.Scrypt , "scrypt" }, // NOT used - //{ AlgorithmType.SHA256 , "sha256" }, // NOT used - //{ AlgorithmType.ScryptNf , "scryptnf" }, // NOT used - //{ AlgorithmType.X11 , "x11" }, // NOT used - { AlgorithmType.X13 , "x13" }, - { AlgorithmType.Keccak , "keccak" }, - { AlgorithmType.X15 , "x15" }, - { AlgorithmType.Nist5 , "nist5" }, - { AlgorithmType.NeoScrypt , "neoscrypt" }, - { AlgorithmType.Lyra2RE , "lyra2re" }, - { AlgorithmType.WhirlpoolX , "whirlpoolx" }, - { AlgorithmType.Qubit , "qubit" }, - { AlgorithmType.Quark , "quark" }, - //{ AlgorithmType.Axiom , "axiom" }, // NOT used - { AlgorithmType.Lyra2REv2 , "lyra2rev2" }, - //{ AlgorithmType.ScryptJaneNf16 , "scryptjanenf16" }, // NOT used - { AlgorithmType.Blake256r8 , "blake256r8" }, - { AlgorithmType.Blake256r14 , "blake256r14" }, - { AlgorithmType.Blake256r8vnl , "blake256r8vnl" }, - { AlgorithmType.Hodl , "hodl" }, - { AlgorithmType.DaggerHashimoto , "daggerhashimoto" }, - { AlgorithmType.Decred , "decred" }, - { AlgorithmType.CryptoNight , "cryptonight" }, - }; - - static private List _keys = null; - - public static string GetName(AlgorithmType type) { return _names[type]; } - - /// - /// GetKey is used for Algorithm initialization, from config files. - /// If algorithm name is invalid it will return INVALID - /// - /// - /// - public static AlgorithmType GetKey(string name) { - foreach (var pair in _names) { - if (pair.Value == name) return pair.Key; - } - - return AlgorithmType.INVALID; - } - - public static List GetAllAvaliableTypes() { - // lazy load - if (_keys == null) { - _keys = new List(_names.Keys); - } - return _keys; - } - } -} diff --git a/NiceHashMiner/BaseLazySingleton.cs b/NiceHashMiner/BaseLazySingleton.cs deleted file mode 100644 index 7a6fa69..0000000 --- a/NiceHashMiner/BaseLazySingleton.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace NiceHashMiner { - public abstract class BaseLazySingleton where T : class { - private static readonly Lazy LazyInstance = - new Lazy(CreateInstanceOfT, LazyThreadSafetyMode.ExecutionAndPublication); - - #region Properties - public static T Instance { - get { return LazyInstance.Value; } - } - #endregion - - #region Methods - private static T CreateInstanceOfT() { - return Activator.CreateInstance(typeof(T), true) as T; - } - - protected BaseLazySingleton() { } - - #endregion - } -} diff --git a/NiceHashMiner/Bitcoin.cs b/NiceHashMiner/Bitcoin.cs deleted file mode 100644 index 4badc58..0000000 --- a/NiceHashMiner/Bitcoin.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Net; -using System.IO; -using Newtonsoft.Json; - -namespace NiceHashMiner -{ - class Bitcoin - { -#pragma warning disable 649 - class CoinbaseResponse - { - public double amount; - public string currency; - } -#pragma warning restore 649 - - public static double GetUSDExchangeRate() - { - string jsondata = null; - - for (int i = 0; i < 2; i++) - { - jsondata = GetCoinbaseAPIData("https://api.coinbase.com/v1/prices/spot_rate"); - if (jsondata != null) break; - } - - if (jsondata == null) return 0; - - try - { - CoinbaseResponse cbr = JsonConvert.DeserializeObject(jsondata, Globals.JsonSettings); - return cbr.amount; - } - catch - { - return 0; - } - } - - private static string GetCoinbaseAPIData(string URL) - { - string ResponseFromServer; - try - { - HttpWebRequest WR = (HttpWebRequest)WebRequest.Create(URL); - WR.Timeout = 10000; - WebResponse Response = WR.GetResponse(); - Stream SS = Response.GetResponseStream(); - SS.ReadTimeout = 10000; - StreamReader Reader = new StreamReader(SS); - ResponseFromServer = Reader.ReadToEnd(); - if (ResponseFromServer.Length == 0 || ResponseFromServer[0] != '{') - throw new Exception("Not JSON!"); - Reader.Close(); - Response.Close(); - } - catch (Exception ex) - { - Helpers.ConsolePrint("COINBASE", ex.Message); - return null; - } - - return ResponseFromServer; - } - } -} diff --git a/NiceHashMiner/Configs/BaseConfigFile.cs b/NiceHashMiner/Configs/BaseConfigFile.cs deleted file mode 100644 index 2677019..0000000 --- a/NiceHashMiner/Configs/BaseConfigFile.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using NiceHashMiner.Interfaces; - -namespace NiceHashMiner.Configs { - [Serializable] - public abstract class BaseConfigFile : IPathsProperties where T : class, IPathsProperties { - #region Members - [field: NonSerialized] - readonly public static string CONF_FOLDER = @"configs\"; - - private string _filePath = ""; - private string _filePathOld = ""; - - [JsonIgnore] - public string FilePath { - get { return _filePath.Contains(CONF_FOLDER) ? _filePath : CONF_FOLDER + _filePath; } - set { _filePath = value; } - } - [JsonIgnore] - public string FilePathOld { - get { return _filePathOld.Contains(CONF_FOLDER) ? _filePathOld : CONF_FOLDER + _filePathOld; } - set { _filePathOld = value; } - } - - [JsonIgnore] - protected bool FileLoaded { get { return _file != null; } } - - [field: NonSerialized] - protected T _file; - - #endregion //Members - - public void InitializeConfig() { - InitializePaths(); - ReadFile(); - if (FileLoaded) { - _file.FilePath = this.FilePath; - _file.FilePathOld = this.FilePathOld; - InitializeObject(); - } - } - - /// - /// InitializePaths should be overrided in the subclass to specify filepath(old) paths. - /// - abstract protected void InitializePaths(); - /// - /// InitializeObject must be overrided in the subclass to reinitialize values and references from the configuration files. - /// Use the _self member and reinitialize all non null references (use DeepCopy or plain reference it is up to the implementor). - /// IMPORTANT!!! Take extra care with arrays, lists and dictionaries, initialize them manually and not by DeepCopy or reference, the - /// reason for this is to be future proof if new keys/values are added so reinitialize them one by one if they exist. - /// - abstract protected void InitializeObject(); - - private static void CheckAndCreateConfigsFolder () { - try { - if (Directory.Exists(CONF_FOLDER) == false) { - Directory.CreateDirectory(CONF_FOLDER); - } - } catch { } - } - - protected void ReadFile() { - CheckAndCreateConfigsFolder(); - try { - if (new FileInfo(FilePath).Exists) { - _file = JsonConvert.DeserializeObject(File.ReadAllText(FilePath), Globals.JsonSettings); - } else { - Commit(); - } - } catch(Exception ex) { - Helpers.ConsolePrint("BaseConfigFile", String.Format("ReadFile {0}: exception {1}", FilePath, ex.ToString())); - } - } - - public void Commit() { - try { - File.WriteAllText(FilePath, JsonConvert.SerializeObject(this, Formatting.Indented)); - } - catch (Exception ex) { - Helpers.ConsolePrint("BaseConfigFile", String.Format("Commit {0}: exception {1}", FilePath, ex.ToString())); - } - } - - public bool ConfigFileExist() { - return File.Exists(FilePath); - } - - - } -} diff --git a/NiceHashMiner/Configs/ConfigJsonFile/ConfigFile.cs b/NiceHashMiner/Configs/ConfigJsonFile/ConfigFile.cs new file mode 100644 index 0000000..bc5703a --- /dev/null +++ b/NiceHashMiner/Configs/ConfigJsonFile/ConfigFile.cs @@ -0,0 +1,81 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace NiceHashMiner.Configs.ConfigJsonFile { + public abstract class ConfigFile where T : class { + // statics/consts + const string TAG_FORMAT = "ConfigFile<{0}>"; + private readonly string CONF_FOLDER; // = @"configs\"; + private readonly string TAG; + + private void CheckAndCreateConfigsFolder() { + try { + if (Directory.Exists(CONF_FOLDER) == false) { + Directory.CreateDirectory(CONF_FOLDER); + } + } catch { } + } + + // member stuff + protected string _filePath = ""; + protected string _filePathOld = ""; + + public ConfigFile(string iCONF_FOLDER, string fileName, string fileNameOld) { + CONF_FOLDER = iCONF_FOLDER; + if(fileName.Contains(CONF_FOLDER)) { + this._filePath = fileName; + } else { + this._filePath = CONF_FOLDER + fileName; + } + if (fileNameOld.Contains(CONF_FOLDER)) { + this._filePathOld = fileNameOld; + } else { + this._filePathOld = CONF_FOLDER + fileNameOld; + } + TAG = String.Format(TAG_FORMAT, typeof(T).Name); + } + + public bool IsFileExists() { + return File.Exists(_filePath); + } + + public T ReadFile() { + CheckAndCreateConfigsFolder(); + T file = null; + try { + if (File.Exists(_filePath)) { + file = JsonConvert.DeserializeObject(File.ReadAllText(_filePath), Globals.JsonSettings); + } + } catch (Exception ex) { + Helpers.ConsolePrint(TAG, String.Format("ReadFile {0}: exception {1}", _filePath, ex.ToString())); + file = null; + } + return file; + } + + public void Commit(T file) { + CheckAndCreateConfigsFolder(); + if (file == null) { + Helpers.ConsolePrint(TAG, String.Format("Commit for FILE {0} IGNORED. Passed null object", _filePath)); + return; + } + try { + File.WriteAllText(_filePath, JsonConvert.SerializeObject(file, Formatting.Indented)); + } catch (Exception ex) { + Helpers.ConsolePrint(TAG, String.Format("Commit {0}: exception {1}", _filePath, ex.ToString())); + } + } + + public void CreateBackup() { + Helpers.ConsolePrint(TAG, String.Format("Backing up {0} to {1}..", _filePath, _filePathOld)); + try { + if (File.Exists(_filePathOld)) + File.Delete(_filePathOld); + File.Copy(_filePath, _filePathOld, true); + } catch { } + } + } +} diff --git a/NiceHashMiner/Configs/ConfigJsonFile/DeviceBenchmarkConfigFile.cs b/NiceHashMiner/Configs/ConfigJsonFile/DeviceBenchmarkConfigFile.cs new file mode 100644 index 0000000..89c87cc --- /dev/null +++ b/NiceHashMiner/Configs/ConfigJsonFile/DeviceBenchmarkConfigFile.cs @@ -0,0 +1,26 @@ +using NiceHashMiner.Configs.Data; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Configs.ConfigJsonFile { + public class DeviceBenchmarkConfigFile : ConfigFile { + const string BENCHMARK_PREFIX = "benchmark_"; + + private static string GetName(string DeviceUUID, string old = "") { + // make device name + char[] invalid = new char[] { '<', '>', ':', '"', '/', '\\', '|', '?', '*' }; + string fileName = BENCHMARK_PREFIX + DeviceUUID.Replace(' ', '_'); + foreach (var c in invalid) { + fileName = fileName.Replace(c.ToString(), String.Empty); + } + const string extension = ".json"; + return fileName + old + extension; + } + + public DeviceBenchmarkConfigFile(string DeviceUUID) + : base(FOLDERS.CONFIG, GetName(DeviceUUID), GetName(DeviceUUID, "_OLD")) { + } + + } +} diff --git a/NiceHashMiner/Configs/ConfigJsonFile/FOLDERS.cs b/NiceHashMiner/Configs/ConfigJsonFile/FOLDERS.cs new file mode 100644 index 0000000..829dc03 --- /dev/null +++ b/NiceHashMiner/Configs/ConfigJsonFile/FOLDERS.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Configs.ConfigJsonFile { + public static class FOLDERS { + public static readonly string CONFIG = @"configs\"; + public static readonly string INTERNALS = @"internals\"; + } +} diff --git a/NiceHashMiner/Configs/ConfigJsonFile/GeneralConfigFile.cs b/NiceHashMiner/Configs/ConfigJsonFile/GeneralConfigFile.cs new file mode 100644 index 0000000..9f67e6c --- /dev/null +++ b/NiceHashMiner/Configs/ConfigJsonFile/GeneralConfigFile.cs @@ -0,0 +1,12 @@ +using NiceHashMiner.Configs.Data; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Configs.ConfigJsonFile { + public class GeneralConfigFile : ConfigFile { + public GeneralConfigFile() + : base(FOLDERS.CONFIG, "General.json", "General_old.json") { + } + } +} diff --git a/NiceHashMiner/Configs/ConfigManager.cs b/NiceHashMiner/Configs/ConfigManager.cs index fa97685..52c9460 100644 --- a/NiceHashMiner/Configs/ConfigManager.cs +++ b/NiceHashMiner/Configs/ConfigManager.cs @@ -1,126 +1,180 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; +using NiceHashMiner.Configs.ConfigJsonFile; +using NiceHashMiner.Configs.Data; using NiceHashMiner.Devices; using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; namespace NiceHashMiner.Configs { - public partial class ConfigManager : BaseLazySingleton { - public GeneralConfig GeneralConfig { get; set; } - public Dictionary BenchmarkConfigs { get; set; } + public static class ConfigManager { + private static readonly string TAG = "ConfigManager"; + public static GeneralConfig GeneralConfig = new GeneralConfig(); + + // helper variables + private static bool IsGeneralConfigFileInit = false; + private static bool hwidLoadFromFile = false; + private static bool hwidOK = false; + private static bool IsNewVersion = false; - private readonly string TAG; + // for loading and saving + private static GeneralConfigFile GeneralConfigFile = new GeneralConfigFile(); + private static Dictionary BenchmarkConfigFiles = new Dictionary(); - protected ConfigManager() { - TAG = this.GetType().Name; - GeneralConfig = new GeneralConfig(true); - BenchmarkConfigs = new Dictionary(); + // backups + private static GeneralConfig GeneralConfigBackup = new GeneralConfig(); + private static Dictionary BenchmarkConfigsBackup = new Dictionary(); + + public static void InitializeConfig() { + // init defaults + ConfigManager.GeneralConfig.SetDefaults(); + ConfigManager.GeneralConfig.hwid = Helpers.GetCpuID(); + // if exists load file + GeneralConfig fromFile = null; + if(GeneralConfigFile.IsFileExists()) { + fromFile = GeneralConfigFile.ReadFile(); + } + // just in case + if (fromFile != null) { + // set config loaded from file + IsGeneralConfigFileInit = true; + ConfigManager.GeneralConfig = fromFile; + if (ConfigManager.GeneralConfig.ConfigFileVersion == null + || ConfigManager.GeneralConfig.ConfigFileVersion.CompareTo(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version) != 0) { + if (ConfigManager.GeneralConfig.ConfigFileVersion == null) { + Helpers.ConsolePrint(TAG, "Loaded Config file no version detected falling back to defaults."); + ConfigManager.GeneralConfig.SetDefaults(); + } + Helpers.ConsolePrint(TAG, "Config file is from an older version of NiceHashMiner.."); + IsNewVersion = true; + GeneralConfigFile.CreateBackup(); + } + ConfigManager.GeneralConfig.FixSettingBounds(); + // check vars + hwidLoadFromFile = true; + hwidOK = Helpers.GetCpuID() == ConfigManager.GeneralConfig.hwid; + } else { + GeneralConfigFileCommit(); + } + } + + public static bool GeneralConfigIsFileExist() { + return IsGeneralConfigFileInit; + } + + public static bool GeneralConfigHwidLoadFromFile() { + return hwidLoadFromFile; + } + + public static bool GeneralConfigHwidOK() { + return hwidOK; } - // TODO remove this eventually, keep for now - public void LegacyConfigMigration() { - // CHECK LEGACY config, migration logic - if (Config.ConfigFileExist()) { - Helpers.ConsolePrint(TAG, "Migrating LEGACY config"); - Config.InitializeConfig(); - - // migrate relevant data - GeneralConfig.Language = (LanguageType)Config.ConfigData.Language; - GeneralConfig.BitcoinAddress = Config.ConfigData.BitcoinAddress; - GeneralConfig.WorkerName = Config.ConfigData.WorkerName; - GeneralConfig.ServiceLocation = Config.ConfigData.ServiceLocation; - //GeneralConfig.LessThreads = Config.ConfigData.LessThreads; - //GeneralConfig.Groups = new Group[0] = Config.ConfigData.Groups = new Group[0]; - GeneralConfig.DebugConsole = Config.ConfigData.DebugConsole; - GeneralConfig.HideMiningWindows = Config.ConfigData.HideMiningWindows; - GeneralConfig.MinimizeToTray = Config.ConfigData.MinimizeToTray; - //GeneralConfig.AutoStartMining = Config.ConfigData.AutoStartMining; - GeneralConfig.DeviceDetection.DisableDetectionNVidia5X = Config.ConfigData.DisableDetectionNVidia5X; - GeneralConfig.DeviceDetection.DisableDetectionNVidia3X = Config.ConfigData.DisableDetectionNVidia3X; - GeneralConfig.DeviceDetection.DisableDetectionNVidia2X = Config.ConfigData.DisableDetectionNVidia2X; - GeneralConfig.DeviceDetection.DisableDetectionAMD = Config.ConfigData.DisableDetectionAMD; - //GeneralConfig.DisableAMDTempControl = Config.ConfigData.DisableAMDTempControl; - GeneralConfig.AutoScaleBTCValues = Config.ConfigData.AutoScaleBTCValues; - GeneralConfig.StartMiningWhenIdle = Config.ConfigData.StartMiningWhenIdle; - GeneralConfig.LogToFile = Config.ConfigData.LogToFile; - GeneralConfig.LogMaxFileSize = Config.ConfigData.LogMaxFileSize; - GeneralConfig.ShowDriverVersionWarning = Config.ConfigData.ShowDriverVersionWarning; - GeneralConfig.DisableWindowsErrorReporting = Config.ConfigData.DisableWindowsErrorReporting; - //GeneralConfig.UseNewSettingsPage = Config.ConfigData.UseNewSettingsPage; - GeneralConfig.NVIDIAP0State = Config.ConfigData.NVIDIAP0State; - GeneralConfig.MinerRestartDelayMS = Config.ConfigData.MinerRestartDelayMS; - GeneralConfig.ethminerDefaultBlockHeight = Config.ConfigData.ethminerDefaultBlockHeight; - //GeneralConfig.MinerAPIGraceSeconds = Config.ConfigData.MinerAPIGraceSeconds; - //GeneralConfig.MinerAPIGraceSecondsAMD = Config.ConfigData.MinerAPIGraceSecondsAMD; - GeneralConfig.SwitchMinSecondsFixed = Config.ConfigData.SwitchMinSecondsFixed; - GeneralConfig.SwitchMinSecondsDynamic = Config.ConfigData.SwitchMinSecondsDynamic; - GeneralConfig.SwitchMinSecondsAMD = Config.ConfigData.SwitchMinSecondsAMD; - GeneralConfig.MinIdleSeconds = Config.ConfigData.MinIdleSeconds; - GeneralConfig.DisplayCurrency = Config.ConfigData.DisplayCurrency; - - // save migration - GeneralConfig.Commit(); - - Config.DeleteLegacy(); + public static void CreateBackup() { + GeneralConfigBackup = MemoryHelper.DeepClone(ConfigManager.GeneralConfig); + BenchmarkConfigsBackup = new Dictionary(); + foreach (var CDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + BenchmarkConfigsBackup[CDev.UUID] = CDev.GetAlgorithmDeviceConfig(); } } - public void CommitBenchmarks() { - foreach (var benchConfig in BenchmarkConfigs) { - benchConfig.Value.Commit(); + public static void RestoreBackup() { + // restore general + GeneralConfig = GeneralConfigBackup; + if (GeneralConfig.LastDevicesSettup != null) { + foreach (var CDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + foreach (var conf in GeneralConfig.LastDevicesSettup) { + CDev.SetFromComputeDeviceConfig(conf); + } + } + } + // restore benchmarks + foreach (var CDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + if (BenchmarkConfigsBackup != null && BenchmarkConfigsBackup.ContainsKey(CDev.UUID)) { + CDev.SetAlgorithmDeviceConfig(BenchmarkConfigsBackup[CDev.UUID]); + } + } + } + + public static bool IsRestartNeeded() { + return ConfigManager.GeneralConfig.DebugConsole != GeneralConfigBackup.DebugConsole + || ConfigManager.GeneralConfig.NVIDIAP0State != GeneralConfigBackup.NVIDIAP0State + || ConfigManager.GeneralConfig.LogToFile != GeneralConfigBackup.LogToFile + || ConfigManager.GeneralConfig.SwitchMinSecondsFixed != GeneralConfigBackup.SwitchMinSecondsFixed + || ConfigManager.GeneralConfig.SwitchMinSecondsAMD != GeneralConfigBackup.SwitchMinSecondsAMD + || ConfigManager.GeneralConfig.SwitchMinSecondsDynamic != GeneralConfigBackup.SwitchMinSecondsDynamic + || ConfigManager.GeneralConfig.MinerAPIQueryInterval != GeneralConfigBackup.MinerAPIQueryInterval + || ConfigManager.GeneralConfig.DisableWindowsErrorReporting != GeneralConfigBackup.DisableWindowsErrorReporting ; + } + + public static void GeneralConfigFileCommit() { + GeneralConfig.LastDevicesSettup.Clear(); + foreach (var CDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + GeneralConfig.LastDevicesSettup.Add(CDev.GetComputeDeviceConfig()); } + GeneralConfigFile.Commit(GeneralConfig); } - private void LoadBenchmarks() { - foreach (var CDev in ComputeDevice.AllAvaliableDevices) { - // doubly check if not added - if (BenchmarkConfigs.ContainsKey(CDev.UUID)) { - Helpers.ConsolePrint(TAG, "BUG - LoadBenchmarks() already added for {0}", CDev.UUID); + public static void CommitBenchmarks() { + foreach (var CDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + string devUUID = CDev.UUID; + if (BenchmarkConfigFiles.ContainsKey(devUUID)) { + BenchmarkConfigFiles[devUUID].Commit(CDev.GetAlgorithmDeviceConfig()); } else { - var benchConfig = DeviceBenchmarkConfigManager.Instance.GetConfig(CDev.DeviceGroupType, CDev.UUID, CDev.Name); - benchConfig.InitializeConfig(); - BenchmarkConfigs.Add(CDev.UUID, benchConfig); + BenchmarkConfigFiles[devUUID] = new DeviceBenchmarkConfigFile(devUUID); + BenchmarkConfigFiles[devUUID].Commit(CDev.GetAlgorithmDeviceConfig()); } } } - public void AfterDeviceQueryInitialization() { - GeneralConfig.AfterDeviceQueryInitialization(); - LoadBenchmarks(); - - SetDeviceBenchmarkReferences(); - - // check ethminers and remove from settings if no device supports it in config - foreach (var config in BenchmarkConfigs) { - bool removeDagger = true; - var cDev = ComputeDevice.GetDeviceWithUUID(config.Value.DeviceUUID); - if (cDev != null) { - // if only one dev ing roup supports terminate - if (cDev.IsEtherumCapale) { - removeDagger = false; - break; + public static void AfterDeviceQueryInitialization() { + // extra check (probably will never happen but just in case) + { + List invalidDevices = new List(); + foreach (var CDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + if (CDev.IsAlgorithmSettingsInitialized() == false) { + Helpers.ConsolePrint(TAG, "CRITICAL ISSUE!!! Device has AlgorithmSettings == null. Will remove"); + invalidDevices.Add(CDev); } } - if (removeDagger) { - config.Value.AlgorithmSettings.Remove(AlgorithmType.DaggerHashimoto); + // remove invalids + foreach (var invalid in invalidDevices) { + ComputeDeviceManager.Avaliable.AllAvaliableDevices.Remove(invalid); } } - - CommitBenchmarks(); - } - - public void SetDeviceBenchmarkReferences() { - // new stuff - // set references - // C# can handle cyclic refs - DeviceBenchmarkConfigManager.Instance.BenchmarkConfigs = BenchmarkConfigs; - BenchmarkConfigs = DeviceBenchmarkConfigManager.Instance.BenchmarkConfigs; - // set Benchmarks for devices - foreach (var cdev in ComputeDevice.AllAvaliableDevices) { - cdev.SetDeviceBenchmarkConfig(DeviceBenchmarkConfigManager.Instance.GetConfig(cdev.DeviceGroupType, cdev.UUID, cdev.Name)); + // set enabled/disabled devs + foreach (var CDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + foreach (var devConf in GeneralConfig.LastDevicesSettup) { + CDev.SetFromComputeDeviceConfig(devConf); + } + } + // create/init device benchmark configs files and configs + foreach (var CDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + string keyUUID = CDev.UUID; + BenchmarkConfigFiles[keyUUID] = new DeviceBenchmarkConfigFile(keyUUID); + // init + { + DeviceBenchmarkConfig currentConfig = null; + if (BenchmarkConfigFiles[keyUUID].IsFileExists()) { + currentConfig = BenchmarkConfigFiles[keyUUID].ReadFile(); + } + // config exists and file load success set from file + if (currentConfig != null) { + CDev.SetAlgorithmDeviceConfig(currentConfig); + // if new version create backup + if (IsNewVersion) { + BenchmarkConfigFiles[keyUUID].CreateBackup(); + } + } else { + // no config file or not loaded, create new + BenchmarkConfigFiles[keyUUID].Commit(CDev.GetAlgorithmDeviceConfig()); + } + } } + // save settings + GeneralConfigFileCommit(); } + } } diff --git a/NiceHashMiner/Configs/Data/AlgorithmConfig.cs b/NiceHashMiner/Configs/Data/AlgorithmConfig.cs new file mode 100644 index 0000000..107d8b0 --- /dev/null +++ b/NiceHashMiner/Configs/Data/AlgorithmConfig.cs @@ -0,0 +1,18 @@ +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Configs.Data { + [Serializable] + public class AlgorithmConfig { + public string Name = ""; // Used as an indicator for easier user interaction + public AlgorithmType NiceHashID = AlgorithmType.NONE; + public MinerBaseType MinerBaseType = MinerBaseType.NONE; + public string MinerName = ""; // probably not needed + public double BenchmarkSpeed = 0; + public string ExtraLaunchParameters= ""; + public bool Enabled = true; + public int LessThreads = 0; + } +} diff --git a/NiceHashMiner/Configs/BenchmarkTimeLimitsConfig.cs b/NiceHashMiner/Configs/Data/BenchmarkTimeLimitsConfig.cs similarity index 98% rename from NiceHashMiner/Configs/BenchmarkTimeLimitsConfig.cs rename to NiceHashMiner/Configs/Data/BenchmarkTimeLimitsConfig.cs index 1141e75..ee823a3 100644 --- a/NiceHashMiner/Configs/BenchmarkTimeLimitsConfig.cs +++ b/NiceHashMiner/Configs/Data/BenchmarkTimeLimitsConfig.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text; -namespace NiceHashMiner.Configs +namespace NiceHashMiner.Configs.Data { /// /// BenchmarkTimeLimitsConfig is used to set the time limits for benchmarking. diff --git a/NiceHashMiner/Configs/Data/ComputeDeviceConfig.cs b/NiceHashMiner/Configs/Data/ComputeDeviceConfig.cs new file mode 100644 index 0000000..0b7ba12 --- /dev/null +++ b/NiceHashMiner/Configs/Data/ComputeDeviceConfig.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Configs.Data { + [Serializable] + public class ComputeDeviceConfig { + public string Name = ""; + public bool Enabled = true; + public string UUID = ""; + } +} diff --git a/NiceHashMiner/Configs/Data/DeviceBenchmarkConfig.cs b/NiceHashMiner/Configs/Data/DeviceBenchmarkConfig.cs new file mode 100644 index 0000000..d81ae99 --- /dev/null +++ b/NiceHashMiner/Configs/Data/DeviceBenchmarkConfig.cs @@ -0,0 +1,14 @@ +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Configs.Data { + [Serializable] + public class DeviceBenchmarkConfig { + public string DeviceUUID = ""; + public string DeviceName = ""; + //public int TimeLimit { get; set; } + public List AlgorithmSettings = new List(); + } +} diff --git a/NiceHashMiner/Configs/Data/DeviceDetectionConfig.cs b/NiceHashMiner/Configs/Data/DeviceDetectionConfig.cs new file mode 100644 index 0000000..d4cfd7e --- /dev/null +++ b/NiceHashMiner/Configs/Data/DeviceDetectionConfig.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Configs.Data +{ + /// + /// DeviceDetectionConfig is used to enable/disable detection of certain GPU type devices + /// + /// + [Serializable] + public class DeviceDetectionConfig { + public bool DisableDetectionAMD { get; set; } + public bool DisableDetectionNVIDIA { get; set; } + + public DeviceDetectionConfig() + { + DisableDetectionAMD = false; + DisableDetectionNVIDIA = false; + } + } +} diff --git a/NiceHashMiner/Configs/Data/GeneralConfig.cs b/NiceHashMiner/Configs/Data/GeneralConfig.cs new file mode 100644 index 0000000..495d7b6 --- /dev/null +++ b/NiceHashMiner/Configs/Data/GeneralConfig.cs @@ -0,0 +1,156 @@ +using NiceHashMiner.Enums; +using NiceHashMiner.Net20_backport; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Configs.Data { + [Serializable] + public class GeneralConfig { + + public Version ConfigFileVersion; + public LanguageType Language = LanguageType.En; + public string DisplayCurrency = "USD"; + + public bool DebugConsole = false; + public string BitcoinAddress = ""; + public string WorkerName = "worker1"; + public int ServiceLocation = 0; + public bool AutoStartMining = false; + public bool HideMiningWindows = false; + public bool MinimizeToTray = false; + //public int LessThreads; + public CPUExtensionType ForceCPUExtension = CPUExtensionType.Automatic; + + public int SwitchMinSecondsFixed = 90; + public int SwitchMinSecondsDynamic = 30; + public int SwitchMinSecondsAMD = 60; + public double SwitchProfitabilityThreshold = 0.05; // percent + public int MinerAPIQueryInterval = 5; + public int MinerRestartDelayMS = 500; + + public BenchmarkTimeLimitsConfig BenchmarkTimeLimits = new BenchmarkTimeLimitsConfig(); + // TODO deprecate this + public DeviceDetectionConfig DeviceDetection = new DeviceDetectionConfig(); + + public bool DisableAMDTempControl = true; + public bool DisableDefaultOptimizations = false; + + public bool AutoScaleBTCValues = true; + public bool StartMiningWhenIdle = false; + + public int MinIdleSeconds = 60; + public bool LogToFile = true; + + // in bytes + public long LogMaxFileSize = 1048576; + + public bool ShowDriverVersionWarning = true; + public bool DisableWindowsErrorReporting = true; + public bool NVIDIAP0State = false; + + public int ethminerDefaultBlockHeight = 2000000; + public DagGenerationType EthminerDagGenerationType = DagGenerationType.SingleKeep; + public int ApiBindPortPoolStart = 5100; + public double MinimumProfit = 0; + public bool IdleWhenNoInternetAccess = true; + public bool DownloadInit = false; + // 3rd party miners + public Use3rdPartyMiners Use3rdPartyMiners = Use3rdPartyMiners.NOT_SET; + public bool DownloadInit3rdParty = false; + + public bool AllowMultipleInstances = true; + + // device enabled disabled stuff + public List LastDevicesSettup = new List(); + // + public string hwid = ""; + public int agreedWithTOS = 0; + + // methods + public void SetDefaults() { + ConfigFileVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; + Language = LanguageType.En; + ForceCPUExtension = CPUExtensionType.Automatic; + BitcoinAddress = ""; + WorkerName = "worker1"; + ServiceLocation = 0; + AutoStartMining = false; + //LessThreads = 0; + DebugConsole = false; + HideMiningWindows = false; + MinimizeToTray = false; + BenchmarkTimeLimits = new BenchmarkTimeLimitsConfig(); + DeviceDetection = new DeviceDetectionConfig(); + DisableAMDTempControl = true; + DisableDefaultOptimizations = false; + AutoScaleBTCValues = true; + StartMiningWhenIdle = false; + LogToFile = true; + LogMaxFileSize = 1048576; + ShowDriverVersionWarning = true; + DisableWindowsErrorReporting = true; + NVIDIAP0State = false; + MinerRestartDelayMS = 500; + ethminerDefaultBlockHeight = 2000000; + SwitchMinSecondsFixed = 90; + SwitchMinSecondsDynamic = 30; + SwitchMinSecondsAMD = 90; + SwitchProfitabilityThreshold = 0.05; // percent + MinIdleSeconds = 60; + DisplayCurrency = "USD"; + ApiBindPortPoolStart = 4000; + MinimumProfit = 0; + EthminerDagGenerationType = DagGenerationType.SingleKeep; + DownloadInit = false; + //ContinueMiningIfNoInternetAccess = false; + IdleWhenNoInternetAccess = true; + Use3rdPartyMiners = Use3rdPartyMiners.NOT_SET; + DownloadInit3rdParty = false; + AllowMultipleInstances = true; + } + + public void FixSettingBounds() { + this.ConfigFileVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; + if (string.IsNullOrEmpty(this.DisplayCurrency) + || StringHelper.IsNullOrWhiteSpace(this.DisplayCurrency)) { + this.DisplayCurrency = "USD"; + } + if (this.SwitchMinSecondsFixed <= 0) { + this.SwitchMinSecondsFixed = 90; + } + if (this.SwitchMinSecondsDynamic <= 0) { + this.SwitchMinSecondsDynamic = 30; + } + if (this.SwitchMinSecondsAMD <= 0) { + this.SwitchMinSecondsAMD = 60; + } + if (this.MinerAPIQueryInterval <= 0) { + this.MinerAPIQueryInterval = 5; + } + if (this.MinerRestartDelayMS <= 0) { + this.MinerRestartDelayMS = 500; + } + if (this.MinIdleSeconds <= 0) { + this.MinIdleSeconds = 60; + } + if (this.LogMaxFileSize <= 0) { + this.LogMaxFileSize = 1048576; + } + // check port start number, leave about 2000 ports pool size, huge yea! + if (this.ApiBindPortPoolStart > (65535 - 2000)) { + this.ApiBindPortPoolStart = 5100; + } + if (this.BenchmarkTimeLimits == null) { + this.BenchmarkTimeLimits = new BenchmarkTimeLimitsConfig(); + } + if (this.DeviceDetection == null) { + this.DeviceDetection = new DeviceDetectionConfig(); + } + if (this.LastDevicesSettup == null) { + this.LastDevicesSettup = new List(); + } + } + + } +} diff --git a/NiceHashMiner/Configs/DeviceBenchmarkConfig.cs b/NiceHashMiner/Configs/DeviceBenchmarkConfig.cs deleted file mode 100644 index 8bacc65..0000000 --- a/NiceHashMiner/Configs/DeviceBenchmarkConfig.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Security.Cryptography; -using System.Text; -using NiceHashMiner.Enums; -using NiceHashMiner.Devices; -using Newtonsoft.Json; -using System.IO; - -namespace NiceHashMiner.Configs -{ - [Serializable] - public class DeviceBenchmarkConfig : BaseConfigFile { - - public string DeviceUUID { get; private set; } - [JsonIgnore] - public DeviceGroupType DeviceGroupType { get; private set; } - - public string DeviceName { get; private set; } - //public int TimeLimit { get; set; } - public Dictionary AlgorithmSettings { get; set; } - - // TODO remove in furure releases - - [field: NonSerialized] - readonly public static string BENCHMARK_PREFIX = "benchmark_"; - - [JsonIgnore] - public bool IsAlgorithmSettingsInit { get; set; } - - public DeviceBenchmarkConfig(DeviceGroupType deviceGroupType, - string deviceUUID, - string deviceName, - Dictionary benchmarkSpeeds = null) { - - DeviceGroupType = deviceGroupType; - DeviceUUID = deviceUUID; - DeviceName = deviceName; - if (benchmarkSpeeds != null) { - AlgorithmSettings = benchmarkSpeeds; - } else { - AlgorithmSettings = GroupAlgorithms.CreateDefaultsForGroup(deviceGroupType); - } - - IsAlgorithmSettingsInit = false; - - // calculate ID - //ID = GetId(); - } - - public static string GetId(DeviceGroupType deviceGroupType, - string deviceGroupName) { - var SHA256 = new SHA256Managed(); - var hash = new StringBuilder(); - string mixedAttr = ((int)deviceGroupType).ToString() + deviceGroupName; - byte[] hashedBytes = SHA256.ComputeHash(Encoding.UTF8.GetBytes(mixedAttr), 0, Encoding.UTF8.GetByteCount(mixedAttr)); - foreach (var b in hashedBytes) { - hash.Append(b.ToString("x2")); - } - return hash.ToString(); - } - - private string GetId() { - return GetId(DeviceGroupType, DeviceName); - } - - protected override void InitializePaths() { - // make device name - char[] invalid = new char[] { '<', '>', ':', '"', '/', '\\', '|', '?', '*' }; - string fileName = BENCHMARK_PREFIX + DeviceUUID.Replace(' ', '_'); - foreach (var c in invalid) { - fileName = fileName.Replace(c.ToString(), String.Empty); - } - const string extension = ".json"; - FilePath = fileName + extension; - FilePathOld = fileName + "_OLD" + extension; - } - - // TODO make generic initializations - protected override void InitializeObject() { - // if new backup benchmarks - if (ConfigManager.Instance.GeneralConfig.IsNewVersion) { - Helpers.ConsolePrint("DeviceBenchmarkConfig", String.Format("Backing up {0} to {1}..", FilePath, FilePathOld)); - try { - if (File.Exists(FilePathOld)) - File.Delete(FilePathOld); - File.Move(FilePath, FilePathOld); - } catch { } - } - - - // check if data tampered - bool IsDataTampered = !( - /*this.ID == _file.ID - && this.DeviceGroupType == _file.DeviceGroupType - && */this.DeviceName == _file.DeviceName - ); - - //this.TimeLimit = _file.TimeLimit; - if (_file.DeviceUUID != null) { - this.DeviceUUID = _file.DeviceUUID; - } - - if (_file.AlgorithmSettings != null) { - // settings from files are initialized - foreach (var key in _file.AlgorithmSettings.Keys) { - if(this.AlgorithmSettings.ContainsKey(key)) { - this.AlgorithmSettings[key] = _file.AlgorithmSettings[key]; - } else { - // TODO think if we let tamnpered data - } - } - } - // if read fromfile then it is initialized - IsAlgorithmSettingsInit = true; - } - } -} diff --git a/NiceHashMiner/Configs/DeviceBenchmarkConfigManager.cs b/NiceHashMiner/Configs/DeviceBenchmarkConfigManager.cs deleted file mode 100644 index 470848d..0000000 --- a/NiceHashMiner/Configs/DeviceBenchmarkConfigManager.cs +++ /dev/null @@ -1,85 +0,0 @@ -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; -using System; -using System.Collections.Generic; -using System.Text; - -namespace NiceHashMiner.Configs { - - public class DeviceBenchmarkConfigManager : BaseLazySingleton { - - private Dictionary _benchmarkConfigs; - public Dictionary BenchmarkConfigs { - get { return _benchmarkConfigs; } - set { - if (value != null) { - _benchmarkConfigs = value; - } - } - } - - protected DeviceBenchmarkConfigManager() { - _benchmarkConfigs = new Dictionary(); - } - - private DeviceBenchmarkConfig GetConfig(string deviceUUID) { - DeviceBenchmarkConfig retConfig = null; - if (_benchmarkConfigs.TryGetValue(deviceUUID, out retConfig) == false) { - retConfig = null; - } - return retConfig; - } - - public DeviceBenchmarkConfig GetConfig(DeviceGroupType deviceGroupType, - string deviceUUID, string deviceName) { - DeviceBenchmarkConfig retConfig = GetConfig(deviceUUID); - if (retConfig == null) { - retConfig = new DeviceBenchmarkConfig(deviceGroupType, deviceUUID, deviceName); - _benchmarkConfigs.Add(deviceUUID, retConfig); - } - - return retConfig; - } - - /// - /// IsEnabledBenchmarksInitialized is to check if currently enabled devices have all enabled algorithms benchmarked. - /// - /// Returns tuple of boolean and dictionary of unbenchmarked algorithms per device - public Tuple> > IsEnabledBenchmarksInitialized() { - bool isEnabledBenchmarksInitialized = true; - // first get all enabled devices names - HashSet enabledDevicesNames = new HashSet(); - foreach (var device in ComputeDevice.AllAvaliableDevices) { - if (device.Enabled) { - enabledDevicesNames.Add(device.UUID); - } - } - // get enabled unbenchmarked algorithms - Dictionary> unbenchmarkedAlgorithmsPerDevice = new Dictionary>(); - // init unbenchmarkedAlgorithmsPerDevice - foreach (var deviceName in enabledDevicesNames) { - unbenchmarkedAlgorithmsPerDevice.Add(deviceName, new List()); - } - // check benchmarks - foreach (var deviceName in enabledDevicesNames) { - if (_benchmarkConfigs.ContainsKey(deviceName)) { - foreach (var kvpAlgorithm in _benchmarkConfigs[deviceName].AlgorithmSettings) { - var algorithm = kvpAlgorithm.Value; - if (!algorithm.Skip && algorithm.BenchmarkSpeed <= 0.0d) { - isEnabledBenchmarksInitialized = false; - // add for reference to bench - unbenchmarkedAlgorithmsPerDevice[deviceName].Add(algorithm.NiceHashID); - } - } - } - } - - return - new Tuple>>( - isEnabledBenchmarksInitialized, - unbenchmarkedAlgorithmsPerDevice - ); - } - - } -} diff --git a/NiceHashMiner/Configs/DeviceDetectionConfig.cs b/NiceHashMiner/Configs/DeviceDetectionConfig.cs deleted file mode 100644 index 0474be9..0000000 --- a/NiceHashMiner/Configs/DeviceDetectionConfig.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace NiceHashMiner.Configs -{ - /// - /// DeviceDetectionConfig is used to enable/disable detection of certain GPU type devices - /// - /// - [Serializable] - public class DeviceDetectionConfig - { - public bool DisableDetectionNVidia6X { get; set; } - public bool DisableDetectionNVidia5X { get; set; } - public bool DisableDetectionNVidia3X { get; set; } - public bool DisableDetectionNVidia2X { get; set; } - public bool DisableDetectionAMD { get; set; } - - public DeviceDetectionConfig() - { - DisableDetectionNVidia6X = false; - DisableDetectionNVidia5X = false; - DisableDetectionNVidia3X = false; - DisableDetectionNVidia2X = false; - DisableDetectionAMD = false; - } - } -} diff --git a/NiceHashMiner/Configs/GeneralConfig.cs b/NiceHashMiner/Configs/GeneralConfig.cs deleted file mode 100644 index df3c7e0..0000000 --- a/NiceHashMiner/Configs/GeneralConfig.cs +++ /dev/null @@ -1,268 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; -using Newtonsoft.Json; -using System.IO; - -namespace NiceHashMiner.Configs { - [Serializable] - public class GeneralConfig : BaseConfigFile { - - #region Members - public Version ConfigFileVersion { get; set; } - public LanguageType Language { get; set; } - - private string _displayCurrency = "USD"; - public string DisplayCurrency { - get { return _displayCurrency; } - set { _displayCurrency = value == null ? "USD" : value; } - } - - public bool DebugConsole { get; set; } - public string BitcoinAddress { get; set; } - public string WorkerName { get; set; } - public int ServiceLocation { get; set; } - public bool HideMiningWindows { get; set; } - public bool MinimizeToTray { get; set; } - //public int LessThreads { get; set; } - public CPUExtensionType ForceCPUExtension { get; set; } // 0 - automatic, 1 - SSE2, 2 - AVX, 3 - AVX2 - - private int _switchMinSecondsFixed = 90; - public int SwitchMinSecondsFixed { - get { return _switchMinSecondsFixed; } - set { - _switchMinSecondsFixed = value <= 0 ? 90 : value; - } - } - private int _switchMinSecondsDynamic = 30; - public int SwitchMinSecondsDynamic { - get { return _switchMinSecondsDynamic; } - set { - _switchMinSecondsDynamic = value <= 0 ? 30 : value; - } - } - - private int _switchMinSecondsAMD = 60; - public int SwitchMinSecondsAMD { - get { return _switchMinSecondsAMD; } - set { _switchMinSecondsAMD = value <= 0 ? 60 : value; } - } - - private int _minerAPIQueryInterval = 5; - public int MinerAPIQueryInterval { - get { return _minerAPIQueryInterval; } - set { _minerAPIQueryInterval = value <= 0 ? 5 : value;} - } - - private int _minerRestartDelayMS = 500; - public int MinerRestartDelayMS { - get { return _minerRestartDelayMS; } - set { _minerRestartDelayMS = value <= 0 ? 500 : value; } - } - - public BenchmarkTimeLimitsConfig BenchmarkTimeLimits { get; set; } - public DeviceDetectionConfig DeviceDetection { get; set; } - - public bool AutoScaleBTCValues { get; set; } - public bool StartMiningWhenIdle { get; set; } - - private int _minIdleSeconds = 60; - public int MinIdleSeconds { - get { return _minIdleSeconds; } - set { _minIdleSeconds = value <= 0 ? 60 : value; } - } - public bool LogToFile { get; set; } - - // in bytes - private long _logMaxFileSize = 1048576; - public long LogMaxFileSize { - get { return _logMaxFileSize; } - set { _logMaxFileSize = value <= 0 ? 1048576 : value; } - } - - public bool ShowDriverVersionWarning { get; set; } - public bool DisableWindowsErrorReporting { get; set; } - public bool NVIDIAP0State { get; set; } - - public int ethminerDefaultBlockHeight { get; set; } - public DagGenerationType EthminerDagGenerationType; - - private int _apiBindPortPoolStart = 5100; - public int ApiBindPortPoolStart { - get { return _apiBindPortPoolStart; } - set { - // check port start number, leave about 2000 ports pool size, huge yea! - if (value < (65535 - 2000)) { - _apiBindPortPoolStart = value; - } else { - // set default - _apiBindPortPoolStart = 5100; - } - } - } - public double MinimumProfit { get; set; } - public string hwid { get; set; } - - public bool DownloadInit { get; set; } - - - [JsonIgnore] - public bool hwidOK { get; private set; } - [JsonIgnore] - public bool hwidLoadFromFile { get; private set; } - [JsonIgnore] - public bool IsNewVersion { get; private set; } - - - // After Device initialization - - /// - /// LastDevicesSettup field should not be manually edited - /// The changes can be of two scenarios: - /// #1 Detect if the device is enabled/disabled, - /// #2 Detect hardware changes/upgrades such as CPUs and GPUs. - /// - public List LastDevicesSettup { get; set; } - - #endregion //Members - - public bool IsFileExist() { - return FileLoaded; - } - - public void SetDefaults() { - ConfigFileVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; - Language = LanguageType.En; - BitcoinAddress = ""; - WorkerName = "worker1"; - ServiceLocation = 0; - //LessThreads = 0; - DebugConsole = false; - HideMiningWindows = false; - MinimizeToTray = false; - BenchmarkTimeLimits = new BenchmarkTimeLimitsConfig(); - DeviceDetection = new DeviceDetectionConfig(); - AutoScaleBTCValues = true; - StartMiningWhenIdle = false; - LogToFile = true; - LogMaxFileSize = 1048576; - ShowDriverVersionWarning = true; - DisableWindowsErrorReporting = true; - NVIDIAP0State = false; - MinerRestartDelayMS = 500; - ethminerDefaultBlockHeight = 2000000; - SwitchMinSecondsFixed = 90; - SwitchMinSecondsDynamic = 30; - SwitchMinSecondsAMD = 90; - MinIdleSeconds = 60; - DisplayCurrency = "USD"; - ApiBindPortPoolStart = 4000; - MinimumProfit = 0; - EthminerDagGenerationType = DagGenerationType.SingleKeep; - DownloadInit = false; - } - - public GeneralConfig(bool initDefaults = false) { - ConfigFileVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; - BenchmarkTimeLimits = new BenchmarkTimeLimitsConfig(); - DeviceDetection = new DeviceDetectionConfig(); - - hwidOK = false; - hwidLoadFromFile = false; - IsNewVersion = false; - - // only init defaults for created config not read - if (initDefaults) { - SetDefaults(); - hwid = Helpers.GetCpuID(); - } - } - - protected override void InitializePaths() { - FilePath = "General.json"; - FilePathOld = "General_old.json"; - } - protected override void InitializeObject() { - if (_file.ConfigFileVersion == null || - _file.ConfigFileVersion.CompareTo(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version) != 0) { - IsNewVersion = true; - Helpers.ConsolePrint("GeneralConfig", "Config file is from an older version of NiceHashMiner.."); - Helpers.ConsolePrint("GeneralConfig", String.Format("Backing up {0} to {1}..", FilePath, FilePathOld)); - try { - if (File.Exists(FilePathOld)) - File.Delete(FilePathOld); - File.Move(FilePath, FilePathOld); - } catch { } - - SetDefaults(); - } - - - // init fields - Language = _file.Language; - DisplayCurrency = _file.DisplayCurrency; - DebugConsole = _file.DebugConsole; - BitcoinAddress = _file.BitcoinAddress; - WorkerName = _file.WorkerName; - ServiceLocation = _file.ServiceLocation; - //AutoStartMining = _file.AutoStartMining; - HideMiningWindows = _file.HideMiningWindows; - MinimizeToTray = _file.MinimizeToTray; - //LessThreads = _file.LessThreads; - ForceCPUExtension = _file.ForceCPUExtension; - SwitchMinSecondsFixed = _file.SwitchMinSecondsFixed; - SwitchMinSecondsDynamic = _file.SwitchMinSecondsDynamic; - SwitchMinSecondsAMD = _file.SwitchMinSecondsAMD; - MinerAPIQueryInterval = _file.MinerAPIQueryInterval; - MinerRestartDelayMS = _file.MinerRestartDelayMS; - if (_file.BenchmarkTimeLimits != null) { - this.BenchmarkTimeLimits = _file.BenchmarkTimeLimits; - } - if (_file.DeviceDetection != null) { - this.DeviceDetection = _file.DeviceDetection; - } - AutoScaleBTCValues = _file.AutoScaleBTCValues; - StartMiningWhenIdle = _file.StartMiningWhenIdle; - MinIdleSeconds = _file.MinIdleSeconds; - LogToFile = _file.LogToFile; - LogMaxFileSize = _file.LogMaxFileSize; - ShowDriverVersionWarning = _file.ShowDriverVersionWarning; - DisableWindowsErrorReporting = _file.DisableWindowsErrorReporting; - NVIDIAP0State = _file.NVIDIAP0State; - ethminerDefaultBlockHeight = _file.ethminerDefaultBlockHeight; - EthminerDagGenerationType = _file.EthminerDagGenerationType; - ApiBindPortPoolStart = _file.ApiBindPortPoolStart; - MinimumProfit = _file.MinimumProfit; - - DownloadInit = _file.DownloadInit; - - hwidLoadFromFile = true; - hwidOK = this.hwid == _file.hwid; - } - - public void AfterDeviceQueryInitialization() { - - if (_file != null && _file.LastDevicesSettup != null) { - foreach (var configDevice in _file.LastDevicesSettup) { - foreach (var usedDevice in ComputeDevice.AllAvaliableDevices) { - if (configDevice.UUID == usedDevice.UUID) { - usedDevice.Enabled = configDevice.Enabled; - continue; - } - } - } - } - - LastDevicesSettup = ComputeDevice.AllAvaliableDevices; - } - - public void Delete() { - try { - File.Delete(FilePath); - } catch { - } - } - } -} diff --git a/NiceHashMiner/Configs/Legacy/Config.cs b/NiceHashMiner/Configs/Legacy/Config.cs deleted file mode 100644 index a64c03c..0000000 --- a/NiceHashMiner/Configs/Legacy/Config.cs +++ /dev/null @@ -1,203 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.IO; -using Newtonsoft.Json; -using NiceHashMiner.Enums; -using NiceHashMiner.Devices; - -namespace NiceHashMiner.Configs -{ - public partial class ConfigManager : BaseLazySingleton { - public class Algo { -#pragma warning disable 649 - public string Name; // only used for easier manual identification in config file - public string ExtraLaunchParameters; - public string UsePassword; - public double BenchmarkSpeed; - public bool Skip; - public bool[] DisabledDevices; -#pragma warning restore 649 - } - - public class Group { -#pragma warning disable 649 - public string Name; // only used for easier manual identification in config file - public int APIBindPort; - public string ExtraLaunchParameters; - public string UsePassword; - public double MinimumProfit; - public int DaggerHashimotoGenerateDevice; - public int[] DisabledDevices; - public Algo[] Algorithms; -#pragma warning restore 649 - - public Group() { - DisabledDevices = new int[0]; - Algorithms = new Algo[0]; - } - } - - public class Config { -#pragma warning disable 649 - public Version ConfigFileVersion; - public int Language; - public string DisplayCurrency; - public bool DebugConsole; - public string BitcoinAddress; - public string WorkerName; - public int ServiceLocation; - public bool AutoStartMining; - public bool HideMiningWindows; - public bool MinimizeToTray; - public int LessThreads; - public int ForceCPUExtension; // 0 - automatic, 1 - SSE2, 2 - AVX, 3 - AVX2 - public int SwitchMinSecondsFixed; - public int SwitchMinSecondsDynamic; - public int SwitchMinSecondsAMD; - public int MinerAPIQueryInterval; - public int MinerRestartDelayMS; - public int MinerAPIGraceSeconds; - public int MinerAPIGraceSecondsAMD; - public int[] BenchmarkTimeLimitsCPU; - public int[] BenchmarkTimeLimitsNVIDIA; - public int[] BenchmarkTimeLimitsAMD; - public bool DisableDetectionNVidia5X; - public bool DisableDetectionNVidia3X; - public bool DisableDetectionNVidia2X; - public bool DisableDetectionAMD; - public bool DisableAMDTempControl; - public bool AutoScaleBTCValues; - public bool StartMiningWhenIdle; - public int MinIdleSeconds; - public bool LogToFile; - public long LogMaxFileSize; // in bytes - public bool ShowDriverVersionWarning; - public bool DisableWindowsErrorReporting; - public bool UseNewSettingsPage; // depriciate this - public bool NVIDIAP0State; - public int ethminerAPIPortNvidia; - public int ethminerAPIPortAMD; - public int ethminerDefaultBlockHeight; - public Group[] Groups; -#pragma warning restore 649 - - public static Config ConfigData; - - public static void InitializeConfig() { - // Set defaults - ConfigData = new Config(); - SetDefaults(); - - try { - if (new FileInfo("config.json").Length > 17000) - ConfigData = JsonConvert.DeserializeObject(File.ReadAllText("config.json"), Globals.JsonSettings); - else { - File.Delete("config.json"); - } - } catch { } - - //if (ConfigData.ConfigFileVersion == null || - // ConfigData.ConfigFileVersion.CompareTo(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version) != 0) { - // Helpers.ConsolePrint("CONFIG", "Config file is from an older version of NiceHashMiner.."); - // Helpers.ConsolePrint("CONFIG", "Backing up config.json to config_old.json.."); - // try { - // if (File.Exists("config_old.json")) - // File.Delete("config_old.json"); - // //File.Move("config.json", "config_old.json"); - // } catch { } - - // SetDefaults(); - //} - - if (ConfigData.SwitchMinSecondsFixed <= 0) - ConfigData.SwitchMinSecondsFixed = 90; - if (ConfigData.SwitchMinSecondsDynamic <= 0) - ConfigData.SwitchMinSecondsDynamic = 30; - if (ConfigData.SwitchMinSecondsAMD <= 0) - ConfigData.SwitchMinSecondsAMD = 60; - if (ConfigData.MinerAPIQueryInterval <= 0) - ConfigData.MinerAPIQueryInterval = 5; - if (ConfigData.MinerRestartDelayMS <= 0) - ConfigData.MinerRestartDelayMS = 500; - if (ConfigData.MinerAPIGraceSeconds < 0) - ConfigData.MinerAPIGraceSeconds = 0; - if (ConfigData.MinerAPIGraceSecondsAMD < 0) - ConfigData.MinerAPIGraceSecondsAMD = 0; - if (ConfigData.BenchmarkTimeLimitsCPU == null || ConfigData.BenchmarkTimeLimitsCPU.Length < 3) - ConfigData.BenchmarkTimeLimitsCPU = new int[] { 10, 20, 60 }; - if (ConfigData.BenchmarkTimeLimitsNVIDIA == null || ConfigData.BenchmarkTimeLimitsNVIDIA.Length < 3) - ConfigData.BenchmarkTimeLimitsNVIDIA = new int[] { 10, 20, 60 }; - if (ConfigData.BenchmarkTimeLimitsAMD == null || ConfigData.BenchmarkTimeLimitsAMD.Length < 3) - ConfigData.BenchmarkTimeLimitsAMD = new int[] { 120, 180, 240 }; - if (ConfigData.MinIdleSeconds <= 0) - ConfigData.MinIdleSeconds = 60; - if (ConfigData.LogMaxFileSize <= 0) - ConfigData.LogMaxFileSize = 1048576; - if (ConfigData.DisplayCurrency == null) - ConfigData.DisplayCurrency = "USD"; - } - - public static void SetDefaults() { - ConfigData.ConfigFileVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; - ConfigData.Language = 0; - ConfigData.BitcoinAddress = ""; - ConfigData.WorkerName = "worker1"; - ConfigData.ServiceLocation = 0; - ConfigData.LessThreads = 0; - ConfigData.Groups = new Group[0]; - ConfigData.DebugConsole = false; - ConfigData.HideMiningWindows = false; - ConfigData.MinimizeToTray = false; - ConfigData.AutoStartMining = false; - ConfigData.DisableDetectionNVidia5X = false; - ConfigData.DisableDetectionNVidia3X = false; - ConfigData.DisableDetectionNVidia2X = false; - ConfigData.DisableDetectionAMD = false; - ConfigData.DisableAMDTempControl = false; - ConfigData.AutoScaleBTCValues = true; - ConfigData.StartMiningWhenIdle = false; - ConfigData.LogToFile = true; - ConfigData.LogMaxFileSize = 1048576; - ConfigData.ShowDriverVersionWarning = true; - ConfigData.DisableWindowsErrorReporting = true; - ConfigData.UseNewSettingsPage = true; - ConfigData.NVIDIAP0State = false; - ConfigData.MinerRestartDelayMS = 500; - ConfigData.ethminerAPIPortNvidia = 34561; - ConfigData.ethminerAPIPortAMD = 34562; - ConfigData.ethminerDefaultBlockHeight = 1700000; - ConfigData.MinerAPIGraceSeconds = 30; - ConfigData.MinerAPIGraceSecondsAMD = 60; - ConfigData.SwitchMinSecondsFixed = 90; - ConfigData.SwitchMinSecondsDynamic = 30; - ConfigData.SwitchMinSecondsAMD = 90; - ConfigData.MinIdleSeconds = 60; - ConfigData.DisplayCurrency = "USD"; - - } - - //public static void Commit() { - // try { File.WriteAllText("config.json", JsonConvert.SerializeObject(ConfigData, Formatting.Indented)); } catch { } - //} - - //public static void RebuildGroups() { - // Config.Commit(); - //} - - public static bool ConfigFileExist() { - if (File.Exists("config.json")) - return true; - - return false; - } - - public static void DeleteLegacy() { - try { - if (File.Exists("config.json")) - File.Delete("config.json"); - } catch { } - } - } - } -} diff --git a/NiceHashMiner/CurrencyConverter.cs b/NiceHashMiner/CurrencyConverter.cs deleted file mode 100644 index 9ae7c39..0000000 --- a/NiceHashMiner/CurrencyConverter.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using NiceHashMiner.Configs; - -namespace NiceHashMiner.CurrencyConverter -{ - public static class CurrencyConverter - { - private static DateTime LastUpdate = DateTime.Now; - private static CurrencyAPIResponse LastResponse; - - private static bool ConverterActive { - get { return ConfigManager.Instance.GeneralConfig.DisplayCurrency != "USD"; } - } - - - public static double ConvertToActiveCurrency(double amount) - { - if (!ConverterActive) - return amount; - - if(LastResponse == null || DateTime.Now - LastUpdate > TimeSpan.FromMinutes(10)) - { - UpdateAPI(); - } - - // if we are still null after an update something went wrong. just use USD hopefully itll update next tick - if (LastResponse == null) - { - Helpers.ConsolePrint("CurrencyConverter", "Unable to retrieve update, Falling back to USD"); - return amount; - } - - //Helpers.ConsolePrint("CurrencyConverter", "Current Currency: " + ConfigManager.Instance.GeneralConfig.DisplayCurrency); - double usdExchangeRate = 1.0; - if (LastResponse.rates.TryGetValue(ConfigManager.Instance.GeneralConfig.DisplayCurrency, out usdExchangeRate)) - return amount * usdExchangeRate; - else - { - Helpers.ConsolePrint("CurrencyConverter", "Unknown Currency Tag: " + ConfigManager.Instance.GeneralConfig.DisplayCurrency + " falling back to USD rates"); - ConfigManager.Instance.GeneralConfig.DisplayCurrency = "USD"; - return amount; - } - } - - private static void UpdateAPI() - { - try { - var Client = new WebClient(); - var Response = Client.DownloadString("http://api.fixer.io/latest?base=USD"); - LastResponse = JsonConvert.DeserializeObject(Response, Globals.JsonSettings); - LastUpdate = DateTime.Now; - } - catch (Exception E) - { - Helpers.ConsolePrint("CurrencyConverter", E.Message); - Helpers.ConsolePrint("CurrencyConverter", "Unable to update API: reverting to usd"); - ConfigManager.Instance.GeneralConfig.DisplayCurrency = "USD"; - } - } - } - - - - - public class CurrencyAPIResponse - { - public string @base { get; set; } - public string date { get; set; } - public Dictionary rates { get; set; } - } -} diff --git a/NiceHashMiner/Devices/AmdGpuDevice.cs b/NiceHashMiner/Devices/AmdGpuDevice.cs index 1598023..6934ae9 100644 --- a/NiceHashMiner/Devices/AmdGpuDevice.cs +++ b/NiceHashMiner/Devices/AmdGpuDevice.cs @@ -1,57 +1,56 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Devices { [Serializable] public class AmdGpuDevice { - public static readonly string DefaultParam = "--keccak-unroll 0 --hamsi-expand-big 4 "; - public static readonly string TemperatureParam = " --gpu-fan 30-95 --temp-cutoff 95 --temp-overheat 90" + - " --temp-target 75 --auto-fan --auto-gpu"; + public static readonly string DefaultParam = "--keccak-unroll 0 --hamsi-expand-big 4 --remove-disabled "; + public static readonly string TemperatureParam = " --gpu-fan 30-95 --temp-cutoff 95 --temp-overheat 90 " + + " --temp-target 75 --auto-fan --auto-gpu "; public int DeviceID { get { return (int)_openClSubset.DeviceID; } } public string DeviceName; // init this with the ADL public string UUID; // init this with the ADL, use PCI_VEN & DEV IDs public ulong DeviceGlobalMemory { get { return _openClSubset._CL_DEVICE_GLOBAL_MEM_SIZE; } } - public bool UseOptimizedVersion { get; private set; } - private OpenCLDevice _openClSubset; + //public bool UseOptimizedVersion { get; private set; } + private OpenCLDevice _openClSubset = new OpenCLDevice(); + public readonly string InfSection; // has arhitecture string + + // new drivers make some algorithms unusable 21.19.164.1 => driver not working with NeoScrypt and + public bool DriverDisableAlgos { get; private set; } public string Codename { get { return _openClSubset._CL_DEVICE_NAME; } } - public AmdGpuDevice(OpenCLDevice openClSubset, bool isOldDriver) { - _openClSubset = openClSubset; + public AmdGpuDevice(OpenCLDevice openClSubset, bool isOldDriver, string infSection, bool driverDisableAlgo) { + DriverDisableAlgos = driverDisableAlgo; + InfSection = infSection; + if (openClSubset != null) { + _openClSubset = openClSubset; + } // Check for optimized version // first if not optimized Helpers.ConsolePrint("AmdGpuDevice", "List: " + _openClSubset._CL_DEVICE_NAME); - if (isOldDriver) { - UseOptimizedVersion = false; - Helpers.ConsolePrint("AmdGpuDevice", "GPU (" + _openClSubset._CL_DEVICE_NAME + ") is optimized => NOO! OLD DRIVER."); - } else if (!( _openClSubset._CL_DEVICE_NAME.Contains("Bonaire") - || _openClSubset._CL_DEVICE_NAME.Contains("Fiji") - || _openClSubset._CL_DEVICE_NAME.Contains("Hawaii") - || _openClSubset._CL_DEVICE_NAME.Contains("Pitcairn") - || _openClSubset._CL_DEVICE_NAME.Contains("Tahiti") - || _openClSubset._CL_DEVICE_NAME.Contains("Tonga"))) { - UseOptimizedVersion = false; - Helpers.ConsolePrint("AmdGpuDevice", "GPU (" + _openClSubset._CL_DEVICE_NAME + ") is optimized => NOO!"); - } else { - UseOptimizedVersion = true; - Helpers.ConsolePrint("AmdGpuDevice", "GPU (" + _openClSubset._CL_DEVICE_NAME + ") is optimized => YES!"); - } + //if (isOldDriver) { + // UseOptimizedVersion = false; + // Helpers.ConsolePrint("AmdGpuDevice", "GPU (" + _openClSubset._CL_DEVICE_NAME + ") is optimized => NOO! OLD DRIVER."); + //} else if (!( _openClSubset._CL_DEVICE_NAME.Contains("Bonaire") + // || _openClSubset._CL_DEVICE_NAME.Contains("Fiji") + // || _openClSubset._CL_DEVICE_NAME.Contains("Hawaii") + // || _openClSubset._CL_DEVICE_NAME.Contains("Pitcairn") + // || _openClSubset._CL_DEVICE_NAME.Contains("Tahiti") + // || _openClSubset._CL_DEVICE_NAME.Contains("Tonga"))) { + // UseOptimizedVersion = false; + // Helpers.ConsolePrint("AmdGpuDevice", "GPU (" + _openClSubset._CL_DEVICE_NAME + ") is optimized => NOO!"); + //} else { + // UseOptimizedVersion = true; + // Helpers.ConsolePrint("AmdGpuDevice", "GPU (" + _openClSubset._CL_DEVICE_NAME + ") is optimized => YES!"); + //} } - private bool _isEtherumCapable = false; - private bool _isEtherumCapableInit = false; public bool IsEtherumCapable() { - if (!_isEtherumCapableInit) { - _isEtherumCapableInit = true; - // check if 2GB device memory - _isEtherumCapable = _openClSubset._CL_DEVICE_GLOBAL_MEM_SIZE >= ComputeDevice.MEMORY_2GB; - } - return _isEtherumCapable; + return _openClSubset._CL_DEVICE_GLOBAL_MEM_SIZE >= ComputeDevice.MEMORY_3GB; } } } diff --git a/NiceHashMiner/Devices/CPUUtils.cs b/NiceHashMiner/Devices/CPUUtils.cs new file mode 100644 index 0000000..e0b8924 --- /dev/null +++ b/NiceHashMiner/Devices/CPUUtils.cs @@ -0,0 +1,65 @@ +using NiceHashMiner.Configs; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Devices { + public static class CPUUtils { + // this is the order we check and initialize if automatic + private static CPUExtensionType[] _detectOrder = new CPUExtensionType[] { + CPUExtensionType.AVX2_AES, + CPUExtensionType.AVX2, + CPUExtensionType.AVX_AES, + CPUExtensionType.AVX, + CPUExtensionType.AES, + CPUExtensionType.SSE2, // disabled + }; + + /// + /// HasExtensionSupport checks CPU extensions support, if type automatic just return false. + /// + /// + /// False if type Automatic otherwise True if supported + private static bool HasExtensionSupport(CPUExtensionType type) { + switch (type) { + case CPUExtensionType.AVX2_AES: return (CPUID.SupportsAVX2() == 1) && (CPUID.SupportsAES() == 1); + case CPUExtensionType.AVX2: return CPUID.SupportsAVX2() == 1; + case CPUExtensionType.AVX_AES: return (CPUID.SupportsAVX() == 1) && (CPUID.SupportsAES() == 1); + case CPUExtensionType.AVX: return CPUID.SupportsAVX() == 1; + case CPUExtensionType.AES: return CPUID.SupportsAES() == 1; + case CPUExtensionType.SSE2: return CPUID.SupportsSSE2() == 1; + default: // CPUExtensionType.Automatic + break; + } + return false; + } + + ///// + ///// Returns most performant CPU extension based on settings. + ///// Returns automatic if NO extension is avaliable + ///// + ///// + //public static CPUExtensionType GetMostOptimized() { + // if (ConfigManager.GeneralConfig.ForceCPUExtension == CPUExtensionType.Automatic) { + // for (int i = 0; i < _detectOrder.Length; ++i) { + // if (HasExtensionSupport(_detectOrder[i])) { + // return _detectOrder[i]; + // } + // } + // } else if (HasExtensionSupport(ConfigManager.GeneralConfig.ForceCPUExtension)) { + // return ConfigManager.GeneralConfig.ForceCPUExtension; + // } + // return CPUExtensionType.Automatic; + //} + + /// + /// Checks if CPU mining is capable, CPU must have AES support + /// + /// + public static bool IsCPUMiningCapable() { + return HasExtensionSupport(CPUExtensionType.AES); + } + } +} diff --git a/NiceHashMiner/Devices/CUDA_Unsupported.cs b/NiceHashMiner/Devices/CUDA_Unsupported.cs new file mode 100644 index 0000000..1e699f7 --- /dev/null +++ b/NiceHashMiner/Devices/CUDA_Unsupported.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Devices { + public static class CUDA_Unsupported { + private static List SM_1_0 = new List() { + "GeForce 8800 Ultra", + "GeForce 8800 GTX", + "GeForce 8800 GTS", + "Quadro FX 5600", + "Quadro FX 4600", + "Quadro Plex 2100 S4", + "Tesla C870", + "Tesla D870", + "Tesla S870", + }; + private static List SM_1_1 = new List() { + "GeForce GTS 250", + "GeForce 9800 GX2", + "GeForce 9800 GTX", + "GeForce 9800 GT", + "GeForce 8800 GTS", + "GeForce 8800 GT", + "GeForce 9600 GT", + "GeForce 9500 GT", + "GeForce 9400 GT", + "GeForce 8600 GTS", + "GeForce 8600 GT", + "GeForce 8500 GT", + "GeForce G110M", + "GeForce 9300M GS", + "GeForce 9200M GS", + "GeForce 9100M G", + "GeForce 8400M GT","GeForce G105M", + "Quadro FX 4700 X2", + "Quadro FX 3700", + "Quadro FX 1800", + "Quadro FX 1700", + "Quadro FX 580", + "Quadro FX 570", + "Quadro FX 470", + "Quadro FX 380", + "Quadro FX 370", + "Quadro FX 370 Low Profile", + "Quadro NVS 450", + "Quadro NVS 420", + "Quadro NVS 290", + "Quadro NVS 295", + "Quadro Plex 2100 D4", + "Quadro FX 3800M", + "Quadro FX 3700M", + "Quadro FX 3600M", + "Quadro FX 2800M", + "Quadro FX 2700M", + "Quadro FX 1700M", + "Quadro FX 1600M", + "Quadro FX 770M", + "Quadro FX 570M", + "Quadro FX 370M", + "Quadro FX 360M", + "Quadro NVS 320M", + "Quadro NVS 160M", + "Quadro NVS 150M", + "Quadro NVS 140M", + "Quadro NVS 135M", + "Quadro NVS 130M", + "Quadro NVS 450", + "Quadro NVS 420", + "Quadro NVS 295", + }; + private static List SM_1_2 = new List() { + "GeForce GT 340", + "GeForce GT 330", + "GeForce GT 320", + "GeForce 315", + "GeForce 310", + "GeForce GT 240", + "GeForce GT 220", + "GeForce 210", + "GeForce GTS 360M", + "GeForce GTS 350M", + "GeForce GT 335M", + "GeForce GT 330M", + "GeForce GT 325M", + "GeForce GT 240M", + "GeForce G210M", + "GeForce 310M", + "GeForce 305M", + "Quadro FX 380 Low Profile", + "Nvidia NVS 300", + "Quadro FX 1800M", + "Quadro FX 880M", + "Quadro FX 380M", + "Nvidia NVS 300", + "NVS 5100M", + "NVS 3100M", + "NVS 2100M", + "ION", + }; + private static List SM_1_3 = new List() { + "GeForce GTX 295", + "GTX 285", + "GTX 280", + "GeForce GTX 275", + "GeForce GTX 260", + "Quadro FX 5800", + "Quadro FX 4800", + "Quadro FX 3800", + "Quadro CX", + "Quadro Plex 2200 D2", + "Tesla C1060", + "Tesla S1070", + "Tesla M1060", + }; + private static List SM_2_0 = new List() { + "GeForce GTX 590", + "GeForce GTX 580", + "GeForce GTX 570", + "GeForce GTX 480", + "GeForce GTX 470", + "GeForce GTX 465", + "GeForce GTX 480M", + "Quadro 6000", + "Quadro 5000", + "Quadro 4000", + "Quadro Plex 7000", + "Quadro 5010M", + "Quadro 5000M", + "Tesla C2075", + "Tesla C2050", + "Tesla C2070", + "Tesla M2050", + "Tesla M2070", + "Tesla M2075", + "Tesla M2090", + }; + + private static bool ContainsSM(List list, string text) { + foreach(var el in list) { + if(text.Contains(el)) { + return true; + } + } + return false; + } + + public static bool IsSupported(string text) { + if (ContainsSM(SM_1_0, text)) { + return false; + } + if (ContainsSM(SM_1_1, text)) { + return false; + } + if (ContainsSM(SM_1_2, text)) { + return false; + } + if (ContainsSM(SM_1_3, text)) { + return false; + } + if (ContainsSM(SM_2_0, text)) { + return false; + } + + return true; + } + } +} diff --git a/NiceHashMiner/Devices/ComputeDevice.cs b/NiceHashMiner/Devices/ComputeDevice.cs index 7531b87..0efa106 100644 --- a/NiceHashMiner/Devices/ComputeDevice.cs +++ b/NiceHashMiner/Devices/ComputeDevice.cs @@ -5,160 +5,121 @@ using NiceHashMiner.Enums; using System.Security.Cryptography; using NiceHashMiner.Configs; +using NiceHashMiner.Configs.Data; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners; namespace NiceHashMiner.Devices { - [Serializable] public class ComputeDevice { - //[JsonIgnore] - //readonly public int PlatformId; - - [JsonIgnore] readonly public int ID; - [JsonIgnore] - readonly public string Group; - public string Name { get; set; } // to identify equality; - [JsonIgnore] - readonly public string _nameNoNums; + readonly public string Name; // { get; set; } // name count is the short name for displaying in moning groups - [JsonIgnore] readonly public string NameCount; public bool Enabled; - [JsonIgnore] - public readonly bool IsEtherumCapale; - - [JsonIgnore] - public string DeviceGroupString { get; private set; } - [JsonIgnore] readonly public DeviceGroupType DeviceGroupType; + // CPU, NVIDIA, AMD + readonly public DeviceType DeviceType; // UUID now used for saving readonly public string UUID; - // CPU, NVIDIA, AMD - [JsonIgnore] - public DeviceType DeviceType { get; private set; } - [JsonIgnore] - public string BenchmarkCopyUUID { get; set; } + // CPU extras + readonly public int Threads; + readonly public ulong AffinityMask; - [JsonIgnore] - public static readonly ulong MEMORY_2GB = 2147483648; + // GPU extras + public readonly ulong GpuRam; + public readonly bool IsEtherumCapale; + public static readonly ulong MEMORY_3GB = 3221225472; - [JsonIgnore] - CudaDevice _cudaDevice = null; - [JsonIgnore] - AmdGpuDevice _amdDevice = null; // sgminer extra quickfix - [JsonIgnore] - public bool IsOptimizedVersion { get; private set; } - [JsonIgnore] - public string Codename { get; private set; } - - // temp value for grouping new profits - [JsonIgnore] - public Algorithm MostProfitableAlgorithm { get; set; } + //public readonly bool IsOptimizedVersion; + public readonly string Codename; + public readonly string InfSection; + // amd has some algos not working with new drivers + public readonly bool DriverDisableAlgos; - [JsonIgnore] - public DeviceBenchmarkConfig DeviceBenchmarkConfig { get; private set; } + private List AlgorithmSettings; - [JsonIgnore] - [field: NonSerialized] - public NiceHashMiner.Forms.Components.DevicesListViewEnableControl.ComputeDeviceEnabledOption ComputeDeviceEnabledOption { get; set; } - - // used for ewverythinf - readonly public static List AllAvaliableDevices = new List(); - // used for numbering - readonly public static List UniqueAvaliableDevices = new List(); - - private static int CPUCount = 0; - private static int GPUCount = 0; + public string BenchmarkCopyUUID { get; set; } - [JsonConstructor] - public ComputeDevice(int id, string group, string name, string uuid, bool enabled = true) { + // Fake dev + public ComputeDevice(int id) { ID = id; - Group = group; - Name = name; - _nameNoNums = name; - UUID = uuid; - Enabled = enabled; - } - - private void InitGlobalsList(bool addToGlobalList) { - if (addToGlobalList) { - // add to all devices - AllAvaliableDevices.Add(this); - // compare new device with unique list scope - { - bool isNewUnique = true; - foreach (var d in UniqueAvaliableDevices) { - if (this.Name == d.Name) { - isNewUnique = false; - break; - } - } - if (isNewUnique) { - UniqueAvaliableDevices.Add(this); - } - } - // add to group manager - ComputeDeviceGroupManager.Instance.AddDevice(this); - } + Name = "fake_" + id; + NameCount = Name; + Enabled = true; + DeviceType = DeviceType.CPU; + DeviceGroupType = DeviceGroupType.NONE; + IsEtherumCapale = false; + //IsOptimizedVersion = false; + Codename = "fake"; + UUID = GetUUID(ID, GroupNames.GetGroupName(DeviceGroupType, ID), Name, DeviceGroupType); + GpuRam = 0; } // CPU - public ComputeDevice(int id, string group, string name, bool addToGlobalList = false, bool enabled = true) + public ComputeDevice(int id, string group, string name, int threads, ulong affinityMask, int CPUCount) { ID = id; - Group = group; Name = name; - _nameNoNums = name; - Enabled = enabled; - DeviceGroupType = GroupNames.GetType(Group); - DeviceGroupString = GroupNames.GetNameGeneral(DeviceGroupType); + Threads = threads; + AffinityMask = affinityMask; + Enabled = true; + DeviceGroupType = DeviceGroupType.CPU; DeviceType = DeviceType.CPU; - InitGlobalsList(addToGlobalList); - NameCount = String.Format(International.GetText("ComputeDevice_Short_Name_CPU"), ++CPUCount); - UUID = GetUUID(ID, Group, Name, DeviceGroupType); + NameCount = String.Format(International.GetText("ComputeDevice_Short_Name_CPU"), CPUCount); + UUID = GetUUID(ID, GroupNames.GetGroupName(DeviceGroupType, ID), Name, DeviceGroupType); + AlgorithmSettings = GroupAlgorithms.CreateForDeviceList(this); + IsEtherumCapale = false; + GpuRam = 0; } // GPU NVIDIA - public ComputeDevice(CudaDevice cudaDevice, string group, bool addToGlobalList = false, bool enabled = true) { - _cudaDevice = cudaDevice; + int _SM_major = -1; + int _SM_minor = -1; + public ComputeDevice(CudaDevice cudaDevice, DeviceGroupType group, int GPUCount) { + _SM_major = cudaDevice.SM_major; + _SM_minor = cudaDevice.SM_minor; ID = (int)cudaDevice.DeviceID; - Group = group; Name = cudaDevice.GetName(); - _nameNoNums = cudaDevice.GetName(); - Enabled = enabled; - DeviceGroupType = GroupNames.GetType(Group); - DeviceGroupString = GroupNames.GetNameGeneral(DeviceGroupType); + Enabled = true; + DeviceGroupType = group; IsEtherumCapale = cudaDevice.IsEtherumCapable(); DeviceType = DeviceType.NVIDIA; - InitGlobalsList(addToGlobalList); - NameCount = String.Format(International.GetText("ComputeDevice_Short_Name_NVIDIA_GPU"), ++GPUCount); + NameCount = String.Format(International.GetText("ComputeDevice_Short_Name_NVIDIA_GPU"), GPUCount); UUID = cudaDevice.UUID; + AlgorithmSettings = GroupAlgorithms.CreateForDeviceList(this); + GpuRam = cudaDevice.DeviceGlobalMemory; } + public bool IsSM50() { return _SM_major == 5 && _SM_minor == 0; } + // GPU AMD - public ComputeDevice(AmdGpuDevice amdDevice, bool addToGlobalList = false, bool enabled = true) { - _amdDevice = amdDevice; + public ComputeDevice(AmdGpuDevice amdDevice, int GPUCount, bool isDetectionFallback) { ID = amdDevice.DeviceID; DeviceGroupType = DeviceGroupType.AMD_OpenCL; - Group = GroupNames.GetName(DeviceGroupType.AMD_OpenCL); - DeviceGroupString = GroupNames.GetNameGeneral(DeviceGroupType); Name = amdDevice.DeviceName; - _nameNoNums = amdDevice.DeviceName; - Enabled = enabled; + Enabled = true; IsEtherumCapale = amdDevice.IsEtherumCapable(); DeviceType = DeviceType.AMD; - InitGlobalsList(addToGlobalList); - NameCount = String.Format(International.GetText("ComputeDevice_Short_Name_AMD_GPU"), ++GPUCount); - UUID = amdDevice.UUID; + NameCount = String.Format(International.GetText("ComputeDevice_Short_Name_AMD_GPU"), GPUCount); + if (isDetectionFallback) { + UUID = GetUUID(ID, GroupNames.GetGroupName(DeviceGroupType, ID), Name, DeviceGroupType); + } else { + UUID = amdDevice.UUID; + } // sgminer extra - IsOptimizedVersion = amdDevice.UseOptimizedVersion; + //IsOptimizedVersion = amdDevice.UseOptimizedVersion; Codename = amdDevice.Codename; + InfSection = amdDevice.InfSection; + AlgorithmSettings = GroupAlgorithms.CreateForDeviceList(this); + DriverDisableAlgos = amdDevice.DriverDisableAlgos; + GpuRam = amdDevice.DeviceGlobalMemory; } // combines long and short name @@ -166,73 +127,138 @@ public string GetFullName() { return String.Format(International.GetText("ComputeDevice_Full_Device_Name"), NameCount, Name); } - // TODO add file check and stuff like that - public void SetDeviceBenchmarkConfig(DeviceBenchmarkConfig deviceBenchmarkConfig) { + public Algorithm GetAlgorithm(MinerBaseType MinerBaseType, AlgorithmType AlgorithmType) { + int toSetIndex = this.AlgorithmSettings.FindIndex((a) => a.NiceHashID == AlgorithmType && a.MinerBaseType == MinerBaseType); + if (toSetIndex > -1) { + return this.AlgorithmSettings[toSetIndex]; + } + return null; + } - DeviceBenchmarkConfig = deviceBenchmarkConfig; - // check initialization - if (!DeviceBenchmarkConfig.IsAlgorithmSettingsInit) { - DeviceBenchmarkConfig.IsAlgorithmSettingsInit = true; - // only AMD has extra initialization - if (_amdDevice != null) { - // Check for optimized version - if (_amdDevice.UseOptimizedVersion) { - DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.Qubit].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 1024 --thread-concurrency 0 --worksize 64 --gpu-threads 1" + AmdGpuDevice.TemperatureParam; - DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.Quark].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 1024 --thread-concurrency 0 --worksize 64 --gpu-threads 1" + AmdGpuDevice.TemperatureParam; - DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.Lyra2REv2].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 512 --thread-concurrency 0 --worksize 64 --gpu-threads 1" + AmdGpuDevice.TemperatureParam; - } else { - // this is not the same as the constructor values?? check! - DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.Qubit].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 64 --thread-concurrency 0 --worksize 128 --gpu-threads 4" + AmdGpuDevice.TemperatureParam; - DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.Quark].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 64 --thread-concurrency 0 --worksize 256 --gpu-threads 1" + AmdGpuDevice.TemperatureParam; - DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.Lyra2REv2].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 64 --thread-concurrency 0 --worksize 64 --gpu-threads 2" + AmdGpuDevice.TemperatureParam; - } - if (!_amdDevice.Codename.Contains("Tahiti")) { - DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.NeoScrypt].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 2 --thread-concurrency 8192 --worksize 64 --gpu-threads 2" + AmdGpuDevice.TemperatureParam; - Helpers.ConsolePrint("ComputeDevice", "The GPU detected (" + _amdDevice.Codename + ") is not Tahiti. Changing default gpu-threads to 2."); - } - } - // CUDA extra initializations - if (_cudaDevice != null) { - if (DeviceBenchmarkConfig.AlgorithmSettings.ContainsKey(AlgorithmType.CryptoNight)) { - var CryptoNightAlgo = DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.CryptoNight]; - if (CryptoNightAlgo.ExtraLaunchParameters == "") { - if (_cudaDevice.SM_major >= 5) { - CryptoNightAlgo.ExtraLaunchParameters = "--bsleep=0 --bfactor=0 --launch=32x" + _cudaDevice.SMX.ToString(); - } - } - } + //public Algorithm GetAlgorithm(string algoID) { + // int toSetIndex = this.AlgorithmSettings.FindIndex((a) => a.AlgorithmStringID == algoID); + // if (toSetIndex > -1) { + // return this.AlgorithmSettings[toSetIndex]; + // } + // return null; + //} + + public void CopyBenchmarkSettingsFrom(ComputeDevice copyBenchCDev) { + foreach (var copyFromAlgo in copyBenchCDev.AlgorithmSettings) { + var setAlgo = GetAlgorithm(copyFromAlgo.MinerBaseType, copyFromAlgo.NiceHashID); + if (setAlgo != null) { + setAlgo.BenchmarkSpeed = copyFromAlgo.BenchmarkSpeed; + setAlgo.ExtraLaunchParameters = copyFromAlgo.ExtraLaunchParameters; + setAlgo.LessThreads = copyFromAlgo.LessThreads; } } } - public void CopyBenchmarkSettingsFrom(ComputeDevice copyBenchCDev) { - foreach (var copyAlgSpeeds in copyBenchCDev.DeviceBenchmarkConfig.AlgorithmSettings) { - if (this.DeviceBenchmarkConfig.AlgorithmSettings.ContainsKey(copyAlgSpeeds.Key)) { - var setAlgo = this.DeviceBenchmarkConfig.AlgorithmSettings[copyAlgSpeeds.Key]; - setAlgo.BenchmarkSpeed = copyAlgSpeeds.Value.BenchmarkSpeed; - setAlgo.ExtraLaunchParameters = copyAlgSpeeds.Value.ExtraLaunchParameters; - setAlgo.Intensity = copyAlgSpeeds.Value.Intensity; - setAlgo.LessThreads = copyAlgSpeeds.Value.LessThreads; + #region Config Setters/Getters + // settings + // setters + public void SetFromComputeDeviceConfig(ComputeDeviceConfig config) { + if (config != null && config.UUID == UUID) { + this.Enabled = config.Enabled; + } + } + public void SetAlgorithmDeviceConfig(DeviceBenchmarkConfig config) { + if (config != null && config.DeviceUUID == UUID && config.AlgorithmSettings != null) { + this.AlgorithmSettings = GroupAlgorithms.CreateForDeviceList(this); + foreach (var conf in config.AlgorithmSettings) { + var setAlgo = GetAlgorithm(conf.MinerBaseType, conf.NiceHashID); + if (setAlgo != null) { + setAlgo.BenchmarkSpeed = conf.BenchmarkSpeed; + setAlgo.ExtraLaunchParameters = conf.ExtraLaunchParameters; + setAlgo.Enabled = conf.Enabled; + setAlgo.LessThreads = conf.LessThreads; + } } } } + // getters + public ComputeDeviceConfig GetComputeDeviceConfig() { + ComputeDeviceConfig ret = new ComputeDeviceConfig(); + ret.Enabled = this.Enabled; + ret.Name = this.Name; + ret.UUID = this.UUID; + return ret; + } + public DeviceBenchmarkConfig GetAlgorithmDeviceConfig() { + DeviceBenchmarkConfig ret = new DeviceBenchmarkConfig(); + ret.DeviceName = this.Name; + ret.DeviceUUID = this.UUID; + // init algo settings + foreach (var algo in this.AlgorithmSettings) { + // create/setup + AlgorithmConfig conf = new AlgorithmConfig(); + conf.Name = algo.AlgorithmStringID; + conf.NiceHashID = algo.NiceHashID; + conf.MinerBaseType = algo.MinerBaseType; + conf.MinerName = algo.MinerName; // TODO probably not needed + conf.BenchmarkSpeed = algo.BenchmarkSpeed; + conf.ExtraLaunchParameters = algo.ExtraLaunchParameters; + conf.Enabled = algo.Enabled; + conf.LessThreads = algo.LessThreads; + // insert + ret.AlgorithmSettings.Add(conf); + } + return ret; + } + #endregion Config Setters/Getters - // static methods - public static ComputeDevice GetDeviceWithUUID(string uuid) { - foreach (var dev in AllAvaliableDevices) { - if (uuid == dev.UUID) return dev; + public List GetAlgorithmSettings() { + // hello state + var algos = GetAlgorithmSettingsThirdParty(ConfigManager.GeneralConfig.Use3rdPartyMiners); + + var retAlgos = MinerPaths.GetAndInitAlgorithmsMinerPaths(algos, this);; + + // NVIDIA + if (this.DeviceGroupType == DeviceGroupType.NVIDIA_5_x || this.DeviceGroupType == DeviceGroupType.NVIDIA_6_x) { + retAlgos = retAlgos.FindAll((a) => a.MinerBaseType != MinerBaseType.nheqminer); + } else if (this.DeviceType == DeviceType.NVIDIA) { + retAlgos = retAlgos.FindAll((a) => a.MinerBaseType != MinerBaseType.eqm); } - return null; + + // sort by algo + retAlgos.Sort((a_1, a_2) => (a_1.NiceHashID - a_2.NiceHashID) != 0 ? (a_1.NiceHashID - a_2.NiceHashID) : (a_1.MinerBaseType - a_2.MinerBaseType)); + + return retAlgos; } - public static int GetEnabledDeviceNameCount(string name) { - int count = 0; - foreach (var dev in AllAvaliableDevices) { - if (dev.Enabled && name == dev.Name) ++count; + public List GetAlgorithmSettingsFastest() { + // hello state + var algosTmp = GetAlgorithmSettings(); + Dictionary sortDict = new Dictionary(); + foreach (var algo in algosTmp) { + var algoKey = algo.NiceHashID; + if (sortDict.ContainsKey(algoKey)) { + if (sortDict[algoKey].BenchmarkSpeed < algo.BenchmarkSpeed) { + sortDict[algoKey] = algo; + } + } else { + sortDict[algoKey] = algo; + } + } + List retAlgos = new List(); + foreach (var fastestAlgo in sortDict.Values) { + retAlgos.Add(fastestAlgo); } - return count; + + return retAlgos; } + private List GetAlgorithmSettingsThirdParty(Use3rdPartyMiners use3rdParty) { + if (use3rdParty == Use3rdPartyMiners.YES) { + return this.AlgorithmSettings; + } + var third_party_miners = new List() { MinerBaseType.ClaymoreAMD, MinerBaseType.OptiminerAMD }; + + return this.AlgorithmSettings.FindAll((a) => third_party_miners.IndexOf(a.MinerBaseType) == -1); + } + + // static methods + private static string GetUUID(int id, string group, string name, DeviceGroupType deviceGroupType) { var SHA256 = new SHA256Managed(); var hash = new StringBuilder(); @@ -245,34 +271,8 @@ private static string GetUUID(int id, string group, string name, DeviceGroupType return "GEN-" + hash.ToString(); } - public static string GetNameForUUID(string uuid) { - foreach (var dev in AllAvaliableDevices) { - if (uuid == dev.UUID) { - return dev.Name; - } - } - return International.GetText("ComputeDevice_Get_With_UUID_NONE"); - } - - public static List GetSameDevicesTypeAsDeviceWithUUID(string uuid) { - List sameTypes = new List(); - var compareDev = GetDeviceWithUUID(uuid); - foreach (var dev in AllAvaliableDevices) { - if (uuid != dev.UUID && compareDev.DeviceType == dev.DeviceType) { - sameTypes.Add(GetDeviceWithUUID(dev.UUID)); - } - } - return sameTypes; - } - - public static ComputeDevice GetCurrentlySelectedComputeDevice(int index, bool unique) { - //// TODO index checking - //if (unique) { - // return ComputeDevice.UniqueAvaliableDevices[index]; - //} else { - // return ComputeDevice.AllAvaliableDevices[index]; - //} - return ComputeDevice.AllAvaliableDevices[index]; + internal bool IsAlgorithmSettingsInitialized() { + return this.AlgorithmSettings != null; } } } diff --git a/NiceHashMiner/Devices/ComputeDeviceGroupManager.cs b/NiceHashMiner/Devices/ComputeDeviceGroupManager.cs deleted file mode 100644 index 2adb5d3..0000000 --- a/NiceHashMiner/Devices/ComputeDeviceGroupManager.cs +++ /dev/null @@ -1,61 +0,0 @@ -using NiceHashMiner.Enums; -using System; -using System.Collections.Generic; -using System.Text; - -namespace NiceHashMiner.Devices -{ - /// - /// ComputeDeviceGroupManager class manages all the avaliable groups. - /// For now used only for the settings. - /// - public class ComputeDeviceGroupManager : BaseLazySingleton - { - - private Dictionary _groupCount; - - DeviceGroupType[] _gpuGroups = new DeviceGroupType[] { - DeviceGroupType.AMD_OpenCL, - DeviceGroupType.NVIDIA_2_1, - DeviceGroupType.NVIDIA_3_x, - DeviceGroupType.NVIDIA_5_x, - DeviceGroupType.NVIDIA_6_x - }; - - protected ComputeDeviceGroupManager() - : base() { - - _groupCount = new Dictionary(); - for (DeviceGroupType type = 0; type < DeviceGroupType.LAST; ++type) { - _groupCount.Add(type, 0); - } - } - - public int GetGroupCount(DeviceGroupType type) { - return _groupCount[type]; - } - - public void AddDevice(ComputeDevice computeDevice) { - _groupCount[computeDevice.DeviceGroupType]++; - } - - public void DisableCpuGroup() { - foreach (var device in ComputeDevice.AllAvaliableDevices) { - if (device.DeviceGroupType == DeviceGroupType.CPU) { - device.Enabled = false; - } - } - } - public bool ContainsGPUs { - get { - foreach (var groupType in _gpuGroups) { - if (_groupCount[groupType] > 0) { - return true; - } - } - return false; - } - } - - } -} diff --git a/NiceHashMiner/Devices/ComputeDeviceManager.cs b/NiceHashMiner/Devices/ComputeDeviceManager.cs new file mode 100644 index 0000000..3766e49 --- /dev/null +++ b/NiceHashMiner/Devices/ComputeDeviceManager.cs @@ -0,0 +1,1012 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using NiceHashMiner.Configs; +using NiceHashMiner.Interfaces; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners; +using System.Diagnostics; +using Newtonsoft.Json; +using ATI.ADL; +using System.Runtime.InteropServices; +using System.Management; +using System.IO; +using System.Globalization; +using NiceHashMiner.Utils; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Net20_backport; + +namespace NiceHashMiner.Devices +{ + /// + /// ComputeDeviceManager class is used to query ComputeDevices avaliable on the system. + /// Query CPUs, GPUs [Nvidia, AMD] + /// + public class ComputeDeviceManager + { + public static class Query { + const string TAG = "ComputeDeviceManager.Query"; + + // format 372.54; + private class NVIDIA_SMI_DRIVER { + public NVIDIA_SMI_DRIVER(int left, int right) { + leftPart = left; + rightPart = right; + } + public bool IsLesserVersionThan(NVIDIA_SMI_DRIVER b) { + if(leftPart < b.leftPart) { + return true; + } + if (leftPart == b.leftPart && getRightVal(rightPart) < getRightVal(b.rightPart)) { + return true; + } + return false; + } + + public override string ToString() { + return String.Format("{0}.{1}", leftPart, rightPart); + } + + public int leftPart; + public int rightPart; + private int getRightVal(int val) { + if(val >= 10) { + return val; + } + return val * 10; + } + } + + static readonly NVIDIA_SMI_DRIVER NVIDIA_RECOMENDED_DRIVER = new NVIDIA_SMI_DRIVER(372, 54); // 372.54; + static readonly NVIDIA_SMI_DRIVER NVIDIA_MIN_DETECTION_DRIVER = new NVIDIA_SMI_DRIVER(362, 61); // 362.61; + static NVIDIA_SMI_DRIVER _currentNvidiaSMIDriver = new NVIDIA_SMI_DRIVER(-1, -1); + static NVIDIA_SMI_DRIVER INVALID_SMI_DRIVER = new NVIDIA_SMI_DRIVER(-1, -1); + + // naming purposes + private static int CPUCount = 0; + private static int GPUCount = 0; + + static private NVIDIA_SMI_DRIVER GetNvidiaSMIDriver() { + if (WindowsDisplayAdapters.HasNvidiaVideoController()) { + string stdOut, stdErr, args, smiPath; + stdOut = stdErr = args = String.Empty; + smiPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\NVIDIA Corporation\\NVSMI\\nvidia-smi.exe"; + if (smiPath.Contains(" (x86)")) smiPath = smiPath.Replace(" (x86)", ""); + try { + Process P = new Process(); + P.StartInfo.FileName = smiPath; + P.StartInfo.UseShellExecute = false; + P.StartInfo.RedirectStandardOutput = true; + P.StartInfo.RedirectStandardError = true; + P.StartInfo.CreateNoWindow = true; + P.Start(); + P.WaitForExit(); + + stdOut = P.StandardOutput.ReadToEnd(); + stdErr = P.StandardError.ReadToEnd(); + + const string FIND_STRING = "Driver Version: "; + using (StringReader reader = new StringReader(stdOut)) { + string line = string.Empty; + do { + line = reader.ReadLine(); + if (line != null) { + if(line.Contains(FIND_STRING)) { + int start = line.IndexOf(FIND_STRING); + string driverVer = line.Substring(start, start + 7); + driverVer = driverVer.Replace(FIND_STRING, "").Substring(0, 7).Trim(); + double drVerDouble = Double.Parse(driverVer, CultureInfo.InvariantCulture); + int dot = driverVer.IndexOf("."); + int leftPart = Int32.Parse(driverVer.Substring(0, 3)); + int rightPart = Int32.Parse(driverVer.Substring(4, 2)); + return new NVIDIA_SMI_DRIVER(leftPart, rightPart); + } + } + } while (line != null); + } + + } catch (Exception ex) { + Helpers.ConsolePrint(TAG, "GetNvidiaSMIDriver Exception: " + ex.Message); + return INVALID_SMI_DRIVER; + } + } + return INVALID_SMI_DRIVER; + } + + private static void showMessageAndStep(string infoMsg) { + if (MessageNotifier != null) MessageNotifier.SetMessageAndIncrementStep(infoMsg); + } + + public static IMessageNotifier MessageNotifier { get; private set; } + + public static void QueryDevices(IMessageNotifier messageNotifier) { + + // check NVIDIA nvml.dll and copy over scope + { + string nvmlPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\NVIDIA Corporation\\NVSMI\\nvml.dll"; + if (nvmlPath.Contains(" (x86)")) nvmlPath = nvmlPath.Replace(" (x86)", ""); + if (File.Exists(nvmlPath)) { + string copyToPath = Directory.GetCurrentDirectory() + "\\nvml.dll"; + try { + File.Copy(nvmlPath, copyToPath, true); + Helpers.ConsolePrint(TAG, String.Format("Copy from {0} to {1} done", nvmlPath, copyToPath)); + } catch (Exception e) { + Helpers.ConsolePrint(TAG, "Copy nvml.dll failed: " + e.Message); + } + } + } + + + MessageNotifier = messageNotifier; + // #0 get video controllers, used for cross checking + WindowsDisplayAdapters.QueryVideoControllers(); + // Order important CPU Query must be first + // #1 CPU + CPU.QueryCPUs(); + // #2 CUDA + if (NVIDIA.IsSkipNVIDIA()) { + Helpers.ConsolePrint(TAG, "Skipping NVIDIA device detection, settings are set to disabled"); + } else { + showMessageAndStep(International.GetText("Compute_Device_Query_Manager_CUDA_Query")); + NVIDIA.QueryCudaDevices(); + } + // OpenCL and AMD + if (ConfigManager.GeneralConfig.DeviceDetection.DisableDetectionAMD) { + Helpers.ConsolePrint(TAG, "Skipping AMD device detection, settings set to disabled"); + showMessageAndStep(International.GetText("Compute_Device_Query_Manager_AMD_Query_Skip")); + } else { + // #3 OpenCL + showMessageAndStep(International.GetText("Compute_Device_Query_Manager_OpenCL_Query")); + OpenCL.QueryOpenCLDevices(); + // #4 AMD query AMD from OpenCL devices, get serial and add devices + AMD.QueryAMD(); + } + // #5 uncheck CPU if GPUs present, call it after we Query all devices + Group.UncheckedCPU(); + + // TODO update this to report undetected hardware + // #6 check NVIDIA, AMD devices count + int NVIDIA_count = 0; + { + int AMD_count = 0; + foreach (var vidCtrl in AvaliableVideoControllers) { + if(vidCtrl.Name.ToLower().Contains("nvidia") && CUDA_Unsupported.IsSupported(vidCtrl.Name)) { + NVIDIA_count += 1; + } else if (vidCtrl.Name.ToLower().Contains("nvidia")) { + Helpers.ConsolePrint(TAG, "Device not supported NVIDIA/CUDA device not supported " + vidCtrl.Name); + } + AMD_count += (vidCtrl.Name.ToLower().Contains("amd")) ? 1 : 0; + } + if (NVIDIA_count == CudaDevices.Count) { + Helpers.ConsolePrint(TAG, "Cuda NVIDIA/CUDA device count GOOD"); + } else { + Helpers.ConsolePrint(TAG, "Cuda NVIDIA/CUDA device count BAD!!!"); + } + if (AMD_count == amdGpus.Count) { + Helpers.ConsolePrint(TAG, "AMD GPU device count GOOD"); + } else { + Helpers.ConsolePrint(TAG, "AMD GPU device count BAD!!!"); + } + } + // allerts + _currentNvidiaSMIDriver = GetNvidiaSMIDriver(); + // if we have nvidia cards but no CUDA devices tell the user to upgrade driver + bool isNvidiaErrorShown = false; // to prevent showing twice + bool showWarning = ConfigManager.GeneralConfig.ShowDriverVersionWarning && WindowsDisplayAdapters.HasNvidiaVideoController(); + if (showWarning && CudaDevices.Count != NVIDIA_count && _currentNvidiaSMIDriver.IsLesserVersionThan(NVIDIA_MIN_DETECTION_DRIVER)) { + isNvidiaErrorShown = true; + var minDriver = NVIDIA_MIN_DETECTION_DRIVER.ToString(); + var recomendDrvier = NVIDIA_RECOMENDED_DRIVER.ToString(); + MessageBox.Show(String.Format(International.GetText("Compute_Device_Query_Manager_NVIDIA_Driver_Detection"), + minDriver, recomendDrvier), + International.GetText("Compute_Device_Query_Manager_NVIDIA_RecomendedDriver_Title"), + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + // recomended driver + if (showWarning && _currentNvidiaSMIDriver.IsLesserVersionThan(NVIDIA_RECOMENDED_DRIVER) && !isNvidiaErrorShown && _currentNvidiaSMIDriver.leftPart > -1) { + var recomendDrvier = NVIDIA_RECOMENDED_DRIVER.ToString(); + var nvdriverString = _currentNvidiaSMIDriver.leftPart > -1 ? String.Format(International.GetText("Compute_Device_Query_Manager_NVIDIA_Driver_Recomended_PART"), _currentNvidiaSMIDriver.ToString()) + : ""; + MessageBox.Show(String.Format(International.GetText("Compute_Device_Query_Manager_NVIDIA_Driver_Recomended"), + recomendDrvier, nvdriverString, recomendDrvier), + International.GetText("Compute_Device_Query_Manager_NVIDIA_RecomendedDriver_Title"), + MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + // get GPUs RAM sum + // bytes + Avaliable.NVIDIA_RAM_SUM = 0; + Avaliable.AMD_RAM_SUM = 0; + foreach (var dev in Avaliable.AllAvaliableDevices) { + if (dev.DeviceType == DeviceType.NVIDIA) { + Avaliable.NVIDIA_RAM_SUM += dev.GpuRam; + } else if (dev.DeviceType == DeviceType.AMD) { + Avaliable.AMD_RAM_SUM += dev.GpuRam; + } + } + double total_GPU_RAM = (Avaliable.NVIDIA_RAM_SUM + Avaliable.AMD_RAM_SUM) / 1024; // b to kb + double total_Sys_RAM = SystemSpecs.FreePhysicalMemory + SystemSpecs.FreeVirtualMemory; + // check + if (ConfigManager.GeneralConfig.ShowDriverVersionWarning && total_Sys_RAM < total_GPU_RAM * 0.6) { + Helpers.ConsolePrint(TAG, "virtual memory size BAD"); + MessageBox.Show(International.GetText("VirtualMemorySize_BAD"), + International.GetText("Warning_with_Exclamation"), + MessageBoxButtons.OK); + } else { + Helpers.ConsolePrint(TAG, "virtual memory size GOOD"); + } + + // #x remove reference + MessageNotifier = null; + } + + #region Helpers + private class VideoControllerData { + public string Name { get; set; } + public string Description { get; set; } + public string PNPDeviceID { get; set; } + public string DriverVersion { get; set; } + public string Status { get; set; } + public string InfSection { get; set; } // get arhitecture + public ulong AdapterRAM { get; set; } + } + private static List AvaliableVideoControllers = new List(); + static class WindowsDisplayAdapters { + + private static string SafeGetProperty(ManagementBaseObject mbo, string key) { + try { + object o = mbo.GetPropertyValue(key); + if(o != null) { + return o.ToString(); + } + } catch {} + + return "key is null"; + } + + public static void QueryVideoControllers() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(""); + stringBuilder.AppendLine("QueryVideoControllers: "); + ManagementObjectCollection moc = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_VideoController").Get(); + bool allVideoContollersOK = true; + foreach (var manObj in moc) { + ulong memTmp = 0; + //Int16 ram_Str = manObj["ProtocolSupported"] as Int16; manObj["AdapterRAM"] as string + UInt64.TryParse(SafeGetProperty(manObj, "AdapterRAM"), out memTmp); + var vidController = new VideoControllerData() { + Name = SafeGetProperty(manObj, "Name"), + Description = SafeGetProperty(manObj, "Description"), + PNPDeviceID = SafeGetProperty(manObj, "PNPDeviceID"), + DriverVersion = SafeGetProperty(manObj, "DriverVersion"), + Status = SafeGetProperty(manObj, "Status"), + InfSection = SafeGetProperty(manObj, "InfSection"), + AdapterRAM = memTmp + }; + stringBuilder.AppendLine("\tWin32_VideoController detected:"); + stringBuilder.AppendLine(String.Format("\t\tName {0}", vidController.Name)); + stringBuilder.AppendLine(String.Format("\t\tDescription {0}", vidController.Description)); + stringBuilder.AppendLine(String.Format("\t\tPNPDeviceID {0}", vidController.PNPDeviceID)); + stringBuilder.AppendLine(String.Format("\t\tDriverVersion {0}", vidController.DriverVersion)); + stringBuilder.AppendLine(String.Format("\t\tStatus {0}", vidController.Status)); + stringBuilder.AppendLine(String.Format("\t\tInfSection {0}", vidController.InfSection)); + stringBuilder.AppendLine(String.Format("\t\tAdapterRAM {0}", vidController.AdapterRAM)); + + // check if controller ok + if (allVideoContollersOK && !vidController.Status.ToLower().Equals("ok")) { + allVideoContollersOK = false; + } + + AvaliableVideoControllers.Add(vidController); + } + Helpers.ConsolePrint(TAG, stringBuilder.ToString()); + if (ConfigManager.GeneralConfig.ShowDriverVersionWarning && !allVideoContollersOK) { + string msg = International.GetText("QueryVideoControllers_NOT_ALL_OK_Msg"); + foreach (var vc in AvaliableVideoControllers) { + if (!vc.Status.ToLower().Equals("ok")) { + msg += Environment.NewLine + + String.Format(International.GetText("QueryVideoControllers_NOT_ALL_OK_Msg_Append"), vc.Name, vc.Status, vc.PNPDeviceID); + } + } + MessageBox.Show(msg, + International.GetText("QueryVideoControllers_NOT_ALL_OK_Title"), + MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } + + public static bool HasNvidiaVideoController() { + foreach (var vctrl in AvaliableVideoControllers) { + if (vctrl.Name.ToLower().Contains("nvidia")) return true; + } + return false; + } + } + + static class CPU { + public static void QueryCPUs() { + Helpers.ConsolePrint(TAG, "QueryCPUs START"); + // get all CPUs + Avaliable.CPUsCount = CPUID.GetPhysicalProcessorCount(); + Avaliable.IsHyperThreadingEnabled = CPUID.IsHypeThreadingEnabled(); + + Helpers.ConsolePrint(TAG, Avaliable.IsHyperThreadingEnabled ? "HyperThreadingEnabled = TRUE" : "HyperThreadingEnabled = FALSE"); + + // get all cores (including virtual - HT can benefit mining) + int ThreadsPerCPU = CPUID.GetVirtualCoresCount() / Avaliable.CPUsCount; + + if (!Helpers.InternalCheckIsWow64()) { + MessageBox.Show(International.GetText("Form_Main_msgbox_CPUMining64bitMsg"), + International.GetText("Warning_with_Exclamation"), + MessageBoxButtons.OK, MessageBoxIcon.Warning); + Avaliable.CPUsCount = 0; + } + + if (ThreadsPerCPU * Avaliable.CPUsCount > 64) { + MessageBox.Show(International.GetText("Form_Main_msgbox_CPUMining64CoresMsg"), + International.GetText("Warning_with_Exclamation"), + MessageBoxButtons.OK, MessageBoxIcon.Warning); + Avaliable.CPUsCount = 0; + } + + // TODO important move this to settings + int ThreadsPerCPUMask = ThreadsPerCPU; + Globals.ThreadsPerCPU = ThreadsPerCPU; + + if (CPUUtils.IsCPUMiningCapable()) { + if (Avaliable.CPUsCount == 1) { + Avaliable.AllAvaliableDevices.Add( + new ComputeDevice(0, "CPU0", CPUID.GetCPUName().Trim(), ThreadsPerCPU, (ulong)0, ++CPUCount) + ); + } else if (Avaliable.CPUsCount > 1) { + for (int i = 0; i < Avaliable.CPUsCount; i++) { + Avaliable.AllAvaliableDevices.Add( + new ComputeDevice(i, "CPU" + i, CPUID.GetCPUName().Trim(), ThreadsPerCPU, CPUID.CreateAffinityMask(i, ThreadsPerCPUMask), ++CPUCount) + ); + } + } + } + + Helpers.ConsolePrint(TAG, "QueryCPUs END"); + } + + } + + static List CudaDevices = new List(); + static class NVIDIA { + static string QueryCudaDevicesString = ""; + static private void QueryCudaDevicesOutputErrorDataReceived(object sender, DataReceivedEventArgs e) { + if (e.Data != null) { + QueryCudaDevicesString += e.Data; + } + } + + public static bool IsSkipNVIDIA() { + return ConfigManager.GeneralConfig.DeviceDetection.DisableDetectionNVIDIA; + } + + static public void QueryCudaDevices() { + Helpers.ConsolePrint(TAG, "QueryCudaDevices START"); + Process CudaDevicesDetection = new Process(); + CudaDevicesDetection.StartInfo.FileName = "CudaDeviceDetection.exe"; + CudaDevicesDetection.StartInfo.UseShellExecute = false; + CudaDevicesDetection.StartInfo.RedirectStandardError = true; + CudaDevicesDetection.StartInfo.RedirectStandardOutput = true; + CudaDevicesDetection.StartInfo.CreateNoWindow = true; + CudaDevicesDetection.OutputDataReceived += QueryCudaDevicesOutputErrorDataReceived; + CudaDevicesDetection.ErrorDataReceived += QueryCudaDevicesOutputErrorDataReceived; + + const int waitTime = 30 * 1000; // 30seconds + try { + if (!CudaDevicesDetection.Start()) { + Helpers.ConsolePrint(TAG, "CudaDevicesDetection process could not start"); + } else { + CudaDevicesDetection.BeginErrorReadLine(); + CudaDevicesDetection.BeginOutputReadLine(); + if (CudaDevicesDetection.WaitForExit(waitTime)) { + CudaDevicesDetection.Close(); + } + } + } catch (Exception ex) { + // TODO + Helpers.ConsolePrint(TAG, "CudaDevicesDetection threw Exception: " + ex.Message); + } finally { + if (QueryCudaDevicesString != "") { + try { + CudaDevices = JsonConvert.DeserializeObject>(QueryCudaDevicesString, Globals.JsonSettings); + } catch { } + } + } + if (CudaDevices != null && CudaDevices.Count != 0) { + Avaliable.HasNVIDIA = true; + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(""); + stringBuilder.AppendLine("CudaDevicesDetection:"); + foreach (var cudaDev in CudaDevices) { + // check sm vesrions + bool isUnderSM21; + { + bool isUnderSM2_major = cudaDev.SM_major < 2; + bool isUnderSM1_minor = cudaDev.SM_minor < 1; + isUnderSM21 = isUnderSM2_major && isUnderSM1_minor; + } + //bool isOverSM6 = cudaDev.SM_major > 6; + bool skip = isUnderSM21; + string skipOrAdd = skip ? "SKIPED" : "ADDED"; + string isDisabledGroupStr = ""; // TODO remove + string etherumCapableStr = cudaDev.IsEtherumCapable() ? "YES" : "NO"; + stringBuilder.AppendLine(String.Format("\t{0} device{1}:", skipOrAdd, isDisabledGroupStr)); + stringBuilder.AppendLine(String.Format("\t\tID: {0}", cudaDev.DeviceID.ToString())); + stringBuilder.AppendLine(String.Format("\t\tNAME: {0}", cudaDev.GetName())); + stringBuilder.AppendLine(String.Format("\t\tVENDOR: {0}", cudaDev.VendorName)); + stringBuilder.AppendLine(String.Format("\t\tUUID: {0}", cudaDev.UUID)); + stringBuilder.AppendLine(String.Format("\t\tSM: {0}", cudaDev.SMVersionString)); + stringBuilder.AppendLine(String.Format("\t\tMEMORY: {0}", cudaDev.DeviceGlobalMemory.ToString())); + stringBuilder.AppendLine(String.Format("\t\tETHEREUM: {0}", etherumCapableStr)); + + if (!skip) { + DeviceGroupType group; + switch (cudaDev.SM_major) { + case 2: + group = DeviceGroupType.NVIDIA_2_1; + break; + case 3: + group = DeviceGroupType.NVIDIA_3_x; + break; + case 5: + group = DeviceGroupType.NVIDIA_5_x; + break; + case 6: + group = DeviceGroupType.NVIDIA_6_x; + break; + default: + group = DeviceGroupType.NVIDIA_6_x; + break; + } + Avaliable.AllAvaliableDevices.Add( + new ComputeDevice(cudaDev, group, ++GPUCount) + ); + } + } + Helpers.ConsolePrint(TAG, stringBuilder.ToString()); + } else { + Helpers.ConsolePrint(TAG, "CudaDevicesDetection found no devices. CudaDevicesDetection returned: " + QueryCudaDevicesString); + } + Helpers.ConsolePrint(TAG, "QueryCudaDevices END"); + } + } + + class OpenCLJSONData_t { + public string PlatformName = "NONE"; + public int PlatformNum = 0; + public List Devices = new List(); + } + static List OpenCLJSONData = new List(); + static bool IsOpenCLQuerrySuccess = false; + static class OpenCL { + static string QueryOpenCLDevicesString = ""; + static private void QueryOpenCLDevicesOutputErrorDataReceived(object sender, DataReceivedEventArgs e) { + if (e.Data != null) { + QueryOpenCLDevicesString += e.Data; + } + } + + static public void QueryOpenCLDevices() { + Helpers.ConsolePrint(TAG, "QueryOpenCLDevices START"); + Process OpenCLDevicesDetection = new Process(); + OpenCLDevicesDetection.StartInfo.FileName = "AMDOpenCLDeviceDetection.exe"; + OpenCLDevicesDetection.StartInfo.UseShellExecute = false; + OpenCLDevicesDetection.StartInfo.RedirectStandardError = true; + OpenCLDevicesDetection.StartInfo.RedirectStandardOutput = true; + OpenCLDevicesDetection.StartInfo.CreateNoWindow = true; + OpenCLDevicesDetection.OutputDataReceived += QueryOpenCLDevicesOutputErrorDataReceived; + OpenCLDevicesDetection.ErrorDataReceived += QueryOpenCLDevicesOutputErrorDataReceived; + + const int waitTime = 30 * 1000; // 30seconds + try { + if (!OpenCLDevicesDetection.Start()) { + Helpers.ConsolePrint(TAG, "AMDOpenCLDeviceDetection process could not start"); + } else { + OpenCLDevicesDetection.BeginErrorReadLine(); + OpenCLDevicesDetection.BeginOutputReadLine(); + if (OpenCLDevicesDetection.WaitForExit(waitTime)) { + OpenCLDevicesDetection.Close(); + } + } + } catch (Exception ex) { + // TODO + Helpers.ConsolePrint(TAG, "AMDOpenCLDeviceDetection threw Exception: " + ex.Message); + } finally { + if (QueryOpenCLDevicesString != "") { + try { + OpenCLJSONData = JsonConvert.DeserializeObject>(QueryOpenCLDevicesString, Globals.JsonSettings); + } catch { + OpenCLJSONData = null; + } + } + } + + if (OpenCLJSONData == null) { + Helpers.ConsolePrint(TAG, "AMDOpenCLDeviceDetection found no devices. AMDOpenCLDeviceDetection returned: " + QueryOpenCLDevicesString); + } else { + IsOpenCLQuerrySuccess = true; + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(""); + stringBuilder.AppendLine("AMDOpenCLDeviceDetection found devices success:"); + foreach (var oclElem in OpenCLJSONData) { + stringBuilder.AppendLine(String.Format("\tFound devices for platform: {0}", oclElem.PlatformName)); + foreach (var oclDev in oclElem.Devices) { + stringBuilder.AppendLine("\t\tDevice:"); + stringBuilder.AppendLine(String.Format("\t\t\tDevice ID {0}", oclDev.DeviceID)); + stringBuilder.AppendLine(String.Format("\t\t\tDevice NAME {0}", oclDev._CL_DEVICE_NAME)); + stringBuilder.AppendLine(String.Format("\t\t\tDevice TYPE {0}", oclDev._CL_DEVICE_TYPE)); + } + } + Helpers.ConsolePrint(TAG, stringBuilder.ToString()); + } + Helpers.ConsolePrint(TAG, "QueryOpenCLDevices END"); + } + } + + static List amdGpus = new List(); + static class AMD { + static public void QueryAMD() { + const int AMD_VENDOR_ID = 1002; + Helpers.ConsolePrint(TAG, "QueryAMD START"); + + #region AMD driver check, ADL returns 0 + // check the driver version bool EnableOptimizedVersion = true; + Dictionary deviceDriverOld = new Dictionary(); + Dictionary deviceDriverNO_neoscrypt_lyra2re = new Dictionary(); + bool ShowWarningDialog = false; + + foreach (var vidContrllr in AvaliableVideoControllers) { + Helpers.ConsolePrint(TAG, String.Format("Checking AMD device (driver): {0} ({1})", vidContrllr.Name, vidContrllr.DriverVersion)); + + deviceDriverOld[vidContrllr.Name] = false; + deviceDriverNO_neoscrypt_lyra2re[vidContrllr.Name] = false; + Version sgminer_NO_neoscrypt_lyra2re = new Version("21.19.164.1"); + // TODO checking radeon drivers only? + if ((vidContrllr.Name.Contains("AMD") || vidContrllr.Name.Contains("Radeon")) && ShowWarningDialog == false) { + Version AMDDriverVersion = new Version(vidContrllr.DriverVersion); + + bool greaterOrEqual = AMDDriverVersion.CompareTo(sgminer_NO_neoscrypt_lyra2re) >= 0; + if (greaterOrEqual) { + deviceDriverNO_neoscrypt_lyra2re[vidContrllr.Name] = true; + Helpers.ConsolePrint(TAG, "Driver version seems to be " + sgminer_NO_neoscrypt_lyra2re.ToString() + " or higher. NeoScrypt and Lyra2REv2 will be removed from list"); + } + + + if (AMDDriverVersion.Major < 15) { + ShowWarningDialog = true; + deviceDriverOld[vidContrllr.Name] = true; + Helpers.ConsolePrint(TAG, "WARNING!!! Old AMD GPU driver detected! All optimized versions disabled, mining " + + "speed will not be optimal. Consider upgrading AMD GPU driver. Recommended AMD GPU driver version is 15.7.1."); + } + } + } + if (ConfigManager.GeneralConfig.ShowDriverVersionWarning && ShowWarningDialog == true) { + Form WarningDialog = new DriverVersionConfirmationDialog(); + WarningDialog.ShowDialog(); + WarningDialog = null; + } + #endregion // AMD driver check + + // get platform version + showMessageAndStep(International.GetText("Compute_Device_Query_Manager_AMD_Query")); + List amdOCLDevices = new List(); + string AMDOpenCLPlatformStringKey = ""; + if (IsOpenCLQuerrySuccess) { + bool amdPlatformNumFound = false; + foreach (var oclEl in OpenCLJSONData) { + if (oclEl.PlatformName.Contains("AMD") || oclEl.PlatformName.Contains("amd")) { + amdPlatformNumFound = true; + AMDOpenCLPlatformStringKey = oclEl.PlatformName; + Avaliable.AMDOpenCLPlatformNum = oclEl.PlatformNum; + amdOCLDevices = oclEl.Devices; + Helpers.ConsolePrint(TAG, String.Format("AMD platform found: Key: {0}, Num: {1}", + AMDOpenCLPlatformStringKey, + Avaliable.AMDOpenCLPlatformNum.ToString())); + break; + } + } + if (amdPlatformNumFound) { + // get only AMD gpus + { + foreach (var oclDev in amdOCLDevices) { + if (oclDev._CL_DEVICE_TYPE.Contains("GPU")) { + amdGpus.Add(oclDev); + } + } + } + bool isBusID_OK = true; + // check if buss ids are unuque and different from -1 + { + HashSet bus_ids = new HashSet(); + foreach (var amdOclDev in amdGpus) { + if (amdOclDev.AMD_BUS_ID < 0) { + isBusID_OK = false; + break; + } + bus_ids.Add(amdOclDev.AMD_BUS_ID); + } + // check if unique + isBusID_OK = isBusID_OK && bus_ids.Count == amdGpus.Count; + } + + if (amdGpus.Count == 0) { + Helpers.ConsolePrint(TAG, "AMD GPUs count is 0"); + } else { + // print BUS id status + if (isBusID_OK) { + Helpers.ConsolePrint(TAG, "AMD Bus IDs are unique and valid. OK"); + } else { + Helpers.ConsolePrint(TAG, "AMD Bus IDs IS INVALID. Using fallback AMD detection mode"); + } + + Helpers.ConsolePrint(TAG, "AMD GPUs count : " + amdGpus.Count.ToString()); + Helpers.ConsolePrint(TAG, "AMD Getting device name and serial from ADL"); + // ADL + bool isAdlInit = true; + // ADL does not get devices in order map devices by bus number + // bus id, + Dictionary> _busIdsInfo = new Dictionary>(); + List _amdDeviceName = new List(); + List _amdDeviceUUID = new List(); + try { + int ADLRet = -1; + int NumberOfAdapters = 0; + if (null != ADL.ADL_Main_Control_Create) + // Second parameter is 1: Get only the present adapters + ADLRet = ADL.ADL_Main_Control_Create(ADL.ADL_Main_Memory_Alloc, 1); + if (ADL.ADL_SUCCESS == ADLRet) { + if (null != ADL.ADL_Adapter_NumberOfAdapters_Get) { + ADL.ADL_Adapter_NumberOfAdapters_Get(ref NumberOfAdapters); + } + Helpers.ConsolePrint(TAG, "Number Of Adapters: " + NumberOfAdapters.ToString()); + + if (0 < NumberOfAdapters) { + // Get OS adpater info from ADL + ADLAdapterInfoArray OSAdapterInfoData; + OSAdapterInfoData = new ADLAdapterInfoArray(); + + if (null != ADL.ADL_Adapter_AdapterInfo_Get) { + IntPtr AdapterBuffer = IntPtr.Zero; + int size = Marshal.SizeOf(OSAdapterInfoData); + AdapterBuffer = Marshal.AllocCoTaskMem((int)size); + Marshal.StructureToPtr(OSAdapterInfoData, AdapterBuffer, false); + + if (null != ADL.ADL_Adapter_AdapterInfo_Get) { + ADLRet = ADL.ADL_Adapter_AdapterInfo_Get(AdapterBuffer, size); + if (ADL.ADL_SUCCESS == ADLRet) { + OSAdapterInfoData = (ADLAdapterInfoArray)Marshal.PtrToStructure(AdapterBuffer, OSAdapterInfoData.GetType()); + int IsActive = 0; + + for (int i = 0; i < NumberOfAdapters; i++) { + // Check if the adapter is active + if (null != ADL.ADL_Adapter_Active_Get) + ADLRet = ADL.ADL_Adapter_Active_Get(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref IsActive); + + if (ADL.ADL_SUCCESS == ADLRet) { + // we are looking for amd + // TODO check discrete and integrated GPU separation + var vendorID = OSAdapterInfoData.ADLAdapterInfo[i].VendorID; + var devName = OSAdapterInfoData.ADLAdapterInfo[i].AdapterName; + if (vendorID == AMD_VENDOR_ID + || devName.ToLower().Contains("amd") + || devName.ToLower().Contains("radeon") + || devName.ToLower().Contains("firepro")) { + + string PNPStr = OSAdapterInfoData.ADLAdapterInfo[i].PNPString; + // find vi controller pnp + string infSection = ""; + foreach (var v_ctrl in AvaliableVideoControllers) { + if(v_ctrl.PNPDeviceID == PNPStr) { + infSection = v_ctrl.InfSection; + } + } + + var backSlashLast = PNPStr.LastIndexOf('\\'); + var serial = PNPStr.Substring(backSlashLast, PNPStr.Length - backSlashLast); + var end_0 = serial.IndexOf('&'); + var end_1 = serial.IndexOf('&', end_0 + 1); + // get serial + serial = serial.Substring(end_0 + 1, (end_1 - end_0) - 1); + + var udid = OSAdapterInfoData.ADLAdapterInfo[i].UDID; + var pciVen_id_strSize = 21; // PCI_VEN_XXXX&DEV_XXXX + var uuid = udid.Substring(0, pciVen_id_strSize) + "_" + serial; + int budId = OSAdapterInfoData.ADLAdapterInfo[i].BusNumber; + if (!_amdDeviceUUID.Contains(uuid)) { + try { + Helpers.ConsolePrint(TAG, String.Format("ADL device added BusNumber:{0} NAME:{1} UUID:{2}"), + budId, + devName, + uuid); + } catch { } + + _amdDeviceUUID.Add(uuid); + //_busIds.Add(OSAdapterInfoData.ADLAdapterInfo[i].BusNumber); + _amdDeviceName.Add(devName); + if (!_busIdsInfo.ContainsKey(budId)) { + var nameUuid = new Tuple3(devName, uuid, infSection); + _busIdsInfo.Add(budId, nameUuid); + } + } + } + } + } + } else { + Helpers.ConsolePrint(TAG, "ADL_Adapter_AdapterInfo_Get() returned error code " + ADLRet.ToString()); + isAdlInit = false; + } + } + // Release the memory for the AdapterInfo structure + if (IntPtr.Zero != AdapterBuffer) + Marshal.FreeCoTaskMem(AdapterBuffer); + } + } + if (null != ADL.ADL_Main_Control_Destroy) + ADL.ADL_Main_Control_Destroy(); + } else { + // TODO + Helpers.ConsolePrint(TAG, "ADL_Main_Control_Create() returned error code " + ADLRet.ToString()); + Helpers.ConsolePrint(TAG, "Check if ADL is properly installed!"); + isAdlInit = false; + } + } catch (Exception ex) { + Helpers.ConsolePrint(TAG, "AMD ADL exception: " + ex.Message); + isAdlInit = false; + } + + /////// + // AMD device creation (in NHM context) + if (isAdlInit && isBusID_OK) { + Helpers.ConsolePrint(TAG, "Using AMD device creation DEFAULT Reliable mappings"); + if (amdGpus.Count == _amdDeviceUUID.Count) { + Helpers.ConsolePrint(TAG, "AMD OpenCL and ADL AMD query COUNTS GOOD/SAME"); + } else { + Helpers.ConsolePrint(TAG, "AMD OpenCL and ADL AMD query COUNTS DIFFERENT/BAD"); + } + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(""); + stringBuilder.AppendLine("QueryAMD [DEFAULT query] devices: "); + for (int i_id = 0; i_id < amdGpus.Count; ++i_id) { + Avaliable.HasAMD = true; + + int busID = amdGpus[i_id].AMD_BUS_ID; + if (busID != -1 && _busIdsInfo.ContainsKey(busID)) { + var deviceName = _busIdsInfo[busID].Item1; + var newAmdDev = new AmdGpuDevice(amdGpus[i_id], deviceDriverOld[deviceName], _busIdsInfo[busID].Item3, deviceDriverNO_neoscrypt_lyra2re[deviceName]); + newAmdDev.DeviceName = deviceName; + newAmdDev.UUID = _busIdsInfo[busID].Item2; + bool isDisabledGroup = ConfigManager.GeneralConfig.DeviceDetection.DisableDetectionAMD; + string skipOrAdd = isDisabledGroup ? "SKIPED" : "ADDED"; + string isDisabledGroupStr = isDisabledGroup ? " (AMD group disabled)" : ""; + string etherumCapableStr = newAmdDev.IsEtherumCapable() ? "YES" : "NO"; + + Avaliable.AllAvaliableDevices.Add( + new ComputeDevice(newAmdDev, ++GPUCount, false)); + // just in case + try { + stringBuilder.AppendLine(String.Format("\t{0} device{1}:", skipOrAdd, isDisabledGroupStr)); + stringBuilder.AppendLine(String.Format("\t\tID: {0}", newAmdDev.DeviceID.ToString())); + stringBuilder.AppendLine(String.Format("\t\tNAME: {0}", newAmdDev.DeviceName)); + stringBuilder.AppendLine(String.Format("\t\tCODE_NAME: {0}", newAmdDev.Codename)); + stringBuilder.AppendLine(String.Format("\t\tUUID: {0}", newAmdDev.UUID)); + stringBuilder.AppendLine(String.Format("\t\tMEMORY: {0}", newAmdDev.DeviceGlobalMemory.ToString())); + stringBuilder.AppendLine(String.Format("\t\tETHEREUM: {0}", etherumCapableStr)); + } catch { } + } else { + stringBuilder.AppendLine(String.Format("\tDevice not added, Bus No. {0} not found:", busID)); + } + } + Helpers.ConsolePrint(TAG, stringBuilder.ToString()); + } else { + Helpers.ConsolePrint(TAG, "Using AMD device creation FALLBACK UnReliable mappings"); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(""); + stringBuilder.AppendLine("QueryAMD [FALLBACK query] devices: "); + + // get video AMD controllers and sort them by RAM + // (find a way to get PCI BUS Numbers from PNPDeviceID) + List AMDVideoControllers = new List(); + foreach (var vcd in AvaliableVideoControllers) { + if (vcd.Name.ToLower().Contains("amd") + || vcd.Name.ToLower().Contains("radeon") + || vcd.Name.ToLower().Contains("firepro")) { + AMDVideoControllers.Add(vcd); + } + } + // sort by ram not ideal + AMDVideoControllers.Sort((a, b) => (int)(a.AdapterRAM - b.AdapterRAM)); + amdGpus.Sort((a, b) => (int)(a._CL_DEVICE_GLOBAL_MEM_SIZE - b._CL_DEVICE_GLOBAL_MEM_SIZE)); + int minCount = Math.Min(AMDVideoControllers.Count, amdGpus.Count); + + for (int i = 0; i < minCount; ++i) { + Avaliable.HasAMD = true; + + var deviceName = AMDVideoControllers[i].Name; + if(AMDVideoControllers[i].InfSection == null) AMDVideoControllers[i].InfSection = ""; + var newAmdDev = new AmdGpuDevice(amdGpus[i], deviceDriverOld[deviceName], AMDVideoControllers[i].InfSection, deviceDriverNO_neoscrypt_lyra2re[deviceName]); + newAmdDev.DeviceName = deviceName; + newAmdDev.UUID = "UNUSED"; + bool isDisabledGroup = ConfigManager.GeneralConfig.DeviceDetection.DisableDetectionAMD; + string skipOrAdd = isDisabledGroup ? "SKIPED" : "ADDED"; + string isDisabledGroupStr = isDisabledGroup ? " (AMD group disabled)" : ""; + string etherumCapableStr = newAmdDev.IsEtherumCapable() ? "YES" : "NO"; + + Avaliable.AllAvaliableDevices.Add( + new ComputeDevice(newAmdDev, ++GPUCount, true)); + // just in case + try { + stringBuilder.AppendLine(String.Format("\t{0} device{1}:", skipOrAdd, isDisabledGroupStr)); + stringBuilder.AppendLine(String.Format("\t\tID: {0}", newAmdDev.DeviceID.ToString())); + stringBuilder.AppendLine(String.Format("\t\tNAME: {0}", newAmdDev.DeviceName)); + stringBuilder.AppendLine(String.Format("\t\tCODE_NAME: {0}", newAmdDev.Codename)); + stringBuilder.AppendLine(String.Format("\t\tUUID: {0}", newAmdDev.UUID)); + stringBuilder.AppendLine(String.Format("\t\tMEMORY: {0}", newAmdDev.DeviceGlobalMemory.ToString())); + stringBuilder.AppendLine(String.Format("\t\tETHEREUM: {0}", etherumCapableStr)); + } catch { } + } + Helpers.ConsolePrint(TAG, stringBuilder.ToString()); + } + } + } // end is amdPlatformNumFound + } // end is OpenCLSuccess + Helpers.ConsolePrint(TAG, "QueryAMD END"); + } + + } + #endregion Helpers + } + + public static class SystemSpecs { + public static UInt64 FreePhysicalMemory; + public static UInt64 FreeSpaceInPagingFiles; + public static UInt64 FreeVirtualMemory; + public static UInt32 LargeSystemCache; + public static UInt32 MaxNumberOfProcesses; + public static UInt64 MaxProcessMemorySize; + + public static UInt32 NumberOfLicensedUsers; + public static UInt32 NumberOfProcesses; + public static UInt32 NumberOfUsers; + public static UInt32 OperatingSystemSKU; + + public static UInt64 SizeStoredInPagingFiles; + + public static UInt32 SuiteMask; + + public static UInt64 TotalSwapSpaceSize; + public static UInt64 TotalVirtualMemorySize; + public static UInt64 TotalVisibleMemorySize; + + + public static void QueryAndLog() { + ObjectQuery winQuery = new ObjectQuery("SELECT * FROM Win32_OperatingSystem"); + + ManagementObjectSearcher searcher = new ManagementObjectSearcher(winQuery); + + foreach (ManagementObject item in searcher.Get()) { + if (item["FreePhysicalMemory"] != null) UInt64.TryParse(item["FreePhysicalMemory"].ToString(), out FreePhysicalMemory); + if (item["FreeSpaceInPagingFiles"] != null) UInt64.TryParse(item["FreeSpaceInPagingFiles"].ToString(), out FreeSpaceInPagingFiles); + if (item["FreeVirtualMemory"] != null) UInt64.TryParse(item["FreeVirtualMemory"].ToString(), out FreeVirtualMemory); + if (item["LargeSystemCache"] != null) UInt32.TryParse(item["LargeSystemCache"].ToString(), out LargeSystemCache); + if (item["MaxNumberOfProcesses"] != null) UInt32.TryParse(item["MaxNumberOfProcesses"].ToString(), out MaxNumberOfProcesses); + if (item["MaxProcessMemorySize"] != null) UInt64.TryParse(item["MaxProcessMemorySize"].ToString(), out MaxProcessMemorySize); + if (item["NumberOfLicensedUsers"] != null) UInt32.TryParse(item["NumberOfLicensedUsers"].ToString(), out NumberOfLicensedUsers); + if (item["NumberOfProcesses"] != null) UInt32.TryParse(item["NumberOfProcesses"].ToString(), out NumberOfProcesses); + if (item["NumberOfUsers"] != null) UInt32.TryParse(item["NumberOfUsers"].ToString(), out NumberOfUsers); + if (item["OperatingSystemSKU"] != null) UInt32.TryParse(item["OperatingSystemSKU"].ToString(), out OperatingSystemSKU); + if (item["SizeStoredInPagingFiles"] != null) UInt64.TryParse(item["SizeStoredInPagingFiles"].ToString(), out SizeStoredInPagingFiles); + if (item["SuiteMask"] != null) UInt32.TryParse(item["SuiteMask"].ToString(), out SuiteMask); + if (item["TotalSwapSpaceSize"] != null) UInt64.TryParse(item["TotalSwapSpaceSize"].ToString(), out TotalSwapSpaceSize); + if (item["TotalVirtualMemorySize"] != null) UInt64.TryParse(item["TotalVirtualMemorySize"].ToString(), out TotalVirtualMemorySize); + if (item["TotalVisibleMemorySize"] != null) UInt64.TryParse(item["TotalVisibleMemorySize"].ToString(), out TotalVisibleMemorySize); + // log + Helpers.ConsolePrint("SystemSpecs", String.Format("FreePhysicalMemory = {0}", FreePhysicalMemory)); + Helpers.ConsolePrint("SystemSpecs", String.Format("FreeSpaceInPagingFiles = {0}", FreeSpaceInPagingFiles)); + Helpers.ConsolePrint("SystemSpecs", String.Format("FreeVirtualMemory = {0}", FreeVirtualMemory)); + Helpers.ConsolePrint("SystemSpecs", String.Format("LargeSystemCache = {0}", LargeSystemCache)); + Helpers.ConsolePrint("SystemSpecs", String.Format("MaxNumberOfProcesses = {0}", MaxNumberOfProcesses)); + Helpers.ConsolePrint("SystemSpecs", String.Format("MaxProcessMemorySize = {0}", MaxProcessMemorySize)); + Helpers.ConsolePrint("SystemSpecs", String.Format("NumberOfLicensedUsers = {0}", NumberOfLicensedUsers)); + Helpers.ConsolePrint("SystemSpecs", String.Format("NumberOfProcesses = {0}", NumberOfProcesses)); + Helpers.ConsolePrint("SystemSpecs", String.Format("NumberOfUsers = {0}", NumberOfUsers)); + Helpers.ConsolePrint("SystemSpecs", String.Format("OperatingSystemSKU = {0}", OperatingSystemSKU)); + Helpers.ConsolePrint("SystemSpecs", String.Format("SizeStoredInPagingFiles = {0}", SizeStoredInPagingFiles)); + Helpers.ConsolePrint("SystemSpecs", String.Format("SuiteMask = {0}", SuiteMask)); + Helpers.ConsolePrint("SystemSpecs", String.Format("TotalSwapSpaceSize = {0}", TotalSwapSpaceSize)); + Helpers.ConsolePrint("SystemSpecs", String.Format("TotalVirtualMemorySize = {0}", TotalVirtualMemorySize)); + Helpers.ConsolePrint("SystemSpecs", String.Format("TotalVisibleMemorySize = {0}", TotalVisibleMemorySize)); + } + } + } + + public static class Avaliable { + public static bool HasNVIDIA = false; + public static bool HasAMD = false; + public static bool HasCPU = false; + public static int CPUsCount = 0; + public static int GPUsCount = 0; + public static int AMDOpenCLPlatformNum = -1; + public static bool IsHyperThreadingEnabled = false; + + public static ulong NVIDIA_RAM_SUM = 0; + public static ulong AMD_RAM_SUM = 0; + + public static List AllAvaliableDevices = new List(); + + // methods + public static ComputeDevice GetDeviceWithUUID(string uuid) { + foreach (var dev in AllAvaliableDevices) { + if (uuid == dev.UUID) return dev; + } + return null; + } + + public static List GetSameDevicesTypeAsDeviceWithUUID(string uuid) { + List sameTypes = new List(); + var compareDev = GetDeviceWithUUID(uuid); + foreach (var dev in AllAvaliableDevices) { + if (uuid != dev.UUID && compareDev.DeviceType == dev.DeviceType) { + sameTypes.Add(GetDeviceWithUUID(dev.UUID)); + } + } + return sameTypes; + } + + public static ComputeDevice GetCurrentlySelectedComputeDevice(int index, bool unique) { + return AllAvaliableDevices[index]; + } + + public static int GetCountForType(DeviceType type) { + int count = 0; + foreach (var device in Avaliable.AllAvaliableDevices) { + if (device.DeviceType == type) { + ++count; + } + } + return count; + } + } + + public static class Group { + public static void DisableCpuGroup() { + foreach (var device in Avaliable.AllAvaliableDevices) { + if (device.DeviceType == DeviceType.CPU) { + device.Enabled = false; + } + } + } + + public static bool ContainsAMD_GPUs { + get { + foreach (var device in Avaliable.AllAvaliableDevices) { + if (device.DeviceType == DeviceType.AMD) { + return true; + } + } + return false; + } + } + + public static bool ContainsGPUs { + get { + foreach (var device in Avaliable.AllAvaliableDevices) { + if (device.DeviceType == DeviceType.NVIDIA + || device.DeviceType == DeviceType.AMD) { + return true; + } + } + return false; + } + } + public static void UncheckedCPU() { + // Auto uncheck CPU if any GPU is found + if (ContainsGPUs) DisableCpuGroup(); + } + } + + } +} diff --git a/NiceHashMiner/Devices/ComputeDeviceQueryManager.cs b/NiceHashMiner/Devices/ComputeDeviceQueryManager.cs deleted file mode 100644 index a37f511..0000000 --- a/NiceHashMiner/Devices/ComputeDeviceQueryManager.cs +++ /dev/null @@ -1,769 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows.Forms; -using NiceHashMiner.Configs; -using NiceHashMiner.Interfaces; -using NiceHashMiner.Enums; -using NiceHashMiner.Miners; -using System.Diagnostics; -using Newtonsoft.Json; -using ATI.ADL; -using System.Runtime.InteropServices; -using System.Management; -using System.IO; -using System.Globalization; -using NiceHashMiner.Utils; - -namespace NiceHashMiner.Devices -{ - /// - /// ComputeDeviceQueryManager class is used to query ComputeDevices avaliable on the system. - /// Query CPUs, GPUs [Nvidia, AMD] - /// - public class ComputeDeviceQueryManager : BaseLazySingleton - { - - const int AMD_VENDOR_ID = 1002; - readonly string TAG; - - const double NVIDIA_RECOMENDED_DRIVER = 372.54; - const double NVIDIA_MIN_DETECTION_DRIVER = 362.61; - double _currentNvidiaOpenCLDriver = -1; - JsonSerializerSettings _jsonSettings = null; - - // for downloading - public bool HasNVIDIA { get; private set; } - public bool HasAMD { get; private set; } - - protected ComputeDeviceQueryManager() { - TAG = this.GetType().Name; - HasNVIDIA = false; - HasAMD = false; - _jsonSettings = new JsonSerializerSettings { - NullValueHandling = NullValueHandling.Ignore, - MissingMemberHandling = MissingMemberHandling.Ignore, - Culture = CultureInfo.InvariantCulture - }; - } - - public int CPUs { get; private set; } - - public int AMDOpenCLPlatformNum { get; private set; } - public string AMDOpenCLPlatformStringKey { get; private set; } - - public IMessageNotifier MessageNotifier { get; private set; } - - public void QueryDevices(IMessageNotifier messageNotifier) - { - MessageNotifier = messageNotifier; - // #0 get video controllers, used for cross checking - QueryVideoControllers(); - // Order important CPU Query must be first - // #1 CPU - QueryCPUs(); - // #2 CUDA - showMessageAndStep(International.GetText("Compute_Device_Query_Manager_CUDA_Query")); - QueryCudaDevices(); - // #3 OpenCL - showMessageAndStep(International.GetText("Compute_Device_Query_Manager_OpenCL_Query")); - QueryOpenCLDevices(); - // #4 AMD query AMD from OpenCL devices, get serial and add devices - QueryAMD(); - // #5 uncheck CPU if GPUs present, call it after we Query all devices - UncheckedCPU(); - // add numberings to same devices - if (ComputeDevice.AllAvaliableDevices.Count != ComputeDevice.UniqueAvaliableDevices.Count) { - // name count - Dictionary namesCount = new Dictionary(); - // init keys and counters - foreach (var uniqueCdev in ComputeDevice.UniqueAvaliableDevices) { - namesCount.Add(uniqueCdev.Name, 0); - } - // count - foreach (var cDev in ComputeDevice.AllAvaliableDevices) { - namesCount[cDev.Name]++; - } - foreach (var nameCount in namesCount) { - string name = nameCount.Key; - int deviceCount = nameCount.Value; - if (deviceCount > 1) { - int numID = 1; - foreach (var cDev in ComputeDevice.AllAvaliableDevices) { - if (cDev.Name == name) { - cDev.Name = cDev.Name + " #" + numID.ToString(); - ++numID; - } - } - } - } - } - - - // TODO update this to report undetected hardware - // #6 check NVIDIA, AMD devices count - { - int NVIDIA_count = 0; - int AMD_count = 0; - foreach (var vidCtrl in AvaliableVideoControllers) { - NVIDIA_count += (vidCtrl.Name.ToLower().Contains("nvidia")) ? 1 : 0; - AMD_count += (vidCtrl.Name.ToLower().Contains("amd")) ? 1 : 0; - } - if (NVIDIA_count == CudaDevices.Count) { - Helpers.ConsolePrint(TAG, "Cuda NVIDIA/CUDA device count GOOD"); - } else { - Helpers.ConsolePrint(TAG, "Cuda NVIDIA/CUDA device count BAD!!!"); - } - if (AMD_count == amdGpus.Count) { - Helpers.ConsolePrint(TAG, "AMD GPU device count GOOD"); - } else { - Helpers.ConsolePrint(TAG, "AMD GPU device count BAD!!!"); - } - } - // #7 init ethminer ID mappings offset - if (OpenCLJSONData != null) { - // helper vars - Dictionary openCLGpuCount = new Dictionary(); - Dictionary openCLPlatformIds = new Dictionary(); - foreach (var oclPlatform in OpenCLJSONData.OCLPlatforms) { - ComputePlatformType current = GetPlatformType(oclPlatform.Key); - if(current != ComputePlatformType.NONE) { - openCLPlatformIds[current] = oclPlatform.Value; - } else { - Helpers.ConsolePrint(TAG, "ethminer platforms mapping NONE"); - } - } - foreach (var oclDevs in OpenCLJSONData.OCLPlatformDevices) { - ComputePlatformType current = GetPlatformType(oclDevs.Key); - if (current != ComputePlatformType.NONE) { - foreach (var oclDev in oclDevs.Value) { - if (oclDev._CL_DEVICE_TYPE.Contains("GPU")) { - if (openCLGpuCount.ContainsKey(current)) { - openCLGpuCount[current]++; - } else { - openCLGpuCount[current] = 1; - } - } - } - } else { - Helpers.ConsolePrint(TAG, "ethminer platforms mapping NONE"); - } - } - // sort platforms by platform values - Dictionary openCLPlatformIdsRev = new Dictionary(); - List platformIds = new List(); - foreach (var platId in openCLPlatformIds) { - openCLPlatformIdsRev[platId.Value] = platId.Key; - platformIds.Add(platId.Value); - } - platformIds.Sort(); - // set mappings - int cumulativeCount = 0; - foreach (var curId in platformIds) { - var key = openCLPlatformIdsRev[curId]; - if (openCLGpuCount.ContainsKey(key)) { - _ethminerIdsOffet[key] = cumulativeCount; - cumulativeCount += openCLGpuCount[key]; - } - } - } - // allerts - _currentNvidiaOpenCLDriver = GetNvidiaOpenCLDriver(); - // if we have nvidia cards but no CUDA devices tell the user to upgrade driver - bool isNvidiaErrorShown = false; // to prevent showing twice - if (HasNvidiaVideoController() && CudaDevices.Count == 0) { - isNvidiaErrorShown = true; - var minDriver = NVIDIA_MIN_DETECTION_DRIVER.ToString(); - var recomendDrvier = NVIDIA_RECOMENDED_DRIVER.ToString(); - MessageBox.Show(String.Format(International.GetText("Compute_Device_Query_Manager_NVIDIA_Driver_Detection"), - minDriver, recomendDrvier), - International.GetText("Compute_Device_Query_Manager_NVIDIA_RecomendedDriver_Title"), - MessageBoxButtons.OK, MessageBoxIcon.Error); - } - // recomended driver - if (HasNvidiaVideoController() && _currentNvidiaOpenCLDriver < NVIDIA_RECOMENDED_DRIVER && !isNvidiaErrorShown) { - var recomendDrvier = NVIDIA_RECOMENDED_DRIVER.ToString(); - var nvdriverString = _currentNvidiaOpenCLDriver > -1 ? String.Format(International.GetText("Compute_Device_Query_Manager_NVIDIA_Driver_Recomended_PART"), _currentNvidiaOpenCLDriver.ToString()) - : ""; - MessageBox.Show(String.Format(International.GetText("Compute_Device_Query_Manager_NVIDIA_Driver_Recomended"), - recomendDrvier, nvdriverString, recomendDrvier), - International.GetText("Compute_Device_Query_Manager_NVIDIA_RecomendedDriver_Title"), - MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - - // #x remove reference - MessageNotifier = null; - } - - private Dictionary _ethminerIdsOffet = new Dictionary(); - public int GetEthminerOpenCLID(ComputePlatformType platformType, int id) { - return _ethminerIdsOffet[platformType] + id; - } - - private ComputePlatformType GetPlatformType(string name) { - if (name.Contains("Intel")) { - return ComputePlatformType.Intel; - } - if (name.Contains("AMD")) { - return ComputePlatformType.AMD; - } - if (name.Contains("NVIDIA")) { - return ComputePlatformType.NVIDIA; - } - return ComputePlatformType.NONE; - } - - private void showMessageAndStep(string infoMsg) { - if (MessageNotifier != null) MessageNotifier.SetMessageAndIncrementStep(infoMsg); - } - - #region Video controllers, driver versions - - private class VideoControllerData { - public string Name { get; set; } - public string Description { get; set; } - public string PNPDeviceID { get; set; } - public string DriverVersion { get; set; } - public string Status { get; set; } - } - - private List AvaliableVideoControllers = new List(); - - private void QueryVideoControllers() { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine(""); - stringBuilder.AppendLine("QueryVideoControllers: "); - ManagementObjectCollection moc = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_VideoController").Get(); - bool allVideoContollersOK = true; - foreach (var manObj in moc) { - var vidController = new VideoControllerData() { - Name = manObj["Name"] as string, - Description = manObj["Description"] as string, - PNPDeviceID = manObj["PNPDeviceID"] as string, - DriverVersion = manObj["DriverVersion"] as string, - Status = manObj["Status"] as string - }; - stringBuilder.AppendLine("\tWin32_VideoController detected:"); - stringBuilder.AppendLine(String.Format("\t\tName {0}", vidController.Name)); - stringBuilder.AppendLine(String.Format("\t\tDescription {0}", vidController.Description)); - stringBuilder.AppendLine(String.Format("\t\tPNPDeviceID {0}", vidController.PNPDeviceID)); - stringBuilder.AppendLine(String.Format("\t\tDriverVersion {0}", vidController.DriverVersion)); - stringBuilder.AppendLine(String.Format("\t\tStatus {0}", vidController.Status)); - - // check if controller ok - if (allVideoContollersOK && !vidController.Status.ToLower().Equals("ok")) { - allVideoContollersOK = false; - } - - AvaliableVideoControllers.Add(vidController); - } - Helpers.ConsolePrint(TAG, stringBuilder.ToString()); - if (!allVideoContollersOK) { - string msg = International.GetText("QueryVideoControllers_NOT_ALL_OK_Msg"); - foreach (var vc in AvaliableVideoControllers) { - if(!vc.Status.ToLower().Equals("ok")) { - msg += Environment.NewLine - + String.Format(International.GetText("QueryVideoControllers_NOT_ALL_OK_Msg_Append"), vc.Name, vc.Status, vc.PNPDeviceID); - } - } - MessageBox.Show(msg, - International.GetText("QueryVideoControllers_NOT_ALL_OK_Title"), - MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - } - - private bool HasNvidiaVideoController() { - foreach (var vctrl in AvaliableVideoControllers) { - if (vctrl.Name.ToLower().Contains("nvidia")) return true; - } - return false; - } - - #endregion // Video controllers, driver versions - - private void QueryCPUs() { - // get all CPUs - CPUs = CPUID.GetPhysicalProcessorCount(); - - // get all cores (including virtual - HT can benefit mining) - int ThreadsPerCPU = CPUID.GetVirtualCoresCount() / CPUs; - - if (!Helpers.InternalCheckIsWow64()) - { - MessageBox.Show(International.GetText("Form_Main_msgbox_CPUMining64bitMsg"), - International.GetText("Warning_with_Exclamation"), - MessageBoxButtons.OK, MessageBoxIcon.Warning); - CPUs = 0; - } - - if (ThreadsPerCPU * CPUs > 64) - { - MessageBox.Show(International.GetText("Form_Main_msgbox_CPUMining64CoresMsg"), - International.GetText("Warning_with_Exclamation"), - MessageBoxButtons.OK, MessageBoxIcon.Warning); - CPUs = 0; - } - - // TODO important move this to settings - int ThreadsPerCPUMask = ThreadsPerCPU; - Globals.ThreadsPerCPU = ThreadsPerCPU; - - if (CPUs == 1) { - MinersManager.Instance.AddCpuMiner(new cpuminer(0, ThreadsPerCPU, 0), 0, CPUID.GetCPUName().Trim()); - } - else { - for (int i = 0; i < CPUs; i++) { - MinersManager.Instance.AddCpuMiner(new cpuminer(i, ThreadsPerCPU, CPUID.CreateAffinityMask(i, ThreadsPerCPUMask)), - i, CPUID.GetCPUName().Trim()); - } - } - } - - List amdGpus = new List(); - private void QueryAMD() { - //showMessageAndStep(International.GetText("Form_Main_loadtext_AMD")); - //var dump = new sgminer(true); - - if(ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionAMD) { - Helpers.ConsolePrint(TAG, "Skipping AMD device detection, settings set to disabled"); - showMessageAndStep(International.GetText("Compute_Device_Query_Manager_AMD_Query_Skip")); - return; - } - - #region AMD driver check, ADL returns 0 - // check the driver version bool EnableOptimizedVersion = true; - Dictionary deviceDriverOld = new Dictionary(); - string minerPath = MinerPaths.sgminer_5_4_0_general; - bool ShowWarningDialog = false; - - foreach (var vidContrllr in AvaliableVideoControllers) { - Helpers.ConsolePrint(TAG, String.Format("Checking AMD device (driver): {0} ({1})", vidContrllr.Name, vidContrllr.DriverVersion)); - - deviceDriverOld[vidContrllr.Name] = false; - // TODO checking radeon drivers only? - if ((vidContrllr.Name.Contains("AMD") || vidContrllr.Name.Contains("Radeon")) && ShowWarningDialog == false) { - Version AMDDriverVersion = new Version(vidContrllr.DriverVersion); - - if (AMDDriverVersion.Major < 15) { - ShowWarningDialog = true; - deviceDriverOld[vidContrllr.Name] = true; - Helpers.ConsolePrint(TAG, "WARNING!!! Old AMD GPU driver detected! All optimized versions disabled, mining " + - "speed will not be optimal. Consider upgrading AMD GPU driver. Recommended AMD GPU driver version is 15.7.1."); - } else if (AMDDriverVersion.Major == 16 && AMDDriverVersion.Minor >= 150) { - if (MinersDownloadManager.Instance.IsMinerBinFolder()) { - // TODO why this copy? - string src = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\" + - minerPath.Split('\\')[0] + "\\" + minerPath.Split('\\')[1] + "\\kernel"; - - foreach (var file in Directory.GetFiles(src)) { - string dest = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Temp\\" + System.IO.Path.GetFileName(file); - if (!File.Exists(dest)) File.Copy(file, dest, false); - } - } - } - } - } - if (ShowWarningDialog == true && ConfigManager.Instance.GeneralConfig.ShowDriverVersionWarning == true) { - Form WarningDialog = new DriverVersionConfirmationDialog(); - WarningDialog.ShowDialog(); - WarningDialog = null; - } - #endregion // AMD driver check - - // get platform version - showMessageAndStep(International.GetText("Compute_Device_Query_Manager_AMD_Query")); - if (IsOpenCLQuerrySuccess) { - bool amdPlatformNumFound = false; - foreach (var kvp in OpenCLJSONData.OCLPlatforms) { - if (kvp.Key.Contains("AMD") || kvp.Key.Contains("amd")) { - amdPlatformNumFound = true; - AMDOpenCLPlatformStringKey = kvp.Key; - AMDOpenCLPlatformNum = kvp.Value; - Helpers.ConsolePrint(TAG, String.Format("AMD platform found: Key: {0}, Num: {1}", - AMDOpenCLPlatformStringKey, - AMDOpenCLPlatformNum.ToString())); - break; - } - } - if (amdPlatformNumFound) { - // get only AMD gpus - { - var amdOCLDevices = OpenCLJSONData.OCLPlatformDevices[AMDOpenCLPlatformStringKey]; - foreach (var oclDev in amdOCLDevices) { - if (oclDev._CL_DEVICE_TYPE.Contains("GPU")) { - amdGpus.Add(oclDev); - } - } - } - if (amdGpus.Count == 0) { - Helpers.ConsolePrint(TAG, "AMD GPUs count is 0"); - } else { - Helpers.ConsolePrint(TAG, "AMD GPUs count : " + amdGpus.Count.ToString()); - Helpers.ConsolePrint(TAG, "AMD Getting device name and serial from ADL"); - // ADL - bool isAdlInit = true; - // ADL does not get devices in order map devices by bus number - // bus id, - Dictionary> _busIdsInfo = new Dictionary>(); - List _amdDeviceName = new List(); - List _amdDeviceUUID = new List(); - try { - int ADLRet = -1; - int NumberOfAdapters = 0; - if (null != ADL.ADL_Main_Control_Create) - // Second parameter is 1: Get only the present adapters - ADLRet = ADL.ADL_Main_Control_Create(ADL.ADL_Main_Memory_Alloc, 1); - if (ADL.ADL_SUCCESS == ADLRet) { - if (null != ADL.ADL_Adapter_NumberOfAdapters_Get) { - ADL.ADL_Adapter_NumberOfAdapters_Get(ref NumberOfAdapters); - } - Helpers.ConsolePrint(TAG, "Number Of Adapters: " + NumberOfAdapters.ToString()); - - if (0 < NumberOfAdapters) { - // Get OS adpater info from ADL - ADLAdapterInfoArray OSAdapterInfoData; - OSAdapterInfoData = new ADLAdapterInfoArray(); - - if (null != ADL.ADL_Adapter_AdapterInfo_Get) { - IntPtr AdapterBuffer = IntPtr.Zero; - int size = Marshal.SizeOf(OSAdapterInfoData); - AdapterBuffer = Marshal.AllocCoTaskMem((int)size); - Marshal.StructureToPtr(OSAdapterInfoData, AdapterBuffer, false); - - if (null != ADL.ADL_Adapter_AdapterInfo_Get) { - ADLRet = ADL.ADL_Adapter_AdapterInfo_Get(AdapterBuffer, size); - if (ADL.ADL_SUCCESS == ADLRet) { - OSAdapterInfoData = (ADLAdapterInfoArray)Marshal.PtrToStructure(AdapterBuffer, OSAdapterInfoData.GetType()); - int IsActive = 0; - - for (int i = 0; i < NumberOfAdapters; i++) { - // Check if the adapter is active - if (null != ADL.ADL_Adapter_Active_Get) - ADLRet = ADL.ADL_Adapter_Active_Get(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref IsActive); - - if (ADL.ADL_SUCCESS == ADLRet) { - // we are looking for amd - // TODO check discrete and integrated GPU separation - var vendorID = OSAdapterInfoData.ADLAdapterInfo[i].VendorID; - var devName = OSAdapterInfoData.ADLAdapterInfo[i].AdapterName; - if (vendorID == AMD_VENDOR_ID - || devName.ToLower().Contains("amd") - || devName.ToLower().Contains("radeon") - || devName.ToLower().Contains("firepro")) { - - string PNPStr = OSAdapterInfoData.ADLAdapterInfo[i].PNPString; - var backSlashLast = PNPStr.LastIndexOf('\\'); - var serial = PNPStr.Substring(backSlashLast, PNPStr.Length - backSlashLast); - var end_0 = serial.IndexOf('&'); - var end_1 = serial.IndexOf('&', end_0 + 1); - // get serial - serial = serial.Substring(end_0 + 1, (end_1 - end_0) - 1); - - var udid = OSAdapterInfoData.ADLAdapterInfo[i].UDID; - var pciVen_id_strSize = 21; // PCI_VEN_XXXX&DEV_XXXX - var uuid = udid.Substring(0, pciVen_id_strSize) + "_" + serial; - int budId = OSAdapterInfoData.ADLAdapterInfo[i].BusNumber; - if (!_amdDeviceUUID.Contains(uuid)) { - try { - Helpers.ConsolePrint(TAG, String.Format("ADL device added BusNumber:{0} NAME:{1} UUID:{2}"), - budId, - devName, - uuid); - } catch { } - - _amdDeviceUUID.Add(uuid); - //_busIds.Add(OSAdapterInfoData.ADLAdapterInfo[i].BusNumber); - _amdDeviceName.Add(devName); - if (!_busIdsInfo.ContainsKey(budId)) { - var nameUuid = new Tuple(devName, uuid); - _busIdsInfo.Add(budId, nameUuid); - } - } - } - } - } - } else { - Helpers.ConsolePrint(TAG, "ADL_Adapter_AdapterInfo_Get() returned error code " + ADLRet.ToString()); - } - } - // Release the memory for the AdapterInfo structure - if (IntPtr.Zero != AdapterBuffer) - Marshal.FreeCoTaskMem(AdapterBuffer); - } - } - if (null != ADL.ADL_Main_Control_Destroy) - ADL.ADL_Main_Control_Destroy(); - } else { - // TODO - Helpers.ConsolePrint(TAG, "ADL_Main_Control_Create() returned error code " + ADLRet.ToString()); - Helpers.ConsolePrint(TAG, "Check if ADL is properly installed!"); - } - } catch (Exception ex) { - Helpers.ConsolePrint(TAG, "AMD ADL exception: " + ex.Message); - isAdlInit = false; - } - if(isAdlInit) { - if (amdGpus.Count == _amdDeviceUUID.Count) { - Helpers.ConsolePrint(TAG, "AMD OpenCL and ADL AMD query COUNTS GOOD/SAME"); - } else { - Helpers.ConsolePrint(TAG, "AMD OpenCL and ADL AMD query COUNTS DIFFERENT/BAD"); - } - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine(""); - stringBuilder.AppendLine("QueryAMD devices: "); - for (int i_id = 0; i_id < amdGpus.Count; ++i_id) { - HasAMD = true; - - int busID = amdGpus[i_id].AMD_BUS_ID; - if (busID != -1 && _busIdsInfo.ContainsKey(busID)) { - var deviceName = _busIdsInfo[busID].Item1; - var newAmdDev = new AmdGpuDevice(amdGpus[i_id], deviceDriverOld[deviceName]); - newAmdDev.DeviceName = deviceName; - newAmdDev.UUID = _busIdsInfo[busID].Item2; - bool isDisabledGroup = ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionAMD; - string skipOrAdd = isDisabledGroup ? "SKIPED" : "ADDED"; - string isDisabledGroupStr = isDisabledGroup ? " (AMD group disabled)" : ""; - string etherumCapableStr = newAmdDev.IsEtherumCapable() ? "YES" : "NO"; - - new ComputeDevice(newAmdDev, true, true); - // just in case - try { - stringBuilder.AppendLine(String.Format("\t{0} device{1}:", skipOrAdd, isDisabledGroupStr)); - stringBuilder.AppendLine(String.Format("\t\tID: {0}", newAmdDev.DeviceID.ToString())); - stringBuilder.AppendLine(String.Format("\t\tNAME: {0}", newAmdDev.DeviceName)); - stringBuilder.AppendLine(String.Format("\t\tCODE_NAME: {0}", newAmdDev.Codename)); - stringBuilder.AppendLine(String.Format("\t\tUUID: {0}", newAmdDev.UUID)); - stringBuilder.AppendLine(String.Format("\t\tMEMORY: {0}", newAmdDev.DeviceGlobalMemory.ToString())); - stringBuilder.AppendLine(String.Format("\t\tETHEREUM: {0}", etherumCapableStr)); - } catch { } - } else { - stringBuilder.AppendLine(String.Format("\tDevice not added, Bus No. {0} not found:", busID)); - } - } - Helpers.ConsolePrint(TAG, stringBuilder.ToString()); - } - } - } - } - } - - private void UncheckedCPU() { - // Auto uncheck CPU if any GPU is found - var cdgm = ComputeDeviceGroupManager.Instance; - if (cdgm.ContainsGPUs) cdgm.DisableCpuGroup(); - } - - #region NEW IMPLEMENTATION - - #region CUDA, NVIDIA Query - - string QueryCudaDevicesString = ""; - List CudaDevices = new List(); - private void QueryCudaDevicesOutputErrorDataReceived(object sender, DataReceivedEventArgs e) { - if (e.Data != null) { - QueryCudaDevicesString += e.Data; - } - } - - private bool IsSMGroupSkip(int sm_major) { - if (sm_major == 6) { - return ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia6X; - } - if (sm_major == 5) { - return ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia5X; - } - if (sm_major == 3) { - return ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia3X; - } - if (sm_major == 2) { - return ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia2X; - } - return false; - } - - private void QueryCudaDevices() { - Process CudaDevicesDetection = new Process(); - CudaDevicesDetection.StartInfo.FileName = "CudaDeviceDetection.exe"; - CudaDevicesDetection.StartInfo.UseShellExecute = false; - CudaDevicesDetection.StartInfo.RedirectStandardError = true; - CudaDevicesDetection.StartInfo.RedirectStandardOutput = true; - CudaDevicesDetection.StartInfo.CreateNoWindow = true; - CudaDevicesDetection.OutputDataReceived += QueryCudaDevicesOutputErrorDataReceived; - CudaDevicesDetection.ErrorDataReceived += QueryCudaDevicesOutputErrorDataReceived; - - const int waitTime = 5 * 1000; // 5seconds - try { - if (!CudaDevicesDetection.Start()) { - Helpers.ConsolePrint(TAG, "CudaDevicesDetection process could not start"); - } else { - CudaDevicesDetection.BeginErrorReadLine(); - CudaDevicesDetection.BeginOutputReadLine(); - if (CudaDevicesDetection.WaitForExit(waitTime)) { - CudaDevicesDetection.Close(); - } - } - } catch (Exception ex) { - // TODO - Helpers.ConsolePrint(TAG, "CudaDevicesDetection threw Exception: " + ex.Message); - } finally { - if (QueryCudaDevicesString != "") { - try { - CudaDevices = JsonConvert.DeserializeObject>(QueryCudaDevicesString, Globals.JsonSettings); - } catch { } - } - } - if (CudaDevices != null && CudaDevices.Count != 0) { - HasNVIDIA = true; - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine(""); - stringBuilder.AppendLine("CudaDevicesDetection:"); - foreach (var cudaDev in CudaDevices) { - // check sm vesrions - bool isUnderSM21; - { - bool isUnderSM2_major = cudaDev.SM_major < 2; - bool isUnderSM1_minor = cudaDev.SM_minor < 1; - isUnderSM21 = isUnderSM2_major && isUnderSM1_minor; - } - //bool isOverSM6 = cudaDev.SM_major > 6; - bool isDisabledGroup = IsSMGroupSkip(cudaDev.SM_major); - bool skip = isUnderSM21 || isDisabledGroup; - string skipOrAdd = skip ? "SKIPED" : "ADDED"; - string isDisabledGroupStr = isDisabledGroup ? " (SM group disabled)" : ""; - string etherumCapableStr = cudaDev.IsEtherumCapable() ? "YES" : "NO"; - stringBuilder.AppendLine(String.Format("\t{0} device{1}:", skipOrAdd, isDisabledGroupStr)); - stringBuilder.AppendLine(String.Format("\t\tID: {0}", cudaDev.DeviceID.ToString())); - stringBuilder.AppendLine(String.Format("\t\tNAME: {0}", cudaDev.GetName())); - stringBuilder.AppendLine(String.Format("\t\tVENDOR: {0}", cudaDev.VendorName)); - stringBuilder.AppendLine(String.Format("\t\tUUID: {0}", cudaDev.UUID)); - stringBuilder.AppendLine(String.Format("\t\tSM: {0}", cudaDev.SMVersionString)); - stringBuilder.AppendLine(String.Format("\t\tMEMORY: {0}", cudaDev.DeviceGlobalMemory.ToString())); - stringBuilder.AppendLine(String.Format("\t\tETHEREUM: {0}", etherumCapableStr)); - - if (!skip) { - string group; - switch (cudaDev.SM_major) { - case 2: - group = GroupNames.GetName(DeviceGroupType.NVIDIA_2_1); - break; - case 3: - group = GroupNames.GetName(DeviceGroupType.NVIDIA_3_x); - break; - case 5: - group = GroupNames.GetName(DeviceGroupType.NVIDIA_5_x); - break; - case 6: - group = GroupNames.GetName(DeviceGroupType.NVIDIA_6_x); - break; - default: - group = GroupNames.GetName(DeviceGroupType.NVIDIA_6_x); - break; - } - new ComputeDevice(cudaDev, group, true); - } - } - Helpers.ConsolePrint(TAG, stringBuilder.ToString()); - } else { - Helpers.ConsolePrint(TAG, "CudaDevicesDetection found no devices. CudaDevicesDetection returned: " + QueryCudaDevicesString); - } - } - - #endregion // CUDA, NVIDIA Query - - - #region OpenCL Query - - private double GetNvidiaOpenCLDriver() { - if (OpenCLJSONData != null) { - List nvidiaOCLs = null; - foreach (var oclPlatDevs in OpenCLJSONData.OCLPlatformDevices) { - if (oclPlatDevs.Key.ToLower().Contains("nvidia")) { - nvidiaOCLs = oclPlatDevs.Value; - } - } - - if (nvidiaOCLs != null && nvidiaOCLs.Count > 0) { - if (Double.TryParse(nvidiaOCLs[0]._CL_DRIVER_VERSION, - NumberStyles.Any, - CultureInfo.InvariantCulture, - out _currentNvidiaOpenCLDriver)) { - return _currentNvidiaOpenCLDriver; - } - } - } - - return -1; - } - - class OpenCLJSON { - public Dictionary OCLPlatforms = new Dictionary(); - public Dictionary> OCLPlatformDevices = new Dictionary>(); - } - string QueryOpenCLDevicesString = ""; - OpenCLJSON OpenCLJSONData = new OpenCLJSON(); - bool IsOpenCLQuerrySuccess = false; - private void QueryOpenCLDevicesOutputErrorDataReceived(object sender, DataReceivedEventArgs e) { - if (e.Data != null) { - QueryOpenCLDevicesString += e.Data; - } - } - - private void QueryOpenCLDevices() { - Process OpenCLDevicesDetection = new Process(); - OpenCLDevicesDetection.StartInfo.FileName = "AMDOpenCLDeviceDetection.exe"; - OpenCLDevicesDetection.StartInfo.UseShellExecute = false; - OpenCLDevicesDetection.StartInfo.RedirectStandardError = true; - OpenCLDevicesDetection.StartInfo.RedirectStandardOutput = true; - OpenCLDevicesDetection.StartInfo.CreateNoWindow = true; - OpenCLDevicesDetection.OutputDataReceived += QueryOpenCLDevicesOutputErrorDataReceived; - OpenCLDevicesDetection.ErrorDataReceived += QueryOpenCLDevicesOutputErrorDataReceived; - - const int waitTime = 5 * 1000; // 5seconds - try { - if (!OpenCLDevicesDetection.Start()) { - Helpers.ConsolePrint(TAG, "AMDOpenCLDeviceDetection process could not start"); - } else { - OpenCLDevicesDetection.BeginErrorReadLine(); - OpenCLDevicesDetection.BeginOutputReadLine(); - if (OpenCLDevicesDetection.WaitForExit(waitTime)) { - OpenCLDevicesDetection.Close(); - } - } - } catch(Exception ex) { - // TODO - Helpers.ConsolePrint(TAG, "AMDOpenCLDeviceDetection threw Exception: " + ex.Message); - } finally { - if (QueryOpenCLDevicesString != "") { - try { - OpenCLJSONData = JsonConvert.DeserializeObject(QueryOpenCLDevicesString, Globals.JsonSettings); - } catch { } - } - } - - if (OpenCLJSONData == null) { - Helpers.ConsolePrint(TAG, "AMDOpenCLDeviceDetection found no devices. AMDOpenCLDeviceDetection returned: " + QueryOpenCLDevicesString); - } else { - IsOpenCLQuerrySuccess = true; - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine(""); - stringBuilder.AppendLine("AMDOpenCLDeviceDetection found devices success:"); - foreach (var kvp in OpenCLJSONData.OCLPlatformDevices) { - stringBuilder.AppendLine(String.Format("\tFound devices for platform: {0}", kvp.Key)); - foreach (var oclDev in kvp.Value) { - stringBuilder.AppendLine("\t\tDevice:"); - stringBuilder.AppendLine(String.Format("\t\t\tDevice ID {0}", oclDev.DeviceID)); - stringBuilder.AppendLine(String.Format("\t\t\tDevice NAME {0}", oclDev._CL_DEVICE_NAME)); - stringBuilder.AppendLine(String.Format("\t\t\tDevice TYPE {0}", oclDev._CL_DEVICE_TYPE)); - } - } - Helpers.ConsolePrint(TAG, stringBuilder.ToString()); - } - } - - #endregion OpenCL Query - - - #endregion // NEW IMPLEMENTATION - - } -} diff --git a/NiceHashMiner/Devices/CudaDevice.cs b/NiceHashMiner/Devices/CudaDevice.cs index 9d0097b..f8d4dbb 100644 --- a/NiceHashMiner/Devices/CudaDevice.cs +++ b/NiceHashMiner/Devices/CudaDevice.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Devices { [Serializable] @@ -28,22 +26,13 @@ public string GetName() { return String.Format("{0} {1}", VendorName, DeviceName); } - private bool _isEtherumCapable = false; - private bool _isEtherumCapableInit = false; public bool IsEtherumCapable() { - if (!_isEtherumCapableInit) { - _isEtherumCapableInit = true; - _isEtherumCapable = SM_major == 3 || SM_major == 5 || SM_major == 6; - // check if 2GB device memory - _isEtherumCapable = _isEtherumCapable && DeviceGlobalMemory >= ComputeDevice.MEMORY_2GB; - - // exception devices - if (DeviceName.Contains("750") && DeviceName.Contains("Ti")) { - Helpers.ConsolePrint("CudaDevice", "GTX 750Ti found! By default this device will be disabled for ethereum as it is generally too slow to mine on it."); - _isEtherumCapable = false; - } + // exception devices + if (DeviceName.Contains("750") && DeviceName.Contains("Ti")) { + Helpers.ConsolePrint("CudaDevice", "GTX 750Ti found! By default this device will be disabled for ethereum as it is generally too slow to mine on it."); + return false; } - return _isEtherumCapable; + return DeviceGlobalMemory >= ComputeDevice.MEMORY_3GB && SM_major >= 3; } } } diff --git a/NiceHashMiner/Devices/GroupAlgorithms.cs b/NiceHashMiner/Devices/GroupAlgorithms.cs index df4a886..7947cf4 100644 --- a/NiceHashMiner/Devices/GroupAlgorithms.cs +++ b/NiceHashMiner/Devices/GroupAlgorithms.cs @@ -1,4 +1,5 @@ -using NiceHashMiner.Enums; +using NiceHashMiner.Configs; +using NiceHashMiner.Enums; using System; using System.Collections.Generic; using System.Text; @@ -10,103 +11,325 @@ namespace NiceHashMiner.Devices { /// public static class GroupAlgorithms { - private static Dictionary> _keys = new Dictionary>(); + private static Dictionary> CreateForDevice(ComputeDevice device) { + if (device != null) { + var algoSettings = CreateDefaultsForGroup(device.DeviceGroupType); + if (algoSettings != null) { + if (device.DeviceType == DeviceType.AMD) { + // sgminer stuff + if (algoSettings.ContainsKey(MinerBaseType.sgminer)) { + var sgminerAlgos = algoSettings[MinerBaseType.sgminer]; + int Lyra2REv2_Index = sgminerAlgos.FindIndex((el) => el.NiceHashID == AlgorithmType.Lyra2REv2); + int NeoScrypt_Index = sgminerAlgos.FindIndex((el) => el.NiceHashID == AlgorithmType.NeoScrypt); + int CryptoNight_Index = sgminerAlgos.FindIndex((el) => el.NiceHashID == AlgorithmType.CryptoNight); - public static Dictionary CreateDefaultsForGroup(DeviceGroupType deviceGroupType) { + // Check for optimized version + if (Lyra2REv2_Index > -1) { + sgminerAlgos[Lyra2REv2_Index].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 64 --thread-concurrency 0 --worksize 64 --gpu-threads 2"; + } + if (!device.Codename.Contains("Tahiti") && NeoScrypt_Index > -1) { + sgminerAlgos[NeoScrypt_Index].ExtraLaunchParameters = AmdGpuDevice.DefaultParam + "--nfactor 10 --xintensity 2 --thread-concurrency 8192 --worksize 64 --gpu-threads 2"; + Helpers.ConsolePrint("ComputeDevice", "The GPU detected (" + device.Codename + ") is not Tahiti. Changing default gpu-threads to 2."); + } + if (CryptoNight_Index > -1 && device.Name.Contains("Hawaii")) { + sgminerAlgos[CryptoNight_Index].ExtraLaunchParameters = "--rawintensity 640 -w 8 -g 2"; + } + } + + // Ellesmere, Polaris + // Ellesmere sgminer workaround, keep this until sgminer is fixed to work with Ellesmere + if ((device.Codename.Contains("Ellesmere") || device.InfSection.ToLower().Contains("polaris"))) { + foreach (var algosInMiner in algoSettings) { + foreach (var algo in algosInMiner.Value) { + // disable all algos in list + if (algo.NiceHashID == AlgorithmType.Decred || algo.NiceHashID == AlgorithmType.Lbry) { + algo.Enabled = false; + } + } + } + } + // non sgminer optimizations + if (algoSettings.ContainsKey(MinerBaseType.ClaymoreAMD)) { + var ClaymoreAlgos = algoSettings[MinerBaseType.ClaymoreAMD]; + int CryptoNight_Index = ClaymoreAlgos.FindIndex((el) => el.NiceHashID == AlgorithmType.CryptoNight); + if (CryptoNight_Index > -1) { + //string regex_a_3 = "[5|6][0-9][0-9][0-9]"; + List a_4 = new List() { + "270", + "270x", + "280", + "280x", + "290", + "290x", + "370", + "380", + "390", + "470", + "480"}; + foreach (var namePart in a_4) { + if (device.Name.Contains(namePart)) { + ClaymoreAlgos[CryptoNight_Index].ExtraLaunchParameters = "-a 4"; + break; + } + } + } + } + + // drivers algos issue + if (device.DriverDisableAlgos) { + algoSettings = FilterMinerAlgos(algoSettings, new List { AlgorithmType.NeoScrypt, AlgorithmType.Lyra2REv2 }); + } + + // disable by default + { + var minerBases = new List() { MinerBaseType.ethminer, MinerBaseType.OptiminerAMD }; + foreach (var minerKey in minerBases) { + if (algoSettings.ContainsKey(minerKey)) { + foreach (var algo in algoSettings[minerKey]) { + algo.Enabled = false; + } + } + } + if (algoSettings.ContainsKey(MinerBaseType.sgminer)) { + foreach (var algo in algoSettings[MinerBaseType.sgminer]) { + if (algo.NiceHashID == AlgorithmType.DaggerHashimoto) { + algo.Enabled = false; + } + } + } + if (algoSettings.ContainsKey(MinerBaseType.ClaymoreAMD)) { + foreach (var algo in algoSettings[MinerBaseType.ClaymoreAMD]) { + if (algo.NiceHashID == AlgorithmType.CryptoNight) { + algo.Enabled = false; + } + } + } + } + } // END AMD case + + // check if it is Etherum capable + if (device.IsEtherumCapale == false) { + algoSettings = FilterMinerAlgos(algoSettings, new List { AlgorithmType.DaggerHashimoto }); + } + + if (algoSettings.ContainsKey(MinerBaseType.ccminer_alexis)) { + foreach (var unstable_algo in algoSettings[MinerBaseType.ccminer_alexis]) { + unstable_algo.Enabled = false; + } + } + if (algoSettings.ContainsKey(MinerBaseType.experimental)) { + foreach (var unstable_algo in algoSettings[MinerBaseType.experimental]) { + unstable_algo.Enabled = false; + } + } + + // This is not needed anymore after excavator v1.1.4a + //if (device.IsSM50() && algoSettings.ContainsKey(MinerBaseType.excavator)) { + // int Equihash_index = algoSettings[MinerBaseType.excavator].FindIndex((algo) => algo.NiceHashID == AlgorithmType.Equihash); + // if (Equihash_index > -1) { + // // -c1 1 needed for SM50 to work ATM + // algoSettings[MinerBaseType.excavator][Equihash_index].ExtraLaunchParameters = "-c1 1"; + // } + //} + // nheqminer exceptions scope + { + const MinerBaseType minerBaseKey = MinerBaseType.nheqminer; + if (algoSettings.ContainsKey(minerBaseKey) && device.Name.Contains("GTX") + && (device.Name.Contains("560") || device.Name.Contains("650") || device.Name.Contains("680") || device.Name.Contains("770")) + ) { + algoSettings = FilterMinerBaseTypes(algoSettings, new List() { minerBaseKey }); + } + } + } // END algoSettings != null + return algoSettings; + } + return null; + } + + public static List CreateForDeviceList(ComputeDevice device) { + List ret = new List(); + var retDict = CreateForDevice(device); + if (retDict != null) { + foreach (var kvp in retDict) { + ret.AddRange(kvp.Value); + } + } + return ret; + } + + public static Dictionary> CreateDefaultsForGroup(DeviceGroupType deviceGroupType) { if (DeviceGroupType.CPU == deviceGroupType) { - return new Dictionary() { - { AlgorithmType.Lyra2RE, new Algorithm(AlgorithmType.Lyra2RE, "lyra2") }, - { AlgorithmType.Hodl, new Algorithm(AlgorithmType.Hodl, "hodl") }, - { AlgorithmType.CryptoNight, new Algorithm(AlgorithmType.CryptoNight, "cryptonight") /* NOT NEDDED { ExtraLaunchParameters = "--no-extranonce"}*/ } + return new Dictionary>() { + { MinerBaseType.XmrStackCPU, + new List() { + new Algorithm(MinerBaseType.XmrStackCPU, AlgorithmType.CryptoNight, "cryptonight") + } + } }; } if (DeviceGroupType.AMD_OpenCL == deviceGroupType) { - // DisableAMDTempControl = false; so temperature params are enabled by default, not sure if TemperatureParam should be lastly appended - string DefaultParam = AmdGpuDevice.DefaultParam + AmdGpuDevice.TemperatureParam; - return new Dictionary() { - { AlgorithmType.X13 , new Algorithm(AlgorithmType.X13, "x13") - { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 64 --thread-concurrency 0 --worksize 64 --gpu-threads 2" } }, - { AlgorithmType.Keccak , new Algorithm(AlgorithmType.Keccak, "keccak") - { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 300 --thread-concurrency 0 --worksize 64 --gpu-threads 1" } }, - { AlgorithmType.X15 , new Algorithm(AlgorithmType.X15, "x15") - { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 64 --thread-concurrency 0 --worksize 64 --gpu-threads 2" } }, - { AlgorithmType.Nist5 , new Algorithm(AlgorithmType.Nist5, "nist5") - { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 16 --thread-concurrency 0 --worksize 64 --gpu-threads 2" } }, - { AlgorithmType.NeoScrypt , new Algorithm(AlgorithmType.NeoScrypt, "neoscrypt") - { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 2 --thread-concurrency 8192 --worksize 64 --gpu-threads 4" } }, - { AlgorithmType.WhirlpoolX , new Algorithm(AlgorithmType.WhirlpoolX, "whirlpoolx") - { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 64 --thread-concurrency 0 --worksize 128 --gpu-threads 2" } }, - { AlgorithmType.Qubit , new Algorithm(AlgorithmType.Qubit, "qubitcoin") - { ExtraLaunchParameters = DefaultParam + "--intensity 18 --worksize 64 --gpu-threads 2" } }, - { AlgorithmType.Quark , new Algorithm(AlgorithmType.Quark, "quarkcoin") - { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 1024 --thread-concurrency 0 --worksize 64 --gpu-threads 1" } }, - { AlgorithmType.Lyra2REv2 , new Algorithm(AlgorithmType.Lyra2REv2, "Lyra2REv2") - { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 160 --thread-concurrency 0 --worksize 64 --gpu-threads 1" } }, - { AlgorithmType.Blake256r8 , new Algorithm(AlgorithmType.Blake256r8, "blakecoin") - { ExtraLaunchParameters = DefaultParam + "--intensity 24 --worksize 128 --gpu-threads 2" } }, - { AlgorithmType.Blake256r14 , new Algorithm(AlgorithmType.Blake256r14, "blake") - { ExtraLaunchParameters = DefaultParam + "--intensity 24 --worksize 128 --gpu-threads 2" } }, - { AlgorithmType.Blake256r8vnl , new Algorithm(AlgorithmType.Blake256r8vnl, "vanilla") - { ExtraLaunchParameters = DefaultParam + "--intensity 24 --worksize 128 --gpu-threads 2" } }, - { AlgorithmType.DaggerHashimoto , new Algorithm(AlgorithmType.DaggerHashimoto, "daggerhashimoto") }, - { AlgorithmType.Decred , new Algorithm(AlgorithmType.Decred, "decred") - { ExtraLaunchParameters = "--gpu-threads 1 --remove-disabled --xintensity 256 --lookup-gap 2 --worksize 64" } } + // DisableAMDTempControl = false; TemperatureParam must be appended lastly + string RemDis = " --remove-disabled "; + string DefaultParam = RemDis + AmdGpuDevice.DefaultParam; + return new Dictionary>() { + { MinerBaseType.sgminer, + new List() { + //new Algorithm(MinerBaseType.sgminer, AlgorithmType.NeoScrypt, "neoscrypt") { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 2 --thread-concurrency 8192 --worksize 64 --gpu-threads 4" }, + //new Algorithm(MinerBaseType.sgminer, AlgorithmType.Lyra2REv2, "Lyra2REv2") { ExtraLaunchParameters = DefaultParam + "--nfactor 10 --xintensity 160 --thread-concurrency 0 --worksize 64 --gpu-threads 1" }, + new Algorithm(MinerBaseType.sgminer, AlgorithmType.DaggerHashimoto, "ethash") { ExtraLaunchParameters = RemDis + "--xintensity 512 -w 192 -g 1" }, + new Algorithm(MinerBaseType.sgminer, AlgorithmType.Decred, "decred") { ExtraLaunchParameters = RemDis + "--gpu-threads 1 --xintensity 256 --lookup-gap 2 --worksize 64" }, + new Algorithm(MinerBaseType.sgminer, AlgorithmType.Lbry, "lbry") { ExtraLaunchParameters = DefaultParam + "--xintensity 512 --worksize 128 --gpu-threads 2" }, + new Algorithm(MinerBaseType.sgminer, AlgorithmType.CryptoNight, "cryptonight") { ExtraLaunchParameters = DefaultParam + "--rawintensity 512 -w 4 -g 2" }, + new Algorithm(MinerBaseType.sgminer, AlgorithmType.Pascal, "pascal") { ExtraLaunchParameters = DefaultParam + "--intensity 21 -w 64 -g 2" }, + new Algorithm(MinerBaseType.sgminer, AlgorithmType.X11Gost, "sibcoin-mod") { ExtraLaunchParameters = DefaultParam + "--intensity 16 -w 64 -g 2" } + } + }, + { MinerBaseType.ClaymoreAMD, + new List() { + new Algorithm(MinerBaseType.ClaymoreAMD, AlgorithmType.CryptoNight, "cryptonight"), + new Algorithm(MinerBaseType.ClaymoreAMD, AlgorithmType.Equihash, "equihash"), + new Algorithm(MinerBaseType.ClaymoreAMD, AlgorithmType.DaggerHashimoto, "") + } + }, + { MinerBaseType.OptiminerAMD, + new List() { + new Algorithm(MinerBaseType.OptiminerAMD, AlgorithmType.Equihash, "equihash") + } + }, }; } // NVIDIA if (DeviceGroupType.NVIDIA_2_1 == deviceGroupType || DeviceGroupType.NVIDIA_3_x == deviceGroupType || DeviceGroupType.NVIDIA_5_x == deviceGroupType || DeviceGroupType.NVIDIA_6_x == deviceGroupType) { - var ret = new Dictionary { - { AlgorithmType.X13 , new Algorithm(AlgorithmType.X13, "x13") }, - { AlgorithmType.Keccak , new Algorithm(AlgorithmType.Keccak, "keccak") }, - { AlgorithmType.X15 , new Algorithm(AlgorithmType.X15, "x15") }, - { AlgorithmType.Nist5 , new Algorithm(AlgorithmType.Nist5, "nist5") }, - { AlgorithmType.NeoScrypt , new Algorithm(AlgorithmType.NeoScrypt, "neoscrypt") }, - { AlgorithmType.WhirlpoolX , new Algorithm(AlgorithmType.WhirlpoolX, "whirlpoolx") }, - { AlgorithmType.Qubit , new Algorithm(AlgorithmType.Qubit, "qubit") }, - { AlgorithmType.Quark , new Algorithm(AlgorithmType.Quark, "quark") }, - { AlgorithmType.Lyra2RE , new Algorithm(AlgorithmType.Lyra2RE, "lyra2") }, - { AlgorithmType.Lyra2REv2 , new Algorithm(AlgorithmType.Lyra2REv2, "lyra2v2") }, - { AlgorithmType.Blake256r8 , new Algorithm(AlgorithmType.Blake256r8, "blakecoin") }, - { AlgorithmType.Blake256r14 , new Algorithm(AlgorithmType.Blake256r14, "blake") }, - { AlgorithmType.Blake256r8vnl , new Algorithm(AlgorithmType.Blake256r8vnl, "vanilla") }, - { AlgorithmType.DaggerHashimoto , new Algorithm(AlgorithmType.DaggerHashimoto, "daggerhashimoto") }, - { AlgorithmType.Decred , new Algorithm(AlgorithmType.Decred, "decred") }, - { AlgorithmType.CryptoNight, new Algorithm(AlgorithmType.CryptoNight, "cryptonight") } + var ToRemoveAlgoTypes = new List(); + var ToRemoveMinerTypes = new List(); + var ret = new Dictionary>() { + { MinerBaseType.ccminer, + new List() { + new Algorithm(MinerBaseType.ccminer, AlgorithmType.NeoScrypt, "neoscrypt"), + new Algorithm(MinerBaseType.ccminer, AlgorithmType.Lyra2REv2, "lyra2v2"), + new Algorithm(MinerBaseType.ccminer, AlgorithmType.Decred, "decred"), + new Algorithm(MinerBaseType.ccminer, AlgorithmType.CryptoNight, "cryptonight"), + new Algorithm(MinerBaseType.ccminer, AlgorithmType.Lbry, "lbry"), + new Algorithm(MinerBaseType.ccminer, AlgorithmType.X11Gost, "sib") + } + }, + { MinerBaseType.ccminer_alexis, + new List() { + new Algorithm(MinerBaseType.ccminer_alexis, AlgorithmType.X11Gost, "sib") + } + }, + { MinerBaseType.ethminer, + new List() { + new Algorithm(MinerBaseType.ethminer, AlgorithmType.DaggerHashimoto, "daggerhashimoto") + } + }, + { MinerBaseType.nheqminer, + new List() { + new Algorithm(MinerBaseType.nheqminer, AlgorithmType.Equihash, "equihash") + } + }, + { MinerBaseType.excavator, + new List() { + new Algorithm(MinerBaseType.excavator, AlgorithmType.Equihash, "equihash"), + new Algorithm(MinerBaseType.excavator, AlgorithmType.Pascal, "pascal") + } + }, + { MinerBaseType.experimental, + new List() { + new Algorithm(MinerBaseType.experimental, AlgorithmType.NeoScrypt, "neoscrypt") + } + }, }; - if(DeviceGroupType.NVIDIA_2_1 == deviceGroupType) { - // minerName change => "whirlpoolx" => "whirlpool" - ret[AlgorithmType.WhirlpoolX] = new Algorithm(AlgorithmType.WhirlpoolX, "whirlpool"); // Needed for new tpruvot's ccminer - // disable/remove neoscrypt, daggerhashimoto - ret.Remove(AlgorithmType.NeoScrypt); - ret.Remove(AlgorithmType.DaggerHashimoto); - - ret.Remove(AlgorithmType.Lyra2RE); - ret.Remove(AlgorithmType.Lyra2REv2); - //ret.Remove(AlgorithmType.CryptoNight); + if (DeviceGroupType.NVIDIA_6_x == deviceGroupType) { + ToRemoveAlgoTypes.AddRange(new AlgorithmType[] { + AlgorithmType.NeoScrypt, + AlgorithmType.CryptoNight + }); + } + if (DeviceGroupType.NVIDIA_6_x != deviceGroupType) { + ToRemoveMinerTypes.Add(MinerBaseType.experimental); + } + if (DeviceGroupType.NVIDIA_6_x == deviceGroupType || DeviceGroupType.NVIDIA_5_x == deviceGroupType) { + ToRemoveMinerTypes.AddRange(new MinerBaseType[] { + MinerBaseType.nheqminer + }); } - if (DeviceGroupType.NVIDIA_3_x == deviceGroupType) { - // minerName change => "whirlpoolx" => "whirlpool" - ret[AlgorithmType.WhirlpoolX] = new Algorithm(AlgorithmType.WhirlpoolX, "whirlpool"); // Needed for new tpruvot's ccminer - // disable/remove neoscrypt - ret.Remove(AlgorithmType.NeoScrypt); - ret.Remove(AlgorithmType.Lyra2RE); - ret.Remove(AlgorithmType.Lyra2REv2); - //ret.Remove(AlgorithmType.CryptoNight); + if(DeviceGroupType.NVIDIA_2_1 == deviceGroupType || DeviceGroupType.NVIDIA_3_x == deviceGroupType) { + ToRemoveAlgoTypes.AddRange(new AlgorithmType[] { + AlgorithmType.NeoScrypt, + AlgorithmType.Lyra2RE, + AlgorithmType.Lyra2REv2 + }); + ToRemoveMinerTypes.AddRange(new MinerBaseType[] { + MinerBaseType.eqm, + MinerBaseType.excavator + }); } - return ret; + if (DeviceGroupType.NVIDIA_2_1 == deviceGroupType) { + ToRemoveAlgoTypes.AddRange(new AlgorithmType[] { + AlgorithmType.DaggerHashimoto, + AlgorithmType.CryptoNight, + AlgorithmType.Pascal, + AlgorithmType.X11Gost + }); + } + + // filter unused + var finalRet = FilterMinerAlgos(ret, ToRemoveAlgoTypes, new List() { MinerBaseType.ccminer }); + finalRet = FilterMinerBaseTypes(finalRet, ToRemoveMinerTypes); + + return finalRet; } return null; } + static Dictionary> FilterMinerBaseTypes(Dictionary> minerAlgos, List toRemove) { + var finalRet = new Dictionary>(); + foreach (var kvp in minerAlgos) { + if (toRemove.IndexOf(kvp.Key) == -1) { + finalRet[kvp.Key] = kvp.Value; + } + } + return finalRet; + } - public static List GetAlgorithmKeysForGroup(DeviceGroupType deviceGroupType) { - var ret = CreateDefaultsForGroup(deviceGroupType); - if (ret != null) { - return new List (ret.Keys); + static Dictionary> FilterMinerAlgos(Dictionary> minerAlgos, List toRemove, List toRemoveBase = null) { + var finalRet = new Dictionary>(); + if (toRemoveBase == null) { // all minerbasekeys + foreach (var kvp in minerAlgos) { + var algoList = kvp.Value.FindAll((a) => toRemove.IndexOf(a.NiceHashID) == -1); + if (algoList.Count > 0) { + finalRet[kvp.Key] = algoList; + } + } + } else { + foreach (var kvp in minerAlgos) { + // filter only if base key is defined + if (toRemoveBase.IndexOf(kvp.Key) > -1) { + var algoList = kvp.Value.FindAll((a) => toRemove.IndexOf(a.NiceHashID) == -1); + if (algoList.Count > 0) { + finalRet[kvp.Key] = algoList; + } + } else { // keep all + finalRet[kvp.Key] = kvp.Value; + } + } } - return null; + return finalRet; } + //static List GetKeysForMinerAlgosGroup(Dictionary> minerAlgos) { + // List ret = new List(); + // foreach (var kvp in minerAlgos) { + // var currentKeys = kvp.Value.ConvertAll((a) => a.NiceHashID); + // foreach (var key in currentKeys) { + // if (ret.Contains(key) == false) { + // ret.Add(key); + // } + // } + // } + // return ret; + //} } } diff --git a/NiceHashMiner/Devices/GroupNames.cs b/NiceHashMiner/Devices/GroupNames.cs index 3b999e8..a206bb8 100644 --- a/NiceHashMiner/Devices/GroupNames.cs +++ b/NiceHashMiner/Devices/GroupNames.cs @@ -8,7 +8,7 @@ namespace NiceHashMiner.Devices static public class GroupNames { private static readonly string[] _names = { - "CPU", // TODO we can have more then one CPU + "CPU", // we can have more then one CPU "AMD_OpenCL", "NVIDIA2.1", "NVIDIA3.x", @@ -16,26 +16,24 @@ static public class GroupNames "NVIDIA6.x", }; - private static readonly string[] _namesGeneral = { - "CPU", - "AMD", - "NVIDIA", - "NVIDIA", - "NVIDIA", - "NVIDIA", - }; - - public static string GetName(DeviceGroupType type) { return _names[(int)type]; } - - public static string GetNameGeneral(DeviceGroupType type) { return _namesGeneral[(int)type]; } - - public static DeviceGroupType GetType(string name) { - int i = 0; - for (; i < _names.Length; ++i) { - if (name.Contains(_names[i])) break; + public static string GetGroupName(DeviceGroupType type, int id) { + if(DeviceGroupType.CPU == type) { + return "CPU"+id; + } else if ((int)type < _names.Length && (int)type >= 0) { + return _names[(int)type]; } - return (DeviceGroupType)i; + return "UnknownGroup"; } + public static string GetNameGeneral(DeviceType type) { + if(DeviceType.CPU == type) { + return "CPU"; + } else if(DeviceType.NVIDIA == type) { + return "NVIDIA"; + } else if (DeviceType.AMD == type) { + return "AMD"; + } + return "UnknownDeviceType"; + } } } diff --git a/NiceHashMiner/Devices/OpenCLDevice.cs b/NiceHashMiner/Devices/OpenCLDevice.cs index b4c707d..fc4592d 100644 --- a/NiceHashMiner/Devices/OpenCLDevice.cs +++ b/NiceHashMiner/Devices/OpenCLDevice.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Devices { [Serializable] @@ -10,7 +8,7 @@ public class OpenCLDevice { public uint DeviceID; public string _CL_DEVICE_NAME; public string _CL_DEVICE_TYPE; - public ulong _CL_DEVICE_GLOBAL_MEM_SIZE; + public ulong _CL_DEVICE_GLOBAL_MEM_SIZE = 0; public string _CL_DEVICE_VENDOR; public string _CL_DEVICE_VERSION; public string _CL_DRIVER_VERSION; diff --git a/NiceHashMiner/Enums/AlgorithmBenchmarkSettingsType.cs b/NiceHashMiner/Enums/AlgorithmBenchmarkSettingsType.cs index 96e1c89..f3bb3d4 100644 --- a/NiceHashMiner/Enums/AlgorithmBenchmarkSettingsType.cs +++ b/NiceHashMiner/Enums/AlgorithmBenchmarkSettingsType.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Enums { public enum AlgorithmBenchmarkSettingsType : int { diff --git a/NiceHashMiner/Enums/AlgorithmType.cs b/NiceHashMiner/Enums/AlgorithmType.cs index 44068ed..a180c28 100644 --- a/NiceHashMiner/Enums/AlgorithmType.cs +++ b/NiceHashMiner/Enums/AlgorithmType.cs @@ -13,30 +13,66 @@ public enum AlgorithmType : int INVALID = -2, NONE = -1, #region NiceHashAPI + //Scrypt_UNUSED = 0, + //SHA256_UNUSED = 1, + //ScryptNf_UNUSED = 2, + //X11_UNUSED = 3, + //X13 = 4, + //Keccak = 5, + //X15 = 6, + //Nist5 = 7, + //NeoScrypt = 8, + //Lyra2RE = 9, + //WhirlpoolX = 10, + //Qubit = 11, + //Quark = 12, + //Axiom_UNUSED = 13, + //Lyra2REv2 = 14, + //ScryptJaneNf16_UNUSED = 15, + //Blake256r8 = 16, + //Blake256r14 = 17, // NOT USED ANYMORE? + //Blake256r8vnl = 18, + //Hodl = 19, + //DaggerHashimoto = 20, + //Decred = 21, + //CryptoNight = 22, + //Lbry = 23, + //Equihash = 24, + //Pascal = 25 + // UNUSED START Scrypt_UNUSED = 0, SHA256_UNUSED = 1, ScryptNf_UNUSED = 2, X11_UNUSED = 3, - X13 = 4, - Keccak = 5, - X15 = 6, - Nist5 = 7, + X13_UNUSED = 4, + Keccak_UNUSED = 5, + X15_UNUSED = 6, + Nist5_UNUSED = 7, + + WhirlpoolX_UNUSED = 10, + Qubit_UNUSED = 11, + Quark_UNUSED = 12, + Axiom_UNUSED = 13, + + ScryptJaneNf16_UNUSED = 15, + Blake256r8_UNUSED = 16, + Blake256r14_UNUSED = 17, + Blake256r8vnl_UNUSED = 18, + // UNUSED END + NeoScrypt = 8, Lyra2RE = 9, - WhirlpoolX = 10, - Qubit = 11, - Quark = 12, - Axiom_UNUSED = 13, + Lyra2REv2 = 14, - ScryptJaneNf16_UNUSED = 15, - Blake256r8 = 16, - Blake256r14 = 17, - Blake256r8vnl = 18, + Hodl = 19, DaggerHashimoto = 20, Decred = 21, - // TODO check CryptoNight CryptoNight = 22, + Lbry = 23, + Equihash = 24, + Pascal = 25, + X11Gost = 26 #endregion // NiceHashAPI } } diff --git a/NiceHashMiner/Enums/BenchmarkProcessStatus.cs b/NiceHashMiner/Enums/BenchmarkProcessStatus.cs index e06cbd7..b712439 100644 --- a/NiceHashMiner/Enums/BenchmarkProcessStatus.cs +++ b/NiceHashMiner/Enums/BenchmarkProcessStatus.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Enums { public enum BenchmarkProcessStatus { @@ -11,6 +9,7 @@ public enum BenchmarkProcessStatus { Running, Killing, DoneKilling, + Finished, Success } } diff --git a/NiceHashMiner/Enums/CPUExtensionType.cs b/NiceHashMiner/Enums/CPUExtensionType.cs index eb09588..dce216e 100644 --- a/NiceHashMiner/Enums/CPUExtensionType.cs +++ b/NiceHashMiner/Enums/CPUExtensionType.cs @@ -5,11 +5,12 @@ namespace NiceHashMiner.Enums { public enum CPUExtensionType : int { - // 0 - automatic, 1 - AVX2, 2 - AVX, 3 - AES, 4 - SSE2 Automatic = 0, - AVX2 = 1, - AVX = 2, - AES = 3, - SSE2 = 4 + AVX2_AES = 1, + AVX2 = 2, + AVX_AES = 3, + AVX = 4, + AES = 5, + SSE2 = 6, } } diff --git a/NiceHashMiner/Enums/ComputePlatformType.cs b/NiceHashMiner/Enums/ComputePlatformType.cs deleted file mode 100644 index ce2db6e..0000000 --- a/NiceHashMiner/Enums/ComputePlatformType.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NiceHashMiner.Enums { - public enum ComputePlatformType { - NONE, - Intel, - NVIDIA, - AMD - } -} diff --git a/NiceHashMiner/Enums/DagGenerationType.cs b/NiceHashMiner/Enums/DagGenerationType.cs index aff3e00..77cf121 100644 --- a/NiceHashMiner/Enums/DagGenerationType.cs +++ b/NiceHashMiner/Enums/DagGenerationType.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Enums { diff --git a/NiceHashMiner/Enums/DeviceMiningStatus.cs b/NiceHashMiner/Enums/DeviceMiningStatus.cs new file mode 100644 index 0000000..6b191c6 --- /dev/null +++ b/NiceHashMiner/Enums/DeviceMiningStatus.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Enums { + public enum DeviceMiningStatus { + Disabled, + NoEnabledAlgorithms, + DeviceNull, + CanMine + } +} diff --git a/NiceHashMiner/Enums/DeviceType.cs b/NiceHashMiner/Enums/DeviceType.cs index 9607111..7c5e158 100644 --- a/NiceHashMiner/Enums/DeviceType.cs +++ b/NiceHashMiner/Enums/DeviceType.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Enums { public enum DeviceType { - CPU, + CPU = 0, NVIDIA, AMD } diff --git a/NiceHashMiner/Enums/MinerAPIReadStatus.cs b/NiceHashMiner/Enums/MinerAPIReadStatus.cs index 8b2ea8e..5eb977a 100644 --- a/NiceHashMiner/Enums/MinerAPIReadStatus.cs +++ b/NiceHashMiner/Enums/MinerAPIReadStatus.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Enums { public enum MinerAPIReadStatus { diff --git a/NiceHashMiner/Enums/MinerBaseType.cs b/NiceHashMiner/Enums/MinerBaseType.cs new file mode 100644 index 0000000..c6aca8b --- /dev/null +++ b/NiceHashMiner/Enums/MinerBaseType.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Enums { + + /// + /// Do not delete obsolete enums! Always add new ones before the END enum. + /// + public enum MinerBaseType { + NONE = 0, + cpuminer, + ccminer, + sgminer, + nheqminer, + eqm, + ethminer, + ClaymoreAMD, + OptiminerAMD, + excavator, + XmrStackCPU, + ccminer_alexis, + experimental, + END + } +} diff --git a/NiceHashMiner/Enums/MinerOptionFlagType.cs b/NiceHashMiner/Enums/MinerOptionFlagType.cs new file mode 100644 index 0000000..fdfc755 --- /dev/null +++ b/NiceHashMiner/Enums/MinerOptionFlagType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Enums { + // indicates if uni flag (no parameter), single param or multi param + public enum MinerOptionFlagType { + Uni, + SingleParam, + MultiParam, + DuplicateMultiParam // the flag is multiplied + } +} diff --git a/NiceHashMiner/Enums/MinerStopType.cs b/NiceHashMiner/Enums/MinerStopType.cs index c0729f1..21b2f53 100644 --- a/NiceHashMiner/Enums/MinerStopType.cs +++ b/NiceHashMiner/Enums/MinerStopType.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Enums { public enum MinerStopType { diff --git a/NiceHashMiner/Enums/MinerType.cs b/NiceHashMiner/Enums/MinerType.cs new file mode 100644 index 0000000..6c1cda6 --- /dev/null +++ b/NiceHashMiner/Enums/MinerType.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Enums { + public enum MinerType { + NONE, + ccminer, + ccminer_CryptoNight, + ethminer_OCL, + ethminer_CUDA, + sgminer, + cpuminer_opt, + nheqminer_CPU, + nheqminer_CUDA, + nheqminer_AMD, + eqm_CPU, + eqm_CUDA, + ClaymoreZcash, + ClaymoreCryptoNight, + OptiminerZcash, + excavator, + ClaymoreDual, + END + } +} diff --git a/NiceHashMiner/Enums/NHMConectionType.cs b/NiceHashMiner/Enums/NHMConectionType.cs new file mode 100644 index 0000000..c45f2ad --- /dev/null +++ b/NiceHashMiner/Enums/NHMConectionType.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Enums { + public enum NHMConectionType { + NONE, + STRATUM_TCP, + STRATUM_SSL, + LOCKED // inhouse miners that are locked on NH (our eqm) + } +} diff --git a/NiceHashMiner/Enums/Use3rdPartyMiners.cs b/NiceHashMiner/Enums/Use3rdPartyMiners.cs new file mode 100644 index 0000000..9812fd3 --- /dev/null +++ b/NiceHashMiner/Enums/Use3rdPartyMiners.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Enums { + public enum Use3rdPartyMiners { + NOT_SET = 0, + NO, + YES + } +} diff --git a/NiceHashMiner/Ethereum.cs b/NiceHashMiner/Ethereum.cs deleted file mode 100644 index 23eb646..0000000 --- a/NiceHashMiner/Ethereum.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using System.IO; -using Newtonsoft.Json; -using System.Net; -using System.Net.Sockets; -using System.Windows.Forms; -using NiceHashMiner.Configs; -using NiceHashMiner.Miners; - -namespace NiceHashMiner -{ - public class EthminerReader - { - /// - /// Initialize ethminer instance that listens on certain UDP port for speed and DAG progress reports. You may have multiple instances, - /// but each one must be listening on another port! - /// - /// UDP listening port. - public EthminerReader(int port) - { - bindPort = port; - } - - /// - /// Start listening. - /// - public void Start() - { - isRunning = true; - speed = 0; - DAGprogress = 0; - lastActiveTime = DateTime.Now; - ipep = new IPEndPoint(IPAddress.Loopback, bindPort); - client = new UdpClient(ipep); - workerTimer = new Timer(); - workerTimer.Tick += workerTimer_Tick; - workerTimer.Interval = 50; - workerTimer.Start(); - } - - /// - /// Stop listening. Call this before application exits or if you are about to restart ethminer reader. - /// - public void Stop() - { - isRunning = false; - speed = 0; - DAGprogress = 0; - workerTimer.Stop(); - client.Close(); - client = null; - } - - /// - /// Get if miner is still running. - /// - /// State of miner. - public bool GetIsRunning() - { - return isRunning; - } - - /// - /// Get speed of miner in MH/s. - /// - /// Speed of miner in MH/s. - public double GetSpeed() - { - return speed; - } - - /// - /// Get DAG progress in %. It only reports correct progress if ethminer is launched with -D parameter. - /// - /// DAG creation progress in %. When mining, this value is 100. - public uint GetDAGprogress() - { - return DAGprogress; - } - - /// - /// Get DateTime when miner sent UDP status packet. - /// - /// DateTime of last active time. - public DateTime GetLastActiveTime() - { - return lastActiveTime; - } - - public string ByteArrayToString(byte[] ba) - { - StringBuilder hex = new StringBuilder(ba.Length * 2); - foreach (byte b in ba) hex.AppendFormat("{0:x2} ", b); - return hex.ToString(); - } - - #region PRIVATE_PROPERTIES - private IPEndPoint ipep; - private UdpClient client; - private double speed; - private uint DAGprogress; - private int bindPort; - private bool isRunning; - private Timer workerTimer; - private DateTime lastActiveTime; - #endregion - - #region PRIVATE_METHODS - private void workerTimer_Tick(object sender, EventArgs e) - { - try - { - client.Client.Blocking = false; - - if (isRunning && client.Available > 0) - { - byte[] data = client.Receive(ref ipep); - //Helpers.ConsolePrint("DEBUG", "ByteArray: " + ByteArrayToString(data)); - speed = BitConverter.ToDouble(data, 0); - DAGprogress = BitConverter.ToUInt32(data, 8); - lastActiveTime = DateTime.Now; - } - } - catch (Exception ex) - { - Helpers.ConsolePrint("EthminerReader", "Error: " + ex.Message); - } - } - - #endregion - } - - public static class Ethereum - { - public static string EtherMinerPath; - public static string CurrentBlockNum; - - static Ethereum() - { - EtherMinerPath = MinerPaths.ethminer; - CurrentBlockNum = ""; - } - - public static void GetCurrentBlock(string worker) - { - string ret = NiceHashStats.GetNiceHashAPIData("https://etherchain.org/api/blocks/count", worker); - - if (ret == null) - { - Helpers.ConsolePrint(worker, "Failed to obtain current block, using default 1700000."); - CurrentBlockNum = ConfigManager.Instance.GeneralConfig.ethminerDefaultBlockHeight.ToString(); - } - else - { - ret = ret.Substring(ret.LastIndexOf("count") + 7); - CurrentBlockNum = ret.Substring(0, ret.Length - 3); - } - } - } -} diff --git a/NiceHashMiner/ExchangeRateAPI.cs b/NiceHashMiner/ExchangeRateAPI.cs new file mode 100644 index 0000000..46b3406 --- /dev/null +++ b/NiceHashMiner/ExchangeRateAPI.cs @@ -0,0 +1,91 @@ +using Newtonsoft.Json; +using NiceHashMiner.Configs; +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; + +namespace NiceHashMiner { + class ExchangeRateAPI { + public class Result { + public Object algorithms { get; set; } + public Object servers { get; set; } + public Object idealratios { get; set; } + public List> exchanges { get; set; } + public Dictionary exchanges_fiat { get; set; } + } + + public class ExchangeRateJSON { + public Result result { get; set; } + public string method { get; set; } + } + + const string apiUrl = "https://api.nicehash.com/api?method=nicehash.service.info"; + + private static Dictionary exchanges_fiat = null; + private static double USD_BTC_rate = -1; + public static string ActiveDisplayCurrency = "USD"; + + private static bool ConverterActive { + get { return ConfigManager.GeneralConfig.DisplayCurrency != "USD"; } + } + + + public static double ConvertToActiveCurrency(double amount) { + if (!ConverterActive) { + return amount; + } + + // if we are still null after an update something went wrong. just use USD hopefully itll update next tick + if (exchanges_fiat == null || ActiveDisplayCurrency == "USD") { + Helpers.ConsolePrint("CurrencyConverter", "Unable to retrieve update, Falling back to USD"); + return amount; + } + + //Helpers.ConsolePrint("CurrencyConverter", "Current Currency: " + ConfigManager.Instance.GeneralConfig.DisplayCurrency); + double usdExchangeRate = 1.0; + if (exchanges_fiat.TryGetValue(ActiveDisplayCurrency, out usdExchangeRate)) + return amount * usdExchangeRate; + else { + Helpers.ConsolePrint("CurrencyConverter", "Unknown Currency Tag: " + ActiveDisplayCurrency + " falling back to USD rates"); + ActiveDisplayCurrency = "USD"; + return amount; + } + } + + public static double GetUSDExchangeRate() { + if (USD_BTC_rate > 0) { + return USD_BTC_rate; + } + return 0.0; + } + + public static void UpdateAPI(string worker) { + string resp = NiceHashStats.GetNiceHashAPIData(apiUrl, worker); + if (resp != null) { + try { + var LastResponse = JsonConvert.DeserializeObject(resp, Globals.JsonSettings); + // set that we have a response + if (LastResponse != null) { + Result last_result = LastResponse.result; + ActiveDisplayCurrency = ConfigManager.GeneralConfig.DisplayCurrency; + exchanges_fiat = last_result.exchanges_fiat; + // ActiveDisplayCurrency = "USD"; + // check if currency avaliable and fill currency list + foreach (var pair in last_result.exchanges) { + if (pair.ContainsKey("USD") && pair.ContainsKey("coin") && pair["coin"] == "BTC" && pair["USD"] != null) { + USD_BTC_rate = Helpers.ParseDouble(pair["USD"]); + break; + } + } + } + } catch(Exception e) { + Helpers.ConsolePrint("ExchangeRateAPI", "UpdateAPI got Exception: " + e.Message); + } + } else { + Helpers.ConsolePrint("ExchangeRateAPI", "UpdateAPI got NULL"); + } + } + + } +} diff --git a/NiceHashMiner/Forms/Components/AlgorithmSettingsControl.Designer.cs b/NiceHashMiner/Forms/Components/AlgorithmSettingsControl.Designer.cs index 9dd39e4..b015f1b 100644 --- a/NiceHashMiner/Forms/Components/AlgorithmSettingsControl.Designer.cs +++ b/NiceHashMiner/Forms/Components/AlgorithmSettingsControl.Designer.cs @@ -30,7 +30,6 @@ private void InitializeComponent() { this.groupBoxExtraLaunchParameters = new System.Windows.Forms.GroupBox(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.richTextBoxExtraLaunchParameters = new System.Windows.Forms.RichTextBox(); - this.fieldIntensity = new NiceHashMiner.Forms.Components.Field(); this.groupBoxSelectedAlgorithmSettings.SuspendLayout(); this.flowLayoutPanel1.SuspendLayout(); this.groupBoxExtraLaunchParameters.SuspendLayout(); @@ -50,7 +49,6 @@ private void InitializeComponent() { // flowLayoutPanel1 // this.flowLayoutPanel1.Controls.Add(this.field_LessThreads); - this.flowLayoutPanel1.Controls.Add(this.fieldIntensity); this.flowLayoutPanel1.Controls.Add(this.fieldBoxBenchmarkSpeed); this.flowLayoutPanel1.Controls.Add(this.groupBoxExtraLaunchParameters); this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; @@ -77,7 +75,7 @@ private void InitializeComponent() { this.fieldBoxBenchmarkSpeed.BackColor = System.Drawing.Color.Transparent; this.fieldBoxBenchmarkSpeed.EntryText = ""; this.fieldBoxBenchmarkSpeed.LabelText = "Benchmark Speed (H/s):"; - this.fieldBoxBenchmarkSpeed.Location = new System.Drawing.Point(3, 109); + this.fieldBoxBenchmarkSpeed.Location = new System.Drawing.Point(3, 56); this.fieldBoxBenchmarkSpeed.Name = "fieldBoxBenchmarkSpeed"; this.fieldBoxBenchmarkSpeed.Size = new System.Drawing.Size(220, 47); this.fieldBoxBenchmarkSpeed.TabIndex = 1; @@ -86,7 +84,7 @@ private void InitializeComponent() { // this.groupBoxExtraLaunchParameters.Controls.Add(this.pictureBox1); this.groupBoxExtraLaunchParameters.Controls.Add(this.richTextBoxExtraLaunchParameters); - this.groupBoxExtraLaunchParameters.Location = new System.Drawing.Point(3, 162); + this.groupBoxExtraLaunchParameters.Location = new System.Drawing.Point(3, 109); this.groupBoxExtraLaunchParameters.Name = "groupBoxExtraLaunchParameters"; this.groupBoxExtraLaunchParameters.Size = new System.Drawing.Size(217, 101); this.groupBoxExtraLaunchParameters.TabIndex = 14; @@ -112,17 +110,6 @@ private void InitializeComponent() { this.richTextBoxExtraLaunchParameters.TabIndex = 0; this.richTextBoxExtraLaunchParameters.Text = ""; // - // fieldIntensity - // - this.fieldIntensity.AutoSize = true; - this.fieldIntensity.BackColor = System.Drawing.Color.Transparent; - this.fieldIntensity.EntryText = ""; - this.fieldIntensity.LabelText = "Intensity:"; - this.fieldIntensity.Location = new System.Drawing.Point(3, 56); - this.fieldIntensity.Name = "fieldIntensity"; - this.fieldIntensity.Size = new System.Drawing.Size(220, 47); - this.fieldIntensity.TabIndex = 16; - // // AlgorithmSettingsControl // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -149,6 +136,5 @@ private void InitializeComponent() { private Field fieldBoxBenchmarkSpeed; private Field field_LessThreads; private System.Windows.Forms.PictureBox pictureBox1; - private Field fieldIntensity; } } diff --git a/NiceHashMiner/Forms/Components/AlgorithmSettingsControl.cs b/NiceHashMiner/Forms/Components/AlgorithmSettingsControl.cs index 487f106..2232fe3 100644 --- a/NiceHashMiner/Forms/Components/AlgorithmSettingsControl.cs +++ b/NiceHashMiner/Forms/Components/AlgorithmSettingsControl.cs @@ -21,11 +21,8 @@ public partial class AlgorithmSettingsControl : UserControl, AlgorithmsListView. public AlgorithmSettingsControl() { InitializeComponent(); fieldBoxBenchmarkSpeed.SetInputModeDoubleOnly(); - fieldIntensity.SetInputModeDoubleOnly(); field_LessThreads.SetInputModeIntOnly(); - // TODO make sure intensity accepts valid ints based on Device and algo, miner... - fieldIntensity.SetOnTextLeave(textLeaveIntensity); field_LessThreads.SetOnTextLeave(LessThreads_Leave); fieldBoxBenchmarkSpeed.SetOnTextChanged(textChangedBenchmarkSpeed); richTextBoxExtraLaunchParameters.TextChanged += textChangedExtraLaunchParameters; @@ -38,7 +35,6 @@ public void Deselect() { International.GetText("AlgorithmsListView_GroupBox_NONE")); Enabled = false; fieldBoxBenchmarkSpeed.EntryText = ""; - fieldIntensity.EntryText = ""; field_LessThreads.EntryText = ""; richTextBoxExtraLaunchParameters.Text = ""; } @@ -47,9 +43,6 @@ public void InitLocale(ToolTip toolTip1) { field_LessThreads.InitLocale(toolTip1, International.GetText("Form_Settings_General_CPU_LessThreads") + ":", International.GetText("Form_Settings_ToolTip_CPU_LessThreads")); - fieldIntensity.InitLocale(toolTip1, - International.GetText("AlgorithmSettingsControl_Label_Intensity") + ":", - International.GetText("AlgorithmSettingsControl_ToolTip_Intensity")); fieldBoxBenchmarkSpeed.InitLocale(toolTip1, International.GetText("Form_Settings_Algo_BenchmarkSpeed") + ":", International.GetText("Form_Settings_ToolTip_AlgoBenchmarkSpeed")); @@ -79,24 +72,7 @@ public void SetCurrentlySelected(ListViewItem lvi, ComputeDevice computeDevice) this.Enabled = lvi.Checked; groupBoxSelectedAlgorithmSettings.Text = String.Format(International.GetText("AlgorithmsListView_GroupBox"), - algorithm.NiceHashName); ; - - - // no intensity for cpu miners and ccminer_cryptonight - fieldIntensity.Enabled = !( - _computeDevice.DeviceGroupType == DeviceGroupType.CPU - || _computeDevice.DeviceGroupType == DeviceGroupType.AMD_OpenCL - || _currentlySelectedAlgorithm.NiceHashID == AlgorithmType.CryptoNight - || _currentlySelectedAlgorithm.NiceHashID == AlgorithmType.DaggerHashimoto); - if (fieldIntensity.Enabled) { - if (algorithm.Intensity == 0) { - fieldIntensity.EntryText = "0"; - } else { - fieldIntensity.EntryText = algorithm.Intensity.ToString("F8"); - } - } else { - fieldIntensity.EntryText = ""; - } + String.Format("{0} ({1})", algorithm.AlgorithmName, algorithm.MinerBaseTypeName)); ; field_LessThreads.Enabled = _computeDevice.DeviceGroupType == DeviceGroupType.CPU; if (field_LessThreads.Enabled) { @@ -116,39 +92,22 @@ public void HandleCheck(ListViewItem lvi) { } } + public void ChangeSpeed(ListViewItem lvi) + { + if (Object.ReferenceEquals(_currentlySelectedLvi, lvi)) + { + var algorithm = lvi.Tag as Algorithm; + if (algorithm != null) { + fieldBoxBenchmarkSpeed.EntryText = ParseDoubleDefault(algorithm.BenchmarkSpeed); + } + } + } + private bool CanEdit() { return _currentlySelectedAlgorithm != null && _selected; } #region Callbacks Events - // TODO Intensity - private void textLeaveIntensity(object sender, EventArgs e) { - if (!CanEdit()) return; - var deviceType = _computeDevice.DeviceGroupType; - var minerPath = MinersManager.Instance.MinerPathChecker[deviceType].GetOptimizedMinerPath(_currentlySelectedAlgorithm.NiceHashID); - if (MinersManager.Instance.CCMinersIntensitiesBoundries.ContainsKey(minerPath)) { - double min = MinersManager.Instance.CCMinersIntensitiesBoundries[minerPath].Item1; - double max = MinersManager.Instance.CCMinersIntensitiesBoundries[minerPath].Item2; - // parse - double value; - if (Double.TryParse(fieldIntensity.EntryText, out value)) { - if (min <= value && value <= max) { - _currentlySelectedAlgorithm.Intensity = value; - } else if (value != 0) { - _currentlySelectedAlgorithm.Intensity = 0; - MessageBox.Show( - String.Format(International.GetText("AlgorithmSettingsControl_IntensityWaringn"), - min.ToString("F2"), - max.ToString("F2")), - International.GetText("Warning_with_Exclamation"), - MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - } else { - _currentlySelectedAlgorithm.Intensity = 0; - } - //_currentlySelectedAlgorithm.Intensity = fieldIntensity.EntryText.Trim(); - } - } private void textChangedBenchmarkSpeed(object sender, EventArgs e) { if (!CanEdit()) return; double value; @@ -190,19 +149,19 @@ private void textChangedExtraLaunchParameters(object sender, EventArgs e) { } #endregion - private void buttonBenchmark_Click(object sender, EventArgs e) { - var device = new List(); - device.Add(_computeDevice); - var BenchmarkForm = new Form_Benchmark( - BenchmarkPerformanceType.Standard, - false, _currentlySelectedAlgorithm.NiceHashID); - BenchmarkForm.ShowDialog(); - fieldBoxBenchmarkSpeed.EntryText = _currentlySelectedAlgorithm.BenchmarkSpeed.ToString(); - // update lvi speed - if (_currentlySelectedLvi != null) { - _currentlySelectedLvi.SubItems[2].Text = Helpers.FormatSpeedOutput(_currentlySelectedAlgorithm.BenchmarkSpeed); - } - } + //private void buttonBenchmark_Click(object sender, EventArgs e) { + // var device = new List(); + // device.Add(_computeDevice); + // var BenchmarkForm = new Form_Benchmark( + // BenchmarkPerformanceType.Standard, + // false, _currentlySelectedAlgorithm.NiceHashID); + // BenchmarkForm.ShowDialog(); + // fieldBoxBenchmarkSpeed.EntryText = _currentlySelectedAlgorithm.BenchmarkSpeed.ToString(); + // // update lvi speed + // if (_currentlySelectedLvi != null) { + // _currentlySelectedLvi.SubItems[2].Text = Helpers.FormatSpeedOutput(_currentlySelectedAlgorithm.BenchmarkSpeed); + // } + //} } } diff --git a/NiceHashMiner/Forms/Components/AlgorithmsListView.Designer.cs b/NiceHashMiner/Forms/Components/AlgorithmsListView.Designer.cs index 75c631a..b9b86d5 100644 --- a/NiceHashMiner/Forms/Components/AlgorithmsListView.Designer.cs +++ b/NiceHashMiner/Forms/Components/AlgorithmsListView.Designer.cs @@ -23,12 +23,14 @@ protected override void Dispose(bool disposing) { /// the contents of this method with the code editor. /// private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); this.listViewAlgorithms = new System.Windows.Forms.ListView(); this.columnHeader0 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.SuspendLayout(); // // listViewAlgorithms @@ -50,6 +52,7 @@ private void InitializeComponent() { this.listViewAlgorithms.TabIndex = 11; this.listViewAlgorithms.UseCompatibleStateImageBehavior = false; this.listViewAlgorithms.View = System.Windows.Forms.View.Details; + this.listViewAlgorithms.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listViewAlgorithms_MouseClick); // // columnHeader0 // @@ -77,6 +80,11 @@ private void InitializeComponent() { this.columnHeader4.Text = "BTC/Day"; this.columnHeader4.Width = 134; // + // contextMenuStrip1 + // + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(61, 4); + // // AlgorithmsListView // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -96,5 +104,6 @@ private void InitializeComponent() { private System.Windows.Forms.ColumnHeader columnHeader2; private System.Windows.Forms.ColumnHeader columnHeader3; private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; } } diff --git a/NiceHashMiner/Forms/Components/AlgorithmsListView.cs b/NiceHashMiner/Forms/Components/AlgorithmsListView.cs index 8781eab..fd95dce 100644 --- a/NiceHashMiner/Forms/Components/AlgorithmsListView.cs +++ b/NiceHashMiner/Forms/Components/AlgorithmsListView.cs @@ -24,10 +24,13 @@ public partial class AlgorithmsListView : UserControl { public interface IAlgorithmsListView { void SetCurrentlySelected(ListViewItem lvi, ComputeDevice computeDevice); void HandleCheck(ListViewItem lvi); + void ChangeSpeed(ListViewItem lvi); } public IAlgorithmsListView ComunicationInterface { get; set; } + public IBenchmarkCalculation BenchmarkCalculation { get; set; } + ComputeDevice _computeDevice; private class DefaultAlgorithmColorSeter : IListItemCheckColorSetter { @@ -37,7 +40,7 @@ private class DefaultAlgorithmColorSeter : IListItemCheckColorSetter { public void LviSetColor(ListViewItem lvi) { Algorithm algorithm = lvi.Tag as Algorithm; if (algorithm != null) { - if (algorithm.Skip && !algorithm.IsBenchmarkPending) { + if (algorithm.Enabled == false && !algorithm.IsBenchmarkPending) { lvi.BackColor = DISABLED_COLOR; } else if (algorithm.BenchmarkSpeed > 0 && !algorithm.IsBenchmarkPending) { lvi.BackColor = BENCHMARKED_COLOR; @@ -82,29 +85,23 @@ public void InitLocale() { listViewAlgorithms.Columns[RATE].Text = International.GetText("AlgorithmsListView_Rate"); } - //public void RemoveRatioRates() { - // listViewAlgorithms.Columns.RemoveAt(RATE); - // listViewAlgorithms.Columns.RemoveAt(RATIO); - //} - public void SetAlgorithms(ComputeDevice computeDevice, bool isEnabled) { _computeDevice = computeDevice; - var config = computeDevice.DeviceBenchmarkConfig; + listViewAlgorithms.BeginUpdate(); listViewAlgorithms.Items.Clear(); - foreach (var alg in config.AlgorithmSettings) { + foreach (var alg in computeDevice.GetAlgorithmSettings()) { ListViewItem lvi = new ListViewItem(); - lvi.Checked = !alg.Value.Skip; - //lvi.Text = alg.Value.NiceHashName; - ListViewItem.ListViewSubItem sub = lvi.SubItems.Add(alg.Value.NiceHashName); + ListViewItem.ListViewSubItem sub = lvi.SubItems.Add(String.Format("{0} ({1})", alg.AlgorithmName, alg.MinerBaseTypeName)); //sub.Tag = alg.Value; - lvi.SubItems.Add(alg.Value.BenchmarkSpeedString()); - lvi.SubItems.Add(alg.Value.CurPayingRatio); - lvi.SubItems.Add(alg.Value.CurPayingRate); - lvi.Tag = alg.Value; - _listItemCheckColorSetter.LviSetColor(lvi); + lvi.SubItems.Add(alg.BenchmarkSpeedString()); + lvi.SubItems.Add(alg.CurPayingRatio); + lvi.SubItems.Add(alg.CurPayingRate); + lvi.Tag = alg; + lvi.Checked = alg.Enabled; listViewAlgorithms.Items.Add(lvi); } + listViewAlgorithms.EndUpdate(); this.Enabled = isEnabled; } @@ -133,38 +130,103 @@ private void listViewAlgorithms_ItemChecked(object sender, ItemCheckedEventArgs } var algo = e.Item.Tag as Algorithm; if (algo != null) { - algo.Skip = !e.Item.Checked; + algo.Enabled = e.Item.Checked; } if (ComunicationInterface != null) { ComunicationInterface.HandleCheck(e.Item); } var lvi = e.Item as ListViewItem; _listItemCheckColorSetter.LviSetColor(lvi); + // update benchmark status data + if (BenchmarkCalculation != null) BenchmarkCalculation.CalcBenchmarkDevicesAlgorithmQueue(); } #endregion //Callbacks Events + public void ResetListItemColors() { + foreach (ListViewItem lvi in listViewAlgorithms.Items) { + if (_listItemCheckColorSetter != null) { + _listItemCheckColorSetter.LviSetColor(lvi); + } + } + } + // benchmark settings - public void SetSpeedStatus(ComputeDevice computeDevice, AlgorithmType algorithmType, string status) { - var algorithm = computeDevice.DeviceBenchmarkConfig.AlgorithmSettings[algorithmType]; - algorithm.BenchmarkStatus = status; + public void SetSpeedStatus(ComputeDevice computeDevice, Algorithm algorithm, string status) { + if (algorithm != null) { + algorithm.BenchmarkStatus = status; + // gui update only if same as selected + if (_computeDevice != null && computeDevice.UUID == _computeDevice.UUID) { + foreach (ListViewItem lvi in listViewAlgorithms.Items) { + Algorithm algo = lvi.Tag as Algorithm; + if (algo != null && algo.AlgorithmStringID == algorithm.AlgorithmStringID) { + // TODO handle numbers + lvi.SubItems[SPEED].Text = algorithm.BenchmarkSpeedString(); + lvi.SubItems[RATE].Text = algorithm.CurPayingRate; + lvi.SubItems[RATIO].Text = algorithm.CurPayingRatio; + _listItemCheckColorSetter.LviSetColor(lvi); + break; + } + } + } + } + } - - + private void listViewAlgorithms_MouseClick(object sender, MouseEventArgs e) { + if (IsInBenchmark) return; + if (e.Button == MouseButtons.Right) { + contextMenuStrip1.Items.Clear(); + // disable all + { + var disableAllItems = new ToolStripMenuItem(); + disableAllItems.Text = International.GetText("AlgorithmsListView_ContextMenu_DisableAll"); + disableAllItems.Click += toolStripMenuItemDisableAll_Click; + contextMenuStrip1.Items.Add(disableAllItems); + } + // enable all + { + var enableAllItems = new ToolStripMenuItem(); + enableAllItems.Text = International.GetText("AlgorithmsListView_ContextMenu_EnableAll"); + enableAllItems.Click += toolStripMenuItemEnableAll_Click; + contextMenuStrip1.Items.Add(enableAllItems); + } + // clear item + { + var clearItem = new ToolStripMenuItem(); + clearItem.Text = International.GetText("AlgorithmsListView_ContextMenu_ClearItem"); + clearItem.Click += toolStripMenuItemClear_Click; + contextMenuStrip1.Items.Add(clearItem); + } + contextMenuStrip1.Show(Cursor.Position); + } + } - // gui update only if same as selected - if (_computeDevice != null && computeDevice.UUID == _computeDevice.UUID) { - foreach (ListViewItem lvi in listViewAlgorithms.Items) { - Algorithm algo = lvi.Tag as Algorithm; - if (algo != null && algo.NiceHashID == algorithmType) { - // TODO handle numbers - lvi.SubItems[SPEED].Text = algorithm.BenchmarkSpeedString(); - lvi.SubItems[RATE].Text = algorithm.CurPayingRate; - lvi.SubItems[RATIO].Text = algorithm.CurPayingRatio; - _listItemCheckColorSetter.LviSetColor(lvi); - break; + private void toolStripMenuItemEnableAll_Click(object sender, EventArgs e) { + foreach (ListViewItem lvi in listViewAlgorithms.Items) { + lvi.Checked = true; + } + } + + private void toolStripMenuItemDisableAll_Click(object sender, EventArgs e) { + foreach (ListViewItem lvi in listViewAlgorithms.Items) { + lvi.Checked = false; + } + } + + private void toolStripMenuItemClear_Click(object sender, EventArgs e) { + if (_computeDevice != null) { + foreach (ListViewItem lvi in listViewAlgorithms.SelectedItems) { + var algorithm = lvi.Tag as Algorithm; + if (algorithm != null) { + algorithm.BenchmarkSpeed = 0; + RepaintStatus(_computeDevice.Enabled, _computeDevice.UUID); + // update benchmark status data + if (BenchmarkCalculation != null) BenchmarkCalculation.CalcBenchmarkDevicesAlgorithmQueue(); + // update settings + if (ComunicationInterface != null) ComunicationInterface.ChangeSpeed(lvi); } } } } + } } diff --git a/NiceHashMiner/Forms/Components/AlgorithmsListView.resx b/NiceHashMiner/Forms/Components/AlgorithmsListView.resx index 1af7de1..ad53752 100644 --- a/NiceHashMiner/Forms/Components/AlgorithmsListView.resx +++ b/NiceHashMiner/Forms/Components/AlgorithmsListView.resx @@ -117,4 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file diff --git a/NiceHashMiner/Forms/Components/DevicesListViewEnableControl.Designer.cs b/NiceHashMiner/Forms/Components/DevicesListViewEnableControl.Designer.cs index 7ab2e0a..4a8fbc8 100644 --- a/NiceHashMiner/Forms/Components/DevicesListViewEnableControl.Designer.cs +++ b/NiceHashMiner/Forms/Components/DevicesListViewEnableControl.Designer.cs @@ -66,7 +66,6 @@ private void InitializeComponent() { this.toolStripMenuItemEnable.Name = "toolStripMenuItemEnable"; this.toolStripMenuItemEnable.Size = new System.Drawing.Size(196, 22); this.toolStripMenuItemEnable.Text = "Enable Benchmark"; - this.toolStripMenuItemEnable.Click += new System.EventHandler(this.toolStripMenuItemEnable_Click); // // toolStripMenuItem1 // diff --git a/NiceHashMiner/Forms/Components/DevicesListViewEnableControl.cs b/NiceHashMiner/Forms/Components/DevicesListViewEnableControl.cs index a248e3e..cc929d1 100644 --- a/NiceHashMiner/Forms/Components/DevicesListViewEnableControl.cs +++ b/NiceHashMiner/Forms/Components/DevicesListViewEnableControl.cs @@ -19,9 +19,9 @@ private class DefaultDevicesColorSeter : IListItemCheckColorSetter { private static Color ENABLED_COLOR = Color.White; private static Color DISABLED_COLOR = Color.DarkGray; public void LviSetColor(ListViewItem lvi) { - ComputeDeviceEnabledOption cdvo = lvi.Tag as ComputeDeviceEnabledOption; + var cdvo = lvi.Tag as ComputeDevice; if (cdvo != null) { - if(cdvo.IsEnabled) { + if(cdvo.Enabled) { lvi.BackColor = ENABLED_COLOR; } else { lvi.BackColor = DISABLED_COLOR; @@ -32,6 +32,8 @@ public void LviSetColor(ListViewItem lvi) { IListItemCheckColorSetter _listItemCheckColorSetter = new DefaultDevicesColorSeter(); + public IBenchmarkCalculation BenchmarkCalculation { get; set; } + private AlgorithmsListView _algorithmsListView = null; // disable checkboxes when in benchmark mode @@ -66,38 +68,23 @@ public bool IsMining { public bool IsBenchmarkForm = false; public bool IsSettingsCopyEnabled = false; - [Serializable] - public class ComputeDeviceEnabledOption { - public bool IsEnabled { get; set; } - public ComputeDevice CDevice { get; set; } - public void SaveOption() { - CDevice.Enabled = IsEnabled; - } - } - public string FirstColumnText { get { return listViewDevices.Columns[ENABLED].Text; } set { if (value != null) listViewDevices.Columns[ENABLED].Text = value; } } - public List Options { get; private set; } - // to automatically save on enabled click or not - public bool AutoSaveChange { get; set; } public bool SaveToGeneralConfig { get; set; } - public bool SetAllEnabled { get; set; } public DevicesListViewEnableControl() { InitializeComponent(); - AutoSaveChange = false; SaveToGeneralConfig = false; - SetAllEnabled = false; - Options = new List(); // intialize ListView callbacks listViewDevices.ItemChecked += new ItemCheckedEventHandler(listViewDevicesItemChecked); //listViewDevices.CheckBoxes = false; IsMining = false; + BenchmarkCalculation = null; } public void SetIListItemCheckColorSetter(IListItemCheckColorSetter listItemCheckColorSetter) { @@ -118,34 +105,27 @@ public void ResetListItemColors() { public void SetComputeDevices(List computeDevices) { // to not run callbacks when setting new - bool tmp_AutoSaveChange = AutoSaveChange; bool tmp_SaveToGeneralConfig = SaveToGeneralConfig; - AutoSaveChange = false; SaveToGeneralConfig = false; + listViewDevices.BeginUpdate(); + listViewDevices.Items.Clear(); // set devices foreach (var computeDevice in computeDevices) { ListViewItem lvi = new ListViewItem(); //lvi.SubItems.Add(computeDevice.Name); - lvi.Checked = computeDevice.Enabled || SetAllEnabled; + lvi.Checked = computeDevice.Enabled; lvi.Text = computeDevice.GetFullName(); - ComputeDeviceEnabledOption newTag = new ComputeDeviceEnabledOption() { - IsEnabled = computeDevice.Enabled || SetAllEnabled, - CDevice = computeDevice - }; - computeDevice.ComputeDeviceEnabledOption = newTag; - Options.Add(newTag); - lvi.Tag = newTag; + lvi.Tag = computeDevice; listViewDevices.Items.Add(lvi); _listItemCheckColorSetter.LviSetColor(lvi); } + listViewDevices.EndUpdate(); + listViewDevices.Invalidate(true); // reset properties - AutoSaveChange = tmp_AutoSaveChange; SaveToGeneralConfig = tmp_SaveToGeneralConfig; } public void ResetComputeDevices(List computeDevices) { - Options.Clear(); - listViewDevices.Items.Clear(); SetComputeDevices(computeDevices); } @@ -155,23 +135,16 @@ public void InitLocale() { } private void listViewDevicesItemChecked(object sender, ItemCheckedEventArgs e) { - ComputeDeviceEnabledOption G = e.Item.Tag as ComputeDeviceEnabledOption; - G.IsEnabled = e.Item.Checked; - if (AutoSaveChange) { - G.SaveOption(); - } + var CDevice = e.Item.Tag as ComputeDevice; + CDevice.Enabled = e.Item.Checked; + if (SaveToGeneralConfig) { - ConfigManager.Instance.GeneralConfig.Commit(); + ConfigManager.GeneralConfigFileCommit(); } var lvi = e.Item as ListViewItem; if (lvi != null) _listItemCheckColorSetter.LviSetColor(lvi); - if (_algorithmsListView != null) _algorithmsListView.RepaintStatus(G.IsEnabled, G.CDevice.UUID); - } - - public void SaveOptions() { - foreach (var option in Options) { - option.SaveOption(); - } + if (_algorithmsListView != null) _algorithmsListView.RepaintStatus(CDevice.Enabled, CDevice.UUID); + if (BenchmarkCalculation != null) BenchmarkCalculation.CalcBenchmarkDevicesAlgorithmQueue(); } public void SetDeviceSelectionChangedCallback(ListViewItemSelectionChangedEventHandler callback) { @@ -184,30 +157,17 @@ private void listViewDevices_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { if (listViewDevices.FocusedItem.Bounds.Contains(e.Location) == true) { contextMenuStrip1.Items.Clear(); - ComputeDeviceEnabledOption G = listViewDevices.FocusedItem.Tag as ComputeDeviceEnabledOption; - //if (G.IsEnabled) { - // var disableItem = new ToolStripMenuItem(); - // disableItem.Text = International.GetText("DeviceListView_ContextMenu_DisableDevice"); - // //disableItem.Checked = true; - // disableItem.Click += toolStripMenuItemEnable_Click; - // contextMenuStrip1.Items.Add(disableItem); - //} else { - // var disableItem = new ToolStripMenuItem(); - // disableItem.Text = International.GetText("DeviceListView_ContextMenu_EnableDevice"); - // //disableItem.Checked = false; - // disableItem.Click += toolStripMenuItemEnable_Click; - // contextMenuStrip1.Items.Add(disableItem); - //} if (IsSettingsCopyEnabled) { - var sameDevTypes = ComputeDevice.GetSameDevicesTypeAsDeviceWithUUID(G.CDevice.UUID); + var CDevice = listViewDevices.FocusedItem.Tag as ComputeDevice; + var sameDevTypes = ComputeDeviceManager.Avaliable.GetSameDevicesTypeAsDeviceWithUUID(CDevice.UUID); if (sameDevTypes.Count > 0) { var copyBenchItem = new ToolStripMenuItem(); //copyBenchItem.DropDownItems foreach (var cDev in sameDevTypes) { - if (cDev.ComputeDeviceEnabledOption.IsEnabled) { + if (cDev.Enabled) { var copyBenchDropDownItem = new ToolStripMenuItem(); copyBenchDropDownItem.Text = cDev.Name; - copyBenchDropDownItem.Checked = cDev.UUID == G.CDevice.BenchmarkCopyUUID; + copyBenchDropDownItem.Checked = cDev.UUID == CDevice.BenchmarkCopyUUID; copyBenchDropDownItem.Click += toolStripMenuItemCopySettings_Click; copyBenchDropDownItem.Tag = cDev.UUID; copyBenchItem.DropDownItems.Add(copyBenchDropDownItem); @@ -222,39 +182,24 @@ private void listViewDevices_MouseClick(object sender, MouseEventArgs e) { } } - private void toolStripMenuItemEnable_Click(object sender, EventArgs e) { - ComputeDeviceEnabledOption G = listViewDevices.FocusedItem.Tag as ComputeDeviceEnabledOption; - var isEnabled = !G.IsEnabled; - G.IsEnabled = isEnabled; - if (AutoSaveChange) { - G.SaveOption(); - } - if (SaveToGeneralConfig) { - ConfigManager.Instance.GeneralConfig.Commit(); - } - var lvi = listViewDevices.FocusedItem as ListViewItem; - if (lvi != null) _listItemCheckColorSetter.LviSetColor(lvi); - if (_algorithmsListView != null) _algorithmsListView.RepaintStatus(G.IsEnabled, G.CDevice.UUID); - } - private void toolStripMenuItemCopySettings_Click(object sender, EventArgs e) { - ComputeDeviceEnabledOption G = listViewDevices.FocusedItem.Tag as ComputeDeviceEnabledOption; + var CDevice = listViewDevices.FocusedItem.Tag as ComputeDevice; ToolStripMenuItem item = sender as ToolStripMenuItem; if(item != null) { var uuid = item.Tag as string; if (uuid != null) { - var copyBenchCDev = ComputeDevice.GetDeviceWithUUID(uuid); - G.CDevice.BenchmarkCopyUUID = uuid; + var copyBenchCDev = ComputeDeviceManager.Avaliable.GetDeviceWithUUID(uuid); + CDevice.BenchmarkCopyUUID = uuid; var result = MessageBox.Show( String.Format( - International.GetText("DeviceListView_ContextMenu_CopySettings_Confirm_Dialog_Msg"), copyBenchCDev.GetFullName(), G.CDevice.GetFullName()), + International.GetText("DeviceListView_ContextMenu_CopySettings_Confirm_Dialog_Msg"), copyBenchCDev.GetFullName(), CDevice.GetFullName()), International.GetText("DeviceListView_ContextMenu_CopySettings_Confirm_Dialog_Title"), MessageBoxButtons.YesNo); if(result == DialogResult.Yes) { // just copy - G.CDevice.CopyBenchmarkSettingsFrom(copyBenchCDev); - if (_algorithmsListView != null) _algorithmsListView.RepaintStatus(G.IsEnabled, G.CDevice.UUID); + CDevice.CopyBenchmarkSettingsFrom(copyBenchCDev); + if (_algorithmsListView != null) _algorithmsListView.RepaintStatus(CDevice.Enabled, CDevice.UUID); } } } @@ -266,5 +211,13 @@ private void DevicesListViewEnableControl_Resize(object sender, EventArgs e) { ch.Width = this.Width - 10; } } + + public void SetFirstSelected() { + if (listViewDevices.Items.Count > 0) { + this.listViewDevices.Items[0].Selected = true; + this.listViewDevices.Select(); + } + } + } } diff --git a/NiceHashMiner/Forms/Components/GroupProfitControl.Designer.cs b/NiceHashMiner/Forms/Components/GroupProfitControl.Designer.cs index fdfeb25..6f0330b 100644 --- a/NiceHashMiner/Forms/Components/GroupProfitControl.Designer.cs +++ b/NiceHashMiner/Forms/Components/GroupProfitControl.Designer.cs @@ -45,7 +45,7 @@ private void InitializeComponent() { this.groupBoxMinerGroup.Size = new System.Drawing.Size(525, 32); this.groupBoxMinerGroup.TabIndex = 108; this.groupBoxMinerGroup.TabStop = false; - this.groupBoxMinerGroup.Text = "GPU NVIDIA5.x: Devices { 1 * GTX 970, 1 x GTX 990 } "; + this.groupBoxMinerGroup.Text = "Mining Devices { N/A } "; // // labelSpeedIndicator // @@ -91,9 +91,9 @@ private void InitializeComponent() { this.labelSpeedValue.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))); this.labelSpeedValue.Location = new System.Drawing.Point(81, 16); this.labelSpeedValue.Name = "labelSpeedValue"; - this.labelSpeedValue.Size = new System.Drawing.Size(71, 13); + this.labelSpeedValue.Size = new System.Drawing.Size(30, 13); this.labelSpeedValue.TabIndex = 107; - this.labelSpeedValue.Text = "0.000 kH/s"; + this.labelSpeedValue.Text = "N/A"; // // GroupProfitControl // diff --git a/NiceHashMiner/Forms/Components/GroupProfitControl.cs b/NiceHashMiner/Forms/Components/GroupProfitControl.cs index 167145e..7dffcb8 100644 --- a/NiceHashMiner/Forms/Components/GroupProfitControl.cs +++ b/NiceHashMiner/Forms/Components/GroupProfitControl.cs @@ -3,9 +3,7 @@ using System.ComponentModel; using System.Drawing; using System.Data; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; namespace NiceHashMiner.Forms.Components { diff --git a/NiceHashMiner/Forms/DriverVersionConfirmationDialog.cs b/NiceHashMiner/Forms/DriverVersionConfirmationDialog.cs index c1ea7f7..ff24b30 100644 --- a/NiceHashMiner/Forms/DriverVersionConfirmationDialog.cs +++ b/NiceHashMiner/Forms/DriverVersionConfirmationDialog.cs @@ -27,7 +27,7 @@ private void buttonOK_Click(object sender, EventArgs e) if (chkBoxDontShowAgain.Checked) { Helpers.ConsolePrint("NICEHASH", "Setting ShowDriverVersionWarning to false"); - ConfigManager.Instance.GeneralConfig.ShowDriverVersionWarning = false; + ConfigManager.GeneralConfig.ShowDriverVersionWarning = false; } this.Close(); diff --git a/NiceHashMiner/Forms/Form_3rdParty_TOS.Designer.cs b/NiceHashMiner/Forms/Form_3rdParty_TOS.Designer.cs new file mode 100644 index 0000000..3dd6ebb --- /dev/null +++ b/NiceHashMiner/Forms/Form_3rdParty_TOS.Designer.cs @@ -0,0 +1,88 @@ +namespace NiceHashMiner.Forms { + partial class Form_3rdParty_TOS { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() { + this.button_Agree = new System.Windows.Forms.Button(); + this.button_Decline = new System.Windows.Forms.Button(); + this.label_Tos = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // button_Agree + // + this.button_Agree.Location = new System.Drawing.Point(12, 260); + this.button_Agree.Name = "button_Agree"; + this.button_Agree.Size = new System.Drawing.Size(146, 23); + this.button_Agree.TabIndex = 0; + this.button_Agree.Text = "button1"; + this.button_Agree.UseVisualStyleBackColor = true; + this.button_Agree.Click += new System.EventHandler(this.button_Agree_Click); + // + // button_Decline + // + this.button_Decline.Location = new System.Drawing.Point(226, 260); + this.button_Decline.Name = "button_Decline"; + this.button_Decline.Size = new System.Drawing.Size(146, 23); + this.button_Decline.TabIndex = 1; + this.button_Decline.Text = "button2"; + this.button_Decline.UseVisualStyleBackColor = true; + this.button_Decline.Click += new System.EventHandler(this.button_Decline_Click); + // + // label_Tos + // + this.label_Tos.AutoSize = true; + this.label_Tos.Location = new System.Drawing.Point(12, 9); + this.label_Tos.MaximumSize = new System.Drawing.Size(350, 0); + this.label_Tos.Name = "label_Tos"; + this.label_Tos.Size = new System.Drawing.Size(35, 13); + this.label_Tos.TabIndex = 2; + this.label_Tos.Text = "label1"; + this.label_Tos.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // Form_ClaymoreTOS + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(384, 295); + this.Controls.Add(this.label_Tos); + this.Controls.Add(this.button_Decline); + this.Controls.Add(this.button_Agree); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "Form_ClaymoreTOS"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Disclaimer on usage of 3rd party software"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button_Agree; + private System.Windows.Forms.Button button_Decline; + private System.Windows.Forms.Label label_Tos; + } +} \ No newline at end of file diff --git a/NiceHashMiner/Forms/Form_3rdParty_TOS.cs b/NiceHashMiner/Forms/Form_3rdParty_TOS.cs new file mode 100644 index 0000000..9d6641b --- /dev/null +++ b/NiceHashMiner/Forms/Form_3rdParty_TOS.cs @@ -0,0 +1,35 @@ +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace NiceHashMiner.Forms { + public partial class Form_3rdParty_TOS : Form { + public Form_3rdParty_TOS() { + InitializeComponent(); + + // TODO update 3rd party TOS + this.Text = International.GetText("Form_Main_3rdParty_Title"); + this.label_Tos.Text = International.GetText("Form_Main_3rdParty_Text"); + this.button_Agree.Text = International.GetText("Form_Main_3rdParty_Button_Agree_Text"); + this.button_Decline.Text = International.GetText("Form_Main_3rdParty_Button_Refuse_Text"); + } + + + private void button_Agree_Click(object sender, EventArgs e) { + ConfigManager.GeneralConfig.Use3rdPartyMiners = Use3rdPartyMiners.YES; + this.Close(); + } + + private void button_Decline_Click(object sender, EventArgs e) { + ConfigManager.GeneralConfig.Use3rdPartyMiners = Use3rdPartyMiners.NO; + this.Close(); + } + } +} diff --git a/NiceHashMiner/Forms/Form_3rdParty_TOS.resx b/NiceHashMiner/Forms/Form_3rdParty_TOS.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/NiceHashMiner/Forms/Form_3rdParty_TOS.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NiceHashMiner/Forms/Form_Benchmark.Designer.cs b/NiceHashMiner/Forms/Form_Benchmark.Designer.cs index b070dd5..04eea90 100644 --- a/NiceHashMiner/Forms/Form_Benchmark.Designer.cs +++ b/NiceHashMiner/Forms/Form_Benchmark.Designer.cs @@ -23,17 +23,17 @@ protected override void Dispose(bool disposing) { /// the contents of this method with the code editor. /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form_Benchmark)); this.StartStopBtn = new System.Windows.Forms.Button(); this.CloseBtn = new System.Windows.Forms.Button(); this.groupBoxBenchmarkProgress = new System.Windows.Forms.GroupBox(); this.labelBenchmarkSteps = new System.Windows.Forms.Label(); this.progressBarBenchmarkSteps = new System.Windows.Forms.ProgressBar(); + this.radioButton_SelectedUnbenchmarked = new System.Windows.Forms.RadioButton(); + this.radioButton_RE_SelectedUnbenchmarked = new System.Windows.Forms.RadioButton(); + this.checkBox_StartMiningAfterBenchmark = new System.Windows.Forms.CheckBox(); this.algorithmsListView1 = new NiceHashMiner.Forms.Components.AlgorithmsListView(); this.benchmarkOptions1 = new NiceHashMiner.Forms.Components.BenchmarkOptions(); this.devicesListViewEnableControl1 = new NiceHashMiner.Forms.Components.DevicesListViewEnableControl(); - this.radioButton_SelectedUnbenchmarked = new System.Windows.Forms.RadioButton(); - this.radioButton_RE_SelectedUnbenchmarked = new System.Windows.Forms.RadioButton(); this.groupBoxBenchmarkProgress.SuspendLayout(); this.SuspendLayout(); // @@ -84,8 +84,44 @@ private void InitializeComponent() { this.progressBarBenchmarkSteps.Size = new System.Drawing.Size(161, 23); this.progressBarBenchmarkSteps.TabIndex = 108; // + // radioButton_SelectedUnbenchmarked + // + this.radioButton_SelectedUnbenchmarked.AutoSize = true; + this.radioButton_SelectedUnbenchmarked.Checked = true; + this.radioButton_SelectedUnbenchmarked.Location = new System.Drawing.Point(21, 295); + this.radioButton_SelectedUnbenchmarked.Name = "radioButton_SelectedUnbenchmarked"; + this.radioButton_SelectedUnbenchmarked.Size = new System.Drawing.Size(260, 17); + this.radioButton_SelectedUnbenchmarked.TabIndex = 110; + this.radioButton_SelectedUnbenchmarked.TabStop = true; + this.radioButton_SelectedUnbenchmarked.Text = "Benchmark Selected Unbenchmarked Algorithms "; + this.radioButton_SelectedUnbenchmarked.UseVisualStyleBackColor = true; + this.radioButton_SelectedUnbenchmarked.CheckedChanged += new System.EventHandler(this.radioButton_SelectedUnbenchmarked_CheckedChanged_1); + // + // radioButton_RE_SelectedUnbenchmarked + // + this.radioButton_RE_SelectedUnbenchmarked.AutoSize = true; + this.radioButton_RE_SelectedUnbenchmarked.Location = new System.Drawing.Point(21, 318); + this.radioButton_RE_SelectedUnbenchmarked.Name = "radioButton_RE_SelectedUnbenchmarked"; + this.radioButton_RE_SelectedUnbenchmarked.Size = new System.Drawing.Size(192, 17); + this.radioButton_RE_SelectedUnbenchmarked.TabIndex = 110; + this.radioButton_RE_SelectedUnbenchmarked.Text = "Benchmark All Selected Algorithms "; + this.radioButton_RE_SelectedUnbenchmarked.UseVisualStyleBackColor = true; + this.radioButton_RE_SelectedUnbenchmarked.CheckedChanged += new System.EventHandler(this.radioButton_RE_SelectedUnbenchmarked_CheckedChanged); + // + // checkBox_StartMiningAfterBenchmark + // + this.checkBox_StartMiningAfterBenchmark.AutoSize = true; + this.checkBox_StartMiningAfterBenchmark.Location = new System.Drawing.Point(350, 318); + this.checkBox_StartMiningAfterBenchmark.Name = "checkBox_StartMiningAfterBenchmark"; + this.checkBox_StartMiningAfterBenchmark.Size = new System.Drawing.Size(161, 17); + this.checkBox_StartMiningAfterBenchmark.TabIndex = 111; + this.checkBox_StartMiningAfterBenchmark.Text = "Start mining after benchmark"; + this.checkBox_StartMiningAfterBenchmark.UseVisualStyleBackColor = true; + this.checkBox_StartMiningAfterBenchmark.CheckedChanged += new System.EventHandler(this.checkBox_StartMiningAfterBenchmark_CheckedChanged); + // // algorithmsListView1 // + this.algorithmsListView1.BenchmarkCalculation = null; this.algorithmsListView1.ComunicationInterface = null; this.algorithmsListView1.IsInBenchmark = false; this.algorithmsListView1.Location = new System.Drawing.Point(12, 133); @@ -102,46 +138,22 @@ private void InitializeComponent() { // // devicesListViewEnableControl1 // - this.devicesListViewEnableControl1.AutoSaveChange = false; + this.devicesListViewEnableControl1.BenchmarkCalculation = null; this.devicesListViewEnableControl1.FirstColumnText = "Benckmark"; this.devicesListViewEnableControl1.IsInBenchmark = false; this.devicesListViewEnableControl1.IsMining = false; this.devicesListViewEnableControl1.Location = new System.Drawing.Point(12, 15); this.devicesListViewEnableControl1.Name = "devicesListViewEnableControl1"; this.devicesListViewEnableControl1.SaveToGeneralConfig = false; - this.devicesListViewEnableControl1.SetAllEnabled = false; this.devicesListViewEnableControl1.Size = new System.Drawing.Size(376, 112); this.devicesListViewEnableControl1.TabIndex = 0; // - // radioButton_SelectedUnbenchmarked - // - this.radioButton_SelectedUnbenchmarked.AutoSize = true; - this.radioButton_SelectedUnbenchmarked.Checked = true; - this.radioButton_SelectedUnbenchmarked.Location = new System.Drawing.Point(21, 295); - this.radioButton_SelectedUnbenchmarked.Name = "radioButton_SelectedUnbenchmarked"; - this.radioButton_SelectedUnbenchmarked.Size = new System.Drawing.Size(260, 17); - this.radioButton_SelectedUnbenchmarked.TabIndex = 110; - this.radioButton_SelectedUnbenchmarked.TabStop = true; - this.radioButton_SelectedUnbenchmarked.Text = "Benchmark Selected Unbenchmarked Algorithms "; - this.radioButton_SelectedUnbenchmarked.UseVisualStyleBackColor = true; - this.radioButton_SelectedUnbenchmarked.CheckedChanged += new System.EventHandler(this.radioButton_SelectedUnbenchmarked_CheckedChanged_1); - // - // radioButton_RE_SelectedUnbenchmarked - // - this.radioButton_RE_SelectedUnbenchmarked.AutoSize = true; - this.radioButton_RE_SelectedUnbenchmarked.Location = new System.Drawing.Point(21, 318); - this.radioButton_RE_SelectedUnbenchmarked.Name = "radioButton_RE_SelectedUnbenchmarked"; - this.radioButton_RE_SelectedUnbenchmarked.Size = new System.Drawing.Size(192, 17); - this.radioButton_RE_SelectedUnbenchmarked.TabIndex = 110; - this.radioButton_RE_SelectedUnbenchmarked.Text = "Benchmark All Selected Algorithms "; - this.radioButton_RE_SelectedUnbenchmarked.UseVisualStyleBackColor = true; - this.radioButton_RE_SelectedUnbenchmarked.CheckedChanged += new System.EventHandler(this.radioButton_RE_SelectedUnbenchmarked_CheckedChanged); - // // Form_Benchmark // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(604, 401); + this.Controls.Add(this.checkBox_StartMiningAfterBenchmark); this.Controls.Add(this.radioButton_RE_SelectedUnbenchmarked); this.Controls.Add(this.radioButton_SelectedUnbenchmarked); this.Controls.Add(this.algorithmsListView1); @@ -151,7 +163,6 @@ private void InitializeComponent() { this.Controls.Add(this.CloseBtn); this.Controls.Add(this.devicesListViewEnableControl1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "Form_Benchmark"; @@ -176,6 +187,7 @@ private void InitializeComponent() { private Components.AlgorithmsListView algorithmsListView1; private System.Windows.Forms.RadioButton radioButton_SelectedUnbenchmarked; private System.Windows.Forms.RadioButton radioButton_RE_SelectedUnbenchmarked; + private System.Windows.Forms.CheckBox checkBox_StartMiningAfterBenchmark; } diff --git a/NiceHashMiner/Forms/Form_Benchmark.cs b/NiceHashMiner/Forms/Form_Benchmark.cs index afc4268..9ce85a1 100644 --- a/NiceHashMiner/Forms/Form_Benchmark.cs +++ b/NiceHashMiner/Forms/Form_Benchmark.cs @@ -12,7 +12,9 @@ using NiceHashMiner.Interfaces; namespace NiceHashMiner.Forms { - public partial class Form_Benchmark : Form, IListItemCheckColorSetter, IBenchmarkComunicator { + using NiceHashMiner.Miners.Grouping; + using NiceHashMiner.Net20_backport; + public partial class Form_Benchmark : Form, IListItemCheckColorSetter, IBenchmarkComunicator, IBenchmarkCalculation { private bool _inBenchmark = false; private int _bechmarkCurrentIndex = 0; @@ -25,11 +27,13 @@ public partial class Form_Benchmark : Form, IListItemCheckColorSetter, IBenchmar private List>> _benchmarkDevicesAlgorithmQueue; private bool ExitWhenFinished = false; - private AlgorithmType _singleBenchmarkType = AlgorithmType.NONE; + //private AlgorithmType _singleBenchmarkType = AlgorithmType.NONE; private Timer _benchmarkingTimer; private int dotCount = 0; + public bool StartMining { get; private set; } + private struct DeviceAlgo { public string Device { get; set; } public string Algorithm { get; set; } @@ -48,16 +52,119 @@ private enum BenchmarkSettingsStatus : int { private string CurrentAlgoName; - + // CPU benchmarking helpers + private class CPUBenchmarkStatus { + private class benchmark { + public benchmark(int lt, double bench) { + LessTreads = lt; + Benchmark = bench; + } + public readonly int LessTreads; + public readonly double Benchmark; + } + public CPUBenchmarkStatus(int max_threads) { + _max_threads = max_threads; + } + + public bool HasTest() { + return _cur_less_threads < _max_threads; + } + + public void SetNextSpeed(double speed) { + if (HasTest()) { + _benchmarks.Add(new benchmark(_cur_less_threads, speed)); + ++_cur_less_threads; + } + } + + public void FindFastest() { + _benchmarks.Sort((a, b) => - a.Benchmark.CompareTo(b.Benchmark)); + } + public double GetBestSpeed() { + return _benchmarks[0].Benchmark; + } + public int GetLessThreads() { + return _benchmarks[0].LessTreads; + } + + private readonly int _max_threads; + private int _cur_less_threads = 0; + private List _benchmarks = new List(); + public int LessTreads { get { return _cur_less_threads; } } + public int Time; + } + private CPUBenchmarkStatus __CPUBenchmarkStatus = null; + + private class ClaymoreZcashStatus { + private const int MAX_BENCH = 2; + private readonly string[] ASM_MODES = new string[] { " -asm 1", " -asm 0" }; + + private double[] speeds = new double[] { 0.0d, 0.0d }; + private int CurIndex = 0; + private readonly string originalExtraParams; + + public ClaymoreZcashStatus(string oep) { + originalExtraParams = oep; + } + + public bool HasTest() { + return CurIndex < MAX_BENCH; + } + + public void SetSpeed(double speed) { + if (HasTest()) { + speeds[CurIndex] = speed; + } + } + + public void SetNext() { + CurIndex += 1; + } + + public string GetTestExtraParams() { + if (HasTest()) { + return originalExtraParams + ASM_MODES[CurIndex]; + } + return originalExtraParams; + } + + private int FastestIndex() { + int maxIndex = 0; + double maxValue = speeds[maxIndex]; + for (int i = 1; i < speeds.Length; ++i) { + if (speeds[i] > maxValue) { + maxIndex = i; + maxValue = speeds[i]; + } + } + + return 0; + } + + public string GetFastestExtraParams() { + return originalExtraParams + ASM_MODES[FastestIndex()]; + } + public double GetFastestTime() { + return speeds[FastestIndex()]; + } + + public int Time = 180; + } + private ClaymoreZcashStatus __ClaymoreZcashStatus = null; + + // CPU sweet spots + private List CPUAlgos = new List() { + AlgorithmType.CryptoNight + }; private static Color DISABLED_COLOR = Color.DarkGray; private static Color BENCHMARKED_COLOR = Color.LightGreen; private static Color UNBENCHMARKED_COLOR = Color.LightBlue; public void LviSetColor(ListViewItem lvi) { - var cdvo = lvi.Tag as NiceHashMiner.Forms.Components.DevicesListViewEnableControl.ComputeDeviceEnabledOption; - if (cdvo != null && _benchmarkDevicesAlgorithmStatus != null) { - var uuid = cdvo.CDevice.UUID; - if (!cdvo.IsEnabled) { + var CDevice = lvi.Tag as ComputeDevice; + if (CDevice != null && _benchmarkDevicesAlgorithmStatus != null) { + var uuid = CDevice.UUID; + if (!CDevice.Enabled) { lvi.BackColor = DISABLED_COLOR; } else { switch (_benchmarkDevicesAlgorithmStatus[uuid]) { @@ -81,20 +188,25 @@ public void LviSetColor(ListViewItem lvi) { } public Form_Benchmark(BenchmarkPerformanceType benchmarkPerformanceType = BenchmarkPerformanceType.Standard, - bool autostart = false, - //List enabledDevices = null, - AlgorithmType singleBenchmarkType = AlgorithmType.NONE) { + bool autostart = false) { + InitializeComponent(); + this.Icon = NiceHashMiner.Properties.Resources.logo; + + StartMining = false; - _singleBenchmarkType = singleBenchmarkType; + // clear prev pending statuses + foreach (var dev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + foreach (var algo in dev.GetAlgorithmSettings()) { + algo.ClearBenchmarkPendingFirst(); + } + } benchmarkOptions1.SetPerformanceType(benchmarkPerformanceType); // benchmark only unique devices devicesListViewEnableControl1.SetIListItemCheckColorSetter(this); - devicesListViewEnableControl1.SetAllEnabled = true; - //devicesListViewEnableControl1.SaveToGeneralConfig = true; - devicesListViewEnableControl1.SetComputeDevices(ComputeDevice.AllAvaliableDevices); + devicesListViewEnableControl1.SetComputeDevices(ComputeDeviceManager.Avaliable.AllAvaliableDevices); // use this to track miner benchmark statuses _benchmarkMiners = new List(); @@ -105,23 +217,23 @@ public Form_Benchmark(BenchmarkPerformanceType benchmarkPerformanceType = Benchm _benchmarkingTimer.Tick += BenchmarkingTimer_Tick; _benchmarkingTimer.Interval = 1000; // 1s - // name, UUID - Dictionary benchNamesUUIDs = new Dictionary(); - // initialize benchmark settings for same cards to only copy settings - foreach (var GdevSetting in devicesListViewEnableControl1.Options) { - var plainDevName = GdevSetting.CDevice._nameNoNums; - if (benchNamesUUIDs.ContainsKey(plainDevName)) { - GdevSetting.IsEnabled = false; - GdevSetting.CDevice.BenchmarkCopyUUID = benchNamesUUIDs[plainDevName]; - } else { - benchNamesUUIDs.Add(plainDevName, GdevSetting.CDevice.UUID); - GdevSetting.IsEnabled = true; // enable benchmark - GdevSetting.CDevice.BenchmarkCopyUUID = null; - } - } + //// name, UUID + //Dictionary benchNamesUUIDs = new Dictionary(); + //// initialize benchmark settings for same cards to only copy settings + //foreach (var cDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + // var plainDevName = cDev.Name; + // if (benchNamesUUIDs.ContainsKey(plainDevName)) { + // cDev.Enabled = false; + // cDev.BenchmarkCopyUUID = benchNamesUUIDs[plainDevName]; + // } else if (cDev.Enabled == true) { + // benchNamesUUIDs.Add(plainDevName, cDev.UUID); + // //cDev.Enabled = true; // enable benchmark + // cDev.BenchmarkCopyUUID = null; + // } + //} //groupBoxAlgorithmBenchmarkSettings.Enabled = _singleBenchmarkType == AlgorithmType.NONE; - devicesListViewEnableControl1.Enabled = _singleBenchmarkType == AlgorithmType.NONE; + devicesListViewEnableControl1.Enabled = true; devicesListViewEnableControl1.SetDeviceSelectionChangedCallback(devicesListView1_ItemSelectionChanged); devicesListViewEnableControl1.SetAlgorithmsListView(algorithmsListView1); @@ -132,6 +244,16 @@ public Form_Benchmark(BenchmarkPerformanceType benchmarkPerformanceType = Benchm CalcBenchmarkDevicesAlgorithmQueue(); devicesListViewEnableControl1.ResetListItemColors(); + // to update laclulation status + devicesListViewEnableControl1.BenchmarkCalculation = this; + algorithmsListView1.BenchmarkCalculation = this; + + // set first device selected { + if (ComputeDeviceManager.Avaliable.AllAvaliableDevices.Count > 0) { + var firstComputedevice = ComputeDeviceManager.Avaliable.AllAvaliableDevices[0]; + algorithmsListView1.SetAlgorithms(firstComputedevice, firstComputedevice.Enabled); + } + if (autostart) { ExitWhenFinished = true; StartStopBtn_Click(null, null); @@ -140,21 +262,21 @@ public Form_Benchmark(BenchmarkPerformanceType benchmarkPerformanceType = Benchm private void CopyBenchmarks() { Helpers.ConsolePrint("CopyBenchmarks", "Checking for benchmarks to copy"); - foreach (var GdevSetting in devicesListViewEnableControl1.Options) { + foreach (var cDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { // check if copy - if (!GdevSetting.IsEnabled && GdevSetting.CDevice.BenchmarkCopyUUID != null) { - var copyCdevSettings = ComputeDevice.GetDeviceWithUUID(GdevSetting.CDevice.BenchmarkCopyUUID); + if (!cDev.Enabled && cDev.BenchmarkCopyUUID != null) { + var copyCdevSettings = ComputeDeviceManager.Avaliable.GetDeviceWithUUID(cDev.BenchmarkCopyUUID); if (copyCdevSettings != null) { - Helpers.ConsolePrint("CopyBenchmarks", String.Format("Copy from {0} to {1}", GdevSetting.CDevice.UUID, GdevSetting.CDevice.BenchmarkCopyUUID)); - GdevSetting.CDevice.CopyBenchmarkSettingsFrom(copyCdevSettings); + Helpers.ConsolePrint("CopyBenchmarks", String.Format("Copy from {0} to {1}", cDev.UUID, cDev.BenchmarkCopyUUID)); + cDev.CopyBenchmarkSettingsFrom(copyCdevSettings); } - } + } } } private void BenchmarkingTimer_Tick(object sender, EventArgs e) { if (_inBenchmark) { - algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm.NiceHashID, getDotsWaitString()); + algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm, getDotsWaitString()); } } @@ -177,6 +299,7 @@ private void InitLocale() { groupBoxBenchmarkProgress.Text = International.GetText("FormBenchmark_Benchmark_GroupBoxStatus"); radioButton_SelectedUnbenchmarked.Text = International.GetText("FormBenchmark_Benchmark_All_Selected_Unbenchmarked"); radioButton_RE_SelectedUnbenchmarked.Text = International.GetText("FormBenchmark_Benchmark_All_Selected_ReUnbenchmarked"); + checkBox_StartMiningAfterBenchmark.Text = International.GetText("Form_Benchmark_checkbox_StartMiningAfterBenchmark"); } private void StartStopBtn_Click(object sender, EventArgs e) { @@ -199,15 +322,12 @@ private void BenchmarkStoppedGUISettings() { } ResetBenchmarkProgressStatus(); CalcBenchmarkDevicesAlgorithmQueue(); - //groupBoxAlgorithmBenchmarkSettings.Enabled = true && _singleBenchmarkType == AlgorithmType.NONE; benchmarkOptions1.Enabled = true; algorithmsListView1.IsInBenchmark = false; devicesListViewEnableControl1.IsInBenchmark = false; - // TODO make scrolable but not checkable - //devicesListViewEnableControl1.Enabled = true && _singleBenchmarkType == AlgorithmType.NONE; if (_currentDevice != null) { - algorithmsListView1.RepaintStatus(_currentDevice.ComputeDeviceEnabledOption.IsEnabled, _currentDevice.UUID); + algorithmsListView1.RepaintStatus(_currentDevice.Enabled, _currentDevice.UUID); } CloseBtn.Enabled = true; @@ -218,10 +338,11 @@ private void StopButonClick() { _benchmarkingTimer.Stop(); _inBenchmark = false; Helpers.ConsolePrint("FormBenchmark", "StopButonClick() benchmark routine stopped"); - // copy benchmarked - CopyBenchmarks(); + //// copy benchmarked + //CopyBenchmarks(); if (_currentMiner != null) { _currentMiner.BenchmarkSignalQuit = true; + _currentMiner.InvokeBenchmarkSignalQuit(); } if (ExitWhenFinished) { this.Close(); @@ -233,8 +354,8 @@ private bool StartButonClick() { // device selection check scope { bool noneSelected = true; - foreach (var option in devicesListViewEnableControl1.Options) { - if (option.IsEnabled) { + foreach (var cDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + if (cDev.Enabled) { noneSelected = false; break; } @@ -266,10 +387,7 @@ private bool StartButonClick() { // current failed new list _benchmarkFailedAlgoPerDev = new List(); // disable gui controls - //groupBoxAlgorithmBenchmarkSettings.Enabled = false; benchmarkOptions1.Enabled = false; - // TODO make scrolable but not checkable - //devicesListViewEnableControl1.Enabled = false; CloseBtn.Enabled = false; algorithmsListView1.IsInBenchmark = true; devicesListViewEnableControl1.IsInBenchmark = true; @@ -280,7 +398,7 @@ private bool StartButonClick() { } } if (_currentDevice != null) { - algorithmsListView1.RepaintStatus(_currentDevice.ComputeDeviceEnabledOption.IsEnabled, _currentDevice.UUID); + algorithmsListView1.RepaintStatus(_currentDevice.Enabled, _currentDevice.UUID); } StartBenchmark(); @@ -288,36 +406,34 @@ private bool StartButonClick() { return true; } - private void CalcBenchmarkDevicesAlgorithmQueue() { + public void CalcBenchmarkDevicesAlgorithmQueue() { _benchmarkAlgorithmsCount = 0; _benchmarkDevicesAlgorithmStatus = new Dictionary(); _benchmarkDevicesAlgorithmQueue = new List>>(); - foreach (var option in devicesListViewEnableControl1.Options) { + foreach (var cDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { var algorithmQueue = new Queue(); - if (_singleBenchmarkType == AlgorithmType.NONE) { - foreach (var kvpAlgorithm in option.CDevice.DeviceBenchmarkConfig.AlgorithmSettings) { - if (ShoulBenchmark(kvpAlgorithm.Value)) { - algorithmQueue.Enqueue(kvpAlgorithm.Value); - } + foreach (var algo in cDev.GetAlgorithmSettings()) { + if (ShoulBenchmark(algo)) { + algorithmQueue.Enqueue(algo); + algo.SetBenchmarkPendingNoMsg(); + } else { + algo.ClearBenchmarkPending(); } - } else { // single bench - var algo = option.CDevice.DeviceBenchmarkConfig.AlgorithmSettings[_singleBenchmarkType]; - algorithmQueue.Enqueue(algo); } BenchmarkSettingsStatus status; - if (option.IsEnabled) { + if (cDev.Enabled) { _benchmarkAlgorithmsCount += algorithmQueue.Count; status = algorithmQueue.Count == 0 ? BenchmarkSettingsStatus.NONE : BenchmarkSettingsStatus.TODO; _benchmarkDevicesAlgorithmQueue.Add( - new Tuple>(option.CDevice, algorithmQueue) + new Tuple>(cDev, algorithmQueue) ); } else { status = algorithmQueue.Count == 0 ? BenchmarkSettingsStatus.DISABLED_NONE : BenchmarkSettingsStatus.DISABLED_TODO; } - _benchmarkDevicesAlgorithmStatus.Add(option.CDevice.UUID, status); + _benchmarkDevicesAlgorithmStatus[cDev.UUID] = status; } // GUI stuff progressBarBenchmarkSteps.Maximum = _benchmarkAlgorithmsCount; @@ -328,13 +444,13 @@ private void CalcBenchmarkDevicesAlgorithmQueue() { private bool ShoulBenchmark(Algorithm algorithm) { bool isBenchmarked = algorithm.BenchmarkSpeed > 0 ? true : false; if (_algorithmOption == AlgorithmBenchmarkSettingsType.SelectedUnbenchmarkedAlgorithms - && !isBenchmarked && !algorithm.Skip) { + && !isBenchmarked && algorithm.Enabled) { return true; } if (_algorithmOption == AlgorithmBenchmarkSettingsType.UnbenchmarkedAlgorithms && !isBenchmarked) { return true; } - if (_algorithmOption == AlgorithmBenchmarkSettingsType.ReBecnhSelectedAlgorithms && !algorithm.Skip) { + if (_algorithmOption == AlgorithmBenchmarkSettingsType.ReBecnhSelectedAlgorithms && algorithm.Enabled) { return true; } if (_algorithmOption == AlgorithmBenchmarkSettingsType.AllAlgorithms) { @@ -353,7 +469,7 @@ void StartBenchmark() { void NextBenchmark() { if (_bechmarkCurrentIndex > -1) { StepUpBenchmarkStepProgress(); - } + } ++_bechmarkCurrentIndex; if (_bechmarkCurrentIndex >= _benchmarkAlgorithmsCount) { EndBenchmark(); @@ -374,22 +490,36 @@ void NextBenchmark() { } } - var currentConfig = _currentDevice.DeviceBenchmarkConfig; - if (_currentDevice.DeviceGroupType == DeviceGroupType.CPU) { - _currentMiner = MinersManager.GetCpuMiner(_currentDevice.Group); - } else { - _currentMiner = MinersManager.CreateMiner(currentConfig.DeviceGroupType, _currentAlgorithm.NiceHashID); + if (_currentDevice != null && _currentAlgorithm != null) { + _currentMiner = MinerFactory.CreateMiner(_currentDevice, _currentAlgorithm); + if (_currentAlgorithm.MinerBaseType == MinerBaseType.XmrStackCPU && _currentAlgorithm.NiceHashID == AlgorithmType.CryptoNight && string.IsNullOrEmpty(_currentAlgorithm.ExtraLaunchParameters) && _currentAlgorithm.ExtraLaunchParameters.Contains("enable_ht=true") == false) { + __CPUBenchmarkStatus = new CPUBenchmarkStatus(Globals.ThreadsPerCPU); + _currentAlgorithm.LessThreads = __CPUBenchmarkStatus.LessTreads; + } else { + __CPUBenchmarkStatus = null; + } + if (_currentAlgorithm.MinerBaseType == MinerBaseType.ClaymoreAMD && _currentAlgorithm.NiceHashID == AlgorithmType.Equihash && _currentAlgorithm.ExtraLaunchParameters != null && !_currentAlgorithm.ExtraLaunchParameters.Contains("-asm")) { + __ClaymoreZcashStatus = new ClaymoreZcashStatus(_currentAlgorithm.ExtraLaunchParameters); + _currentAlgorithm.ExtraLaunchParameters = __ClaymoreZcashStatus.GetTestExtraParams(); + } else { + __ClaymoreZcashStatus = null; + } } if (_currentMiner != null && _currentAlgorithm != null) { _benchmarkMiners.Add(_currentMiner); CurrentAlgoName = AlgorithmNiceHashNames.GetName(_currentAlgorithm.NiceHashID); - // this has no effect for CPU miners - _currentMiner.SetCDevs(new string[] { _currentDevice.UUID }); + _currentMiner.InitBenchmarkSetup(new MiningPair(_currentDevice, _currentAlgorithm)); - var time = ConfigManager.Instance.GeneralConfig.BenchmarkTimeLimits + var time = ConfigManager.GeneralConfig.BenchmarkTimeLimits .GetBenchamrktime(benchmarkOptions1.PerformanceType, _currentDevice.DeviceGroupType); //currentConfig.TimeLimit = time; + if (__CPUBenchmarkStatus != null) { + __CPUBenchmarkStatus.Time = time; + } + if (__ClaymoreZcashStatus != null) { + __ClaymoreZcashStatus.Time = time; + } // dagger about 4 minutes var showWaitTime = _currentAlgorithm.NiceHashID == AlgorithmType.DaggerHashimoto ? 4 * 60 : time; @@ -397,8 +527,8 @@ void NextBenchmark() { dotCount = 0; _benchmarkingTimer.Start(); - _currentMiner.BenchmarkStart(_currentDevice, _currentAlgorithm, time, this); - algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm.NiceHashID, + _currentMiner.BenchmarkStart(time, this); + algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm, getDotsWaitString()); } else { NextBenchmark(); @@ -411,16 +541,16 @@ void EndBenchmark() { _inBenchmark = false; Helpers.ConsolePrint("FormBenchmark", "EndBenchmark() benchmark routine finished"); - CopyBenchmarks(); + //CopyBenchmarks(); BenchmarkStoppedGUISettings(); // check if all ok - if(_benchmarkFailedAlgoPerDev.Count == 0) { + if(_benchmarkFailedAlgoPerDev.Count == 0 && StartMining == false) { MessageBox.Show( International.GetText("FormBenchmark_Benchmark_Finish_Succes_MsgBox_Msg"), International.GetText("FormBenchmark_Benchmark_Finish_MsgBox_Title"), MessageBoxButtons.OK); - } else { + } else if (StartMining == false) { var result = MessageBox.Show( International.GetText("FormBenchmark_Benchmark_Finish_Fail_MsgBox_Msg"), International.GetText("FormBenchmark_Benchmark_Finish_MsgBox_Title"), @@ -434,12 +564,12 @@ void EndBenchmark() { CalcBenchmarkDevicesAlgorithmQueue(); foreach (var deviceAlgoQueue in _benchmarkDevicesAlgorithmQueue) { foreach (var algorithm in deviceAlgoQueue.Item2) { - algorithm.Skip = true; + algorithm.Enabled = false; } } } } - if (ExitWhenFinished) { + if (ExitWhenFinished || StartMining) { this.Close(); } } @@ -447,8 +577,7 @@ void EndBenchmark() { public void SetCurrentStatus(string status) { this.Invoke((MethodInvoker)delegate { - //algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm.NiceHashID, status); - algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm.NiceHashID, getDotsWaitString()); + algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm, getDotsWaitString()); }); } @@ -456,21 +585,64 @@ public void OnBenchmarkComplete(bool success, string status) { if (!_inBenchmark) return; this.Invoke((MethodInvoker)delegate { _bechmarkedSuccessCount += success ? 1 : 0; - _benchmarkingTimer.Stop(); - if (!success) { + bool rebenchSame = false; + if(success && __CPUBenchmarkStatus != null && CPUAlgos.Contains(_currentAlgorithm.NiceHashID) && _currentAlgorithm.MinerBaseType == MinerBaseType.XmrStackCPU) { + __CPUBenchmarkStatus.SetNextSpeed(_currentAlgorithm.BenchmarkSpeed); + rebenchSame = __CPUBenchmarkStatus.HasTest(); + _currentAlgorithm.LessThreads = __CPUBenchmarkStatus.LessTreads; + if (rebenchSame == false) { + __CPUBenchmarkStatus.FindFastest(); + _currentAlgorithm.BenchmarkSpeed = __CPUBenchmarkStatus.GetBestSpeed(); + _currentAlgorithm.LessThreads = __CPUBenchmarkStatus.GetLessThreads(); + } + } + + if (__ClaymoreZcashStatus != null && _currentAlgorithm.MinerBaseType == MinerBaseType.ClaymoreAMD && _currentAlgorithm.NiceHashID == AlgorithmType.Equihash) { + if (__ClaymoreZcashStatus.HasTest()) { + _currentMiner = MinerFactory.CreateMiner(_currentDevice, _currentAlgorithm); + rebenchSame = true; + //System.Threading.Thread.Sleep(1000*60*5); + __ClaymoreZcashStatus.SetSpeed(_currentAlgorithm.BenchmarkSpeed); + __ClaymoreZcashStatus.SetNext(); + _currentAlgorithm.ExtraLaunchParameters = __ClaymoreZcashStatus.GetTestExtraParams(); + Helpers.ConsolePrint("ClaymoreAMD_Equihash", _currentAlgorithm.ExtraLaunchParameters); + _currentMiner.InitBenchmarkSetup(new MiningPair(_currentDevice, _currentAlgorithm)); + } + + if (__ClaymoreZcashStatus.HasTest() == false) { + rebenchSame = false; + // set fastest mode + _currentAlgorithm.BenchmarkSpeed = __ClaymoreZcashStatus.GetFastestTime(); + _currentAlgorithm.ExtraLaunchParameters = __ClaymoreZcashStatus.GetFastestExtraParams(); + } + } + + if(!rebenchSame) { + _benchmarkingTimer.Stop(); + } + + if (!success && !rebenchSame) { // add new failed list _benchmarkFailedAlgoPerDev.Add( new DeviceAlgo() { Device = _currentDevice.Name, - Algorithm = _currentAlgorithm.NiceHashName + Algorithm = _currentAlgorithm.AlgorithmName } ); - algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm.NiceHashID, status); - } else { + algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm, status); + } else if (!rebenchSame) { // set status to empty string it will return speed _currentAlgorithm.ClearBenchmarkPending(); - algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm.NiceHashID, ""); + algorithmsListView1.SetSpeedStatus(_currentDevice, _currentAlgorithm, ""); + } + if (rebenchSame) { + if (__CPUBenchmarkStatus != null) { + _currentMiner.BenchmarkStart(__CPUBenchmarkStatus.Time, this); + } else if (__ClaymoreZcashStatus != null) { + _currentMiner.BenchmarkStart(__ClaymoreZcashStatus.Time, this); + } + } else { + NextBenchmark(); } - NextBenchmark(); }); } @@ -495,70 +667,59 @@ private void CloseBtn_Click(object sender, EventArgs e) { this.Close(); } - //private void radioButton_SelectedUnbenchmarked_CheckedChanged(object sender, EventArgs e) { - // _algorithmOption = AlgorithmBenchmarkSettingsType.SelectedUnbenchmarkedAlgorithms; - // CalcBenchmarkDevicesAlgorithmQueue(); - // devicesListViewEnableControl1.ResetListItemColors(); - //} - - //private void radioButton_Unbenchmarked_CheckedChanged(object sender, EventArgs e) { - // _algorithmOption = AlgorithmBenchmarkSettingsType.UnbenchmarkedAlgorithms; - // CalcBenchmarkDevicesAlgorithmQueue(); - // devicesListViewEnableControl1.ResetListItemColors(); - //} - - //private void radioButton_ReOnlySelected_CheckedChanged(object sender, EventArgs e) { - // _algorithmOption = AlgorithmBenchmarkSettingsType.ReBecnhSelectedAlgorithms; - // CalcBenchmarkDevicesAlgorithmQueue(); - // devicesListViewEnableControl1.ResetListItemColors(); - //} - - //private void radioButton_All_CheckedChanged(object sender, EventArgs e) { - // _algorithmOption = AlgorithmBenchmarkSettingsType.AllAlgorithms; - // CalcBenchmarkDevicesAlgorithmQueue(); - // devicesListViewEnableControl1.ResetListItemColors(); - //} - private void FormBenchmark_New_FormClosing(object sender, FormClosingEventArgs e) { if (_inBenchmark) { e.Cancel = true; return; } + + // disable all pending benchmark + foreach (var cDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + foreach (var algorithm in cDev.GetAlgorithmSettings()) { + algorithm.ClearBenchmarkPending(); + } + } + // save already benchmarked algorithms - ConfigManager.Instance.CommitBenchmarks(); + ConfigManager.CommitBenchmarks(); // check devices without benchmarks - foreach (var cdev in ComputeDevice.AllAvaliableDevices) { - bool Enabled = false; - foreach (var algo in cdev.DeviceBenchmarkConfig.AlgorithmSettings) { - if (algo.Value.BenchmarkSpeed > 0) { - Enabled = true; - break; + foreach (var cdev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + if (cdev.Enabled) { + bool Enabled = false; + foreach (var algo in cdev.GetAlgorithmSettings()) { + if (algo.BenchmarkSpeed > 0) { + Enabled = true; + break; + } } + cdev.Enabled = Enabled; } - cdev.ComputeDeviceEnabledOption.IsEnabled = Enabled; } - devicesListViewEnableControl1.SaveOptions(); } private void devicesListView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { - //algorithmSettingsControl1.Deselect(); // show algorithms - var _selectedComputeDevice = ComputeDevice.GetCurrentlySelectedComputeDevice(e.ItemIndex, true); - algorithmsListView1.SetAlgorithms(_selectedComputeDevice, _selectedComputeDevice.ComputeDeviceEnabledOption.IsEnabled); - //groupBoxAlgorithmSettings.Text = String.Format("Algorithm settings for {0} :", _selectedComputeDevice.Name); + var _selectedComputeDevice = ComputeDeviceManager.Avaliable.GetCurrentlySelectedComputeDevice(e.ItemIndex, true); + algorithmsListView1.SetAlgorithms(_selectedComputeDevice, _selectedComputeDevice.Enabled); } private void radioButton_SelectedUnbenchmarked_CheckedChanged_1(object sender, EventArgs e) { _algorithmOption = AlgorithmBenchmarkSettingsType.SelectedUnbenchmarkedAlgorithms; CalcBenchmarkDevicesAlgorithmQueue(); devicesListViewEnableControl1.ResetListItemColors(); + algorithmsListView1.ResetListItemColors(); } private void radioButton_RE_SelectedUnbenchmarked_CheckedChanged(object sender, EventArgs e) { _algorithmOption = AlgorithmBenchmarkSettingsType.ReBecnhSelectedAlgorithms; CalcBenchmarkDevicesAlgorithmQueue(); devicesListViewEnableControl1.ResetListItemColors(); + algorithmsListView1.ResetListItemColors(); + } + + private void checkBox_StartMiningAfterBenchmark_CheckedChanged(object sender, EventArgs e) { + this.StartMining = this.checkBox_StartMiningAfterBenchmark.Checked; } } diff --git a/NiceHashMiner/Forms/Form_Benchmark.resx b/NiceHashMiner/Forms/Form_Benchmark.resx index 31d6164..1af7de1 100644 --- a/NiceHashMiner/Forms/Form_Benchmark.resx +++ b/NiceHashMiner/Forms/Form_Benchmark.resx @@ -117,1209 +117,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - AAABAAQAEBAAAAEAIABoBAAARgAAAAAAAAABACAAGd4AAK4EAAAgIAAAAQAgAKgQAADH4gAAMDAAAAEA - IACoJQAAb/MAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAQQFGhdFVoMogKHNMZvE8DGawu4ofZ3JFD9PfAECAxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAACFkRWhz6/6/xCyv7/QMr+/0HK/v9Dyv7/RMv+/0XL/v8/uOb6FDpIeAAAAAAAAAAAAAAAAAAA - AAAAAAACImqFtEHK/f9Gz/7/Qcr+/0HF9/85p9D/O6nS/0fI+P9KzP7/S8z+/0vM/f8iW3CjAAAAAAAA - AAAAAAAAGk1gi0XO/f9Gz/7/RMXw/yFec/8mZn7/NpCx/ziQsf8uaYD/MGqB/0/H9P9Tzv7/Us79/xk/ - TXgAAAAAAwoMJDu87PxByv7/Pr3s/0Z4gf9Pzfb/Tc/+/1DO/v9Tz/7/V8/+/1bI9P88c4r/Wcn0/1zR - /v9QueL3AgQFFhpSZ4tAyv7/NqjR/yt8mf9Jzfz/TtT+/1PU/v9X0P7/XNH+/2DS/v9j0/7/ZdH6/1GR - rf9dud3/ZdP+/yFGVHgrh6rNQsr+/0XL/f85n8T/Ts7+/1TS/v9e1f7/X9L+/2XT/v9r1f7/b9b+/3LW - /v9ntNP/c9f9/3HW/v9CgJi6NKHK7EPL/v9HzP7/TM39/2XT/P9x0vX/bM/1/2jU/v9w1v7/fNPz/4PY - 9/+C2fz/gtr9/4Ha/v9/2v7/WJ242TWhyutFy/7/T8z7/3DP9P9sxe3/WbXm/0iq4/9Zuuv/VLPm/0yr - 4/9fuef/csjv/4LV9f+R3v3/jt7+/2Oft9gth6nJSMz+/1bE9P9FpeD/Io3Z/y+X3P87qeX/edb6/3/U - 9v8zpOX/KpLa/yiQ2f9HqOP/l9v5/57i/v9ahZe3G1BkhEnM/v9Qyfr/Nqfm/zqx6/9CvPH/V8z3/4Xb - /v+S3/7/Tcn3/0G47v84sOv/UK/m/7Xn/v+x5///N0pTcwMJCx5Gvev6Vs/7/0zK+f8qpej/W8Ty/4nb - +P+M3f7/nOH+/5De+P9IuO7/M6ro/07N/P/J7P3/rNDg9AMEBBIAAAAAHElaflnQ/f+D2ff/l932/6fm - +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 - AAAHETRBlzq04f5Bzf7/R8/+/0HL/v9Ayv7/Qcr+/0HK/v9Cyv7/Qsr+/0PL/v9Ey/7/RMv+/0XL/v9F - y/7/Rsv+/0bL/v9Gy/7/OaXO+AwjLHsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAADxtVasRAx/r/Qcr+/0HM/v9J0f7/Qcr+/0HK/v9Cyv7/Q8r+/0PL/v9Ey/7/Rcv+/0bL/v9G - y/7/R8z+/0jM/v9IzP7/Scz+/0nM/v9JzP7/RcHw/xY9TKUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAocWW/HQMr9/0HK/v9By/7/Ss7+/0PQ/v9Byv7/Qsr+/0PL/f89uOX/MpW5/y6Eo/8w - hqX/N5q+/0S+7P9KzP7/S8z+/0vN/v9Mzf7/TM3+/03N/v9Mzf7/Ssf2/xc+TaYAAAABAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAFEBOp0DM/P9BzP7/Q8v+/0rO/v9Ez/7/Qs7+/0HG+P8qfZv/EjA6/wkND/8T - KjP/Gj1K/xs9Sv8WKzP/EhUZ/x9ATf85jq7/Tsz7/0/O/v9Qzv7/UM7+/1DO/v9Qzv7/TMTx/w8nMH4A - AAAAAAAAAAAAAAAAAAAAAAAAAAgUGl1Bvu3/R8/+/0nQ/v9I0P7/Qs/+/0TP/v9Ircz/Eysu/xc8Sf8y - ja7/RcTz/0rM/v9Lzf7/Tc3+/07N/v9KwOz/Ooqo/yM9Sf8lQU3/SrTc/1TP/v9Uz/7/VM/+/1TP/v9U - z/7/Rq3U+QMHCTcAAAAAAAAAAAAAAAAAAAAMK4Wm6ELL/v9By/7/Qcz+/0HM/v9Cy/7/QZqy/3NSNv9M - p7z/SM/9/0rO/v9Lzf7/Tc3+/0/N/v9Qzv7/Us7+/1PP/v9Vz/7/Vc36/0GPrf8mN0H/SqfL/1nQ/v9Z - 0P7/WdD+/1jQ/v9Y0P7/K2Z8ygAAAAEAAAAAAAAAAAsjK3c/yPz/QMr+/0DK/v9Byv7/Qsr+/zObwf8Y - OD3/WMfp/1LT/v9L0P7/TdH+/0/R/v9Qzv7/Us7+/1TP/v9Wz/7/V9D+/1nQ/v9a0P7/XNH+/1O33P8w - RlL/VLbc/17R/v9e0f7/XdH+/13R/v9WxO7/Bg4RTgAAAAAAAAABJnmY30DK/v9Ayv7/Qcr+/0LK/v9A - wPD/FDVA/0G86f9K0P7/TND+/07W/v9Q1P7/UtP+/1TQ/v9Wz/7/WND+/1rQ/v9c0f7/XtH+/1/S/v9h - 0v7/YtL+/1m53f87WWj/YtH6/2PT/v9j0/7/YtL+/2HS/v8rXHC4AAAAAAEDBDo7vOz/QMr+/0HK/v8w - mLz/K4Sj/yFfdf83n8T/Scz+/0zR/v9O0v7/Udb+/1PV/v9W1f7/V9H+/1rQ/v9c0f7/X9H+/2HS/v9j - 0/7/ZdP+/2bT/v9n1P7/aNT+/1abt/9Qi6T/VJm1/1yy1P9o1P7/ZtP+/0+mx/kAAAAUDi46fkDK/v9B - yv7/Qsr+/0PL/v9BwvP/J2yE/0K45P9LzP7/TtD+/1HS/v9U1f7/V9b+/1zV/v9b0f7/XtH+/2HS/v9k - 0/7/ZtP+/2jU/v9q1P7/bNX+/23V/v9u1f7/Zbnb/1iPqP9u0/v/b9b+/27V/v9s1f7/adH5/wgPElQb - VmyvQMr+/0HK/v9Dy/7/RMv+/0bL/v9Hyfr/MH+a/03N/v9Qzv7/U9H+/1bS/v9a0/7/adX+/1/S/v9j - 0/7/ZtP+/2nU/v9s1f7/btX+/3DW/v9y1/7/dNf+/3XX/v9hm7T/dtj+/3bY/v911/7/dNf+/3PX/v9x - 1v7/HTlDhiRxj9BByv3/Qsr+/0TL/v9Gy/7/SMz+/0rM/v9KxvP/T87+/23T9/9yz/H/Y9H6/3PQ8v9g - 0v3/ZNP+/2fU/v9r1f7/btX+/3TS9v+C1/X/dNH1/4zb9v981/r/fNn+/3vT9v992f7/fdn+/3zZ/v97 - 2f7/edj+/3fY/v8vVmWnKX+g4UHK/v9Dy/7/Rcv+/0fM/v9JzP7/TM3+/0/O/v9Szv7/etn6/3LQ8v9x - 1fr/ccrt/2TT/f9o1P7/bNX+/3DW/v901/7/cs3x/4TX9/930fX/it/6/4ja+v+E2/7/hdv+/4Xb/v+F - 2/7/hNv+/4Lb/v+A2v7/ftn+/zpmd7gpgKHhQsr+/0TL/v9Gy/7/SMz+/0vM/v9ZzPj/b9L2/3LR9f92 - 0PT/bMjv/2jF7v9cuOf/Zcjx/2rN9P9w0vn/c9H2/3PN8v9sw+r/Y73s/3PI7v9yzPL/gNPz/4bX9f+L - 2fb/i9v6/43d/v+M3f7/it3+/4jc/v+F2/7/Pmd4uCZ1k9JDy/7/Rcv+/0fL/v9KzP7/Xsv1/3vT9f9u - y/P/Z8Hs/2C55/9Ur+L/RaTf/zmd3/80md3/NZre/2K+6v9Hpd3/M5jd/zaa3f89oOD/S6jf/1iz5P9k - vOj/aMXw/3LO9f+D1PP/ktz6/5Tf/v+S3/7/kN7+/4zd/v85XGqqHl10s0TL/v9Gy/7/SMz+/0vM/v9q - xe7/Wbjq/06r4P8xltv/IYzZ/yKN2f88ndv/Lpfe/z2j3/9kw+//dtL3/3HK8f9lvuj/MZrg/zab3/8w - lNj/IYzZ/yOO2v89ndn/VLLo/1687P+P1/X/neH+/5vh/v+Y4P7/lN/+/ytBS4oSNkSDRMv+/0fL/v9J - zP7/TM39/1q16P87nt//Pp7c/yGM2f8hjdn/IY7a/z2k4f8uqOr/Tbnr/3rZ/v+A2v7/htv+/4XX9/80 - rOj/Mafp/zWb3P8hjtr/IY3Z/yyT2f88nt3/P6Hg/4nR9P+m5P//o+P//6Di//+c4f7/EBgbWgMKDEFD - w/T/R8z+/0rM/v9Ozf7/Urnr/zCX3v84oOL/OqHe/y+Y2f8lktj/QbXr/znB+v9cx/H/f9r+/4Xb/v+L - 3f7/kd79/0S/8P83v/j/OaPf/yqV2P8zm9v/Qafi/y6Y3/86nN3/pd/6/7Dm//+t5f//qeT//4m91P0A - AAAaAAAABi+IquZIzP7/S83+/0/O/v9Szfz/RrLl/y+v7/8zuPT/QMP4/07M+/9Nz/7/UtL+/23O8v+D - 2/7/itz+/5De/v+X4P7/Yczz/07Q/v9Qz/3/SMn6/zq/9/8xtPL/Na7t/5TQ7f+96v//uur//7fp//+y - 6P//WHWBwQAAAAAAAAAAEjRBgUnM/f9Mzf7/UM7+/1bJ9f89wvn/P8T4/zyu5/8ypeT/Mafk/3LY+f96 - 3v//e9Hy/4fc/v+O3v7/ld/+/5zh/v+C1fP/c93//1nD7/8wpuT/NKfk/0G47P87xPv/V8f0/8Pq/P/F - 7P//wOv//7fm+v8VGx5aAAAAAAAAAAABAgMUN5m97k3N/v9Rzv7/YNP8/1DR/v9bzPT/JqTp/yen6/8r - qen/nuf9/6Tq/v+A0fL/it3+/5Lf/v+Z4P7/oeP//5vb8/+e6P//c87z/yep7P8mpur/Pa/o/1jU//9Q - 0f7/yO39/9Du///K7f//dIuW2AAAAAQAAAAAAAAAAAAAAAAOJi9sTMj3/1HO/v9t2P3/d97+/4ji/v9y - zPH/R7bq/0q36f+67///v/H+/4LT9P+N3f7/ld/+/53h/v+m5P//q+H1/7zw//+V2/X/PLPq/1S76/+I - 2/j/f+D//4Df/f/e8/7/2/L//8Lc6f4RExVGAAAAAAAAAAAAAAAAAAAAAAAAAAQjXHG3Us7+/1fP/f9t - zO//mNzy/7Xs/f+/8f//w/P//8L0///B9f//suz5/5ve9P+X4P7/nd/7/67m9f+/8/3/wfX//8P0///C - 8///u/D//6zm+P+k3PD/0+r2/+73///m9P3/QkhMkgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAxMy - fZrVV8/+/1vR/v9h0f3/qOf5/5fb8f+g4/f/quj1/5nh9v+f5Pb/ltzz/5ng/v+e3/v/p+Ty/7Dn9v+s - 4fH/wPf+/8Tm9P+16PX/3PH5//f6///6/P//+Pv+/2xvcrwAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAIEBRs0fJjTXNH+/2HS/v+t7Pr/g9by/5jl+v+S3vH/gdr+/4nc/v+R3v7/muH+/6Pj//+t - 5f//uOj//7Dg9P+x8/v/1e/7/7Dn8v/e9Pr//f3///39/f91dXW9AAAACwAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAECAxEoWm2xXsz2/3jV9v9y0/j/hdv3/4TX8/+B2v7/idz+/5He/v+a - 4f7/o+P//63m//+46f//vej7/7Dl8v/V7/v/zuv1/+j0+v/r6+z+UFBQlwAAAAYAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQIypiSpe16GzV/f9z1/7/etj+/4Ha/v+J - 3P7/kd7+/5ng/v+i4/7/rOX//7fp///B7P//zO7//9jx///j8vz/mp+i3BkZGUkAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEOGC43ckeGnthx - yu3/gNr+/4fc/v+P3v7/mOD+/6Di//+q5f7/tOj+/77r//+01eX+eIiRyyIlJ2MAAAAFAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAwQGBy8cMDdvN1lmnkt0hb1YgpTMXIOTy1Z1g7pEWWKZIywwaAICAyMAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///AAH//gAAf/gAAB/wAAAP4AAAB+AAAAfA - AAADgAAAAYAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGA - AAABgAAAAcAAAAPAAAAH4AAAB/AAAA/4AAAf/AAAf/8AAP//wAf/KAAAADAAAABgAAAAAQAgAAAAAAAA - JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIFBgUPMDwKBQ8TOAQMDmQDCg2AAwoNjQMKDYsD - Cw18BAwPWwYSFysOKzYIAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEJHyZmHVlwpSRxjtwpgaL/MZnB/ziw3P88 - vu//PsT2/z7E9v89u+z/N6vY/y+Tuv8pfp7/I2yI0RpRZZcBAwNYAAAAEgAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkCBogvTKLrPg9wPD+PsX4/0DK/v9A - y///QMr//0HK/v9Byv7/Qcr+/0HK/v9Byv7/Qcr+/0LK//9Cy///Qsv9/0HF9v8+v+/8JXKO8wEGB5gA - AAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMFBQAAAAAAAAAAJBVDUpspg6D/Q9P//03S//9A - y/7/QMr+/0DK/v9Ayv7/Qcr+/0HK/v9Byv7/Qcr+/0HK/v9Cy/7/Qsv+/0PL/v9Dy/7/Q8v+/0TL/v9E - y/7/R9L//0PJ+/8lbIf/EjZDeAAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAEDA95LY6x7z3B7v9C - 0///RM/+/0nN/v9Ayv7/Qcr+/0HK/v9Byv7/Qcr+/0LK/v9Cy/7/Q8v+/0PL/v9Dy/7/RMv+/0TL/v9E - y/7/Rcv+/0XL/v9Gy/7/Rsv+/0bM/v9Hzv//QLnm/yp4lt8AAABQAAAAAAAAAQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwwnML84 - r9z/Qs///0HN/v9Azv7/TtL+/0PN/v9Byv7/Qcr+/0HK/v9Byv7/Qsv+/0LL/v9Dy/7/RMv+/0TL/v9E - y/7/RMv+/0XL/v9Gy/7/Rsv+/0fM/v9HzP7/R8z+/0fM/v9HzP7/R8z+/0nP//8zkbT/CyAofAAAAAEA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAbHl111T/D9f9Czf//Qcv+/0HM/v9Gzv7/TNT+/0HM/v9Byv7/Qcr+/0LL/v9Dy/7/Q8v+/0TL/v9E - y/7/RMv+/0XL/v9Gy/7/R8z+/0fM/v9HzP7/R8z+/0jM/v9JzP7/Scz+/0nM/v9KzP7/Ss3+/0rN/v9M - 0///P6/Z/xtKXLEAAAAHGEFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAABkaUmb4Q8///0HK/v9Byv7/Qcv+/0LM/v9O0f7/Q9L+/0HL/v9Cyv7/Qsv+/0PL/v9E - y/7/RMv+/0XL/v9Fy/7/Rsz+/0fM/v9HzP7/SMz+/0jM/v9JzP7/Ssz+/0rN/v9Kzf7/S83+/0vN/v9L - zf7/TM3+/0zN/v9Mzf7/TM3+/0jC8f8TMz/IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAFx9geN9E1f//Qcv+/0HL/v9By/7/Qcz+/03O/v9H0f7/QtH+/0LL/v9C - y/7/Rc3//0bU//8+vOn/NJzB/y6Gpf8oc4z/Jmh//yZpgf8reJL/M4qr/zyjyf9GxfP/TtX//03O//9M - zf7/Ts3+/03N/v9Ozf7/Ts7+/07O/v9Ozv7/Ts7+/07Q//9KxPL/GD9OugAAAAcAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAQOEgAAAAAAFD9NyD/H9/9Bzf7/Qcz+/0HM/v9DzP7/Uc/+/0bR/v9C - 0P7/Q8/+/0PL/v9H0///NqrS/xY+S/8MFxz/CgsO/wgDAv8IAAD/CQAA/wsCAf8MAwP/DgkK/xIUGP8W - ICb/JFZm/0a85v9Q0///UM7+/1DO/v9Qzv7/UM7+/1HO/v9Rzv7/Uc7+/1HO/v9Rz///Sbvn/xY5RocA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGFBqRO7/p/0HR//9Bzv7/Q87+/0nO/v9P - 0P7/RND+/0PQ/v9D0P7/Q83//zir1P8VP0z/AgAA/wwVGf8VMTv/JGN4/zSSs/8+sNf/Qr/o/0O95/8/ - rNP/No6r/yhfcf8eNT//Fxsg/xEJCv8sYnX/S73n/1PR//9Tz/7/U8/+/1TP/v9Uz/7/VM/+/1TP/v9U - z/7/VNH//zqQsf8CBgdAAAAAAAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAEA9ocn7TND//0zQ/v9N - 0/7/S9P+/0jS/v9D0f7/Q9L+/0PQ/v9U1f//RH6C/xMaEP8KFBf/K32Z/z6y3P9Jzv//TNL//0zQ//9N - z///Ts///07P//9Q0P//UdH//1PU//9QzPr/R6/W/zR1jP8YFRf/HiUr/z6Oq/9Z2v//VtD+/1bQ/v9W - 0P7/VtD+/1bQ/v9W0P7/VdD+/1jW//8vcovxAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyBheb1C - yvr/Q87+/0LN/v9AzP7/Qs7+/0LP/v9Cz/7/Q8v+/0XH9/9qcGT/hEEZ/0Nzbf9Jz/7/Sc///0rM/v9K - zf7/TM3+/03N/v9Nzv7/UM7+/1DO/v9Sz/7/Us/+/1TP/v9Uz/7/Vc/+/1fT//9Uy/f/LE1c/x8YHP84 - c4r/WdH//1nR/v9Z0P7/WdD+/1nQ/v9Z0P7/WdD+/1jQ/v9Z0v//GDxImQAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAARDOfyP9Ay///QMr+/0HK/v9Byv7/Qcr+/0LK/v9Dy/7/RM///x1OW/9APiP/c6m2/2Tf//9M - 0v//S9L+/0zS/v9N0f7/Ts/+/0/O/v9Qzv7/Us7+/1PP/v9Uz/7/VdD+/1bQ/v9X0P7/WND+/1nR/v9a - 0f//W9P//0KIpP8kIif/P3qR/1/Y//9c0f7/XdL+/1zS/v9c0v7/XNH+/1zR/v9b0f7/P5Cv8gsaHxkA - AAAAAAAAAAAAAAAAAAAAF0ZX50LR//9Ayv7/QMr+/0HK/v9Byv7/Qsr+/0PL/v9F0P//HFFj/woQE/9D - stb/Wtf+/1LT/v9L0P7/TdD+/07R/v9P0v7/UdL+/1HO/v9Sz/7/VM/+/1XP/v9W0P7/WND+/1nQ/v9a - 0f7/W9H+/1zR/v9d0f7/XdL+/1/S/v9Qqcr/KSct/0iSrf9i1///YNL+/2DS/v9g0v7/YNL+/1/S/v9f - 0v7/Wcjy/xAlLIwAAAAAAgECAAAAAAAAAABJN6/c/0HM//9Ayv7/Qcr+/0HK/v9Cyv7/Q8v+/0TL/v8y - l7v/ChIV/zimzP9K1P//SdH+/0vQ/v9N0/7/T9b+/1DU/v9R0/7/U9P+/1TQ/v9Vz/7/VtD+/1jQ/v9Z - 0P7/W9H+/1zR/v9d0f7/XtH+/1/S/v9g0v7/YdL+/2LT/v9k1///TZSv/y4sMv9aut7/ZNT+/2TT/v9j - 0/7/Y9P+/2LT/v9i0/7/ZNn//zJuhf8AAAADAAAAAAAAAAAYSFyjQc3//0DK/v9Byv7/Qcr+/0TR//9G - 1f//RtD//0fS//8PKC//M5Gz/0nP//9Kz/7/TNL+/03R/v9O2P7/Udj+/1LV/v9U1v7/VdT+/1fR/v9X - 0P7/WdH+/1vR/v9c0f7/XtL+/1/S/v9g0/7/YtP+/2LT/v9k0/7/ZdT+/2XU/v9m1P7/aNj//0yIov9C - ZHX/Z9P9/2nZ//9q3f//aNf//2bU/v9l1P7/ZdX//2DM9v8AAABrAAAAAAAAABAriKvUQMr//0HK/v9B - yv7/Q87//yNyi/8VQk//KHyW/yp8mP8YOkf/R8r7/0nM/v9L0P7/TdL+/0/S/v9R1f7/Utb+/1TV/v9V - 1v7/WNb+/1jR/v9a0P7/XNH+/17R/v9f0v7/YNL+/2LT/v9j0/7/ZdP+/2bU/v9o1P7/aNT+/2nV/v9q - 1f7/atX+/2vS+/9BVGL/X7TU/1CHnv9DYG7/WanH/2vY//9q1f7/aNT+/2vb//8oU2PGAAAAAA8uOiAx - nMT7Qcr+/0HK/v9Byv7/Qsv+/0XP//9DzP//OqzV/yFcb/8mZ33/StD//0vN/v9Mzv7/T9P+/1HS/v9S - 1f7/VNb+/1bW/v9Y1/7/WNT+/1vR/v9d0f7/X9L+/2DT/v9i0/7/ZNT+/2bU/v9o1P7/adX+/2vV/v9r - 1f7/bNb+/27W/v9u1v7/b9b+/2/W/v9RfJH/V4+o/2nD5v9v2f//cNj//27W/v9t1v7/bdb+/2zX//9N - mrjiAAAAFxQ+TUg3q9f/Qcr+/0HK/v9Cy/7/Q8v+/0TL/v9Fy/7/R8v+/0jP//8qc4v/QrPd/0zN/v9O - zv7/UM/+/1PU/v9U1P7/VtX+/1jW/v9l2P7/ctr+/17S/v9f0v7/YtP+/2PT/v9m1P7/Z9T+/2rV/v9r - 1f7/bNX+/27W/v9v1v7/cdb+/3LX/v9y1/7/dNj//2q+3/9ck6z/dNj+/3TY/v9z1/7/c9f+/3PX/v9x - 1/7/cNb+/2/W/v9fudzzBQkLMhE2Q30+wfP/Qcr+/0HK/v9Dy/7/RMv+/0TL/v9GzP7/R8z+/0nM/v9A - rtf/MYGa/0/R//9Qzv7/Ts7//1HQ//9V0v7/WNP+/1nT//9e0/7/Y9T+/2DS/v9i0/7/ZNP+/2fU/v9p - 1P7/a9X+/23W/v9u1v//cNf//3LX/v9z2P//c9j//3bY/v932f7/euD//1V0hP920/b/edj+/3nY/v94 - 2P7/d9j+/3fZ/v922P7/dNf+/3TY/v9ju97/JkdUSBM8SqVCzv//Qcr+/0LL/v9EzP7/RMz+/0bM/v9H - zP7/SM3+/0rN/v9Lzfz/Ssfz/0/P//9Oz///g9Hs/4DP6v9cz/v/Xs/6/2rH6/9mz/f/YNP+/2TT/v9l - 1P7/Z9T+/2rV/v9s1v7/b9b+/3LV/P92ze7/fM/u/3XZ//+CzOf/jdTs/3zY/P982f7/fdv//3nR8/9+ - 2///ftr+/37a/v992v7/fNr+/3vZ/v972f7/edn+/3jY/v9rxOf/MFdmYxlPY75Cz///Qsr+/0PL/v9E - y/7/Rcv+/0fM/v9HzP7/Ss3+/0vO/v9Nzv7/T87+/1HO/v9Ozf7/meP4/4HY9f9c0Pv/cNb7/5jo//9o - w+b/Y9T//2bU/v9p1P7/a9X+/27V/v9w1v7/c9f+/3HP9P+G3fr/mef//3vZ/v92yeb/lef+/4Ha/f+A - 2v7/gdv+/4Lb/v+C2/7/gtv+/4Lb/v+C2/7/gdv+/4Da/v9/2v7/fdr+/3zZ/v9zzO//M1tqehxYb8xD - z///Q8v+/0PL/v9Fy/7/Rsv+/0fM/v9JzP7/Ss3+/03N/v9Ozv7/UM7//1HP//9Nyvv/n+j9/3nT8v9b - z/v/eNb4/33V+f9cveX/Z9X//2nV/v9s1f7/btb+/3DX/v901/7/dtj+/3LP9P91z/P/gtf5/4be//9z - xeT/lef//4HW+P+G3f//h93//4fd/v+H3f7/iN3+/4fd/v+H3P7/htz+/4Xc/v+E3P7/gtv+/4Hb/v95 - 0fP/Nl1thB1ZcM1Dz///Q8v+/0TL/v9Fy/7/R8z+/0jM/v9KzP7/TM3+/03N/f9Uzvz/XMny/23O8f9u - y+7/h9v6/3HM8f9dyvT/dM/0/2W/7f9bv+j/atT9/2zU/P9u1f3/ddj+/3jY/f931/z/etf8/3bQ9f9k - ver/a8Xw/4HU9f92x+n/ftj7/4bS7/+J1PH/h9Pw/4jY+P+M3f3/jd7+/4ze/v+M3v7/i93+/4rd/v+I - 3f7/h9z+/4bc/v9+0vT/OF9uhRtUacFE0P//RMv+/0TL/v9Gy/7/R8z+/0nM/v9Lzf7/UMr4/3fT9P+E - 2fb/hdr6/3nU+P9xzfX/ZsTy/2LA7/9guen/VbHm/0mq5f9SruP/T6zh/1Gv4/9XtOT/c9P6/2K54v9U - sOT/Uq3h/1Ot4v9KquT/Tq7m/1y25/9hvu//Y8Hw/2zJ9P900Pf/ftj6/4Xa+P+L2fX/jNXy/5Ph//+R - 4P7/kd/+/5Df/v+O3/7/jN7+/4rd/v+B0PD/Ol5tfBZDVKlE0P//RMv+/0XL/v9HzP7/Scz+/0rN/v9N - zP3/ddDy/3fT9/9wzPT/aMXy/2TA7v9ft+P/XbPg/1Sr3P9Kp93/QKLh/zec3/8zmN3/L5fd/y6W3f84 - m9z/c9L4/0yn2P8tlt7/L5bc/zGX3P82m97/O57g/0al3/9Pqdr/W7Lf/2C14f9hu+n/ZsTx/2zK8/9y - 0Pb/h9n3/5DX8/+X4f//l+D+/5Xg/v+U4P7/kd/+/4/f/v+CzOn/PF5saBI3RINCx/n/RMv+/0bL/v9I - zP7/Sc3+/0vN/v9Ry/r/dcnv/2G/7/9auez/VrHi/0Og2v8tlN3/JpDb/yeQ2/8okNj/S6Ta/y6W3f8u - l97/QKPf/1i35/9evOj/e9f7/27G7P9euuf/VrLh/y+X3v8ult3/N5rc/ziZ2P8pktv/JI7b/yeR3P84 - mtz/Uard/1e36/9evO7/ZcPx/4zU8v+d4v//nOL//5vh//+Z4P7/l+D+/5Tf/v+BxeD/OVViTBVBUU87 - st//Rcv+/0bM/v9IzP7/Ssz+/0vN/v9hzvj/XLbp/0ys5f9IqOT/MZDO/yCM2v8hjNn/IY3Z/yGN2v8e - jNn/U63g/y2c4/8uoeb/Vbno/3nZ/v982/7/f9v+/4Tc/v+I3v//iN76/zGe3f8un+X/N5/h/zWa3P8h - jdr/IY3Z/yGM2f8gjNr/JYnN/0up4v9IqeX/T7Dn/3nJ8f+k5P7/ouT//6Hj//+e4///nOL//5rh//+E - xN72GSQoNhdEViI2oMn/Rsv+/0fM/v9JzP7/S83+/0vN/v9q0/v/Sabj/zmc3/83m97/S6fi/x6L2f8h - jtr/IY7a/yKQ2/8fjtr/VLfp/y2r7v8wsvD/XcLt/3vZ/v9/2v7/g9v+/4fc/v+L3f7/kOD//zet4/8u - r/D/N63r/zef3/8ikNv/Io/b/yGO2v8fjNr/P6Df/zye3/83m97/O5/h/3PC7v+s5v//qOX//6bk//+k - 5P//ouP//6Dk//99tMzlAAAAHAAAABMzlbvZR8z+/0jM/v9KzP7/S83+/03O/v9Uzv3/UKzl/y6W3f8t - lt7/R6nm/0ak2/8kjtX/H4/c/x+R3v8fjtf/WMr4/zO9+P87w/r/Zsnv/37a/v+C2/7/htz+/4rd/v+O - 3v7/k9/+/0m96/82wPr/O773/zml4v8gkd7/H5Dd/x+M1/83mNb/T63l/y6X3v8uld3/M5ne/5HT9P+y - 6P//r+f//63m//+r5v//p+X//6jp//9QcX7MAAAAAAAAAAAhYXqtSM7//0jM/v9Kzf7/TM3+/07O/v9Q - zv7/Tr7r/z2h3v8voOX/LaXp/zKs7v9LvO7/S7bj/0uz4v9Kr97/S87//0PL//9Mz/7/b8zw/4Hb/v+F - 2/7/id3+/47e/v+S3/7/l+D+/1zG7f9Gzf//Qsr+/0y86v9KseD/TLTj/1G86v87tfH/Lafq/y6h5v81 - oOH/abPb/73s//+46f//tuj//7Po//+x5///ref//6zq//8NERN8AAAAAAAAAAAAAABWRMLx/0nN//9L - zf7/Tc3+/0/O/v9Sz/7/VND//1O75f84tPH/MLb0/zW++f89wfb/SMj4/0rK+P9L0P7/TtL//1fU//9k - 2P7/dc3v/4Tc/v+I3P7/jd7+/5Df/v+V4P7/muH//3DL7f9b1v//UtP//0zR//9LzPn/Scn4/0LD9v84 - v/j/Mrn2/zGz8v9cvOj/vuj8/8Hs//+/7P//vev//7rr//+36v//uO7//3OYqP8AAAAQAAAAAAAAAAAA - AAAAJGR99EzU//9Mzf7/Ts3+/1DO/v9Sz/7/W8ny/zu+9v83wfr/QMn//1G75/89rOf/L6Xn/zGp6f9Z - vun/atz//3Dd//+B4P7/ds3w/4fc/v+L3f7/kN/+/5Tg/v+Z4f//nuL//4HQ7f933v//bNz//2XM8v82 - rOr/LqXn/zWo6P9Ks+b/R8f4/zrE+/81v/n/bcjs/8rt///G7f//w+3//8Ls//++6///uev//zM/RqMA - AAAAAAAAAAAAAAAAAAAAAwgKW0K44/9Mzf//Ts7+/1DO/v9Uz/3/V834/0LL//9Iz///Srvl/yWg5/8k - ouf/JqTp/yOl6v9pxOz/heT//47l//+U3vb/e9L1/4jc/v+N3v7/kt/+/5fg/v+c4v//ouP//5LW8P+S - 5f7/iOT//3/W9P8lpuv/Jqbp/yWj6P8joOf/Pqze/0rR//9DzP//Rcv//7zl9v/O7///y+7//8ft///D - 7P//krTC/DU/RiEAAAAAAAAAAAAAAAAAAAAABAoLAyx4lM5MzP3/Ts7+/1HP/v9X0P7/Ztj+/1XU//9c - 1///ctT1/x+i6v8oqez/Kavt/ySr7/+C0u//oer//6vt//+Z1ur/gdn9/4rd/v+Q3v7/leD+/5rh//+f - 4///pOT//5/b9P+p6Pv/pOv//57h9v8nre7/Kazu/yiq7P8kpuv/W8Lv/2HZ//9X1f//T9L//8Lu/v/W - 8f//0vD//87u///M8P//XnJ6qQAAAAISERUAAAAAAAAAAAAAAAAAAAAAAA4mL1BGuub8UM///1HP/v9X - 0P7/ed7+/2/c//933v//j+f//2rF7f8xsO3/LrDu/ySv7/+f3fP/t/D//7/y//+Z0ub/ht3//43e/v+R - 3/7/luD+/5zh//+i5P//p+X//6bd9f+57fv/ufD//77t+f8or+7/LbHv/zGx7v9Etuz/juH7/3vf//9x - 3f//b93//9z1///e8///2fH//9n0//+etcL5AAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ - Q1OsT87+/1LP/v9Vz/7/ZdL7/4HT7/+c7P//nun//6zt//+l4vb/l9rz/4/W8v+97vv/wfP//8P1//+5 - 6/j/jNb1/4PR8v+V4P//mOH//5/j//+c3Pj/otrz/7bn9//C9P7/wvT//8f0//+Q1vL/lNrz/57e9f+u - 6vv/o+v//5vq//+G3Pf/tub3/+34///n9f//4/b//7nM1/8mKS1lAAAAAAMGBQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAJWB34FPR//9Vz/7/WND+/1jL+P9wvt7/p+Dx/77y///A8v//wvP//8L0///C - 9v//wvb//8L3///B9///wPj//8L0+v+N1/b/muH//5/i/v+v5/b/wPj//8D3///C9///wvb//8L2///C - 9f//wvP//8Hy//+/8f//tOr5/5bP4//D3ev/9Pr///H6///u+P//4e72/2hvdaEAAAAAFhUZAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAABxMWJDmPr+tY1v//WND+/1zR/v9d1P//Xcz4/5LX8P/L - +v//hM3o/53g9f+/9v7/sOr2/6bn9/+p6ff/q+z4/5/e6v+R3fz/nOL//6Hj//+d3O//rOz2/7Ds9/+1 - 6/f/tOn2/7z0/f++6/b/tt7u/8Dy/P/E8fv/1+nz//r8///9/v//+/3///r8///3/f//iIyR0gAAABIX - FxoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAAAAAAAADA4h6X/XNj//1zR/v9g - 0v7/X9L//6Di9//F9Pv/Zsju/4re/P+59///jdTn/3/Z/f+H2/z/jN38/5He+/+W4P7/nOL//6Pj//+n - 5P3/rub9/7Xn/f+86f3/uOb5/6jr9f/D7vf/0ur5/7bp8//I9v7/7vj9//v8///+/f////7///7///91 - d3jiCAUKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAAAAAAAA - AAAsPI6t61zR/v9g0///XtL//6rm9v+v6PD/bNL6/43g+/+y+f//g8/n/4Hb//+G3P7/jN3+/5Hf/v+X - 4P7/neL//6Pj//+p5v//sOf//7fp//++6///vOj6/6Hq9f+78Pj/4PL//6Hb6P+68/z/7fj8//79//// - ////9vb2/5qZmtEAAAASAAAAAEE/RQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAEAAQAAAAAACA8TIixjd9Zez/v/YtT//33Y+P+C1fD/b9b+/4PZ9/+c4/H/gs7p/4Hb//+G - 3P7/jN3+/5Lf/v+X4P7/neL//6Pk//+p5v//sOf//7jp//+/7P//v+n7/6Df7P+x5PD/4fP//7/j8P/Q - 7/f/8/n9///////f3+D/b29vpAAAABAAAAAAQUBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQIAAAAAAAAAAAAcO0idWLzi+2XT/P9r1v//b9b+/3PX/v92 - 2f//fNr//4Hb/v+G3P7/i93+/5Hf/v+W4P7/neL//6Pj//+p5v//sOf//7fp//++7P//xe3//8/v///W - 8f//3vP//+j2///x+f//8/f7/9LT1vQ3Nzd0AAAAABAQEAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYGACl0kQAAAAAADBofRj19lr5b - ttn/ct3//3TZ//932P7/fNn+/4Hb/v+G3P7/i93+/5Df/v+W4P7/m+L//6Lj//+o5f//ruf//7Xp//+9 - 6///xO3//8vu///S8P//3fX//+v9//+3wMb/hIiLpgAAAC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAkLDwMEBwk/MF5v3WW/4v942///e9r//4Db/v+F3P7/it7+/5Df/v+V4P7/m+L//6Hj//+n - 5f//reb//7Tp//+66///wez//8nv///R8f//rcPO/0xSV7wlISglAAIAAAAAAAAAAAAAS0lMAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAATEwAAAAAAAAAAAAAAADoyWmqZV5u1y2exzu5vuNb/f8zs/47e/v+X - 5P//nOX//6Lm//+o6f//qOL7/6DS5/+ZwtT/mb3N6IOdqcRIUliIAAAAJQAAAAAAAAAAHRogAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgHiMAAAAAAAAAAAAAAAAAAAAACx8zPBw+ - ZHQwM05aXi5GUIM4Ul2cPlpmpkFbaKU8UVuXOkxVfUdaZVRWanQqISgsGQAAAAcAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//gAH/ - /wAA//4AAH//AAD/+AAAH/8AAP/gAAAH/wAA/8AAAAP/AAD/AAAAAP8AAP4AAAAAfwAA/AAAAAB/AAD4 - AAAAAB8AAPgAAAAAHwAA8AAAAAAPAADgAAAAAAcAAMAAAAAABwAAwAAAAAADAADAAAAAAAMAAIAAAAAA - AQAAgAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AQAAgAAAAAABAACAAAAAAAEAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAOAAAAAABwAA8AAAAAAPAAD4 - AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/8AAAAP/AAD/4AAAB/8AAP/wAAAf - /wAA//4AAH//AAD//4AB//8AAA== - - \ No newline at end of file diff --git a/NiceHashMiner/Forms/Form_ChooseLanguage.Designer.cs b/NiceHashMiner/Forms/Form_ChooseLanguage.Designer.cs index 562afa9..4f419d6 100644 --- a/NiceHashMiner/Forms/Form_ChooseLanguage.Designer.cs +++ b/NiceHashMiner/Forms/Form_ChooseLanguage.Designer.cs @@ -1,7 +1,5 @@ -namespace NiceHashMiner -{ - partial class Form_ChooseLanguage - { +namespace NiceHashMiner.Forms { + partial class Form_ChooseLanguage { /// /// Required designer variable. /// @@ -11,10 +9,8 @@ partial class Form_ChooseLanguage /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); @@ -26,17 +22,19 @@ protected override void Dispose(bool disposing) /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// - private void InitializeComponent() - { + private void InitializeComponent() { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form_ChooseLanguage)); this.label_Instruction = new System.Windows.Forms.Label(); this.comboBox_Languages = new System.Windows.Forms.ComboBox(); this.button_OK = new System.Windows.Forms.Button(); + this.checkBox_TOS = new System.Windows.Forms.CheckBox(); + this.textBox_TOS = new System.Windows.Forms.TextBox(); this.SuspendLayout(); // // label_Instruction // this.label_Instruction.AutoSize = true; - this.label_Instruction.Location = new System.Drawing.Point(59, 9); + this.label_Instruction.Location = new System.Drawing.Point(10, 367); this.label_Instruction.Name = "label_Instruction"; this.label_Instruction.Size = new System.Drawing.Size(231, 13); this.label_Instruction.TabIndex = 0; @@ -45,36 +43,63 @@ private void InitializeComponent() // comboBox_Languages // this.comboBox_Languages.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_Languages.Enabled = false; this.comboBox_Languages.FormattingEnabled = true; - this.comboBox_Languages.Location = new System.Drawing.Point(84, 29); + this.comboBox_Languages.Location = new System.Drawing.Point(15, 384); this.comboBox_Languages.Name = "comboBox_Languages"; - this.comboBox_Languages.Size = new System.Drawing.Size(180, 21); + this.comboBox_Languages.Size = new System.Drawing.Size(195, 21); this.comboBox_Languages.TabIndex = 1; // // button_OK // - this.button_OK.Location = new System.Drawing.Point(119, 56); + this.button_OK.Enabled = false; + this.button_OK.Location = new System.Drawing.Point(216, 382); this.button_OK.Name = "button_OK"; - this.button_OK.Size = new System.Drawing.Size(110, 23); + this.button_OK.Size = new System.Drawing.Size(106, 23); this.button_OK.TabIndex = 2; - this.button_OK.Text = "&OK"; + this.button_OK.Text = "OK"; this.button_OK.UseVisualStyleBackColor = true; this.button_OK.Click += new System.EventHandler(this.button_OK_Click); // + // checkBox_TOS + // + this.checkBox_TOS.AutoSize = true; + this.checkBox_TOS.Location = new System.Drawing.Point(292, 359); + this.checkBox_TOS.Name = "checkBox_TOS"; + this.checkBox_TOS.Size = new System.Drawing.Size(151, 17); + this.checkBox_TOS.TabIndex = 3; + this.checkBox_TOS.Text = "I accept the Terms Of Use"; + this.checkBox_TOS.UseVisualStyleBackColor = true; + this.checkBox_TOS.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // textBox_TOS + // + this.textBox_TOS.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.textBox_TOS.Location = new System.Drawing.Point(13, 13); + this.textBox_TOS.Multiline = true; + this.textBox_TOS.Name = "textBox_TOS"; + this.textBox_TOS.ReadOnly = true; + this.textBox_TOS.Size = new System.Drawing.Size(430, 340); + this.textBox_TOS.TabIndex = 4; + this.textBox_TOS.TabStop = false; + this.textBox_TOS.Text = resources.GetString("textBox_TOS.Text"); + // // Form_ChooseLanguage // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(334, 91); - this.ControlBox = false; + this.ClientSize = new System.Drawing.Size(455, 427); + this.Controls.Add(this.textBox_TOS); + this.Controls.Add(this.checkBox_TOS); this.Controls.Add(this.button_OK); this.Controls.Add(this.comboBox_Languages); this.Controls.Add(this.label_Instruction); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; + this.MinimizeBox = false; this.Name = "Form_ChooseLanguage"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Choose Language"; + this.Text = "NiceHash Miner Term Of Use / Choose Language"; this.ResumeLayout(false); this.PerformLayout(); @@ -85,5 +110,7 @@ private void InitializeComponent() private System.Windows.Forms.Label label_Instruction; private System.Windows.Forms.ComboBox comboBox_Languages; private System.Windows.Forms.Button button_OK; + private System.Windows.Forms.CheckBox checkBox_TOS; + private System.Windows.Forms.TextBox textBox_TOS; } } \ No newline at end of file diff --git a/NiceHashMiner/Forms/Form_ChooseLanguage.cs b/NiceHashMiner/Forms/Form_ChooseLanguage.cs index 970f4b8..839cbfc 100644 --- a/NiceHashMiner/Forms/Form_ChooseLanguage.cs +++ b/NiceHashMiner/Forms/Form_ChooseLanguage.cs @@ -1,41 +1,54 @@ -using System; +using NiceHashMiner.Configs; +using NiceHashMiner.Enums; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; -using NiceHashMiner.Configs; -using NiceHashMiner.Enums; -namespace NiceHashMiner -{ - public partial class Form_ChooseLanguage : Form - { - public Form_ChooseLanguage() - { +namespace NiceHashMiner.Forms { + public partial class Form_ChooseLanguage : Form { + + private static readonly string TOS_TEXT = "NiceHash Miner Term Of Use\r\n\r\nNiceHash operates as in intermediate service by providing hashing power from hashing power owners to hashing power buyers. NiceHash does not directly provide it's own hashing power. We will do our best to provide stable, secure and feature full service. We do not take responsibility for any kind of hashing power loss or funds loss and do not take any kind of financial, material, legal or other responsibilities for any issues that my arise from using NiceHash Miner. NiceHash service and it's products (NiceHash Miner, etc.) is still in development, therefore some bugs or other issues may arise. We will work hard to fix any issues as soon as possible, add new features and overall improve our service. NiceHash reserves the rights to seize any funds of suspicious illegal activity such as mining with botnets, money laundering, hacking attempts, etc.\r\n\r\nAs a user of NiceHash Miner, you are providing your hashing power (you are a seller) to the hashing power buyers through NiceHash's hashing power marketplace. You earn Bitcoins from selling your hashing power for every valid share your miner generates and is accepted by NiceHash service. In some cases no shares are sent to or are accepted by NiceHash service. This cases are rare and include usage of slower hardware, software or network errors or simmilar. In these cases (no shares generated and accepted by NiceHash service) no reward in form of Bitcoins can be accounted to you. Payouts are automatic and are paid to BTC address, used in NiceHash Miner. Payment schedule can be found in FAQ on our website and is subject to change. You can always monitor your statistics on this site: https://www.nicehash.com/?p=myminer \r\n\r\nDue to possible software bugs or driver version combination you accept that the information displayed in the NiceHash Miner may be incorrect and/or that you may not get credited for mining.\r\n\r\nIf you have any questions relating to these Terms of Use, your rights and obligations arising from these Terms and/or your use of the NiceHash service, or any other matter, please contact us at support@nicehash.com."; + + public Form_ChooseLanguage() { InitializeComponent(); // Add language selections list Dictionary lang = International.GetAvailableLanguages(); comboBox_Languages.Items.Clear(); - for (int i = 0; i < lang.Count; i++) - { + for (int i = 0; i < lang.Count; i++) { comboBox_Languages.Items.Add(lang[(LanguageType)i]); } comboBox_Languages.SelectedIndex = 0; - label_Instruction.Location = new Point((this.Width - label_Instruction.Size.Width) / 2, label_Instruction.Location.Y); - button_OK.Location = new Point((this.Width - button_OK.Size.Width) / 2, button_OK.Location.Y); - comboBox_Languages.Location = new Point((this.Width - comboBox_Languages.Size.Width) / 2, comboBox_Languages.Location.Y); + //label_Instruction.Location = new Point((this.Width - label_Instruction.Size.Width) / 2, label_Instruction.Location.Y); + //button_OK.Location = new Point((this.Width - button_OK.Size.Width) / 2, button_OK.Location.Y); + //comboBox_Languages.Location = new Point((this.Width - comboBox_Languages.Size.Width) / 2, comboBox_Languages.Location.Y); + this.textBox_TOS.Text = TOS_TEXT; + } - private void button_OK_Click(object sender, EventArgs e) - { - ConfigManager.Instance.GeneralConfig.Language = (LanguageType)comboBox_Languages.SelectedIndex; + private void button_OK_Click(object sender, EventArgs e) { + ConfigManager.GeneralConfig.Language = (LanguageType)comboBox_Languages.SelectedIndex; + ConfigManager.GeneralConfigFileCommit(); this.Close(); } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) { + if (checkBox_TOS.Checked) { + ConfigManager.GeneralConfig.agreedWithTOS = Globals.CURRENT_TOS_VER; + comboBox_Languages.Enabled = true; + button_OK.Enabled = true; + } else { + ConfigManager.GeneralConfig.agreedWithTOS = 0; + comboBox_Languages.Enabled = false; + button_OK.Enabled = false; + } + } } } diff --git a/NiceHashMiner/Forms/Form_ChooseLanguage.resx b/NiceHashMiner/Forms/Form_ChooseLanguage.resx index 7080a7d..02afb7d 100644 --- a/NiceHashMiner/Forms/Form_ChooseLanguage.resx +++ b/NiceHashMiner/Forms/Form_ChooseLanguage.resx @@ -117,4 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + "NiceHash Miner Term Of Use NiceHash operates as in intermediate service by providing hashing power from hashing power owners to hashing power buyers. NiceHash does not directly provide it's own hashing power. We will do our best to provide stable, secure and feature full service. We do not take responsibility for any kind of hashing power loss or funds loss and do not take any kind of financial, material, legal or other responsibilities for any issues that my arise from using NiceHash Miner. NiceHash service and it's products (NiceHash Miner, etc.) is still in development, therefore some bugs or other issues may arise. We will work hard to fix any issues as soon as possible, add new features and overall improve our service. NiceHash reserves the rights to seize any funds of suspicious illegal activity such as mining with botnets, money laundering, hacking attempts, etc.\r\n\r\nAs a user of NiceHash Miner, you are providing your hashing power (your are a seller) to the hashing power buyers though NiceHash's hashing power marketplace. You earn Bitcoins from selling your hashing power for every valid share your miner generates and is accepted by NiceHash service. In some cases no shares are sent to or are accepted by NiceHash service. This cases are rare and includes usage of slower hardware, software or network errors or simmilar. In these cases (no shares generated and accepted by NiceHash service) no reward in form of Bitcoins can be accounted to you. Payouts are automatic and are paid to BTC address, used in NiceHash Miner. Payment schedule can be found in FAQ on our website and is subject to change. You can always monitor your statistics on this site: <a href=\"https://www.nicehash.com/?p=myminer\">https://www.nicehash.com/?p=myminer</a> \r\n\r\nIf you have any questions relating to these Terms of Use, your rights and obligations arising from these Terms and/or your use of the NiceHash service, or any other matter, please contact us at support@nicehash.com." + \ No newline at end of file diff --git a/NiceHashMiner/Forms/Form_Loading.cs b/NiceHashMiner/Forms/Form_Loading.cs index 65d75d3..8e27a39 100644 --- a/NiceHashMiner/Forms/Form_Loading.cs +++ b/NiceHashMiner/Forms/Form_Loading.cs @@ -20,6 +20,7 @@ public interface IAfterInitializationCaller { private int TotalLoadSteps = 12; private readonly IAfterInitializationCaller AfterInitCaller; + // init loading stuff public Form_Loading(IAfterInitializationCaller initCaller, string loadFormTitle, string startInfoMsg, int totalLoadSteps) { InitializeComponent(); @@ -36,11 +37,12 @@ public Form_Loading(IAfterInitializationCaller initCaller, string loadFormTitle, SetInfoMsg(startInfoMsg); } - // download miners - public Form_Loading() { + // download miners constructor + MinersDownloader _minersDownloader = null; + public Form_Loading(MinersDownloader minersDownloader) { InitializeComponent(); label_LoadingText.Location = new Point((this.Size.Width - label_LoadingText.Size.Width) / 2, label_LoadingText.Location.Y); - _startMinersInitLogic = true; + _minersDownloader = minersDownloader; } public void IncreaseLoadCounterAndMessage(string infoMsg) { @@ -117,13 +119,13 @@ public void SetTitle(string title) { }); } - public void FinishMsg(bool success) { + public void FinishMsg(bool ok) { this.Invoke((MethodInvoker)delegate { - //if (success) { - // label_LoadingText.Text = "Init Finished!"; - //} else { - // label_LoadingText.Text = "Init Failed!"; - //} + if (ok) { + label_LoadingText.Text = "Init Finished!"; + } else { + label_LoadingText.Text = "Init Failed!"; + } System.Threading.Thread.Sleep(1000); Close(); }); @@ -131,10 +133,10 @@ public void FinishMsg(bool success) { #endregion IMinerUpdateIndicator - bool _startMinersInitLogic = false; + private void Form_Loading_Shown(object sender, EventArgs e) { - if (_startMinersInitLogic) { - MinersDownloadManager.Instance.Start(this); + if (_minersDownloader != null) { + _minersDownloader.Start(this); } } } diff --git a/NiceHashMiner/Forms/Form_Main.Designer.cs b/NiceHashMiner/Forms/Form_Main.Designer.cs index 6b09f8a..60a3e81 100644 --- a/NiceHashMiner/Forms/Form_Main.Designer.cs +++ b/NiceHashMiner/Forms/Form_Main.Designer.cs @@ -129,7 +129,7 @@ private void InitializeComponent() this.toolStripStatusLabelBalanceDollarText, this.toolStripStatusLabelBalanceDollarValue, this.toolStripStatusLabel10}); - this.statusStrip1.Location = new System.Drawing.Point(0, 345); + this.statusStrip1.Location = new System.Drawing.Point(0, 266); this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.Size = new System.Drawing.Size(565, 25); this.statusStrip1.TabIndex = 8; @@ -323,7 +323,7 @@ private void InitializeComponent() this.flowLayoutPanelRates.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; this.flowLayoutPanelRates.Location = new System.Drawing.Point(3, 16); this.flowLayoutPanelRates.Name = "flowLayoutPanelRates"; - this.flowLayoutPanelRates.Size = new System.Drawing.Size(536, 123); + this.flowLayoutPanelRates.Size = new System.Drawing.Size(536, 40); this.flowLayoutPanelRates.TabIndex = 107; this.flowLayoutPanelRates.WrapContents = false; // @@ -333,7 +333,7 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.flowLayoutPanelRates); this.groupBox1.Location = new System.Drawing.Point(11, 202); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(542, 142); + this.groupBox1.Size = new System.Drawing.Size(542, 59); this.groupBox1.TabIndex = 108; this.groupBox1.TabStop = false; this.groupBox1.Text = "Group/Device Rates:"; @@ -351,14 +351,13 @@ private void InitializeComponent() // // devicesListViewEnableControl1 // - this.devicesListViewEnableControl1.AutoSaveChange = false; + this.devicesListViewEnableControl1.BenchmarkCalculation = null; this.devicesListViewEnableControl1.FirstColumnText = "Enabled"; this.devicesListViewEnableControl1.IsInBenchmark = false; this.devicesListViewEnableControl1.IsMining = false; this.devicesListViewEnableControl1.Location = new System.Drawing.Point(11, 91); this.devicesListViewEnableControl1.Name = "devicesListViewEnableControl1"; this.devicesListViewEnableControl1.SaveToGeneralConfig = false; - this.devicesListViewEnableControl1.SetAllEnabled = false; this.devicesListViewEnableControl1.Size = new System.Drawing.Size(435, 105); this.devicesListViewEnableControl1.TabIndex = 109; // @@ -366,7 +365,7 @@ private void InitializeComponent() // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(565, 370); + this.ClientSize = new System.Drawing.Size(565, 291); this.Controls.Add(this.devicesListViewEnableControl1); this.Controls.Add(this.groupBox1); this.Controls.Add(this.labelDemoMode); @@ -389,6 +388,7 @@ private void InitializeComponent() this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; + this.MinimumSize = new System.Drawing.Size(581, 330); this.Name = "Form_Main"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "NiceHash Miner"; diff --git a/NiceHashMiner/Forms/Form_Main.cs b/NiceHashMiner/Forms/Form_Main.cs index 3836480..bf82d5e 100644 --- a/NiceHashMiner/Forms/Form_Main.cs +++ b/NiceHashMiner/Forms/Form_Main.cs @@ -18,15 +18,22 @@ using NiceHashMiner.Utils; using NiceHashMiner.PInvoke; +using SystemTimer = System.Timers.Timer; +using Timer = System.Windows.Forms.Timer; +using System.Timers; + namespace NiceHashMiner { + using NiceHashMiner.Miners.Grouping; + using NiceHashMiner.Net20_backport; + using NiceHashMiner.Miners.Parsing; public partial class Form_Main : Form, Form_Loading.IAfterInitializationCaller, IMainFormRatesComunication { - private static string VisitURL = "http://www.nicehash.com"; + private static string VisitURL = Links.VisitURL; private Timer MinerStatsCheck; private Timer UpdateCheck; - private Timer SMACheck; + private SystemTimer SMACheck; private Timer BalanceCheck; private Timer SMAMinerCheck; private Timer BitcoinExchangeCheck; @@ -38,24 +45,30 @@ public partial class Form_Main : Form, Form_Loading.IAfterInitializationCaller, private Random R; - private Form_Loading _downloadUnzipForm; private Form_Loading LoadingScreen; - private Form BenchmarkForm; + private Form_Benchmark BenchmarkForm; int flowLayoutPanelVisibleCount = 0; int flowLayoutPanelRatesIndex = 0; - - const string _betaAlphaPostfixString = ""; + const string _betaAlphaPostfixString = " Pre Release_01"; private bool _isDeviceDetectionInitialized = false; + private bool IsManuallyStarted = false; + + int MainFormHeight = 0; + int EmtpyGroupPanelHeight = 0; + public Form_Main() { InitializeComponent(); + this.Icon = NiceHashMiner.Properties.Resources.logo; InitLocalization(); + ComputeDeviceManager.SystemSpecs.QueryAndLog(); + // Log the computer's amount of Total RAM and Page File Size ManagementObjectCollection moc = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_OperatingSystem").Get(); foreach (ManagementObject mo in moc) @@ -73,8 +86,17 @@ public Form_Main() label_NotProfitable.Visible = false; InitMainConfigGUIData(); + // for resizing InitFlowPanelStart(); + + if (groupBox1.Size.Height > 0 && this.Size.Height > 0) { + EmtpyGroupPanelHeight = groupBox1.Size.Height; + MainFormHeight = this.Size.Height - EmtpyGroupPanelHeight; + } else { + EmtpyGroupPanelHeight = 59; + MainFormHeight = 330 - EmtpyGroupPanelHeight; + } ClearRatesALL(); } @@ -93,14 +115,9 @@ private void InitLocalization() { linkLabelCheckStats.Text = International.GetText("Form_Main_check_stats"); linkLabelChooseBTCWallet.Text = International.GetText("Form_Main_choose_bitcoin_wallet"); - // these strings are no longer used, check and use them as base - string rateString = International.GetText("Rate") + ":"; - string ratesBTCInitialString = "0.00000000 BTC/" + International.GetText("Day"); - string ratesDollarInitialString = String.Format("0.00 {0}/", ConfigManager.Instance.GeneralConfig.DisplayCurrency) + International.GetText("Day"); - toolStripStatusLabelGlobalRateText.Text = International.GetText("Form_Main_global_rate") + ":"; toolStripStatusLabelBTCDayText.Text = "BTC/" + International.GetText("Day"); - toolStripStatusLabelBalanceText.Text = (ConfigManager.Instance.GeneralConfig.DisplayCurrency + "/") + International.GetText("Day") + " " + International.GetText("Form_Main_balance") + ":"; + toolStripStatusLabelBalanceText.Text = (ExchangeRateAPI.ActiveDisplayCurrency + "/") + International.GetText("Day") + " " + International.GetText("Form_Main_balance") + ":"; devicesListViewEnableControl1.InitLocale(); @@ -114,20 +131,25 @@ private void InitLocalization() { } private void InitMainConfigGUIData() { - if (ConfigManager.Instance.GeneralConfig.ServiceLocation >= 0 && ConfigManager.Instance.GeneralConfig.ServiceLocation < Globals.MiningLocation.Length) - comboBoxLocation.SelectedIndex = ConfigManager.Instance.GeneralConfig.ServiceLocation; + if (ConfigManager.GeneralConfig.ServiceLocation >= 0 && ConfigManager.GeneralConfig.ServiceLocation < Globals.MiningLocation.Length) + comboBoxLocation.SelectedIndex = ConfigManager.GeneralConfig.ServiceLocation; else comboBoxLocation.SelectedIndex = 0; - textBoxBTCAddress.Text = ConfigManager.Instance.GeneralConfig.BitcoinAddress; - textBoxWorkerName.Text = ConfigManager.Instance.GeneralConfig.WorkerName; + textBoxBTCAddress.Text = ConfigManager.GeneralConfig.BitcoinAddress; + textBoxWorkerName.Text = ConfigManager.GeneralConfig.WorkerName; ShowWarningNiceHashData = true; DemoMode = false; - toolStripStatusLabelBalanceDollarValue.Text = "(" + ConfigManager.Instance.GeneralConfig.DisplayCurrency + ")"; + // init active display currency after config load + ExchangeRateAPI.ActiveDisplayCurrency = ConfigManager.GeneralConfig.DisplayCurrency; + + toolStripStatusLabelBalanceDollarValue.Text = "(" + ExchangeRateAPI.ActiveDisplayCurrency + ")"; + toolStripStatusLabelBalanceText.Text = (ExchangeRateAPI.ActiveDisplayCurrency + "/") + International.GetText("Day") + " " + International.GetText("Form_Main_balance") + ":"; + BalanceCheck_Tick(null, null); // update currency changes if (_isDeviceDetectionInitialized) { - devicesListViewEnableControl1.ResetComputeDevices(ComputeDevice.AllAvaliableDevices); + devicesListViewEnableControl1.ResetComputeDevices(ComputeDeviceManager.Avaliable.AllAvaliableDevices); } } @@ -145,34 +167,39 @@ public void AfterLoadComplete() private void IdleCheck_Tick(object sender, EventArgs e) { - if (!ConfigManager.Instance.GeneralConfig.StartMiningWhenIdle) return; + if (!ConfigManager.GeneralConfig.StartMiningWhenIdle || IsManuallyStarted) return; uint MSIdle = Helpers.GetIdleTime(); if (MinerStatsCheck.Enabled) { - if (MSIdle < (ConfigManager.Instance.GeneralConfig.MinIdleSeconds * 1000)) + if (MSIdle < (ConfigManager.GeneralConfig.MinIdleSeconds * 1000)) { - buttonStopMining_Click(null, null); + StopMining(); Helpers.ConsolePrint("NICEHASH", "Resumed from idling"); } } else { - if (BenchmarkForm == null && (MSIdle > (ConfigManager.Instance.GeneralConfig.MinIdleSeconds * 1000))) + if (BenchmarkForm == null && (MSIdle > (ConfigManager.GeneralConfig.MinIdleSeconds * 1000))) { Helpers.ConsolePrint("NICEHASH", "Entering idling state"); - buttonStartMining_Click(null, null); + if (StartMining(false) != StartMiningReturnType.StartMining) { + StopMining(); + } } } } // This is a single shot _benchmarkTimer - private void StartupTimer_Tick(object sender, EventArgs e) - { + private void StartupTimer_Tick(object sender, EventArgs e) { StartupTimer.Stop(); StartupTimer = null; + // Internals Init + // TODO add loading step + MinersSettingsManager.Init(); + if (!Helpers.InternalCheckIsWow64()) { MessageBox.Show(International.GetText("Form_Main_x64_Support_Only"), International.GetText("Warning_with_Exclamation"), @@ -182,32 +209,41 @@ private void StartupTimer_Tick(object sender, EventArgs e) return; } + // 3rdparty miners check scope #1 + { + // check if setting set + if (ConfigManager.GeneralConfig.Use3rdPartyMiners == Use3rdPartyMiners.NOT_SET) { + // Show TOS + Form tos = new Form_3rdParty_TOS(); + tos.ShowDialog(this); + } + } + // Query Avaliable ComputeDevices - ComputeDeviceQueryManager.Instance.QueryDevices(LoadingScreen); + ComputeDeviceManager.Query.QueryDevices(LoadingScreen); _isDeviceDetectionInitialized = true; ///////////////////////////////////////////// /////// from here on we have our devices and Miners initialized - ConfigManager.Instance.AfterDeviceQueryInitialization(); + ConfigManager.AfterDeviceQueryInitialization(); LoadingScreen.IncreaseLoadCounterAndMessage(International.GetText("Form_Main_loadtext_SaveConfig")); - + // All devices settup should be initialized in AllDevices - devicesListViewEnableControl1.ResetComputeDevices(ComputeDevice.AllAvaliableDevices); + devicesListViewEnableControl1.ResetComputeDevices(ComputeDeviceManager.Avaliable.AllAvaliableDevices); // set properties after - devicesListViewEnableControl1.AutoSaveChange = true; devicesListViewEnableControl1.SaveToGeneralConfig = true; LoadingScreen.IncreaseLoadCounterAndMessage(International.GetText("Form_Main_loadtext_CheckLatestVersion")); MinerStatsCheck = new Timer(); MinerStatsCheck.Tick += MinerStatsCheck_Tick; - MinerStatsCheck.Interval = ConfigManager.Instance.GeneralConfig.MinerAPIQueryInterval * 1000; + MinerStatsCheck.Interval = ConfigManager.GeneralConfig.MinerAPIQueryInterval * 1000; SMAMinerCheck = new Timer(); SMAMinerCheck.Tick += SMAMinerCheck_Tick; - SMAMinerCheck.Interval = ConfigManager.Instance.GeneralConfig.SwitchMinSecondsFixed * 1000 + R.Next(ConfigManager.Instance.GeneralConfig.SwitchMinSecondsDynamic * 1000); - if (ComputeDeviceGroupManager.Instance.GetGroupCount(DeviceGroupType.AMD_OpenCL) > 0) { - SMAMinerCheck.Interval = (ConfigManager.Instance.GeneralConfig.SwitchMinSecondsAMD + ConfigManager.Instance.GeneralConfig.SwitchMinSecondsFixed) * 1000 + R.Next(ConfigManager.Instance.GeneralConfig.SwitchMinSecondsDynamic * 1000); + SMAMinerCheck.Interval = ConfigManager.GeneralConfig.SwitchMinSecondsFixed * 1000 + R.Next(ConfigManager.GeneralConfig.SwitchMinSecondsDynamic * 1000); + if (ComputeDeviceManager.Group.ContainsAMD_GPUs) { + SMAMinerCheck.Interval = (ConfigManager.GeneralConfig.SwitchMinSecondsAMD + ConfigManager.GeneralConfig.SwitchMinSecondsFixed) * 1000 + R.Next(ConfigManager.GeneralConfig.SwitchMinSecondsDynamic * 1000); } UpdateCheck = new Timer(); @@ -218,9 +254,9 @@ private void StartupTimer_Tick(object sender, EventArgs e) LoadingScreen.IncreaseLoadCounterAndMessage(International.GetText("Form_Main_loadtext_GetNiceHashSMA")); - SMACheck = new Timer(); - SMACheck.Tick += SMACheck_Tick; - SMACheck.Interval = 60 * 1000; // every 60 seconds + SMACheck = new SystemTimer(); + SMACheck.Elapsed += SMACheck_Tick; + SMACheck.Interval = 60 * 1000 * 2; // every 2 minutes SMACheck.Start(); // increase timeout @@ -244,24 +280,21 @@ private void StartupTimer_Tick(object sender, EventArgs e) BalanceCheck = new Timer(); BalanceCheck.Tick += BalanceCheck_Tick; - BalanceCheck.Interval = 61 * 1000; // every 61 seconds + BalanceCheck.Interval = 61 * 1000 * 5; // every ~5 minutes BalanceCheck.Start(); BalanceCheck_Tick(null, null); LoadingScreen.IncreaseLoadCounterAndMessage(International.GetText("Form_Main_loadtext_SetEnvironmentVariable")); - - SetEnvironmentVariables(); + Helpers.SetDefaultEnvironmentVariables(); LoadingScreen.IncreaseLoadCounterAndMessage(International.GetText("Form_Main_loadtext_SetWindowsErrorReporting")); - - Helpers.DisableWindowsErrorReporting(ConfigManager.Instance.GeneralConfig.DisableWindowsErrorReporting); + + Helpers.DisableWindowsErrorReporting(ConfigManager.GeneralConfig.DisableWindowsErrorReporting); LoadingScreen.IncreaseLoadCounter(); - if (ConfigManager.Instance.GeneralConfig.NVIDIAP0State) - { + if (ConfigManager.GeneralConfig.NVIDIAP0State) { LoadingScreen.SetInfoMsg(International.GetText("Form_Main_loadtext_NVIDIAP0State")); - try - { + try { ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "nvidiasetp0state.exe"; psi.Verb = "runas"; @@ -273,39 +306,79 @@ private void StartupTimer_Tick(object sender, EventArgs e) Helpers.ConsolePrint("NICEHASH", "nvidiasetp0state returned error code: " + p.ExitCode.ToString()); else Helpers.ConsolePrint("NICEHASH", "nvidiasetp0state all OK"); - } - catch (Exception ex) - { + } catch (Exception ex) { Helpers.ConsolePrint("NICEHASH", "nvidiasetp0state error: " + ex.Message); } } LoadingScreen.FinishLoad(); - // check if download needed - if (!MinersDownloadManager.Instance.IsMinersBinsInit() && !ConfigManager.Instance.GeneralConfig.DownloadInit) { - _downloadUnzipForm = new Form_Loading(); - SetChildFormCenter(_downloadUnzipForm); - _downloadUnzipForm.ShowDialog(); + bool runVCRed = !MinersExistanceChecker.IsMinersBinsInit() && !ConfigManager.GeneralConfig.DownloadInit; + // standard miners check scope + { + // check if download needed + if (!MinersExistanceChecker.IsMinersBinsInit() && !ConfigManager.GeneralConfig.DownloadInit) { + Form_Loading downloadUnzipForm = new Form_Loading(new MinersDownloader(MinersDownloadManager.StandardDlSetup)); + SetChildFormCenter(downloadUnzipForm); + downloadUnzipForm.ShowDialog(); + } + // check if files are mising + if (!MinersExistanceChecker.IsMinersBinsInit()) { + var result = MessageBox.Show(International.GetText("Form_Main_bins_folder_files_missing"), + International.GetText("Warning_with_Exclamation"), + MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + if (result == DialogResult.Yes) { + ConfigManager.GeneralConfig.DownloadInit = false; + ConfigManager.GeneralConfigFileCommit(); + Process PHandle = new Process(); + PHandle.StartInfo.FileName = Application.ExecutablePath; + PHandle.Start(); + Close(); + return; + } + } else if (!ConfigManager.GeneralConfig.DownloadInit) { + // all good + ConfigManager.GeneralConfig.DownloadInit = true; + ConfigManager.GeneralConfigFileCommit(); + } } - // check if files are mising - if (!MinersDownloadManager.Instance.IsMinersBinsInit()) { - var result = MessageBox.Show(International.GetText("Form_Main_bins_folder_files_missing"), - International.GetText("Warning_with_Exclamation"), - MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - if (result == DialogResult.Yes) { - ConfigManager.Instance.GeneralConfig.DownloadInit = false; - ConfigManager.Instance.GeneralConfig.Commit(); - Process PHandle = new Process(); - PHandle.StartInfo.FileName = Application.ExecutablePath; - PHandle.Start(); - Close(); - return; + // 3rdparty miners check scope #2 + { + // check if download needed + if (ConfigManager.GeneralConfig.Use3rdPartyMiners == Use3rdPartyMiners.YES) { + if (!MinersExistanceChecker.IsMiners3rdPartyBinsInit() && !ConfigManager.GeneralConfig.DownloadInit3rdParty) { + Form_Loading download3rdPartyUnzipForm = new Form_Loading(new MinersDownloader(MinersDownloadManager.ThirdPartyDlSetup)); + SetChildFormCenter(download3rdPartyUnzipForm); + download3rdPartyUnzipForm.ShowDialog(); + } + // check if files are mising + if (!MinersExistanceChecker.IsMiners3rdPartyBinsInit()) { + var result = MessageBox.Show(International.GetText("Form_Main_bins_folder_files_missing"), + International.GetText("Warning_with_Exclamation"), + MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + if (result == DialogResult.Yes) { + ConfigManager.GeneralConfig.DownloadInit3rdParty = false; + ConfigManager.GeneralConfigFileCommit(); + Process PHandle = new Process(); + PHandle.StartInfo.FileName = Application.ExecutablePath; + PHandle.Start(); + Close(); + return; + } + } else if (!ConfigManager.GeneralConfig.DownloadInit3rdParty) { + // all good + ConfigManager.GeneralConfig.DownloadInit3rdParty = true; + ConfigManager.GeneralConfigFileCommit(); + } } } + if (runVCRed) { + Helpers.InstallVcRedist(); + } + // no bots please - if (ConfigManager.Instance.GeneralConfig.hwidLoadFromFile && !ConfigManager.Instance.GeneralConfig.hwidOK) { + if (ConfigManager.GeneralConfigHwidLoadFromFile() && !ConfigManager.GeneralConfigHwidOK()) { var result = MessageBox.Show("NiceHash Miner has detected change of hardware ID. If you did not download and install NiceHash Miner, your computer may be compromised. In that case, we suggest you to install an antivirus program or reinstall your Windows.\r\n\r\nContinue with NiceHash Miner?", //International.GetText("Form_Main_msgbox_anti_botnet_msgbox"), International.GetText("Warning_with_Exclamation"), @@ -313,6 +386,18 @@ private void StartupTimer_Tick(object sender, EventArgs e) if (result == System.Windows.Forms.DialogResult.No) { Close(); return; + } else { + // users agrees he installed it so commit changes + ConfigManager.GeneralConfigFileCommit(); + } + } else { + if (ConfigManager.GeneralConfig.AutoStartMining) { + // well this is started manually as we want it to start at runtime + IsManuallyStarted = true; + if (StartMining(true) != StartMiningReturnType.StartMining) { + IsManuallyStarted = false; + StopMining(); + } } } } @@ -340,26 +425,26 @@ private void Form_Main_Shown(object sender, EventArgs e) private void SMAMinerCheck_Tick(object sender, EventArgs e) { - SMAMinerCheck.Interval = ConfigManager.Instance.GeneralConfig.SwitchMinSecondsFixed * 1000 + R.Next(ConfigManager.Instance.GeneralConfig.SwitchMinSecondsDynamic * 1000); - if (ComputeDeviceGroupManager.Instance.GetGroupCount(DeviceGroupType.AMD_OpenCL) > 0) { - SMAMinerCheck.Interval = (ConfigManager.Instance.GeneralConfig.SwitchMinSecondsAMD + ConfigManager.Instance.GeneralConfig.SwitchMinSecondsFixed) * 1000 + R.Next(ConfigManager.Instance.GeneralConfig.SwitchMinSecondsDynamic * 1000); + SMAMinerCheck.Interval = ConfigManager.GeneralConfig.SwitchMinSecondsFixed * 1000 + R.Next(ConfigManager.GeneralConfig.SwitchMinSecondsDynamic * 1000); + if (ComputeDeviceManager.Group.ContainsAMD_GPUs) { + SMAMinerCheck.Interval = (ConfigManager.GeneralConfig.SwitchMinSecondsAMD + ConfigManager.GeneralConfig.SwitchMinSecondsFixed) * 1000 + R.Next(ConfigManager.GeneralConfig.SwitchMinSecondsDynamic * 1000); } #if (SWITCH_TESTING) - SMAMinerCheck.Interval = MinersManager.SMAMinerCheckInterval; + SMAMinerCheck.Interval = MiningDevice.SMAMinerCheckInterval; #endif - MinersManager.Instance.SwichMostProfitableGroupUpMethod(Globals.NiceHashData); + MinersManager.SwichMostProfitableGroupUpMethod(Globals.NiceHashData); } private void MinerStatsCheck_Tick(object sender, EventArgs e) { - MinersManager.Instance.MinerStatsCheck(Globals.NiceHashData); + MinersManager.MinerStatsCheck(Globals.NiceHashData); } private void InitFlowPanelStart() { flowLayoutPanelRates.Controls.Clear(); // add for every cdev a - foreach (var cdev in ComputeDevice.AllAvaliableDevices) { + foreach (var cdev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { if(cdev.Enabled) { var newGroupProfitControl = new GroupProfitControl(); newGroupProfitControl.Visible = false; @@ -383,22 +468,33 @@ public void ClearRates(int groupCount) { ++hideIndex; } } - - var oldHeight = groupBox1.Size.Height; flowLayoutPanelRatesIndex = 0; - if (groupCount < 0) groupCount = 0; - groupBox1.Size = new Size(groupBox1.Size.Width, (groupCount + 1) * 40); + int visibleGroupCount = 1; + if (groupCount > 0) visibleGroupCount += groupCount; + + int groupBox1Height = EmtpyGroupPanelHeight; + if (flowLayoutPanelRates.Controls != null && flowLayoutPanelRates.Controls.Count > 0) { + var control = flowLayoutPanelRates.Controls[0]; + float panelHeight = ((GroupProfitControl)control).Size.Height * 1.2f; + groupBox1Height = (int)((visibleGroupCount) * panelHeight); + } + + groupBox1.Size = new Size(groupBox1.Size.Width, groupBox1Height); // set new height - this.Size = new Size(this.Size.Width, this.Size.Height - (oldHeight - groupBox1.Size.Height)); + this.Size = new Size(this.Size.Width, MainFormHeight + groupBox1Height); } public void AddRateInfo(string groupName, string deviceStringInfo, APIData iAPIData, double paying, bool isApiGetException) { string ApiGetExceptionString = isApiGetException ? "**" : ""; string speedString = Helpers.FormatSpeedOutput(iAPIData.Speed) + iAPIData.AlgorithmName + ApiGetExceptionString; + if (iAPIData.AlgorithmID == AlgorithmType.Equihash) { + speedString = speedString.Replace("H/s", "Sols/s"); + } + string rateBTCString = FormatPayingOutput(paying); - string rateCurrencyString = CurrencyConverter.CurrencyConverter.ConvertToActiveCurrency(paying * Globals.BitcoinRate).ToString("F2", CultureInfo.InvariantCulture) - + String.Format(" {0}/", ConfigManager.Instance.GeneralConfig.DisplayCurrency) + International.GetText("Day"); + string rateCurrencyString = ExchangeRateAPI.ConvertToActiveCurrency(paying * Globals.BitcoinUSDRate).ToString("F2", CultureInfo.InvariantCulture) + + String.Format(" {0}/", ExchangeRateAPI.ActiveDisplayCurrency) + International.GetText("Day"); ((GroupProfitControl)flowLayoutPanelRates.Controls[flowLayoutPanelRatesIndex++]) .UpdateProfitStats(groupName, deviceStringInfo, speedString, rateBTCString, rateCurrencyString); @@ -406,8 +502,9 @@ public void AddRateInfo(string groupName, string deviceStringInfo, APIData iAPID UpdateGlobalRate(); } - public void ShowNotProfitable() { + public void ShowNotProfitable(string msg) { label_NotProfitable.Visible = true; + label_NotProfitable.Text = msg; label_NotProfitable.Invalidate(); } public void HideNotProfitable() { @@ -417,20 +514,20 @@ public void HideNotProfitable() { private void UpdateGlobalRate() { - double TotalRate = MinersManager.Instance.GetTotalRate(); + double TotalRate = MinersManager.GetTotalRate(); - if (ConfigManager.Instance.GeneralConfig.AutoScaleBTCValues && TotalRate < 0.1) + if (ConfigManager.GeneralConfig.AutoScaleBTCValues && TotalRate < 0.1) { toolStripStatusLabelBTCDayText.Text = "mBTC/" + International.GetText("Day"); - toolStripStatusLabelGlobalRateValue.Text = (TotalRate * 1000).ToString("F7", CultureInfo.InvariantCulture); + toolStripStatusLabelGlobalRateValue.Text = (TotalRate * 1000).ToString("F5", CultureInfo.InvariantCulture); } else { toolStripStatusLabelBTCDayText.Text = "BTC/" + International.GetText("Day"); - toolStripStatusLabelGlobalRateValue.Text = (TotalRate).ToString("F8", CultureInfo.InvariantCulture); + toolStripStatusLabelGlobalRateValue.Text = (TotalRate).ToString("F6", CultureInfo.InvariantCulture); } - toolStripStatusLabelBTCDayValue.Text = CurrencyConverter.CurrencyConverter.ConvertToActiveCurrency((TotalRate * Globals.BitcoinRate)).ToString("F2", CultureInfo.InvariantCulture); + toolStripStatusLabelBTCDayValue.Text = ExchangeRateAPI.ConvertToActiveCurrency((TotalRate * Globals.BitcoinUSDRate)).ToString("F2", CultureInfo.InvariantCulture); } @@ -442,20 +539,20 @@ void BalanceCheck_Tick(object sender, EventArgs e) double Balance = NiceHashStats.GetBalance(textBoxBTCAddress.Text.Trim(), textBoxBTCAddress.Text.Trim() + "." + textBoxWorkerName.Text.Trim()); if (Balance > 0) { - if (ConfigManager.Instance.GeneralConfig.AutoScaleBTCValues && Balance < 0.1) + if (ConfigManager.GeneralConfig.AutoScaleBTCValues && Balance < 0.1) { toolStripStatusLabelBalanceBTCCode.Text = "mBTC"; - toolStripStatusLabelBalanceBTCValue.Text = (Balance * 1000).ToString("F7", CultureInfo.InvariantCulture); + toolStripStatusLabelBalanceBTCValue.Text = (Balance * 1000).ToString("F5", CultureInfo.InvariantCulture); } else { toolStripStatusLabelBalanceBTCCode.Text = "BTC"; - toolStripStatusLabelBalanceBTCValue.Text = Balance.ToString("F8", CultureInfo.InvariantCulture); + toolStripStatusLabelBalanceBTCValue.Text = Balance.ToString("F6", CultureInfo.InvariantCulture); } //Helpers.ConsolePrint("CurrencyConverter", "Using CurrencyConverter" + ConfigManager.Instance.GeneralConfig.DisplayCurrency); - double Amount = (Balance * Globals.BitcoinRate); - Amount = CurrencyConverter.CurrencyConverter.ConvertToActiveCurrency(Amount); + double Amount = (Balance * Globals.BitcoinUSDRate); + Amount = ExchangeRateAPI.ConvertToActiveCurrency(Amount); toolStripStatusLabelBalanceDollarText.Text = Amount.ToString("F2", CultureInfo.InvariantCulture); } } @@ -464,10 +561,11 @@ void BalanceCheck_Tick(object sender, EventArgs e) void BitcoinExchangeCheck_Tick(object sender, EventArgs e) { - Helpers.ConsolePrint("COINBASE", "Bitcoin rate get"); - double BR = Bitcoin.GetUSDExchangeRate(); - if (BR > 0) Globals.BitcoinRate = BR; - Helpers.ConsolePrint("COINBASE", "Current Bitcoin rate: " + Globals.BitcoinRate.ToString("F2", CultureInfo.InvariantCulture)); + Helpers.ConsolePrint("NICEHASH", "Bitcoin rate get"); + ExchangeRateAPI.UpdateAPI(textBoxWorkerName.Text.Trim()); + double BR = ExchangeRateAPI.GetUSDExchangeRate(); + if (BR > 0) Globals.BitcoinUSDRate = BR; + Helpers.ConsolePrint("NICEHASH", "Current Bitcoin rate: " + Globals.BitcoinUSDRate.ToString("F2", CultureInfo.InvariantCulture)); } @@ -475,12 +573,11 @@ void SMACheck_Tick(object sender, EventArgs e) { string worker = textBoxBTCAddress.Text.Trim() + "." + textBoxWorkerName.Text.Trim(); Helpers.ConsolePrint("NICEHASH", "SMA get"); - Dictionary t = NiceHashStats.GetAlgorithmRates(worker); + Dictionary t = null; - for (int i = 0; i < 3; i++) - { - if (t != null) - { + for (int i = 0; i < 5; i++) { + t = NiceHashStats.GetAlgorithmRates(worker); + if (t != null) { Globals.NiceHashData = t; break; } @@ -490,8 +587,7 @@ void SMACheck_Tick(object sender, EventArgs e) t = NiceHashStats.GetAlgorithmRates(worker); } - if (t == null && Globals.NiceHashData == null && ShowWarningNiceHashData) - { + if (t == null && Globals.NiceHashData == null && ShowWarningNiceHashData) { ShowWarningNiceHashData = false; DialogResult dialogResult = MessageBox.Show(International.GetText("Form_Main_msgbox_NoInternetMsg"), International.GetText("Form_Main_msgbox_NoInternetTitle"), @@ -519,38 +615,10 @@ void UpdateCheck_Tick(object sender, EventArgs e) if (ret < 0) { linkLabelVisitUs.Text = String.Format(International.GetText("Form_Main_new_version_released"), ver); - VisitURL = "https://github.com/nicehash/NiceHashMiner/releases/tag/" + ver; - } - } - - - void SetEnvironmentVariables() - { - Helpers.ConsolePrint("NICEHASH", "Setting environment variables"); - - string[] envName = { "GPU_MAX_ALLOC_PERCENT", "GPU_USE_SYNC_OBJECTS", - "GPU_SINGLE_ALLOC_PERCENT", "GPU_MAX_HEAP_SIZE", "GPU_FORCE_64BIT_PTR" }; - string[] envValue = { "100", "1", "100", "100", "0" }; - - for (int i = 0; i < envName.Length; i++) - { - // Check if all the variables is set - if (Environment.GetEnvironmentVariable(envName[i]) == null) - { - try { Environment.SetEnvironmentVariable(envName[i], envValue[i]); } - catch (Exception e) { Helpers.ConsolePrint("NICEHASH", e.ToString()); } - } - - // Check to make sure all the values are set correctly - if (!Environment.GetEnvironmentVariable(envName[i]).Equals(envValue[i])) - { - try { Environment.SetEnvironmentVariable(envName[i], envValue[i]); } - catch (Exception e) { Helpers.ConsolePrint("NICEHASH", e.ToString()); } - } + VisitURL = Links.VisitURLNew + ver; } } - private bool VerifyMiningAddress(bool ShowError) { if (!BitcoinAddress.ValidateBitcoinAddress(textBoxBTCAddress.Text.Trim()) && ShowError) @@ -560,7 +628,7 @@ private bool VerifyMiningAddress(bool ShowError) MessageBoxButtons.YesNo, MessageBoxIcon.Error); if (result == System.Windows.Forms.DialogResult.Yes) - System.Diagnostics.Process.Start("https://www.nicehash.com/index.jsp?p=faq#faqs15"); + System.Diagnostics.Process.Start(Links.NHM_BTC_Wallet_Faq); textBoxBTCAddress.Focus(); return false; @@ -589,35 +657,37 @@ private void linkLabelCheckStats_LinkClicked(object sender, LinkLabelLinkClicked { if (!VerifyMiningAddress(true)) return; - System.Diagnostics.Process.Start("http://www.nicehash.com/index.jsp?p=miners&addr=" + textBoxBTCAddress.Text.Trim()); + System.Diagnostics.Process.Start(Links.CheckStats + textBoxBTCAddress.Text.Trim()); } private void linkLabelChooseBTCWallet_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { - System.Diagnostics.Process.Start("https://www.nicehash.com/index.jsp?p=faq#faqs15"); + System.Diagnostics.Process.Start(Links.NHM_BTC_Wallet_Faq); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { - MinersManager.Instance.StopAllMiners(); + MinersManager.StopAllMiners(); MessageBoxManager.Unregister(); } private void buttonBenchmark_Click(object sender, EventArgs e) { - ConfigManager.Instance.GeneralConfig.ServiceLocation = comboBoxLocation.SelectedIndex; + ConfigManager.GeneralConfig.ServiceLocation = comboBoxLocation.SelectedIndex; - SMACheck.Stop(); BenchmarkForm = new Form_Benchmark(); SetChildFormCenter(BenchmarkForm); BenchmarkForm.ShowDialog(); + bool startMining = BenchmarkForm.StartMining; BenchmarkForm = null; - SMACheck.Start(); InitMainConfigGUIData(); + if (startMining) { + buttonStartMining_Click(null, null); + } } @@ -639,59 +709,151 @@ private void buttonSettings_Click(object sender, EventArgs e) } else if (Settings.IsChange && Settings.IsChangeSaved) { InitLocalization(); InitMainConfigGUIData(); - UpdateGlobalRate(); // update currency changes + } + } + + private void buttonStartMining_Click(object sender, EventArgs e) { + IsManuallyStarted = true; + if (StartMining(true) == StartMiningReturnType.ShowNoMining) { + IsManuallyStarted = false; + StopMining(); + MessageBox.Show(International.GetText("Form_Main_StartMiningReturnedFalse"), + International.GetText("Warning_with_Exclamation"), + MessageBoxButtons.OK, MessageBoxIcon.Warning); } } - private void buttonStartMining_Click(object sender, EventArgs e) + private void buttonStopMining_Click(object sender, EventArgs e) { + IsManuallyStarted = false; + StopMining(); + } + + private string FormatPayingOutput(double paying) { - if (textBoxBTCAddress.Text.Equals("")) + string ret = ""; + + if (ConfigManager.GeneralConfig.AutoScaleBTCValues && paying < 0.1) + ret = (paying * 1000).ToString("F5", CultureInfo.InvariantCulture) + " mBTC/" + International.GetText("Day"); + else + ret = paying.ToString("F6", CultureInfo.InvariantCulture) + " BTC/" + International.GetText("Day"); + + return ret; + } + + + private void buttonHelp_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start(Links.NHM_Help); + } + + private void toolStripStatusLabel10_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start(Links.NHM_Paying_Faq); + } + + private void toolStripStatusLabel10_MouseHover(object sender, EventArgs e) + { + statusStrip1.Cursor = Cursors.Hand; + } + + private void toolStripStatusLabel10_MouseLeave(object sender, EventArgs e) + { + statusStrip1.Cursor = Cursors.Default; + } + + private void textBoxCheckBoxMain_Leave(object sender, EventArgs e) + { + if (VerifyMiningAddress(false)) { - DialogResult result = MessageBox.Show(International.GetText("Form_Main_DemoModeMsg"), + // Commit to config.json + ConfigManager.GeneralConfig.BitcoinAddress = textBoxBTCAddress.Text.Trim(); + ConfigManager.GeneralConfig.WorkerName = textBoxWorkerName.Text.Trim(); + ConfigManager.GeneralConfig.ServiceLocation = comboBoxLocation.SelectedIndex; + ConfigManager.GeneralConfigFileCommit(); + } + } + + // Minimize to system tray if MinimizeToTray is set to true + private void Form1_Resize(object sender, EventArgs e) + { + notifyIcon1.Icon = Properties.Resources.logo; + notifyIcon1.Text = Application.ProductName + " v" + Application.ProductVersion + "\nDouble-click to restore.."; + + if (ConfigManager.GeneralConfig.MinimizeToTray && FormWindowState.Minimized == this.WindowState) + { + notifyIcon1.Visible = true; + this.Hide(); + } + } + + // Restore NiceHashMiner from the system tray + private void notifyIcon1_DoubleClick(object sender, EventArgs e) + { + this.Show(); + this.WindowState = FormWindowState.Normal; + notifyIcon1.Visible = false; + } + + /////////////////////////////////////// + // Miner control functions + private enum StartMiningReturnType { + StartMining, + ShowNoMining, + IgnoreMsg + } + + private StartMiningReturnType StartMining(bool showWarnings) { + if (textBoxBTCAddress.Text.Equals("")) { + if (showWarnings) { + DialogResult result = MessageBox.Show(International.GetText("Form_Main_DemoModeMsg"), International.GetText("Form_Main_DemoModeTitle"), MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - if (result == System.Windows.Forms.DialogResult.Yes) - { - DemoMode = true; - labelDemoMode.Visible = true; - labelDemoMode.Text = International.GetText("Form_Main_DemoModeLabel"); - - //textBoxBTCAddress.Text = "34HKWdzLxWBduUfJE9JxaFhoXnfC6gmePG"; + if (result == System.Windows.Forms.DialogResult.Yes) { + DemoMode = true; + labelDemoMode.Visible = true; + labelDemoMode.Text = International.GetText("Form_Main_DemoModeLabel"); + } else { + return StartMiningReturnType.IgnoreMsg; + } + } else { + return StartMiningReturnType.IgnoreMsg; ; } - else - return; - } - else if (!VerifyMiningAddress(true)) return; + } else if (!VerifyMiningAddress(true)) return StartMiningReturnType.IgnoreMsg; - if (Globals.NiceHashData == null) - { - MessageBox.Show(International.GetText("Form_Main_msgbox_NullNiceHashDataMsg"), + if (Globals.NiceHashData == null) { + if (showWarnings) { + MessageBox.Show(International.GetText("Form_Main_msgbox_NullNiceHashDataMsg"), International.GetText("Error_with_Exclamation"), MessageBoxButtons.OK, MessageBoxIcon.Error); - return; + } + return StartMiningReturnType.IgnoreMsg; } - // first value is a boolean if initialized or not - var tuplePair = DeviceBenchmarkConfigManager.Instance.IsEnabledBenchmarksInitialized(); - bool isBenchInit = tuplePair.Item1; - Dictionary> nonBenchmarkedPerDevice = tuplePair.Item2; + + // Check if there are unbenchmakred algorithms + bool isBenchInit = true; + bool hasAnyAlgoEnabled = false; + foreach (var cdev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + if (cdev.Enabled) { + foreach (var algo in cdev.GetAlgorithmSettings()) { + if (algo.Enabled == true) { + hasAnyAlgoEnabled = true; + if (algo.BenchmarkSpeed == 0) { + isBenchInit = false; + break; + } + } + } + } + } // Check if the user has run benchmark first if (!isBenchInit) { DialogResult result = MessageBox.Show(International.GetText("EnabledUnbenchmarkedAlgorithmsWarning"), International.GetText("Warning_with_Exclamation"), MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning); if (result == System.Windows.Forms.DialogResult.Yes) { - SMACheck.Stop(); - List enabledDevices = new List(); - HashSet deviceNames = new HashSet(); - foreach (var cdev in ComputeDevice.AllAvaliableDevices) { - if (cdev.Enabled && !deviceNames.Contains(cdev.Name)) { - deviceNames.Add(cdev.Name); - enabledDevices.Add(cdev); - } - } BenchmarkForm = new Form_Benchmark( BenchmarkPerformanceType.Standard, true); @@ -699,21 +861,22 @@ private void buttonStartMining_Click(object sender, EventArgs e) BenchmarkForm.ShowDialog(); BenchmarkForm = null; InitMainConfigGUIData(); - SMACheck.Start(); } else if (result == System.Windows.Forms.DialogResult.No) { // check devices without benchmarks - foreach (var cdev in ComputeDevice.AllAvaliableDevices) { - bool Enabled = false; - foreach (var algo in cdev.DeviceBenchmarkConfig.AlgorithmSettings) { - if (algo.Value.BenchmarkSpeed > 0) { - Enabled = true; - break; + foreach (var cdev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + if (cdev.Enabled) { + bool Enabled = false; + foreach (var algo in cdev.GetAlgorithmSettings()) { + if (algo.BenchmarkSpeed > 0) { + Enabled = true; + break; + } } + cdev.Enabled = Enabled; } - cdev.ComputeDeviceEnabledOption.IsEnabled = Enabled; } } else { - return; + return StartMiningReturnType.IgnoreMsg; } } @@ -726,31 +889,30 @@ private void buttonStartMining_Click(object sender, EventArgs e) devicesListViewEnableControl1.IsMining = true; buttonStopMining.Enabled = true; - ConfigManager.Instance.GeneralConfig.BitcoinAddress = textBoxBTCAddress.Text.Trim(); - ConfigManager.Instance.GeneralConfig.WorkerName = textBoxWorkerName.Text.Trim(); - ConfigManager.Instance.GeneralConfig.ServiceLocation = comboBoxLocation.SelectedIndex; + ConfigManager.GeneralConfig.BitcoinAddress = textBoxBTCAddress.Text.Trim(); + ConfigManager.GeneralConfig.WorkerName = textBoxWorkerName.Text.Trim(); + ConfigManager.GeneralConfig.ServiceLocation = comboBoxLocation.SelectedIndex; InitFlowPanelStart(); ClearRatesALL(); var btcAdress = DemoMode ? Globals.DemoUser : textBoxBTCAddress.Text.Trim(); - var isMining = MinersManager.Instance.StartInitialize(this, Globals.MiningLocation[comboBoxLocation.SelectedIndex], textBoxWorkerName.Text.Trim(), btcAdress); + var isMining = MinersManager.StartInitialize(this, Globals.MiningLocation[comboBoxLocation.SelectedIndex], textBoxWorkerName.Text.Trim(), btcAdress); - if (!DemoMode) ConfigManager.Instance.GeneralConfig.Commit(); + if (!DemoMode) ConfigManager.GeneralConfigFileCommit(); SMAMinerCheck.Interval = 100; SMAMinerCheck.Start(); - //SMAMinerCheck_Tick(null, null); MinerStatsCheck.Start(); - } + return isMining ? StartMiningReturnType.StartMining : StartMiningReturnType.ShowNoMining; + } - private void buttonStopMining_Click(object sender, EventArgs e) - { + private void StopMining() { MinerStatsCheck.Stop(); SMAMinerCheck.Stop(); - MinersManager.Instance.StopAllMiners(); + MinersManager.StopAllMiners(); textBoxBTCAddress.Enabled = true; textBoxWorkerName.Enabled = true; @@ -761,82 +923,12 @@ private void buttonStopMining_Click(object sender, EventArgs e) devicesListViewEnableControl1.IsMining = false; buttonStopMining.Enabled = false; - if (DemoMode) - { + if (DemoMode) { DemoMode = false; labelDemoMode.Visible = false; - - //textBoxBTCAddress.Text = ""; - //ConfigManager.Instance.GeneralConfig.BitcoinAddress = ""; } UpdateGlobalRate(); } - - private string FormatPayingOutput(double paying) - { - string ret = ""; - - if (ConfigManager.Instance.GeneralConfig.AutoScaleBTCValues && paying < 0.1) - ret = (paying * 1000).ToString("F7", CultureInfo.InvariantCulture) + " mBTC/" + International.GetText("Day"); - else - ret = paying.ToString("F8", CultureInfo.InvariantCulture) + " BTC/" + International.GetText("Day"); - - return ret; - } - - - private void buttonHelp_Click(object sender, EventArgs e) - { - System.Diagnostics.Process.Start("https://github.com/nicehash/NiceHashMiner"); - } - - private void toolStripStatusLabel10_Click(object sender, EventArgs e) - { - System.Diagnostics.Process.Start("https://www.nicehash.com/index.jsp?p=faq#faqs6"); - } - - private void toolStripStatusLabel10_MouseHover(object sender, EventArgs e) - { - statusStrip1.Cursor = Cursors.Hand; - } - - private void toolStripStatusLabel10_MouseLeave(object sender, EventArgs e) - { - statusStrip1.Cursor = Cursors.Default; - } - - private void textBoxCheckBoxMain_Leave(object sender, EventArgs e) - { - if (VerifyMiningAddress(false)) - { - // Commit to config.json - ConfigManager.Instance.GeneralConfig.BitcoinAddress = textBoxBTCAddress.Text.Trim(); - ConfigManager.Instance.GeneralConfig.WorkerName = textBoxWorkerName.Text.Trim(); - ConfigManager.Instance.GeneralConfig.ServiceLocation = comboBoxLocation.SelectedIndex; - ConfigManager.Instance.GeneralConfig.Commit(); - } - } - - // Minimize to system tray if MinimizeToTray is set to true - private void Form1_Resize(object sender, EventArgs e) - { - notifyIcon1.Icon = Properties.Resources.logo; - notifyIcon1.Text = Application.ProductName + " v" + Application.ProductVersion + "\nDouble-click to restore.."; - - if (ConfigManager.Instance.GeneralConfig.MinimizeToTray && FormWindowState.Minimized == this.WindowState) - { - notifyIcon1.Visible = true; - this.Hide(); - } - } - - // Restore NiceHashMiner from the system tray - private void notifyIcon1_DoubleClick(object sender, EventArgs e) - { - this.Show(); - this.WindowState = FormWindowState.Normal; - notifyIcon1.Visible = false; - } } } diff --git a/NiceHashMiner/Forms/Form_Main.resx b/NiceHashMiner/Forms/Form_Main.resx index 6ac5fe2..d4f816a 100644 --- a/NiceHashMiner/Forms/Form_Main.resx +++ b/NiceHashMiner/Forms/Form_Main.resx @@ -117,1215 +117,11 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + 17, 17 - - + + 133, 17 - - - - - AAABAAQAEBAAAAEAIABoBAAARgAAAAAAAAABACAAGd4AAK4EAAAgIAAAAQAgAKgQAADH4gAAMDAAAAEA - IACoJQAAb/MAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAQQFGhdFVoMogKHNMZvE8DGawu4ofZ3JFD9PfAECAxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAACFkRWhz6/6/xCyv7/QMr+/0HK/v9Dyv7/RMv+/0XL/v8/uOb6FDpIeAAAAAAAAAAAAAAAAAAA - AAAAAAACImqFtEHK/f9Gz/7/Qcr+/0HF9/85p9D/O6nS/0fI+P9KzP7/S8z+/0vM/f8iW3CjAAAAAAAA - AAAAAAAAGk1gi0XO/f9Gz/7/RMXw/yFec/8mZn7/NpCx/ziQsf8uaYD/MGqB/0/H9P9Tzv7/Us79/xk/ - TXgAAAAAAwoMJDu87PxByv7/Pr3s/0Z4gf9Pzfb/Tc/+/1DO/v9Tz/7/V8/+/1bI9P88c4r/Wcn0/1zR - /v9QueL3AgQFFhpSZ4tAyv7/NqjR/yt8mf9Jzfz/TtT+/1PU/v9X0P7/XNH+/2DS/v9j0/7/ZdH6/1GR - rf9dud3/ZdP+/yFGVHgrh6rNQsr+/0XL/f85n8T/Ts7+/1TS/v9e1f7/X9L+/2XT/v9r1f7/b9b+/3LW - /v9ntNP/c9f9/3HW/v9CgJi6NKHK7EPL/v9HzP7/TM39/2XT/P9x0vX/bM/1/2jU/v9w1v7/fNPz/4PY - 9/+C2fz/gtr9/4Ha/v9/2v7/WJ242TWhyutFy/7/T8z7/3DP9P9sxe3/WbXm/0iq4/9Zuuv/VLPm/0yr - 4/9fuef/csjv/4LV9f+R3v3/jt7+/2Oft9gth6nJSMz+/1bE9P9FpeD/Io3Z/y+X3P87qeX/edb6/3/U - 9v8zpOX/KpLa/yiQ2f9HqOP/l9v5/57i/v9ahZe3G1BkhEnM/v9Qyfr/Nqfm/zqx6/9CvPH/V8z3/4Xb - /v+S3/7/Tcn3/0G47v84sOv/UK/m/7Xn/v+x5///N0pTcwMJCx5Gvev6Vs/7/0zK+f8qpej/W8Ty/4nb - +P+M3f7/nOH+/5De+P9IuO7/M6ro/07N/P/J7P3/rNDg9AMEBBIAAAAAHElaflnQ/f+D2ff/l932/6fm - +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 - AAAHETRBlzq04f5Bzf7/R8/+/0HL/v9Ayv7/Qcr+/0HK/v9Cyv7/Qsr+/0PL/v9Ey/7/RMv+/0XL/v9F - y/7/Rsv+/0bL/v9Gy/7/OaXO+AwjLHsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAADxtVasRAx/r/Qcr+/0HM/v9J0f7/Qcr+/0HK/v9Cyv7/Q8r+/0PL/v9Ey/7/Rcv+/0bL/v9G - y/7/R8z+/0jM/v9IzP7/Scz+/0nM/v9JzP7/RcHw/xY9TKUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAocWW/HQMr9/0HK/v9By/7/Ss7+/0PQ/v9Byv7/Qsr+/0PL/f89uOX/MpW5/y6Eo/8w - hqX/N5q+/0S+7P9KzP7/S8z+/0vN/v9Mzf7/TM3+/03N/v9Mzf7/Ssf2/xc+TaYAAAABAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAFEBOp0DM/P9BzP7/Q8v+/0rO/v9Ez/7/Qs7+/0HG+P8qfZv/EjA6/wkND/8T - KjP/Gj1K/xs9Sv8WKzP/EhUZ/x9ATf85jq7/Tsz7/0/O/v9Qzv7/UM7+/1DO/v9Qzv7/TMTx/w8nMH4A - AAAAAAAAAAAAAAAAAAAAAAAAAAgUGl1Bvu3/R8/+/0nQ/v9I0P7/Qs/+/0TP/v9Ircz/Eysu/xc8Sf8y - ja7/RcTz/0rM/v9Lzf7/Tc3+/07N/v9KwOz/Ooqo/yM9Sf8lQU3/SrTc/1TP/v9Uz/7/VM/+/1TP/v9U - z/7/Rq3U+QMHCTcAAAAAAAAAAAAAAAAAAAAMK4Wm6ELL/v9By/7/Qcz+/0HM/v9Cy/7/QZqy/3NSNv9M - p7z/SM/9/0rO/v9Lzf7/Tc3+/0/N/v9Qzv7/Us7+/1PP/v9Vz/7/Vc36/0GPrf8mN0H/SqfL/1nQ/v9Z - 0P7/WdD+/1jQ/v9Y0P7/K2Z8ygAAAAEAAAAAAAAAAAsjK3c/yPz/QMr+/0DK/v9Byv7/Qsr+/zObwf8Y - OD3/WMfp/1LT/v9L0P7/TdH+/0/R/v9Qzv7/Us7+/1TP/v9Wz/7/V9D+/1nQ/v9a0P7/XNH+/1O33P8w - RlL/VLbc/17R/v9e0f7/XdH+/13R/v9WxO7/Bg4RTgAAAAAAAAABJnmY30DK/v9Ayv7/Qcr+/0LK/v9A - wPD/FDVA/0G86f9K0P7/TND+/07W/v9Q1P7/UtP+/1TQ/v9Wz/7/WND+/1rQ/v9c0f7/XtH+/1/S/v9h - 0v7/YtL+/1m53f87WWj/YtH6/2PT/v9j0/7/YtL+/2HS/v8rXHC4AAAAAAEDBDo7vOz/QMr+/0HK/v8w - mLz/K4Sj/yFfdf83n8T/Scz+/0zR/v9O0v7/Udb+/1PV/v9W1f7/V9H+/1rQ/v9c0f7/X9H+/2HS/v9j - 0/7/ZdP+/2bT/v9n1P7/aNT+/1abt/9Qi6T/VJm1/1yy1P9o1P7/ZtP+/0+mx/kAAAAUDi46fkDK/v9B - yv7/Qsr+/0PL/v9BwvP/J2yE/0K45P9LzP7/TtD+/1HS/v9U1f7/V9b+/1zV/v9b0f7/XtH+/2HS/v9k - 0/7/ZtP+/2jU/v9q1P7/bNX+/23V/v9u1f7/Zbnb/1iPqP9u0/v/b9b+/27V/v9s1f7/adH5/wgPElQb - VmyvQMr+/0HK/v9Dy/7/RMv+/0bL/v9Hyfr/MH+a/03N/v9Qzv7/U9H+/1bS/v9a0/7/adX+/1/S/v9j - 0/7/ZtP+/2nU/v9s1f7/btX+/3DW/v9y1/7/dNf+/3XX/v9hm7T/dtj+/3bY/v911/7/dNf+/3PX/v9x - 1v7/HTlDhiRxj9BByv3/Qsr+/0TL/v9Gy/7/SMz+/0rM/v9KxvP/T87+/23T9/9yz/H/Y9H6/3PQ8v9g - 0v3/ZNP+/2fU/v9r1f7/btX+/3TS9v+C1/X/dNH1/4zb9v981/r/fNn+/3vT9v992f7/fdn+/3zZ/v97 - 2f7/edj+/3fY/v8vVmWnKX+g4UHK/v9Dy/7/Rcv+/0fM/v9JzP7/TM3+/0/O/v9Szv7/etn6/3LQ8v9x - 1fr/ccrt/2TT/f9o1P7/bNX+/3DW/v901/7/cs3x/4TX9/930fX/it/6/4ja+v+E2/7/hdv+/4Xb/v+F - 2/7/hNv+/4Lb/v+A2v7/ftn+/zpmd7gpgKHhQsr+/0TL/v9Gy/7/SMz+/0vM/v9ZzPj/b9L2/3LR9f92 - 0PT/bMjv/2jF7v9cuOf/Zcjx/2rN9P9w0vn/c9H2/3PN8v9sw+r/Y73s/3PI7v9yzPL/gNPz/4bX9f+L - 2fb/i9v6/43d/v+M3f7/it3+/4jc/v+F2/7/Pmd4uCZ1k9JDy/7/Rcv+/0fL/v9KzP7/Xsv1/3vT9f9u - y/P/Z8Hs/2C55/9Ur+L/RaTf/zmd3/80md3/NZre/2K+6v9Hpd3/M5jd/zaa3f89oOD/S6jf/1iz5P9k - vOj/aMXw/3LO9f+D1PP/ktz6/5Tf/v+S3/7/kN7+/4zd/v85XGqqHl10s0TL/v9Gy/7/SMz+/0vM/v9q - xe7/Wbjq/06r4P8xltv/IYzZ/yKN2f88ndv/Lpfe/z2j3/9kw+//dtL3/3HK8f9lvuj/MZrg/zab3/8w - lNj/IYzZ/yOO2v89ndn/VLLo/1687P+P1/X/neH+/5vh/v+Y4P7/lN/+/ytBS4oSNkSDRMv+/0fL/v9J - zP7/TM39/1q16P87nt//Pp7c/yGM2f8hjdn/IY7a/z2k4f8uqOr/Tbnr/3rZ/v+A2v7/htv+/4XX9/80 - rOj/Mafp/zWb3P8hjtr/IY3Z/yyT2f88nt3/P6Hg/4nR9P+m5P//o+P//6Di//+c4f7/EBgbWgMKDEFD - w/T/R8z+/0rM/v9Ozf7/Urnr/zCX3v84oOL/OqHe/y+Y2f8lktj/QbXr/znB+v9cx/H/f9r+/4Xb/v+L - 3f7/kd79/0S/8P83v/j/OaPf/yqV2P8zm9v/Qafi/y6Y3/86nN3/pd/6/7Dm//+t5f//qeT//4m91P0A - AAAaAAAABi+IquZIzP7/S83+/0/O/v9Szfz/RrLl/y+v7/8zuPT/QMP4/07M+/9Nz/7/UtL+/23O8v+D - 2/7/itz+/5De/v+X4P7/Yczz/07Q/v9Qz/3/SMn6/zq/9/8xtPL/Na7t/5TQ7f+96v//uur//7fp//+y - 6P//WHWBwQAAAAAAAAAAEjRBgUnM/f9Mzf7/UM7+/1bJ9f89wvn/P8T4/zyu5/8ypeT/Mafk/3LY+f96 - 3v//e9Hy/4fc/v+O3v7/ld/+/5zh/v+C1fP/c93//1nD7/8wpuT/NKfk/0G47P87xPv/V8f0/8Pq/P/F - 7P//wOv//7fm+v8VGx5aAAAAAAAAAAABAgMUN5m97k3N/v9Rzv7/YNP8/1DR/v9bzPT/JqTp/yen6/8r - qen/nuf9/6Tq/v+A0fL/it3+/5Lf/v+Z4P7/oeP//5vb8/+e6P//c87z/yep7P8mpur/Pa/o/1jU//9Q - 0f7/yO39/9Du///K7f//dIuW2AAAAAQAAAAAAAAAAAAAAAAOJi9sTMj3/1HO/v9t2P3/d97+/4ji/v9y - zPH/R7bq/0q36f+67///v/H+/4LT9P+N3f7/ld/+/53h/v+m5P//q+H1/7zw//+V2/X/PLPq/1S76/+I - 2/j/f+D//4Df/f/e8/7/2/L//8Lc6f4RExVGAAAAAAAAAAAAAAAAAAAAAAAAAAQjXHG3Us7+/1fP/f9t - zO//mNzy/7Xs/f+/8f//w/P//8L0///B9f//suz5/5ve9P+X4P7/nd/7/67m9f+/8/3/wfX//8P0///C - 8///u/D//6zm+P+k3PD/0+r2/+73///m9P3/QkhMkgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAxMy - fZrVV8/+/1vR/v9h0f3/qOf5/5fb8f+g4/f/quj1/5nh9v+f5Pb/ltzz/5ng/v+e3/v/p+Ty/7Dn9v+s - 4fH/wPf+/8Tm9P+16PX/3PH5//f6///6/P//+Pv+/2xvcrwAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAIEBRs0fJjTXNH+/2HS/v+t7Pr/g9by/5jl+v+S3vH/gdr+/4nc/v+R3v7/muH+/6Pj//+t - 5f//uOj//7Dg9P+x8/v/1e/7/7Dn8v/e9Pr//f3///39/f91dXW9AAAACwAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAECAxEoWm2xXsz2/3jV9v9y0/j/hdv3/4TX8/+B2v7/idz+/5He/v+a - 4f7/o+P//63m//+46f//vej7/7Dl8v/V7/v/zuv1/+j0+v/r6+z+UFBQlwAAAAYAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQIypiSpe16GzV/f9z1/7/etj+/4Ha/v+J - 3P7/kd7+/5ng/v+i4/7/rOX//7fp///B7P//zO7//9jx///j8vz/mp+i3BkZGUkAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEOGC43ckeGnthx - yu3/gNr+/4fc/v+P3v7/mOD+/6Di//+q5f7/tOj+/77r//+01eX+eIiRyyIlJ2MAAAAFAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAwQGBy8cMDdvN1lmnkt0hb1YgpTMXIOTy1Z1g7pEWWKZIywwaAICAyMAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///AAH//gAAf/gAAB/wAAAP4AAAB+AAAAfA - AAADgAAAAYAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGA - AAABgAAAAcAAAAPAAAAH4AAAB/AAAA/4AAAf/AAAf/8AAP//wAf/KAAAADAAAABgAAAAAQAgAAAAAAAA - JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIFBgUPMDwKBQ8TOAQMDmQDCg2AAwoNjQMKDYsD - Cw18BAwPWwYSFysOKzYIAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEJHyZmHVlwpSRxjtwpgaL/MZnB/ziw3P88 - vu//PsT2/z7E9v89u+z/N6vY/y+Tuv8pfp7/I2yI0RpRZZcBAwNYAAAAEgAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkCBogvTKLrPg9wPD+PsX4/0DK/v9A - y///QMr//0HK/v9Byv7/Qcr+/0HK/v9Byv7/Qcr+/0LK//9Cy///Qsv9/0HF9v8+v+/8JXKO8wEGB5gA - AAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMFBQAAAAAAAAAAJBVDUpspg6D/Q9P//03S//9A - y/7/QMr+/0DK/v9Ayv7/Qcr+/0HK/v9Byv7/Qcr+/0HK/v9Cy/7/Qsv+/0PL/v9Dy/7/Q8v+/0TL/v9E - y/7/R9L//0PJ+/8lbIf/EjZDeAAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAEDA95LY6x7z3B7v9C - 0///RM/+/0nN/v9Ayv7/Qcr+/0HK/v9Byv7/Qcr+/0LK/v9Cy/7/Q8v+/0PL/v9Dy/7/RMv+/0TL/v9E - y/7/Rcv+/0XL/v9Gy/7/Rsv+/0bM/v9Hzv//QLnm/yp4lt8AAABQAAAAAAAAAQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwwnML84 - r9z/Qs///0HN/v9Azv7/TtL+/0PN/v9Byv7/Qcr+/0HK/v9Byv7/Qsv+/0LL/v9Dy/7/RMv+/0TL/v9E - y/7/RMv+/0XL/v9Gy/7/Rsv+/0fM/v9HzP7/R8z+/0fM/v9HzP7/R8z+/0nP//8zkbT/CyAofAAAAAEA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAbHl111T/D9f9Czf//Qcv+/0HM/v9Gzv7/TNT+/0HM/v9Byv7/Qcr+/0LL/v9Dy/7/Q8v+/0TL/v9E - y/7/RMv+/0XL/v9Gy/7/R8z+/0fM/v9HzP7/R8z+/0jM/v9JzP7/Scz+/0nM/v9KzP7/Ss3+/0rN/v9M - 0///P6/Z/xtKXLEAAAAHGEFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAABkaUmb4Q8///0HK/v9Byv7/Qcv+/0LM/v9O0f7/Q9L+/0HL/v9Cyv7/Qsv+/0PL/v9E - y/7/RMv+/0XL/v9Fy/7/Rsz+/0fM/v9HzP7/SMz+/0jM/v9JzP7/Ssz+/0rN/v9Kzf7/S83+/0vN/v9L - zf7/TM3+/0zN/v9Mzf7/TM3+/0jC8f8TMz/IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAFx9geN9E1f//Qcv+/0HL/v9By/7/Qcz+/03O/v9H0f7/QtH+/0LL/v9C - y/7/Rc3//0bU//8+vOn/NJzB/y6Gpf8oc4z/Jmh//yZpgf8reJL/M4qr/zyjyf9GxfP/TtX//03O//9M - zf7/Ts3+/03N/v9Ozf7/Ts7+/07O/v9Ozv7/Ts7+/07Q//9KxPL/GD9OugAAAAcAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAQOEgAAAAAAFD9NyD/H9/9Bzf7/Qcz+/0HM/v9DzP7/Uc/+/0bR/v9C - 0P7/Q8/+/0PL/v9H0///NqrS/xY+S/8MFxz/CgsO/wgDAv8IAAD/CQAA/wsCAf8MAwP/DgkK/xIUGP8W - ICb/JFZm/0a85v9Q0///UM7+/1DO/v9Qzv7/UM7+/1HO/v9Rzv7/Uc7+/1HO/v9Rz///Sbvn/xY5RocA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGFBqRO7/p/0HR//9Bzv7/Q87+/0nO/v9P - 0P7/RND+/0PQ/v9D0P7/Q83//zir1P8VP0z/AgAA/wwVGf8VMTv/JGN4/zSSs/8+sNf/Qr/o/0O95/8/ - rNP/No6r/yhfcf8eNT//Fxsg/xEJCv8sYnX/S73n/1PR//9Tz/7/U8/+/1TP/v9Uz/7/VM/+/1TP/v9U - z/7/VNH//zqQsf8CBgdAAAAAAAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAEA9ocn7TND//0zQ/v9N - 0/7/S9P+/0jS/v9D0f7/Q9L+/0PQ/v9U1f//RH6C/xMaEP8KFBf/K32Z/z6y3P9Jzv//TNL//0zQ//9N - z///Ts///07P//9Q0P//UdH//1PU//9QzPr/R6/W/zR1jP8YFRf/HiUr/z6Oq/9Z2v//VtD+/1bQ/v9W - 0P7/VtD+/1bQ/v9W0P7/VdD+/1jW//8vcovxAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyBheb1C - yvr/Q87+/0LN/v9AzP7/Qs7+/0LP/v9Cz/7/Q8v+/0XH9/9qcGT/hEEZ/0Nzbf9Jz/7/Sc///0rM/v9K - zf7/TM3+/03N/v9Nzv7/UM7+/1DO/v9Sz/7/Us/+/1TP/v9Uz/7/Vc/+/1fT//9Uy/f/LE1c/x8YHP84 - c4r/WdH//1nR/v9Z0P7/WdD+/1nQ/v9Z0P7/WdD+/1jQ/v9Z0v//GDxImQAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAARDOfyP9Ay///QMr+/0HK/v9Byv7/Qcr+/0LK/v9Dy/7/RM///x1OW/9APiP/c6m2/2Tf//9M - 0v//S9L+/0zS/v9N0f7/Ts/+/0/O/v9Qzv7/Us7+/1PP/v9Uz/7/VdD+/1bQ/v9X0P7/WND+/1nR/v9a - 0f//W9P//0KIpP8kIif/P3qR/1/Y//9c0f7/XdL+/1zS/v9c0v7/XNH+/1zR/v9b0f7/P5Cv8gsaHxkA - AAAAAAAAAAAAAAAAAAAAF0ZX50LR//9Ayv7/QMr+/0HK/v9Byv7/Qsr+/0PL/v9F0P//HFFj/woQE/9D - stb/Wtf+/1LT/v9L0P7/TdD+/07R/v9P0v7/UdL+/1HO/v9Sz/7/VM/+/1XP/v9W0P7/WND+/1nQ/v9a - 0f7/W9H+/1zR/v9d0f7/XdL+/1/S/v9Qqcr/KSct/0iSrf9i1///YNL+/2DS/v9g0v7/YNL+/1/S/v9f - 0v7/Wcjy/xAlLIwAAAAAAgECAAAAAAAAAABJN6/c/0HM//9Ayv7/Qcr+/0HK/v9Cyv7/Q8v+/0TL/v8y - l7v/ChIV/zimzP9K1P//SdH+/0vQ/v9N0/7/T9b+/1DU/v9R0/7/U9P+/1TQ/v9Vz/7/VtD+/1jQ/v9Z - 0P7/W9H+/1zR/v9d0f7/XtH+/1/S/v9g0v7/YdL+/2LT/v9k1///TZSv/y4sMv9aut7/ZNT+/2TT/v9j - 0/7/Y9P+/2LT/v9i0/7/ZNn//zJuhf8AAAADAAAAAAAAAAAYSFyjQc3//0DK/v9Byv7/Qcr+/0TR//9G - 1f//RtD//0fS//8PKC//M5Gz/0nP//9Kz/7/TNL+/03R/v9O2P7/Udj+/1LV/v9U1v7/VdT+/1fR/v9X - 0P7/WdH+/1vR/v9c0f7/XtL+/1/S/v9g0/7/YtP+/2LT/v9k0/7/ZdT+/2XU/v9m1P7/aNj//0yIov9C - ZHX/Z9P9/2nZ//9q3f//aNf//2bU/v9l1P7/ZdX//2DM9v8AAABrAAAAAAAAABAriKvUQMr//0HK/v9B - yv7/Q87//yNyi/8VQk//KHyW/yp8mP8YOkf/R8r7/0nM/v9L0P7/TdL+/0/S/v9R1f7/Utb+/1TV/v9V - 1v7/WNb+/1jR/v9a0P7/XNH+/17R/v9f0v7/YNL+/2LT/v9j0/7/ZdP+/2bU/v9o1P7/aNT+/2nV/v9q - 1f7/atX+/2vS+/9BVGL/X7TU/1CHnv9DYG7/WanH/2vY//9q1f7/aNT+/2vb//8oU2PGAAAAAA8uOiAx - nMT7Qcr+/0HK/v9Byv7/Qsv+/0XP//9DzP//OqzV/yFcb/8mZ33/StD//0vN/v9Mzv7/T9P+/1HS/v9S - 1f7/VNb+/1bW/v9Y1/7/WNT+/1vR/v9d0f7/X9L+/2DT/v9i0/7/ZNT+/2bU/v9o1P7/adX+/2vV/v9r - 1f7/bNb+/27W/v9u1v7/b9b+/2/W/v9RfJH/V4+o/2nD5v9v2f//cNj//27W/v9t1v7/bdb+/2zX//9N - mrjiAAAAFxQ+TUg3q9f/Qcr+/0HK/v9Cy/7/Q8v+/0TL/v9Fy/7/R8v+/0jP//8qc4v/QrPd/0zN/v9O - zv7/UM/+/1PU/v9U1P7/VtX+/1jW/v9l2P7/ctr+/17S/v9f0v7/YtP+/2PT/v9m1P7/Z9T+/2rV/v9r - 1f7/bNX+/27W/v9v1v7/cdb+/3LX/v9y1/7/dNj//2q+3/9ck6z/dNj+/3TY/v9z1/7/c9f+/3PX/v9x - 1/7/cNb+/2/W/v9fudzzBQkLMhE2Q30+wfP/Qcr+/0HK/v9Dy/7/RMv+/0TL/v9GzP7/R8z+/0nM/v9A - rtf/MYGa/0/R//9Qzv7/Ts7//1HQ//9V0v7/WNP+/1nT//9e0/7/Y9T+/2DS/v9i0/7/ZNP+/2fU/v9p - 1P7/a9X+/23W/v9u1v//cNf//3LX/v9z2P//c9j//3bY/v932f7/euD//1V0hP920/b/edj+/3nY/v94 - 2P7/d9j+/3fZ/v922P7/dNf+/3TY/v9ju97/JkdUSBM8SqVCzv//Qcr+/0LL/v9EzP7/RMz+/0bM/v9H - zP7/SM3+/0rN/v9Lzfz/Ssfz/0/P//9Oz///g9Hs/4DP6v9cz/v/Xs/6/2rH6/9mz/f/YNP+/2TT/v9l - 1P7/Z9T+/2rV/v9s1v7/b9b+/3LV/P92ze7/fM/u/3XZ//+CzOf/jdTs/3zY/P982f7/fdv//3nR8/9+ - 2///ftr+/37a/v992v7/fNr+/3vZ/v972f7/edn+/3jY/v9rxOf/MFdmYxlPY75Cz///Qsr+/0PL/v9E - y/7/Rcv+/0fM/v9HzP7/Ss3+/0vO/v9Nzv7/T87+/1HO/v9Ozf7/meP4/4HY9f9c0Pv/cNb7/5jo//9o - w+b/Y9T//2bU/v9p1P7/a9X+/27V/v9w1v7/c9f+/3HP9P+G3fr/mef//3vZ/v92yeb/lef+/4Ha/f+A - 2v7/gdv+/4Lb/v+C2/7/gtv+/4Lb/v+C2/7/gdv+/4Da/v9/2v7/fdr+/3zZ/v9zzO//M1tqehxYb8xD - z///Q8v+/0PL/v9Fy/7/Rsv+/0fM/v9JzP7/Ss3+/03N/v9Ozv7/UM7//1HP//9Nyvv/n+j9/3nT8v9b - z/v/eNb4/33V+f9cveX/Z9X//2nV/v9s1f7/btb+/3DX/v901/7/dtj+/3LP9P91z/P/gtf5/4be//9z - xeT/lef//4HW+P+G3f//h93//4fd/v+H3f7/iN3+/4fd/v+H3P7/htz+/4Xc/v+E3P7/gtv+/4Hb/v95 - 0fP/Nl1thB1ZcM1Dz///Q8v+/0TL/v9Fy/7/R8z+/0jM/v9KzP7/TM3+/03N/f9Uzvz/XMny/23O8f9u - y+7/h9v6/3HM8f9dyvT/dM/0/2W/7f9bv+j/atT9/2zU/P9u1f3/ddj+/3jY/f931/z/etf8/3bQ9f9k - ver/a8Xw/4HU9f92x+n/ftj7/4bS7/+J1PH/h9Pw/4jY+P+M3f3/jd7+/4ze/v+M3v7/i93+/4rd/v+I - 3f7/h9z+/4bc/v9+0vT/OF9uhRtUacFE0P//RMv+/0TL/v9Gy/7/R8z+/0nM/v9Lzf7/UMr4/3fT9P+E - 2fb/hdr6/3nU+P9xzfX/ZsTy/2LA7/9guen/VbHm/0mq5f9SruP/T6zh/1Gv4/9XtOT/c9P6/2K54v9U - sOT/Uq3h/1Ot4v9KquT/Tq7m/1y25/9hvu//Y8Hw/2zJ9P900Pf/ftj6/4Xa+P+L2fX/jNXy/5Ph//+R - 4P7/kd/+/5Df/v+O3/7/jN7+/4rd/v+B0PD/Ol5tfBZDVKlE0P//RMv+/0XL/v9HzP7/Scz+/0rN/v9N - zP3/ddDy/3fT9/9wzPT/aMXy/2TA7v9ft+P/XbPg/1Sr3P9Kp93/QKLh/zec3/8zmN3/L5fd/y6W3f84 - m9z/c9L4/0yn2P8tlt7/L5bc/zGX3P82m97/O57g/0al3/9Pqdr/W7Lf/2C14f9hu+n/ZsTx/2zK8/9y - 0Pb/h9n3/5DX8/+X4f//l+D+/5Xg/v+U4P7/kd/+/4/f/v+CzOn/PF5saBI3RINCx/n/RMv+/0bL/v9I - zP7/Sc3+/0vN/v9Ry/r/dcnv/2G/7/9auez/VrHi/0Og2v8tlN3/JpDb/yeQ2/8okNj/S6Ta/y6W3f8u - l97/QKPf/1i35/9evOj/e9f7/27G7P9euuf/VrLh/y+X3v8ult3/N5rc/ziZ2P8pktv/JI7b/yeR3P84 - mtz/Uard/1e36/9evO7/ZcPx/4zU8v+d4v//nOL//5vh//+Z4P7/l+D+/5Tf/v+BxeD/OVViTBVBUU87 - st//Rcv+/0bM/v9IzP7/Ssz+/0vN/v9hzvj/XLbp/0ys5f9IqOT/MZDO/yCM2v8hjNn/IY3Z/yGN2v8e - jNn/U63g/y2c4/8uoeb/Vbno/3nZ/v982/7/f9v+/4Tc/v+I3v//iN76/zGe3f8un+X/N5/h/zWa3P8h - jdr/IY3Z/yGM2f8gjNr/JYnN/0up4v9IqeX/T7Dn/3nJ8f+k5P7/ouT//6Hj//+e4///nOL//5rh//+E - xN72GSQoNhdEViI2oMn/Rsv+/0fM/v9JzP7/S83+/0vN/v9q0/v/Sabj/zmc3/83m97/S6fi/x6L2f8h - jtr/IY7a/yKQ2/8fjtr/VLfp/y2r7v8wsvD/XcLt/3vZ/v9/2v7/g9v+/4fc/v+L3f7/kOD//zet4/8u - r/D/N63r/zef3/8ikNv/Io/b/yGO2v8fjNr/P6Df/zye3/83m97/O5/h/3PC7v+s5v//qOX//6bk//+k - 5P//ouP//6Dk//99tMzlAAAAHAAAABMzlbvZR8z+/0jM/v9KzP7/S83+/03O/v9Uzv3/UKzl/y6W3f8t - lt7/R6nm/0ak2/8kjtX/H4/c/x+R3v8fjtf/WMr4/zO9+P87w/r/Zsnv/37a/v+C2/7/htz+/4rd/v+O - 3v7/k9/+/0m96/82wPr/O773/zml4v8gkd7/H5Dd/x+M1/83mNb/T63l/y6X3v8uld3/M5ne/5HT9P+y - 6P//r+f//63m//+r5v//p+X//6jp//9QcX7MAAAAAAAAAAAhYXqtSM7//0jM/v9Kzf7/TM3+/07O/v9Q - zv7/Tr7r/z2h3v8voOX/LaXp/zKs7v9LvO7/S7bj/0uz4v9Kr97/S87//0PL//9Mz/7/b8zw/4Hb/v+F - 2/7/id3+/47e/v+S3/7/l+D+/1zG7f9Gzf//Qsr+/0y86v9KseD/TLTj/1G86v87tfH/Lafq/y6h5v81 - oOH/abPb/73s//+46f//tuj//7Po//+x5///ref//6zq//8NERN8AAAAAAAAAAAAAABWRMLx/0nN//9L - zf7/Tc3+/0/O/v9Sz/7/VND//1O75f84tPH/MLb0/zW++f89wfb/SMj4/0rK+P9L0P7/TtL//1fU//9k - 2P7/dc3v/4Tc/v+I3P7/jd7+/5Df/v+V4P7/muH//3DL7f9b1v//UtP//0zR//9LzPn/Scn4/0LD9v84 - v/j/Mrn2/zGz8v9cvOj/vuj8/8Hs//+/7P//vev//7rr//+36v//uO7//3OYqP8AAAAQAAAAAAAAAAAA - AAAAJGR99EzU//9Mzf7/Ts3+/1DO/v9Sz/7/W8ny/zu+9v83wfr/QMn//1G75/89rOf/L6Xn/zGp6f9Z - vun/atz//3Dd//+B4P7/ds3w/4fc/v+L3f7/kN/+/5Tg/v+Z4f//nuL//4HQ7f933v//bNz//2XM8v82 - rOr/LqXn/zWo6P9Ks+b/R8f4/zrE+/81v/n/bcjs/8rt///G7f//w+3//8Ls//++6///uev//zM/RqMA - AAAAAAAAAAAAAAAAAAAAAwgKW0K44/9Mzf//Ts7+/1DO/v9Uz/3/V834/0LL//9Iz///Srvl/yWg5/8k - ouf/JqTp/yOl6v9pxOz/heT//47l//+U3vb/e9L1/4jc/v+N3v7/kt/+/5fg/v+c4v//ouP//5LW8P+S - 5f7/iOT//3/W9P8lpuv/Jqbp/yWj6P8joOf/Pqze/0rR//9DzP//Rcv//7zl9v/O7///y+7//8ft///D - 7P//krTC/DU/RiEAAAAAAAAAAAAAAAAAAAAABAoLAyx4lM5MzP3/Ts7+/1HP/v9X0P7/Ztj+/1XU//9c - 1///ctT1/x+i6v8oqez/Kavt/ySr7/+C0u//oer//6vt//+Z1ur/gdn9/4rd/v+Q3v7/leD+/5rh//+f - 4///pOT//5/b9P+p6Pv/pOv//57h9v8nre7/Kazu/yiq7P8kpuv/W8Lv/2HZ//9X1f//T9L//8Lu/v/W - 8f//0vD//87u///M8P//XnJ6qQAAAAISERUAAAAAAAAAAAAAAAAAAAAAAA4mL1BGuub8UM///1HP/v9X - 0P7/ed7+/2/c//933v//j+f//2rF7f8xsO3/LrDu/ySv7/+f3fP/t/D//7/y//+Z0ub/ht3//43e/v+R - 3/7/luD+/5zh//+i5P//p+X//6bd9f+57fv/ufD//77t+f8or+7/LbHv/zGx7v9Etuz/juH7/3vf//9x - 3f//b93//9z1///e8///2fH//9n0//+etcL5AAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ - Q1OsT87+/1LP/v9Vz/7/ZdL7/4HT7/+c7P//nun//6zt//+l4vb/l9rz/4/W8v+97vv/wfP//8P1//+5 - 6/j/jNb1/4PR8v+V4P//mOH//5/j//+c3Pj/otrz/7bn9//C9P7/wvT//8f0//+Q1vL/lNrz/57e9f+u - 6vv/o+v//5vq//+G3Pf/tub3/+34///n9f//4/b//7nM1/8mKS1lAAAAAAMGBQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAJWB34FPR//9Vz/7/WND+/1jL+P9wvt7/p+Dx/77y///A8v//wvP//8L0///C - 9v//wvb//8L3///B9///wPj//8L0+v+N1/b/muH//5/i/v+v5/b/wPj//8D3///C9///wvb//8L2///C - 9f//wvP//8Hy//+/8f//tOr5/5bP4//D3ev/9Pr///H6///u+P//4e72/2hvdaEAAAAAFhUZAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAABxMWJDmPr+tY1v//WND+/1zR/v9d1P//Xcz4/5LX8P/L - +v//hM3o/53g9f+/9v7/sOr2/6bn9/+p6ff/q+z4/5/e6v+R3fz/nOL//6Hj//+d3O//rOz2/7Ds9/+1 - 6/f/tOn2/7z0/f++6/b/tt7u/8Dy/P/E8fv/1+nz//r8///9/v//+/3///r8///3/f//iIyR0gAAABIX - FxoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAAAAAAAADA4h6X/XNj//1zR/v9g - 0v7/X9L//6Di9//F9Pv/Zsju/4re/P+59///jdTn/3/Z/f+H2/z/jN38/5He+/+W4P7/nOL//6Pj//+n - 5P3/rub9/7Xn/f+86f3/uOb5/6jr9f/D7vf/0ur5/7bp8//I9v7/7vj9//v8///+/f////7///7///91 - d3jiCAUKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAAAAAAAA - AAAsPI6t61zR/v9g0///XtL//6rm9v+v6PD/bNL6/43g+/+y+f//g8/n/4Hb//+G3P7/jN3+/5Hf/v+X - 4P7/neL//6Pj//+p5v//sOf//7fp//++6///vOj6/6Hq9f+78Pj/4PL//6Hb6P+68/z/7fj8//79//// - ////9vb2/5qZmtEAAAASAAAAAEE/RQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAEAAQAAAAAACA8TIixjd9Zez/v/YtT//33Y+P+C1fD/b9b+/4PZ9/+c4/H/gs7p/4Hb//+G - 3P7/jN3+/5Lf/v+X4P7/neL//6Pk//+p5v//sOf//7jp//+/7P//v+n7/6Df7P+x5PD/4fP//7/j8P/Q - 7/f/8/n9///////f3+D/b29vpAAAABAAAAAAQUBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQIAAAAAAAAAAAAcO0idWLzi+2XT/P9r1v//b9b+/3PX/v92 - 2f//fNr//4Hb/v+G3P7/i93+/5Hf/v+W4P7/neL//6Pj//+p5v//sOf//7fp//++7P//xe3//8/v///W - 8f//3vP//+j2///x+f//8/f7/9LT1vQ3Nzd0AAAAABAQEAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYGACl0kQAAAAAADBofRj19lr5b - ttn/ct3//3TZ//932P7/fNn+/4Hb/v+G3P7/i93+/5Df/v+W4P7/m+L//6Lj//+o5f//ruf//7Xp//+9 - 6///xO3//8vu///S8P//3fX//+v9//+3wMb/hIiLpgAAAC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAkLDwMEBwk/MF5v3WW/4v942///e9r//4Db/v+F3P7/it7+/5Df/v+V4P7/m+L//6Hj//+n - 5f//reb//7Tp//+66///wez//8nv///R8f//rcPO/0xSV7wlISglAAIAAAAAAAAAAAAAS0lMAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAATEwAAAAAAAAAAAAAAADoyWmqZV5u1y2exzu5vuNb/f8zs/47e/v+X - 5P//nOX//6Lm//+o6f//qOL7/6DS5/+ZwtT/mb3N6IOdqcRIUliIAAAAJQAAAAAAAAAAHRogAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgHiMAAAAAAAAAAAAAAAAAAAAACx8zPBw+ - ZHQwM05aXi5GUIM4Ul2cPlpmpkFbaKU8UVuXOkxVfUdaZVRWanQqISgsGQAAAAcAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//gAH/ - /wAA//4AAH//AAD/+AAAH/8AAP/gAAAH/wAA/8AAAAP/AAD/AAAAAP8AAP4AAAAAfwAA/AAAAAB/AAD4 - AAAAAB8AAPgAAAAAHwAA8AAAAAAPAADgAAAAAAcAAMAAAAAABwAAwAAAAAADAADAAAAAAAMAAIAAAAAA - AQAAgAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AQAAgAAAAAABAACAAAAAAAEAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAOAAAAAABwAA8AAAAAAPAAD4 - AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/8AAAAP/AAD/4AAAB/8AAP/wAAAf - /wAA//4AAH//AAD//4AB//8AAA== - \ No newline at end of file diff --git a/NiceHashMiner/Forms/Form_Settings.Designer.cs b/NiceHashMiner/Forms/Form_Settings.Designer.cs index a86c7a1..7808a78 100644 --- a/NiceHashMiner/Forms/Form_Settings.Designer.cs +++ b/NiceHashMiner/Forms/Form_Settings.Designer.cs @@ -24,29 +24,32 @@ protected override void Dispose(bool disposing) { /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form_Settings)); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); this.tabControlGeneral = new System.Windows.Forms.TabControl(); this.tabPageGeneral = new System.Windows.Forms.TabPage(); this.groupBox_Misc = new System.Windows.Forms.GroupBox(); + this.checkBox_AllowMultipleInstances = new System.Windows.Forms.CheckBox(); + this.checkBox_DisableDefaultOptimizations = new System.Windows.Forms.CheckBox(); + this.checkBox_AMD_DisableAMDTempControl = new System.Windows.Forms.CheckBox(); + this.checkBox_AutoStartMining = new System.Windows.Forms.CheckBox(); this.checkBox_HideMiningWindows = new System.Windows.Forms.CheckBox(); + this.pictureBox_AllowMultipleInstances = new System.Windows.Forms.PictureBox(); this.checkBox_MinimizeToTray = new System.Windows.Forms.CheckBox(); - this.checkBox_DisableDetectionNVidia6X = new System.Windows.Forms.CheckBox(); - this.checkBox_DisableDetectionNVidia5X = new System.Windows.Forms.CheckBox(); + this.pictureBox_DisableDefaultOptimizations = new System.Windows.Forms.PictureBox(); + this.pictureBox_AMD_DisableAMDTempControl = new System.Windows.Forms.PictureBox(); this.pictureBox_NVIDIAP0State = new System.Windows.Forms.PictureBox(); this.pictureBox_DisableWindowsErrorReporting = new System.Windows.Forms.PictureBox(); this.pictureBox_ShowDriverVersionWarning = new System.Windows.Forms.PictureBox(); this.pictureBox_StartMiningWhenIdle = new System.Windows.Forms.PictureBox(); this.pictureBox_AutoScaleBTCValues = new System.Windows.Forms.PictureBox(); this.pictureBox_DisableDetectionAMD = new System.Windows.Forms.PictureBox(); - this.pictureBox_DisableDetectionNVidia2X = new System.Windows.Forms.PictureBox(); - this.pictureBox_DisableDetectionNVidia3X = new System.Windows.Forms.PictureBox(); - this.pictureBox_DisableDetectionNVidia5X = new System.Windows.Forms.PictureBox(); - this.pictureBox_DisableDetectionNVidia6X = new System.Windows.Forms.PictureBox(); + this.pictureBox_Use3rdPartyMiners = new System.Windows.Forms.PictureBox(); + this.pictureBox_DisableDetectionNVIDIA = new System.Windows.Forms.PictureBox(); + this.pictureBox_AutoStartMining = new System.Windows.Forms.PictureBox(); this.pictureBox_MinimizeToTray = new System.Windows.Forms.PictureBox(); this.pictureBox_HideMiningWindows = new System.Windows.Forms.PictureBox(); - this.checkBox_DisableDetectionNVidia3X = new System.Windows.Forms.CheckBox(); - this.checkBox_DisableDetectionNVidia2X = new System.Windows.Forms.CheckBox(); + this.checkBox_Use3rdPartyMiners = new System.Windows.Forms.CheckBox(); + this.checkBox_DisableDetectionNVIDIA = new System.Windows.Forms.CheckBox(); this.checkBox_DisableDetectionAMD = new System.Windows.Forms.CheckBox(); this.checkBox_NVIDIAP0State = new System.Windows.Forms.CheckBox(); this.checkBox_AutoScaleBTCValues = new System.Windows.Forms.CheckBox(); @@ -62,11 +65,13 @@ private void InitializeComponent() { this.pictureBox_LogToFile = new System.Windows.Forms.PictureBox(); this.checkBox_DebugConsole = new System.Windows.Forms.CheckBox(); this.groupBox_Main = new System.Windows.Forms.GroupBox(); + this.checkBox_IdleWhenNoInternetAccess = new System.Windows.Forms.CheckBox(); this.pictureBox_WorkerName = new System.Windows.Forms.PictureBox(); this.pictureBox_MinProfit = new System.Windows.Forms.PictureBox(); this.pictureBox_ServiceLocation = new System.Windows.Forms.PictureBox(); this.pictureBox_Info_BitcoinAddress = new System.Windows.Forms.PictureBox(); this.textBox_MinProfit = new System.Windows.Forms.TextBox(); + this.pictureBox_IdleWhenNoInternetAccess = new System.Windows.Forms.PictureBox(); this.label_BitcoinAddress = new System.Windows.Forms.Label(); this.label_MinProfit = new System.Windows.Forms.Label(); this.label_WorkerName = new System.Windows.Forms.Label(); @@ -88,6 +93,7 @@ private void InitializeComponent() { this.pictureBox_MinerRestartDelayMS = new System.Windows.Forms.PictureBox(); this.pictureBox_APIBindPortStart = new System.Windows.Forms.PictureBox(); this.pictureBox_SwitchMinSecondsDynamic = new System.Windows.Forms.PictureBox(); + this.pictureBox_SwitchProfitabilityThreshold = new System.Windows.Forms.PictureBox(); this.pictureBox_ethminerDefaultBlockHeight = new System.Windows.Forms.PictureBox(); this.pictureBox_DagGeneration = new System.Windows.Forms.PictureBox(); this.pictureBox_CPU0_ForceCPUExtension = new System.Windows.Forms.PictureBox(); @@ -105,7 +111,9 @@ private void InitializeComponent() { this.label_MinerRestartDelayMS = new System.Windows.Forms.Label(); this.textBox_SwitchMinSecondsAMD = new System.Windows.Forms.TextBox(); this.label_APIBindPortStart = new System.Windows.Forms.Label(); + this.textBox_SwitchProfitabilityThreshold = new System.Windows.Forms.TextBox(); this.textBox_ethminerDefaultBlockHeight = new System.Windows.Forms.TextBox(); + this.label_SwitchProfitabilityThreshold = new System.Windows.Forms.Label(); this.label_ethminerDefaultBlockHeight = new System.Windows.Forms.Label(); this.textBox_APIBindPortStart = new System.Windows.Forms.TextBox(); this.label_SwitchMinSecondsAMD = new System.Windows.Forms.Label(); @@ -115,32 +123,34 @@ private void InitializeComponent() { this.textBox_MinerRestartDelayMS = new System.Windows.Forms.TextBox(); this.textBox_MinerAPIQueryInterval = new System.Windows.Forms.TextBox(); this.groupBoxBenchmarkTimeLimits = new System.Windows.Forms.GroupBox(); + this.benchmarkLimitControlNVIDIA = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); + this.benchmarkLimitControlCPU = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); + this.benchmarkLimitControlAMD = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); this.tabPageDevicesAlgos = new System.Windows.Forms.TabPage(); + this.devicesListViewEnableControl1 = new NiceHashMiner.Forms.Components.DevicesListViewEnableControl(); + this.algorithmSettingsControl1 = new NiceHashMiner.Forms.Components.AlgorithmSettingsControl(); this.groupBoxAlgorithmSettings = new System.Windows.Forms.GroupBox(); + this.algorithmsListView1 = new NiceHashMiner.Forms.Components.AlgorithmsListView(); this.buttonAllProfit = new System.Windows.Forms.Button(); this.buttonSelectedProfit = new System.Windows.Forms.Button(); this.buttonSaveClose = new System.Windows.Forms.Button(); this.buttonDefaults = new System.Windows.Forms.Button(); this.buttonCloseNoSave = new System.Windows.Forms.Button(); - this.benchmarkLimitControlNVIDIA = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); - this.benchmarkLimitControlCPU = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); - this.benchmarkLimitControlAMD = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); - this.devicesListViewEnableControl1 = new NiceHashMiner.Forms.Components.DevicesListViewEnableControl(); - this.algorithmSettingsControl1 = new NiceHashMiner.Forms.Components.AlgorithmSettingsControl(); - this.algorithmsListView1 = new NiceHashMiner.Forms.Components.AlgorithmsListView(); this.tabControlGeneral.SuspendLayout(); this.tabPageGeneral.SuspendLayout(); this.groupBox_Misc.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AllowMultipleInstances)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDefaultOptimizations)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AMD_DisableAMDTempControl)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_NVIDIAP0State)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableWindowsErrorReporting)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ShowDriverVersionWarning)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_StartMiningWhenIdle)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AutoScaleBTCValues)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionAMD)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia2X)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia3X)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia5X)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia6X)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_Use3rdPartyMiners)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVIDIA)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AutoStartMining)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinimizeToTray)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_HideMiningWindows)).BeginInit(); this.groupBox_Logging.SuspendLayout(); @@ -152,6 +162,7 @@ private void InitializeComponent() { ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinProfit)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ServiceLocation)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_Info_BitcoinAddress)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_IdleWhenNoInternetAccess)).BeginInit(); this.groupBox_Localization.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_displayCurrency)).BeginInit(); @@ -162,6 +173,7 @@ private void InitializeComponent() { ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinerRestartDelayMS)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_APIBindPortStart)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchMinSecondsDynamic)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchProfitabilityThreshold)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ethminerDefaultBlockHeight)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DagGeneration)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_CPU0_ForceCPUExtension)).BeginInit(); @@ -188,6 +200,7 @@ private void InitializeComponent() { this.tabControlGeneral.SelectedIndex = 0; this.tabControlGeneral.Size = new System.Drawing.Size(612, 380); this.tabControlGeneral.TabIndex = 0; + this.tabControlGeneral.Selected += new System.Windows.Forms.TabControlEventHandler(this.tabControlGeneral_Selected); // // tabPageGeneral // @@ -205,24 +218,28 @@ private void InitializeComponent() { // // groupBox_Misc // + this.groupBox_Misc.Controls.Add(this.checkBox_AllowMultipleInstances); + this.groupBox_Misc.Controls.Add(this.checkBox_DisableDefaultOptimizations); + this.groupBox_Misc.Controls.Add(this.checkBox_AMD_DisableAMDTempControl); + this.groupBox_Misc.Controls.Add(this.checkBox_AutoStartMining); this.groupBox_Misc.Controls.Add(this.checkBox_HideMiningWindows); + this.groupBox_Misc.Controls.Add(this.pictureBox_AllowMultipleInstances); this.groupBox_Misc.Controls.Add(this.checkBox_MinimizeToTray); - this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVidia6X); - this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVidia5X); + this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDefaultOptimizations); + this.groupBox_Misc.Controls.Add(this.pictureBox_AMD_DisableAMDTempControl); this.groupBox_Misc.Controls.Add(this.pictureBox_NVIDIAP0State); this.groupBox_Misc.Controls.Add(this.pictureBox_DisableWindowsErrorReporting); this.groupBox_Misc.Controls.Add(this.pictureBox_ShowDriverVersionWarning); this.groupBox_Misc.Controls.Add(this.pictureBox_StartMiningWhenIdle); this.groupBox_Misc.Controls.Add(this.pictureBox_AutoScaleBTCValues); this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionAMD); - this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVidia2X); - this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVidia3X); - this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVidia5X); - this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVidia6X); + this.groupBox_Misc.Controls.Add(this.pictureBox_Use3rdPartyMiners); + this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVIDIA); + this.groupBox_Misc.Controls.Add(this.pictureBox_AutoStartMining); this.groupBox_Misc.Controls.Add(this.pictureBox_MinimizeToTray); this.groupBox_Misc.Controls.Add(this.pictureBox_HideMiningWindows); - this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVidia3X); - this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVidia2X); + this.groupBox_Misc.Controls.Add(this.checkBox_Use3rdPartyMiners); + this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVIDIA); this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionAMD); this.groupBox_Misc.Controls.Add(this.checkBox_NVIDIAP0State); this.groupBox_Misc.Controls.Add(this.checkBox_AutoScaleBTCValues); @@ -231,55 +248,108 @@ private void InitializeComponent() { this.groupBox_Misc.Controls.Add(this.checkBox_ShowDriverVersionWarning); this.groupBox_Misc.Location = new System.Drawing.Point(357, 6); this.groupBox_Misc.Name = "groupBox_Misc"; - this.groupBox_Misc.Size = new System.Drawing.Size(229, 304); + this.groupBox_Misc.Size = new System.Drawing.Size(244, 345); this.groupBox_Misc.TabIndex = 391; this.groupBox_Misc.TabStop = false; this.groupBox_Misc.Text = "Misc:"; // + // checkBox_AllowMultipleInstances + // + this.checkBox_AllowMultipleInstances.AutoSize = true; + this.checkBox_AllowMultipleInstances.Location = new System.Drawing.Point(6, 289); + this.checkBox_AllowMultipleInstances.Name = "checkBox_AllowMultipleInstances"; + this.checkBox_AllowMultipleInstances.Size = new System.Drawing.Size(139, 17); + this.checkBox_AllowMultipleInstances.TabIndex = 365; + this.checkBox_AllowMultipleInstances.Text = "Allow Multiple Instances"; + this.checkBox_AllowMultipleInstances.UseVisualStyleBackColor = true; + this.checkBox_AllowMultipleInstances.CheckedChanged += new System.EventHandler(this.checkBox_DisableDefaultOptimizations_CheckedChanged); + // + // checkBox_DisableDefaultOptimizations + // + this.checkBox_DisableDefaultOptimizations.AutoSize = true; + this.checkBox_DisableDefaultOptimizations.Location = new System.Drawing.Point(6, 268); + this.checkBox_DisableDefaultOptimizations.Name = "checkBox_DisableDefaultOptimizations"; + this.checkBox_DisableDefaultOptimizations.Size = new System.Drawing.Size(163, 17); + this.checkBox_DisableDefaultOptimizations.TabIndex = 365; + this.checkBox_DisableDefaultOptimizations.Text = "Disable Default Optimizations"; + this.checkBox_DisableDefaultOptimizations.UseVisualStyleBackColor = true; + this.checkBox_DisableDefaultOptimizations.CheckedChanged += new System.EventHandler(this.checkBox_DisableDefaultOptimizations_CheckedChanged); + // + // checkBox_AMD_DisableAMDTempControl + // + this.checkBox_AMD_DisableAMDTempControl.AutoSize = true; + this.checkBox_AMD_DisableAMDTempControl.Location = new System.Drawing.Point(6, 247); + this.checkBox_AMD_DisableAMDTempControl.Name = "checkBox_AMD_DisableAMDTempControl"; + this.checkBox_AMD_DisableAMDTempControl.Size = new System.Drawing.Size(145, 17); + this.checkBox_AMD_DisableAMDTempControl.TabIndex = 365; + this.checkBox_AMD_DisableAMDTempControl.Text = "DisableAMDTempControl"; + this.checkBox_AMD_DisableAMDTempControl.UseVisualStyleBackColor = true; + this.checkBox_AMD_DisableAMDTempControl.CheckedChanged += new System.EventHandler(this.checkBox_AMD_DisableAMDTempControl_CheckedChanged); + // + // checkBox_AutoStartMining + // + this.checkBox_AutoStartMining.AutoSize = true; + this.checkBox_AutoStartMining.Location = new System.Drawing.Point(6, 19); + this.checkBox_AutoStartMining.Name = "checkBox_AutoStartMining"; + this.checkBox_AutoStartMining.Size = new System.Drawing.Size(102, 17); + this.checkBox_AutoStartMining.TabIndex = 315; + this.checkBox_AutoStartMining.Text = "Autostart Mining"; + this.checkBox_AutoStartMining.UseVisualStyleBackColor = true; + // // checkBox_HideMiningWindows // this.checkBox_HideMiningWindows.AutoSize = true; - this.checkBox_HideMiningWindows.Location = new System.Drawing.Point(6, 19); + this.checkBox_HideMiningWindows.Location = new System.Drawing.Point(6, 40); this.checkBox_HideMiningWindows.Name = "checkBox_HideMiningWindows"; this.checkBox_HideMiningWindows.Size = new System.Drawing.Size(123, 17); this.checkBox_HideMiningWindows.TabIndex = 315; this.checkBox_HideMiningWindows.Text = "HideMiningWindows"; this.checkBox_HideMiningWindows.UseVisualStyleBackColor = true; // + // pictureBox_AllowMultipleInstances + // + this.pictureBox_AllowMultipleInstances.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_AllowMultipleInstances.Location = new System.Drawing.Point(221, 288); + this.pictureBox_AllowMultipleInstances.Name = "pictureBox_AllowMultipleInstances"; + this.pictureBox_AllowMultipleInstances.Size = new System.Drawing.Size(18, 18); + this.pictureBox_AllowMultipleInstances.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_AllowMultipleInstances.TabIndex = 364; + this.pictureBox_AllowMultipleInstances.TabStop = false; + // // checkBox_MinimizeToTray // this.checkBox_MinimizeToTray.AutoSize = true; - this.checkBox_MinimizeToTray.Location = new System.Drawing.Point(6, 41); + this.checkBox_MinimizeToTray.Location = new System.Drawing.Point(6, 61); this.checkBox_MinimizeToTray.Name = "checkBox_MinimizeToTray"; this.checkBox_MinimizeToTray.Size = new System.Drawing.Size(100, 17); this.checkBox_MinimizeToTray.TabIndex = 316; this.checkBox_MinimizeToTray.Text = "MinimizeToTray"; this.checkBox_MinimizeToTray.UseVisualStyleBackColor = true; // - // checkBox_DisableDetectionNVidia6X + // pictureBox_DisableDefaultOptimizations // - this.checkBox_DisableDetectionNVidia6X.AutoSize = true; - this.checkBox_DisableDetectionNVidia6X.Location = new System.Drawing.Point(6, 63); - this.checkBox_DisableDetectionNVidia6X.Name = "checkBox_DisableDetectionNVidia6X"; - this.checkBox_DisableDetectionNVidia6X.Size = new System.Drawing.Size(151, 17); - this.checkBox_DisableDetectionNVidia6X.TabIndex = 317; - this.checkBox_DisableDetectionNVidia6X.Text = "DisableDetectionNVidia6X"; - this.checkBox_DisableDetectionNVidia6X.UseVisualStyleBackColor = true; + this.pictureBox_DisableDefaultOptimizations.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DisableDefaultOptimizations.Location = new System.Drawing.Point(221, 267); + this.pictureBox_DisableDefaultOptimizations.Name = "pictureBox_DisableDefaultOptimizations"; + this.pictureBox_DisableDefaultOptimizations.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DisableDefaultOptimizations.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DisableDefaultOptimizations.TabIndex = 364; + this.pictureBox_DisableDefaultOptimizations.TabStop = false; // - // checkBox_DisableDetectionNVidia5X + // pictureBox_AMD_DisableAMDTempControl // - this.checkBox_DisableDetectionNVidia5X.AutoSize = true; - this.checkBox_DisableDetectionNVidia5X.Location = new System.Drawing.Point(6, 85); - this.checkBox_DisableDetectionNVidia5X.Name = "checkBox_DisableDetectionNVidia5X"; - this.checkBox_DisableDetectionNVidia5X.Size = new System.Drawing.Size(151, 17); - this.checkBox_DisableDetectionNVidia5X.TabIndex = 317; - this.checkBox_DisableDetectionNVidia5X.Text = "DisableDetectionNVidia5X"; - this.checkBox_DisableDetectionNVidia5X.UseVisualStyleBackColor = true; + this.pictureBox_AMD_DisableAMDTempControl.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_AMD_DisableAMDTempControl.Location = new System.Drawing.Point(221, 246); + this.pictureBox_AMD_DisableAMDTempControl.Name = "pictureBox_AMD_DisableAMDTempControl"; + this.pictureBox_AMD_DisableAMDTempControl.Size = new System.Drawing.Size(18, 18); + this.pictureBox_AMD_DisableAMDTempControl.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_AMD_DisableAMDTempControl.TabIndex = 364; + this.pictureBox_AMD_DisableAMDTempControl.TabStop = false; // // pictureBox_NVIDIAP0State // this.pictureBox_NVIDIAP0State.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_NVIDIAP0State.Location = new System.Drawing.Point(205, 261); + this.pictureBox_NVIDIAP0State.Location = new System.Drawing.Point(221, 225); this.pictureBox_NVIDIAP0State.Name = "pictureBox_NVIDIAP0State"; this.pictureBox_NVIDIAP0State.Size = new System.Drawing.Size(18, 18); this.pictureBox_NVIDIAP0State.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -289,7 +359,7 @@ private void InitializeComponent() { // pictureBox_DisableWindowsErrorReporting // this.pictureBox_DisableWindowsErrorReporting.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_DisableWindowsErrorReporting.Location = new System.Drawing.Point(205, 239); + this.pictureBox_DisableWindowsErrorReporting.Location = new System.Drawing.Point(221, 204); this.pictureBox_DisableWindowsErrorReporting.Name = "pictureBox_DisableWindowsErrorReporting"; this.pictureBox_DisableWindowsErrorReporting.Size = new System.Drawing.Size(18, 18); this.pictureBox_DisableWindowsErrorReporting.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -299,7 +369,7 @@ private void InitializeComponent() { // pictureBox_ShowDriverVersionWarning // this.pictureBox_ShowDriverVersionWarning.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_ShowDriverVersionWarning.Location = new System.Drawing.Point(205, 217); + this.pictureBox_ShowDriverVersionWarning.Location = new System.Drawing.Point(221, 183); this.pictureBox_ShowDriverVersionWarning.Name = "pictureBox_ShowDriverVersionWarning"; this.pictureBox_ShowDriverVersionWarning.Size = new System.Drawing.Size(18, 18); this.pictureBox_ShowDriverVersionWarning.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -309,7 +379,7 @@ private void InitializeComponent() { // pictureBox_StartMiningWhenIdle // this.pictureBox_StartMiningWhenIdle.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_StartMiningWhenIdle.Location = new System.Drawing.Point(205, 195); + this.pictureBox_StartMiningWhenIdle.Location = new System.Drawing.Point(221, 162); this.pictureBox_StartMiningWhenIdle.Name = "pictureBox_StartMiningWhenIdle"; this.pictureBox_StartMiningWhenIdle.Size = new System.Drawing.Size(18, 18); this.pictureBox_StartMiningWhenIdle.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -319,7 +389,7 @@ private void InitializeComponent() { // pictureBox_AutoScaleBTCValues // this.pictureBox_AutoScaleBTCValues.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_AutoScaleBTCValues.Location = new System.Drawing.Point(205, 173); + this.pictureBox_AutoScaleBTCValues.Location = new System.Drawing.Point(221, 141); this.pictureBox_AutoScaleBTCValues.Name = "pictureBox_AutoScaleBTCValues"; this.pictureBox_AutoScaleBTCValues.Size = new System.Drawing.Size(18, 18); this.pictureBox_AutoScaleBTCValues.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -329,57 +399,47 @@ private void InitializeComponent() { // pictureBox_DisableDetectionAMD // this.pictureBox_DisableDetectionAMD.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_DisableDetectionAMD.Location = new System.Drawing.Point(205, 151); + this.pictureBox_DisableDetectionAMD.Location = new System.Drawing.Point(221, 120); this.pictureBox_DisableDetectionAMD.Name = "pictureBox_DisableDetectionAMD"; this.pictureBox_DisableDetectionAMD.Size = new System.Drawing.Size(18, 18); this.pictureBox_DisableDetectionAMD.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; this.pictureBox_DisableDetectionAMD.TabIndex = 364; this.pictureBox_DisableDetectionAMD.TabStop = false; // - // pictureBox_DisableDetectionNVidia2X - // - this.pictureBox_DisableDetectionNVidia2X.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_DisableDetectionNVidia2X.Location = new System.Drawing.Point(205, 129); - this.pictureBox_DisableDetectionNVidia2X.Name = "pictureBox_DisableDetectionNVidia2X"; - this.pictureBox_DisableDetectionNVidia2X.Size = new System.Drawing.Size(18, 18); - this.pictureBox_DisableDetectionNVidia2X.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; - this.pictureBox_DisableDetectionNVidia2X.TabIndex = 364; - this.pictureBox_DisableDetectionNVidia2X.TabStop = false; - // - // pictureBox_DisableDetectionNVidia3X - // - this.pictureBox_DisableDetectionNVidia3X.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_DisableDetectionNVidia3X.Location = new System.Drawing.Point(205, 107); - this.pictureBox_DisableDetectionNVidia3X.Name = "pictureBox_DisableDetectionNVidia3X"; - this.pictureBox_DisableDetectionNVidia3X.Size = new System.Drawing.Size(18, 18); - this.pictureBox_DisableDetectionNVidia3X.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; - this.pictureBox_DisableDetectionNVidia3X.TabIndex = 364; - this.pictureBox_DisableDetectionNVidia3X.TabStop = false; - // - // pictureBox_DisableDetectionNVidia5X - // - this.pictureBox_DisableDetectionNVidia5X.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_DisableDetectionNVidia5X.Location = new System.Drawing.Point(205, 85); - this.pictureBox_DisableDetectionNVidia5X.Name = "pictureBox_DisableDetectionNVidia5X"; - this.pictureBox_DisableDetectionNVidia5X.Size = new System.Drawing.Size(18, 18); - this.pictureBox_DisableDetectionNVidia5X.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; - this.pictureBox_DisableDetectionNVidia5X.TabIndex = 364; - this.pictureBox_DisableDetectionNVidia5X.TabStop = false; - // - // pictureBox_DisableDetectionNVidia6X - // - this.pictureBox_DisableDetectionNVidia6X.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_DisableDetectionNVidia6X.Location = new System.Drawing.Point(205, 63); - this.pictureBox_DisableDetectionNVidia6X.Name = "pictureBox_DisableDetectionNVidia6X"; - this.pictureBox_DisableDetectionNVidia6X.Size = new System.Drawing.Size(18, 18); - this.pictureBox_DisableDetectionNVidia6X.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; - this.pictureBox_DisableDetectionNVidia6X.TabIndex = 364; - this.pictureBox_DisableDetectionNVidia6X.TabStop = false; + // pictureBox_Use3rdPartyMiners + // + this.pictureBox_Use3rdPartyMiners.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_Use3rdPartyMiners.Location = new System.Drawing.Point(221, 79); + this.pictureBox_Use3rdPartyMiners.Name = "pictureBox_Use3rdPartyMiners"; + this.pictureBox_Use3rdPartyMiners.Size = new System.Drawing.Size(18, 18); + this.pictureBox_Use3rdPartyMiners.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_Use3rdPartyMiners.TabIndex = 364; + this.pictureBox_Use3rdPartyMiners.TabStop = false; + // + // pictureBox_DisableDetectionNVIDIA + // + this.pictureBox_DisableDetectionNVIDIA.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DisableDetectionNVIDIA.Location = new System.Drawing.Point(221, 99); + this.pictureBox_DisableDetectionNVIDIA.Name = "pictureBox_DisableDetectionNVIDIA"; + this.pictureBox_DisableDetectionNVIDIA.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DisableDetectionNVIDIA.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DisableDetectionNVIDIA.TabIndex = 364; + this.pictureBox_DisableDetectionNVIDIA.TabStop = false; + // + // pictureBox_AutoStartMining + // + this.pictureBox_AutoStartMining.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_AutoStartMining.Location = new System.Drawing.Point(221, 18); + this.pictureBox_AutoStartMining.Name = "pictureBox_AutoStartMining"; + this.pictureBox_AutoStartMining.Size = new System.Drawing.Size(18, 18); + this.pictureBox_AutoStartMining.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_AutoStartMining.TabIndex = 364; + this.pictureBox_AutoStartMining.TabStop = false; // // pictureBox_MinimizeToTray // this.pictureBox_MinimizeToTray.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_MinimizeToTray.Location = new System.Drawing.Point(205, 41); + this.pictureBox_MinimizeToTray.Location = new System.Drawing.Point(221, 60); this.pictureBox_MinimizeToTray.Name = "pictureBox_MinimizeToTray"; this.pictureBox_MinimizeToTray.Size = new System.Drawing.Size(18, 18); this.pictureBox_MinimizeToTray.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -389,37 +449,38 @@ private void InitializeComponent() { // pictureBox_HideMiningWindows // this.pictureBox_HideMiningWindows.Image = global::NiceHashMiner.Properties.Resources.info_black_18; - this.pictureBox_HideMiningWindows.Location = new System.Drawing.Point(205, 19); + this.pictureBox_HideMiningWindows.Location = new System.Drawing.Point(221, 39); this.pictureBox_HideMiningWindows.Name = "pictureBox_HideMiningWindows"; this.pictureBox_HideMiningWindows.Size = new System.Drawing.Size(18, 18); this.pictureBox_HideMiningWindows.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; this.pictureBox_HideMiningWindows.TabIndex = 364; this.pictureBox_HideMiningWindows.TabStop = false; // - // checkBox_DisableDetectionNVidia3X + // checkBox_Use3rdPartyMiners // - this.checkBox_DisableDetectionNVidia3X.AutoSize = true; - this.checkBox_DisableDetectionNVidia3X.Location = new System.Drawing.Point(6, 107); - this.checkBox_DisableDetectionNVidia3X.Name = "checkBox_DisableDetectionNVidia3X"; - this.checkBox_DisableDetectionNVidia3X.Size = new System.Drawing.Size(151, 17); - this.checkBox_DisableDetectionNVidia3X.TabIndex = 318; - this.checkBox_DisableDetectionNVidia3X.Text = "DisableDetectionNVidia3X"; - this.checkBox_DisableDetectionNVidia3X.UseVisualStyleBackColor = true; + this.checkBox_Use3rdPartyMiners.AutoSize = true; + this.checkBox_Use3rdPartyMiners.Location = new System.Drawing.Point(6, 80); + this.checkBox_Use3rdPartyMiners.Name = "checkBox_Use3rdPartyMiners"; + this.checkBox_Use3rdPartyMiners.Size = new System.Drawing.Size(129, 17); + this.checkBox_Use3rdPartyMiners.TabIndex = 319; + this.checkBox_Use3rdPartyMiners.Text = "Enable3rdPartyMiners"; + this.checkBox_Use3rdPartyMiners.UseVisualStyleBackColor = true; + this.checkBox_Use3rdPartyMiners.CheckedChanged += new System.EventHandler(this.checkBox_Use3rdPartyMiners_CheckedChanged); // - // checkBox_DisableDetectionNVidia2X + // checkBox_DisableDetectionNVIDIA // - this.checkBox_DisableDetectionNVidia2X.AutoSize = true; - this.checkBox_DisableDetectionNVidia2X.Location = new System.Drawing.Point(6, 129); - this.checkBox_DisableDetectionNVidia2X.Name = "checkBox_DisableDetectionNVidia2X"; - this.checkBox_DisableDetectionNVidia2X.Size = new System.Drawing.Size(151, 17); - this.checkBox_DisableDetectionNVidia2X.TabIndex = 319; - this.checkBox_DisableDetectionNVidia2X.Text = "DisableDetectionNVidia2X"; - this.checkBox_DisableDetectionNVidia2X.UseVisualStyleBackColor = true; + this.checkBox_DisableDetectionNVIDIA.AutoSize = true; + this.checkBox_DisableDetectionNVIDIA.Location = new System.Drawing.Point(6, 100); + this.checkBox_DisableDetectionNVIDIA.Name = "checkBox_DisableDetectionNVIDIA"; + this.checkBox_DisableDetectionNVIDIA.Size = new System.Drawing.Size(143, 17); + this.checkBox_DisableDetectionNVIDIA.TabIndex = 319; + this.checkBox_DisableDetectionNVIDIA.Text = "DisableDetectionNVIDIA"; + this.checkBox_DisableDetectionNVIDIA.UseVisualStyleBackColor = true; // // checkBox_DisableDetectionAMD // this.checkBox_DisableDetectionAMD.AutoSize = true; - this.checkBox_DisableDetectionAMD.Location = new System.Drawing.Point(6, 151); + this.checkBox_DisableDetectionAMD.Location = new System.Drawing.Point(6, 121); this.checkBox_DisableDetectionAMD.Name = "checkBox_DisableDetectionAMD"; this.checkBox_DisableDetectionAMD.Size = new System.Drawing.Size(131, 17); this.checkBox_DisableDetectionAMD.TabIndex = 320; @@ -429,7 +490,7 @@ private void InitializeComponent() { // checkBox_NVIDIAP0State // this.checkBox_NVIDIAP0State.AutoSize = true; - this.checkBox_NVIDIAP0State.Location = new System.Drawing.Point(6, 261); + this.checkBox_NVIDIAP0State.Location = new System.Drawing.Point(6, 226); this.checkBox_NVIDIAP0State.Name = "checkBox_NVIDIAP0State"; this.checkBox_NVIDIAP0State.Size = new System.Drawing.Size(100, 17); this.checkBox_NVIDIAP0State.TabIndex = 326; @@ -439,7 +500,7 @@ private void InitializeComponent() { // checkBox_AutoScaleBTCValues // this.checkBox_AutoScaleBTCValues.AutoSize = true; - this.checkBox_AutoScaleBTCValues.Location = new System.Drawing.Point(6, 173); + this.checkBox_AutoScaleBTCValues.Location = new System.Drawing.Point(6, 142); this.checkBox_AutoScaleBTCValues.Name = "checkBox_AutoScaleBTCValues"; this.checkBox_AutoScaleBTCValues.Size = new System.Drawing.Size(128, 17); this.checkBox_AutoScaleBTCValues.TabIndex = 321; @@ -449,7 +510,7 @@ private void InitializeComponent() { // checkBox_DisableWindowsErrorReporting // this.checkBox_DisableWindowsErrorReporting.AutoSize = true; - this.checkBox_DisableWindowsErrorReporting.Location = new System.Drawing.Point(6, 239); + this.checkBox_DisableWindowsErrorReporting.Location = new System.Drawing.Point(6, 205); this.checkBox_DisableWindowsErrorReporting.Name = "checkBox_DisableWindowsErrorReporting"; this.checkBox_DisableWindowsErrorReporting.Size = new System.Drawing.Size(173, 17); this.checkBox_DisableWindowsErrorReporting.TabIndex = 324; @@ -459,7 +520,7 @@ private void InitializeComponent() { // checkBox_StartMiningWhenIdle // this.checkBox_StartMiningWhenIdle.AutoSize = true; - this.checkBox_StartMiningWhenIdle.Location = new System.Drawing.Point(6, 195); + this.checkBox_StartMiningWhenIdle.Location = new System.Drawing.Point(6, 163); this.checkBox_StartMiningWhenIdle.Name = "checkBox_StartMiningWhenIdle"; this.checkBox_StartMiningWhenIdle.Size = new System.Drawing.Size(125, 17); this.checkBox_StartMiningWhenIdle.TabIndex = 322; @@ -469,7 +530,7 @@ private void InitializeComponent() { // checkBox_ShowDriverVersionWarning // this.checkBox_ShowDriverVersionWarning.AutoSize = true; - this.checkBox_ShowDriverVersionWarning.Location = new System.Drawing.Point(6, 217); + this.checkBox_ShowDriverVersionWarning.Location = new System.Drawing.Point(6, 184); this.checkBox_ShowDriverVersionWarning.Name = "checkBox_ShowDriverVersionWarning"; this.checkBox_ShowDriverVersionWarning.Size = new System.Drawing.Size(156, 17); this.checkBox_ShowDriverVersionWarning.TabIndex = 323; @@ -485,7 +546,7 @@ private void InitializeComponent() { this.groupBox_Logging.Controls.Add(this.pictureBox_LogMaxFileSize); this.groupBox_Logging.Controls.Add(this.pictureBox_LogToFile); this.groupBox_Logging.Controls.Add(this.checkBox_DebugConsole); - this.groupBox_Logging.Location = new System.Drawing.Point(6, 240); + this.groupBox_Logging.Location = new System.Drawing.Point(6, 268); this.groupBox_Logging.Name = "groupBox_Logging"; this.groupBox_Logging.Size = new System.Drawing.Size(345, 70); this.groupBox_Logging.TabIndex = 388; @@ -560,11 +621,13 @@ private void InitializeComponent() { // // groupBox_Main // + this.groupBox_Main.Controls.Add(this.checkBox_IdleWhenNoInternetAccess); this.groupBox_Main.Controls.Add(this.pictureBox_WorkerName); this.groupBox_Main.Controls.Add(this.pictureBox_MinProfit); this.groupBox_Main.Controls.Add(this.pictureBox_ServiceLocation); this.groupBox_Main.Controls.Add(this.pictureBox_Info_BitcoinAddress); this.groupBox_Main.Controls.Add(this.textBox_MinProfit); + this.groupBox_Main.Controls.Add(this.pictureBox_IdleWhenNoInternetAccess); this.groupBox_Main.Controls.Add(this.label_BitcoinAddress); this.groupBox_Main.Controls.Add(this.label_MinProfit); this.groupBox_Main.Controls.Add(this.label_WorkerName); @@ -574,11 +637,22 @@ private void InitializeComponent() { this.groupBox_Main.Controls.Add(this.textBox_WorkerName); this.groupBox_Main.Location = new System.Drawing.Point(6, 6); this.groupBox_Main.Name = "groupBox_Main"; - this.groupBox_Main.Size = new System.Drawing.Size(345, 152); + this.groupBox_Main.Size = new System.Drawing.Size(345, 180); this.groupBox_Main.TabIndex = 386; this.groupBox_Main.TabStop = false; this.groupBox_Main.Text = "Main:"; // + // checkBox_IdleWhenNoInternetAccess + // + this.checkBox_IdleWhenNoInternetAccess.AutoSize = true; + this.checkBox_IdleWhenNoInternetAccess.Location = new System.Drawing.Point(10, 149); + this.checkBox_IdleWhenNoInternetAccess.Name = "checkBox_IdleWhenNoInternetAccess"; + this.checkBox_IdleWhenNoInternetAccess.Size = new System.Drawing.Size(205, 17); + this.checkBox_IdleWhenNoInternetAccess.TabIndex = 365; + this.checkBox_IdleWhenNoInternetAccess.Text = "Continue Mining If No Internet Access"; + this.checkBox_IdleWhenNoInternetAccess.UseVisualStyleBackColor = true; + this.checkBox_IdleWhenNoInternetAccess.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); + // // pictureBox_WorkerName // this.pictureBox_WorkerName.Image = global::NiceHashMiner.Properties.Resources.info_black_18; @@ -626,6 +700,16 @@ private void InitializeComponent() { this.textBox_MinProfit.Size = new System.Drawing.Size(237, 20); this.textBox_MinProfit.TabIndex = 334; // + // pictureBox_IdleWhenNoInternetAccess + // + this.pictureBox_IdleWhenNoInternetAccess.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_IdleWhenNoInternetAccess.Location = new System.Drawing.Point(302, 149); + this.pictureBox_IdleWhenNoInternetAccess.Name = "pictureBox_IdleWhenNoInternetAccess"; + this.pictureBox_IdleWhenNoInternetAccess.Size = new System.Drawing.Size(18, 18); + this.pictureBox_IdleWhenNoInternetAccess.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_IdleWhenNoInternetAccess.TabIndex = 364; + this.pictureBox_IdleWhenNoInternetAccess.TabStop = false; + // // label_BitcoinAddress // this.label_BitcoinAddress.AutoSize = true; @@ -699,7 +783,7 @@ private void InitializeComponent() { this.groupBox_Localization.Controls.Add(this.comboBox_Language); this.groupBox_Localization.Controls.Add(this.currencyConverterCombobox); this.groupBox_Localization.Controls.Add(this.label_displayCurrency); - this.groupBox_Localization.Location = new System.Drawing.Point(6, 164); + this.groupBox_Localization.Location = new System.Drawing.Point(6, 192); this.groupBox_Localization.Name = "groupBox_Localization"; this.groupBox_Localization.Size = new System.Drawing.Size(345, 70); this.groupBox_Localization.TabIndex = 385; @@ -825,6 +909,7 @@ private void InitializeComponent() { this.groupBox_Miners.Controls.Add(this.pictureBox_MinerRestartDelayMS); this.groupBox_Miners.Controls.Add(this.pictureBox_APIBindPortStart); this.groupBox_Miners.Controls.Add(this.pictureBox_SwitchMinSecondsDynamic); + this.groupBox_Miners.Controls.Add(this.pictureBox_SwitchProfitabilityThreshold); this.groupBox_Miners.Controls.Add(this.pictureBox_ethminerDefaultBlockHeight); this.groupBox_Miners.Controls.Add(this.pictureBox_DagGeneration); this.groupBox_Miners.Controls.Add(this.pictureBox_CPU0_ForceCPUExtension); @@ -842,7 +927,9 @@ private void InitializeComponent() { this.groupBox_Miners.Controls.Add(this.label_MinerRestartDelayMS); this.groupBox_Miners.Controls.Add(this.textBox_SwitchMinSecondsAMD); this.groupBox_Miners.Controls.Add(this.label_APIBindPortStart); + this.groupBox_Miners.Controls.Add(this.textBox_SwitchProfitabilityThreshold); this.groupBox_Miners.Controls.Add(this.textBox_ethminerDefaultBlockHeight); + this.groupBox_Miners.Controls.Add(this.label_SwitchProfitabilityThreshold); this.groupBox_Miners.Controls.Add(this.label_ethminerDefaultBlockHeight); this.groupBox_Miners.Controls.Add(this.textBox_APIBindPortStart); this.groupBox_Miners.Controls.Add(this.label_SwitchMinSecondsAMD); @@ -898,6 +985,16 @@ private void InitializeComponent() { this.pictureBox_SwitchMinSecondsDynamic.TabIndex = 385; this.pictureBox_SwitchMinSecondsDynamic.TabStop = false; // + // pictureBox_SwitchProfitabilityThreshold + // + this.pictureBox_SwitchProfitabilityThreshold.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_SwitchProfitabilityThreshold.Location = new System.Drawing.Point(560, 104); + this.pictureBox_SwitchProfitabilityThreshold.Name = "pictureBox_SwitchProfitabilityThreshold"; + this.pictureBox_SwitchProfitabilityThreshold.Size = new System.Drawing.Size(18, 18); + this.pictureBox_SwitchProfitabilityThreshold.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_SwitchProfitabilityThreshold.TabIndex = 385; + this.pictureBox_SwitchProfitabilityThreshold.TabStop = false; + // // pictureBox_ethminerDefaultBlockHeight // this.pictureBox_ethminerDefaultBlockHeight.Image = global::NiceHashMiner.Properties.Resources.info_black_18; @@ -927,6 +1024,7 @@ private void InitializeComponent() { this.pictureBox_CPU0_ForceCPUExtension.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; this.pictureBox_CPU0_ForceCPUExtension.TabIndex = 385; this.pictureBox_CPU0_ForceCPUExtension.TabStop = false; + this.pictureBox_CPU0_ForceCPUExtension.Visible = false; // // pictureBox_MinerAPIQueryInterval // @@ -987,14 +1085,16 @@ private void InitializeComponent() { this.comboBox_CPU0_ForceCPUExtension.FormattingEnabled = true; this.comboBox_CPU0_ForceCPUExtension.Items.AddRange(new object[] { "Automatic", + "AVX2_AES", "AVX2", + "AVX_AES", "AVX", - "AES", - "SSE2"}); + "AES"}); this.comboBox_CPU0_ForceCPUExtension.Location = new System.Drawing.Point(9, 165); this.comboBox_CPU0_ForceCPUExtension.Name = "comboBox_CPU0_ForceCPUExtension"; this.comboBox_CPU0_ForceCPUExtension.Size = new System.Drawing.Size(177, 21); this.comboBox_CPU0_ForceCPUExtension.TabIndex = 379; + this.comboBox_CPU0_ForceCPUExtension.Visible = false; this.comboBox_CPU0_ForceCPUExtension.SelectedIndexChanged += new System.EventHandler(this.comboBox_CPU0_ForceCPUExtension_SelectedIndexChanged); // // label_CPU0_ForceCPUExtension @@ -1005,6 +1105,7 @@ private void InitializeComponent() { this.label_CPU0_ForceCPUExtension.Size = new System.Drawing.Size(105, 13); this.label_CPU0_ForceCPUExtension.TabIndex = 382; this.label_CPU0_ForceCPUExtension.Text = "ForceCPUExtension:"; + this.label_CPU0_ForceCPUExtension.Visible = false; // // label_MinIdleSeconds // @@ -1067,6 +1168,14 @@ private void InitializeComponent() { this.label_APIBindPortStart.TabIndex = 357; this.label_APIBindPortStart.Text = "API Bind port pool start:"; // + // textBox_SwitchProfitabilityThreshold + // + this.textBox_SwitchProfitabilityThreshold.Location = new System.Drawing.Point(406, 123); + this.textBox_SwitchProfitabilityThreshold.Name = "textBox_SwitchProfitabilityThreshold"; + this.textBox_SwitchProfitabilityThreshold.Size = new System.Drawing.Size(172, 20); + this.textBox_SwitchProfitabilityThreshold.TabIndex = 333; + this.textBox_SwitchProfitabilityThreshold.Leave += new System.EventHandler(this.GeneralTextBoxes_Leave); + // // textBox_ethminerDefaultBlockHeight // this.textBox_ethminerDefaultBlockHeight.Location = new System.Drawing.Point(209, 121); @@ -1074,6 +1183,15 @@ private void InitializeComponent() { this.textBox_ethminerDefaultBlockHeight.Size = new System.Drawing.Size(172, 20); this.textBox_ethminerDefaultBlockHeight.TabIndex = 333; // + // label_SwitchProfitabilityThreshold + // + this.label_SwitchProfitabilityThreshold.AutoSize = true; + this.label_SwitchProfitabilityThreshold.Location = new System.Drawing.Point(406, 102); + this.label_SwitchProfitabilityThreshold.Name = "label_SwitchProfitabilityThreshold"; + this.label_SwitchProfitabilityThreshold.Size = new System.Drawing.Size(142, 13); + this.label_SwitchProfitabilityThreshold.TabIndex = 361; + this.label_SwitchProfitabilityThreshold.Text = "ethminerDefaultBlockHeight:"; + // // label_ethminerDefaultBlockHeight // this.label_ethminerDefaultBlockHeight.AutoSize = true; @@ -1146,6 +1264,36 @@ private void InitializeComponent() { this.groupBoxBenchmarkTimeLimits.TabStop = false; this.groupBoxBenchmarkTimeLimits.Text = "Benchmark Time Limits:"; // + // benchmarkLimitControlNVIDIA + // + this.benchmarkLimitControlNVIDIA.GroupName = "NVIDIA"; + this.benchmarkLimitControlNVIDIA.Location = new System.Drawing.Point(9, 17); + this.benchmarkLimitControlNVIDIA.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); + this.benchmarkLimitControlNVIDIA.Name = "benchmarkLimitControlNVIDIA"; + this.benchmarkLimitControlNVIDIA.Size = new System.Drawing.Size(177, 121); + this.benchmarkLimitControlNVIDIA.TabIndex = 4; + this.benchmarkLimitControlNVIDIA.TimeLimits = null; + // + // benchmarkLimitControlCPU + // + this.benchmarkLimitControlCPU.GroupName = "CPU"; + this.benchmarkLimitControlCPU.Location = new System.Drawing.Point(209, 17); + this.benchmarkLimitControlCPU.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); + this.benchmarkLimitControlCPU.Name = "benchmarkLimitControlCPU"; + this.benchmarkLimitControlCPU.Size = new System.Drawing.Size(177, 121); + this.benchmarkLimitControlCPU.TabIndex = 3; + this.benchmarkLimitControlCPU.TimeLimits = null; + // + // benchmarkLimitControlAMD + // + this.benchmarkLimitControlAMD.GroupName = "AMD"; + this.benchmarkLimitControlAMD.Location = new System.Drawing.Point(409, 17); + this.benchmarkLimitControlAMD.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); + this.benchmarkLimitControlAMD.Name = "benchmarkLimitControlAMD"; + this.benchmarkLimitControlAMD.Size = new System.Drawing.Size(177, 121); + this.benchmarkLimitControlAMD.TabIndex = 5; + this.benchmarkLimitControlAMD.TimeLimits = null; + // // tabPageDevicesAlgos // this.tabPageDevicesAlgos.Controls.Add(this.devicesListViewEnableControl1); @@ -1161,6 +1309,25 @@ private void InitializeComponent() { this.tabPageDevicesAlgos.Text = "Devices/Algorithms"; this.tabPageDevicesAlgos.UseVisualStyleBackColor = true; // + // devicesListViewEnableControl1 + // + this.devicesListViewEnableControl1.BenchmarkCalculation = null; + this.devicesListViewEnableControl1.FirstColumnText = "Enabled"; + this.devicesListViewEnableControl1.IsInBenchmark = false; + this.devicesListViewEnableControl1.IsMining = false; + this.devicesListViewEnableControl1.Location = new System.Drawing.Point(6, 6); + this.devicesListViewEnableControl1.Name = "devicesListViewEnableControl1"; + this.devicesListViewEnableControl1.SaveToGeneralConfig = false; + this.devicesListViewEnableControl1.Size = new System.Drawing.Size(352, 130); + this.devicesListViewEnableControl1.TabIndex = 397; + // + // algorithmSettingsControl1 + // + this.algorithmSettingsControl1.Location = new System.Drawing.Point(363, 64); + this.algorithmSettingsControl1.Name = "algorithmSettingsControl1"; + this.algorithmSettingsControl1.Size = new System.Drawing.Size(238, 278); + this.algorithmSettingsControl1.TabIndex = 396; + // // groupBoxAlgorithmSettings // this.groupBoxAlgorithmSettings.Controls.Add(this.algorithmsListView1); @@ -1171,6 +1338,16 @@ private void InitializeComponent() { this.groupBoxAlgorithmSettings.TabStop = false; this.groupBoxAlgorithmSettings.Text = "Algorithm settings for selected device:"; // + // algorithmsListView1 + // + this.algorithmsListView1.BenchmarkCalculation = null; + this.algorithmsListView1.ComunicationInterface = null; + this.algorithmsListView1.IsInBenchmark = false; + this.algorithmsListView1.Location = new System.Drawing.Point(6, 15); + this.algorithmsListView1.Name = "algorithmsListView1"; + this.algorithmsListView1.Size = new System.Drawing.Size(339, 191); + this.algorithmsListView1.TabIndex = 2; + // // buttonAllProfit // this.buttonAllProfit.Location = new System.Drawing.Point(364, 6); @@ -1224,65 +1401,6 @@ private void InitializeComponent() { this.buttonCloseNoSave.UseVisualStyleBackColor = true; this.buttonCloseNoSave.Click += new System.EventHandler(this.buttonCloseNoSave_Click); // - // benchmarkLimitControlNVIDIA - // - this.benchmarkLimitControlNVIDIA.GroupName = "NVIDIA"; - this.benchmarkLimitControlNVIDIA.Location = new System.Drawing.Point(9, 17); - this.benchmarkLimitControlNVIDIA.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); - this.benchmarkLimitControlNVIDIA.Name = "benchmarkLimitControlNVIDIA"; - this.benchmarkLimitControlNVIDIA.Size = new System.Drawing.Size(177, 121); - this.benchmarkLimitControlNVIDIA.TabIndex = 4; - this.benchmarkLimitControlNVIDIA.TimeLimits = null; - // - // benchmarkLimitControlCPU - // - this.benchmarkLimitControlCPU.GroupName = "CPU"; - this.benchmarkLimitControlCPU.Location = new System.Drawing.Point(209, 17); - this.benchmarkLimitControlCPU.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); - this.benchmarkLimitControlCPU.Name = "benchmarkLimitControlCPU"; - this.benchmarkLimitControlCPU.Size = new System.Drawing.Size(177, 121); - this.benchmarkLimitControlCPU.TabIndex = 3; - this.benchmarkLimitControlCPU.TimeLimits = null; - // - // benchmarkLimitControlAMD - // - this.benchmarkLimitControlAMD.GroupName = "AMD"; - this.benchmarkLimitControlAMD.Location = new System.Drawing.Point(409, 17); - this.benchmarkLimitControlAMD.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); - this.benchmarkLimitControlAMD.Name = "benchmarkLimitControlAMD"; - this.benchmarkLimitControlAMD.Size = new System.Drawing.Size(177, 121); - this.benchmarkLimitControlAMD.TabIndex = 5; - this.benchmarkLimitControlAMD.TimeLimits = null; - // - // devicesListViewEnableControl1 - // - this.devicesListViewEnableControl1.AutoSaveChange = true; - this.devicesListViewEnableControl1.FirstColumnText = "Enabled"; - this.devicesListViewEnableControl1.IsInBenchmark = false; - this.devicesListViewEnableControl1.IsMining = false; - this.devicesListViewEnableControl1.Location = new System.Drawing.Point(6, 6); - this.devicesListViewEnableControl1.Name = "devicesListViewEnableControl1"; - this.devicesListViewEnableControl1.SaveToGeneralConfig = false; - this.devicesListViewEnableControl1.SetAllEnabled = false; - this.devicesListViewEnableControl1.Size = new System.Drawing.Size(352, 130); - this.devicesListViewEnableControl1.TabIndex = 397; - // - // algorithmSettingsControl1 - // - this.algorithmSettingsControl1.Location = new System.Drawing.Point(363, 64); - this.algorithmSettingsControl1.Name = "algorithmSettingsControl1"; - this.algorithmSettingsControl1.Size = new System.Drawing.Size(238, 278); - this.algorithmSettingsControl1.TabIndex = 396; - // - // algorithmsListView1 - // - this.algorithmsListView1.ComunicationInterface = null; - this.algorithmsListView1.IsInBenchmark = false; - this.algorithmsListView1.Location = new System.Drawing.Point(6, 15); - this.algorithmsListView1.Name = "algorithmsListView1"; - this.algorithmsListView1.Size = new System.Drawing.Size(339, 191); - this.algorithmsListView1.TabIndex = 2; - // // Form_Settings // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -1293,27 +1411,27 @@ private void InitializeComponent() { this.Controls.Add(this.tabControlGeneral); this.Controls.Add(this.buttonCloseNoSave); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "Form_Settings"; this.Text = "Settings"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormSettings_FormClosing); - this.Resize += new System.EventHandler(this.Form_Settings_Resize); this.tabControlGeneral.ResumeLayout(false); this.tabPageGeneral.ResumeLayout(false); this.groupBox_Misc.ResumeLayout(false); this.groupBox_Misc.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AllowMultipleInstances)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDefaultOptimizations)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AMD_DisableAMDTempControl)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_NVIDIAP0State)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableWindowsErrorReporting)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ShowDriverVersionWarning)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_StartMiningWhenIdle)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AutoScaleBTCValues)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionAMD)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia2X)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia3X)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia5X)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia6X)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_Use3rdPartyMiners)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVIDIA)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AutoStartMining)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinimizeToTray)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_HideMiningWindows)).EndInit(); this.groupBox_Logging.ResumeLayout(false); @@ -1327,6 +1445,7 @@ private void InitializeComponent() { ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinProfit)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ServiceLocation)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_Info_BitcoinAddress)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_IdleWhenNoInternetAccess)).EndInit(); this.groupBox_Localization.ResumeLayout(false); this.groupBox_Localization.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).EndInit(); @@ -1339,6 +1458,7 @@ private void InitializeComponent() { ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinerRestartDelayMS)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_APIBindPortStart)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchMinSecondsDynamic)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchProfitabilityThreshold)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ethminerDefaultBlockHeight)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DagGeneration)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_CPU0_ForceCPUExtension)).EndInit(); @@ -1402,10 +1522,7 @@ private void InitializeComponent() { private System.Windows.Forms.GroupBox groupBox_Misc; private System.Windows.Forms.CheckBox checkBox_HideMiningWindows; private System.Windows.Forms.CheckBox checkBox_MinimizeToTray; - private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVidia6X; - private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVidia5X; - private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVidia3X; - private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVidia2X; + private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVIDIA; private System.Windows.Forms.CheckBox checkBox_DisableDetectionAMD; private System.Windows.Forms.CheckBox checkBox_NVIDIAP0State; private System.Windows.Forms.CheckBox checkBox_AutoScaleBTCValues; @@ -1431,10 +1548,7 @@ private void InitializeComponent() { private System.Windows.Forms.PictureBox pictureBox_StartMiningWhenIdle; private System.Windows.Forms.PictureBox pictureBox_AutoScaleBTCValues; private System.Windows.Forms.PictureBox pictureBox_DisableDetectionAMD; - private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVidia2X; - private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVidia3X; - private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVidia5X; - private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVidia6X; + private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVIDIA; private System.Windows.Forms.PictureBox pictureBox_MinimizeToTray; private System.Windows.Forms.PictureBox pictureBox_HideMiningWindows; private System.Windows.Forms.PictureBox pictureBox_DebugConsole; @@ -1457,6 +1571,21 @@ private void InitializeComponent() { private System.Windows.Forms.PictureBox pictureBox_SwitchMinSecondsDynamic; private System.Windows.Forms.PictureBox pictureBox_ethminerDefaultBlockHeight; private System.Windows.Forms.PictureBox pictureBox_DagGeneration; + private System.Windows.Forms.CheckBox checkBox_AutoStartMining; + private System.Windows.Forms.PictureBox pictureBox_AutoStartMining; + private System.Windows.Forms.CheckBox checkBox_AMD_DisableAMDTempControl; + private System.Windows.Forms.PictureBox pictureBox_AMD_DisableAMDTempControl; + private System.Windows.Forms.CheckBox checkBox_DisableDefaultOptimizations; + private System.Windows.Forms.PictureBox pictureBox_DisableDefaultOptimizations; + private System.Windows.Forms.CheckBox checkBox_IdleWhenNoInternetAccess; + private System.Windows.Forms.PictureBox pictureBox_IdleWhenNoInternetAccess; + private System.Windows.Forms.PictureBox pictureBox_Use3rdPartyMiners; + private System.Windows.Forms.CheckBox checkBox_Use3rdPartyMiners; + private System.Windows.Forms.CheckBox checkBox_AllowMultipleInstances; + private System.Windows.Forms.PictureBox pictureBox_AllowMultipleInstances; + private System.Windows.Forms.PictureBox pictureBox_SwitchProfitabilityThreshold; + private System.Windows.Forms.TextBox textBox_SwitchProfitabilityThreshold; + private System.Windows.Forms.Label label_SwitchProfitabilityThreshold; } } \ No newline at end of file diff --git a/NiceHashMiner/Forms/Form_Settings.Designer.cs.orig b/NiceHashMiner/Forms/Form_Settings.Designer.cs.orig new file mode 100644 index 0000000..8b28e5d --- /dev/null +++ b/NiceHashMiner/Forms/Form_Settings.Designer.cs.orig @@ -0,0 +1,1534 @@ +namespace NiceHashMiner.Forms { + partial class Form_Settings { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form_Settings)); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.tabControlGeneral = new System.Windows.Forms.TabControl(); + this.tabPageGeneral = new System.Windows.Forms.TabPage(); + this.groupBox_Misc = new System.Windows.Forms.GroupBox(); + this.checkBox_AutoStartMining = new System.Windows.Forms.CheckBox(); + this.checkBox_HideMiningWindows = new System.Windows.Forms.CheckBox(); + this.checkBox_MinimizeToTray = new System.Windows.Forms.CheckBox(); + this.checkBox_DisableDetectionNVidia6X = new System.Windows.Forms.CheckBox(); + this.checkBox_DisableDetectionNVidia5X = new System.Windows.Forms.CheckBox(); + this.pictureBox_NVIDIAP0State = new System.Windows.Forms.PictureBox(); + this.pictureBox_DisableWindowsErrorReporting = new System.Windows.Forms.PictureBox(); + this.pictureBox_ShowDriverVersionWarning = new System.Windows.Forms.PictureBox(); + this.pictureBox_StartMiningWhenIdle = new System.Windows.Forms.PictureBox(); + this.pictureBox_AutoScaleBTCValues = new System.Windows.Forms.PictureBox(); + this.pictureBox_DisableDetectionAMD = new System.Windows.Forms.PictureBox(); + this.pictureBox_DisableDetectionNVidia2X = new System.Windows.Forms.PictureBox(); + this.pictureBox_DisableDetectionNVidia3X = new System.Windows.Forms.PictureBox(); + this.pictureBox_DisableDetectionNVidia5X = new System.Windows.Forms.PictureBox(); + this.pictureBox_DisableDetectionNVidia6X = new System.Windows.Forms.PictureBox(); + this.pictureBox_AutoStartMining = new System.Windows.Forms.PictureBox(); + this.pictureBox_MinimizeToTray = new System.Windows.Forms.PictureBox(); + this.pictureBox_HideMiningWindows = new System.Windows.Forms.PictureBox(); + this.checkBox_DisableDetectionNVidia3X = new System.Windows.Forms.CheckBox(); + this.checkBox_DisableDetectionNVidia2X = new System.Windows.Forms.CheckBox(); + this.checkBox_DisableDetectionAMD = new System.Windows.Forms.CheckBox(); + this.checkBox_NVIDIAP0State = new System.Windows.Forms.CheckBox(); + this.checkBox_AutoScaleBTCValues = new System.Windows.Forms.CheckBox(); + this.checkBox_DisableWindowsErrorReporting = new System.Windows.Forms.CheckBox(); + this.checkBox_StartMiningWhenIdle = new System.Windows.Forms.CheckBox(); + this.checkBox_ShowDriverVersionWarning = new System.Windows.Forms.CheckBox(); + this.groupBox_Logging = new System.Windows.Forms.GroupBox(); + this.label_LogMaxFileSize = new System.Windows.Forms.Label(); + this.textBox_LogMaxFileSize = new System.Windows.Forms.TextBox(); + this.checkBox_LogToFile = new System.Windows.Forms.CheckBox(); + this.pictureBox_DebugConsole = new System.Windows.Forms.PictureBox(); + this.pictureBox_LogMaxFileSize = new System.Windows.Forms.PictureBox(); + this.pictureBox_LogToFile = new System.Windows.Forms.PictureBox(); + this.checkBox_DebugConsole = new System.Windows.Forms.CheckBox(); + this.groupBox_Main = new System.Windows.Forms.GroupBox(); + this.pictureBox_WorkerName = new System.Windows.Forms.PictureBox(); + this.pictureBox_MinProfit = new System.Windows.Forms.PictureBox(); + this.pictureBox_ServiceLocation = new System.Windows.Forms.PictureBox(); + this.pictureBox_Info_BitcoinAddress = new System.Windows.Forms.PictureBox(); + this.textBox_MinProfit = new System.Windows.Forms.TextBox(); + this.label_BitcoinAddress = new System.Windows.Forms.Label(); + this.label_MinProfit = new System.Windows.Forms.Label(); + this.label_WorkerName = new System.Windows.Forms.Label(); + this.label_ServiceLocation = new System.Windows.Forms.Label(); + this.comboBox_ServiceLocation = new System.Windows.Forms.ComboBox(); + this.textBox_BitcoinAddress = new System.Windows.Forms.TextBox(); + this.textBox_WorkerName = new System.Windows.Forms.TextBox(); + this.groupBox_Localization = new System.Windows.Forms.GroupBox(); + this.label_Language = new System.Windows.Forms.Label(); + this.pictureBox5 = new System.Windows.Forms.PictureBox(); + this.pictureBox_displayCurrency = new System.Windows.Forms.PictureBox(); + this.pictureBox_Language = new System.Windows.Forms.PictureBox(); + this.comboBox_Language = new System.Windows.Forms.ComboBox(); + this.currencyConverterCombobox = new System.Windows.Forms.ComboBox(); + this.label_displayCurrency = new System.Windows.Forms.Label(); + this.tabPageAdvanced = new System.Windows.Forms.TabPage(); + this.groupBox_Miners = new System.Windows.Forms.GroupBox(); + this.pictureBox_SwitchMinSecondsFixed = new System.Windows.Forms.PictureBox(); + this.pictureBox_MinerRestartDelayMS = new System.Windows.Forms.PictureBox(); + this.pictureBox_APIBindPortStart = new System.Windows.Forms.PictureBox(); + this.pictureBox_SwitchMinSecondsDynamic = new System.Windows.Forms.PictureBox(); + this.pictureBox_ethminerDefaultBlockHeight = new System.Windows.Forms.PictureBox(); + this.pictureBox_DagGeneration = new System.Windows.Forms.PictureBox(); + this.pictureBox_CPU0_ForceCPUExtension = new System.Windows.Forms.PictureBox(); + this.pictureBox_MinerAPIQueryInterval = new System.Windows.Forms.PictureBox(); + this.pictureBox_SwitchMinSecondsAMD = new System.Windows.Forms.PictureBox(); + this.pictureBox_MinIdleSeconds = new System.Windows.Forms.PictureBox(); + this.comboBox_DagLoadMode = new System.Windows.Forms.ComboBox(); + this.label_DagGeneration = new System.Windows.Forms.Label(); + this.comboBox_CPU0_ForceCPUExtension = new System.Windows.Forms.ComboBox(); + this.label_CPU0_ForceCPUExtension = new System.Windows.Forms.Label(); + this.label_MinIdleSeconds = new System.Windows.Forms.Label(); + this.label_SwitchMinSecondsFixed = new System.Windows.Forms.Label(); + this.label_SwitchMinSecondsDynamic = new System.Windows.Forms.Label(); + this.label_MinerAPIQueryInterval = new System.Windows.Forms.Label(); + this.label_MinerRestartDelayMS = new System.Windows.Forms.Label(); + this.textBox_SwitchMinSecondsAMD = new System.Windows.Forms.TextBox(); + this.label_APIBindPortStart = new System.Windows.Forms.Label(); + this.textBox_ethminerDefaultBlockHeight = new System.Windows.Forms.TextBox(); + this.label_ethminerDefaultBlockHeight = new System.Windows.Forms.Label(); + this.textBox_APIBindPortStart = new System.Windows.Forms.TextBox(); + this.label_SwitchMinSecondsAMD = new System.Windows.Forms.Label(); + this.textBox_MinIdleSeconds = new System.Windows.Forms.TextBox(); + this.textBox_SwitchMinSecondsFixed = new System.Windows.Forms.TextBox(); + this.textBox_SwitchMinSecondsDynamic = new System.Windows.Forms.TextBox(); + this.textBox_MinerRestartDelayMS = new System.Windows.Forms.TextBox(); + this.textBox_MinerAPIQueryInterval = new System.Windows.Forms.TextBox(); + this.groupBoxBenchmarkTimeLimits = new System.Windows.Forms.GroupBox(); + this.tabPageDevicesAlgos = new System.Windows.Forms.TabPage(); + this.groupBoxAlgorithmSettings = new System.Windows.Forms.GroupBox(); + this.buttonAllProfit = new System.Windows.Forms.Button(); + this.buttonSelectedProfit = new System.Windows.Forms.Button(); + this.buttonSaveClose = new System.Windows.Forms.Button(); + this.buttonDefaults = new System.Windows.Forms.Button(); + this.buttonCloseNoSave = new System.Windows.Forms.Button(); +<<<<<<< HEAD +======= + this.benchmarkLimitControlNVIDIA = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); + this.benchmarkLimitControlCPU = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); + this.benchmarkLimitControlAMD = new NiceHashMiner.Forms.Components.BenchmarkLimitControl(); + this.devicesListViewEnableControl1 = new NiceHashMiner.Forms.Components.DevicesListViewEnableControl(); + this.algorithmSettingsControl1 = new NiceHashMiner.Forms.Components.AlgorithmSettingsControl(); + this.algorithmsListView1 = new NiceHashMiner.Forms.Components.AlgorithmsListView(); + this.checkBox_AMD_DisableAMDTempControl = new System.Windows.Forms.CheckBox(); + this.pictureBox_AMD_DisableAMDTempControl = new System.Windows.Forms.PictureBox(); +>>>>>>> ExtraLaunchParamsRefactor + this.tabControlGeneral.SuspendLayout(); + this.tabPageGeneral.SuspendLayout(); + this.groupBox_Misc.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_NVIDIAP0State)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableWindowsErrorReporting)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ShowDriverVersionWarning)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_StartMiningWhenIdle)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AutoScaleBTCValues)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionAMD)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia2X)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia3X)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia5X)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia6X)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AutoStartMining)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinimizeToTray)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_HideMiningWindows)).BeginInit(); + this.groupBox_Logging.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DebugConsole)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_LogMaxFileSize)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_LogToFile)).BeginInit(); + this.groupBox_Main.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_WorkerName)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinProfit)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ServiceLocation)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_Info_BitcoinAddress)).BeginInit(); + this.groupBox_Localization.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_displayCurrency)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_Language)).BeginInit(); + this.tabPageAdvanced.SuspendLayout(); + this.groupBox_Miners.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchMinSecondsFixed)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinerRestartDelayMS)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_APIBindPortStart)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchMinSecondsDynamic)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ethminerDefaultBlockHeight)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DagGeneration)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_CPU0_ForceCPUExtension)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinerAPIQueryInterval)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchMinSecondsAMD)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinIdleSeconds)).BeginInit(); + this.groupBoxBenchmarkTimeLimits.SuspendLayout(); + this.tabPageDevicesAlgos.SuspendLayout(); + this.groupBoxAlgorithmSettings.SuspendLayout(); +<<<<<<< HEAD +======= + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AMD_DisableAMDTempControl)).BeginInit(); +>>>>>>> ExtraLaunchParamsRefactor + this.SuspendLayout(); + // + // toolTip1 + // + this.toolTip1.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info; + this.toolTip1.Popup += new System.Windows.Forms.PopupEventHandler(this.toolTip1_Popup); + // + // tabControlGeneral + // + this.tabControlGeneral.Controls.Add(this.tabPageGeneral); + this.tabControlGeneral.Controls.Add(this.tabPageAdvanced); + this.tabControlGeneral.Controls.Add(this.tabPageDevicesAlgos); + this.tabControlGeneral.Location = new System.Drawing.Point(12, 12); + this.tabControlGeneral.Name = "tabControlGeneral"; + this.tabControlGeneral.SelectedIndex = 0; + this.tabControlGeneral.Size = new System.Drawing.Size(612, 380); + this.tabControlGeneral.TabIndex = 0; + // + // tabPageGeneral + // + this.tabPageGeneral.Controls.Add(this.groupBox_Misc); + this.tabPageGeneral.Controls.Add(this.groupBox_Logging); + this.tabPageGeneral.Controls.Add(this.groupBox_Main); + this.tabPageGeneral.Controls.Add(this.groupBox_Localization); + this.tabPageGeneral.Location = new System.Drawing.Point(4, 22); + this.tabPageGeneral.Name = "tabPageGeneral"; + this.tabPageGeneral.Padding = new System.Windows.Forms.Padding(3); + this.tabPageGeneral.Size = new System.Drawing.Size(604, 354); + this.tabPageGeneral.TabIndex = 0; + this.tabPageGeneral.Text = "General"; + this.tabPageGeneral.UseVisualStyleBackColor = true; + // + // groupBox_Misc + // + this.groupBox_Misc.Controls.Add(this.checkBox_AMD_DisableAMDTempControl); + this.groupBox_Misc.Controls.Add(this.pictureBox_AMD_DisableAMDTempControl); + this.groupBox_Misc.Controls.Add(this.checkBox_AutoStartMining); + this.groupBox_Misc.Controls.Add(this.checkBox_HideMiningWindows); + this.groupBox_Misc.Controls.Add(this.checkBox_MinimizeToTray); + this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVidia6X); + this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVidia5X); + this.groupBox_Misc.Controls.Add(this.pictureBox_NVIDIAP0State); + this.groupBox_Misc.Controls.Add(this.pictureBox_DisableWindowsErrorReporting); + this.groupBox_Misc.Controls.Add(this.pictureBox_ShowDriverVersionWarning); + this.groupBox_Misc.Controls.Add(this.pictureBox_StartMiningWhenIdle); + this.groupBox_Misc.Controls.Add(this.pictureBox_AutoScaleBTCValues); + this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionAMD); + this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVidia2X); + this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVidia3X); + this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVidia5X); + this.groupBox_Misc.Controls.Add(this.pictureBox_DisableDetectionNVidia6X); + this.groupBox_Misc.Controls.Add(this.pictureBox_AutoStartMining); + this.groupBox_Misc.Controls.Add(this.pictureBox_MinimizeToTray); + this.groupBox_Misc.Controls.Add(this.pictureBox_HideMiningWindows); + this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVidia3X); + this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionNVidia2X); + this.groupBox_Misc.Controls.Add(this.checkBox_DisableDetectionAMD); + this.groupBox_Misc.Controls.Add(this.checkBox_NVIDIAP0State); + this.groupBox_Misc.Controls.Add(this.checkBox_AutoScaleBTCValues); + this.groupBox_Misc.Controls.Add(this.checkBox_DisableWindowsErrorReporting); + this.groupBox_Misc.Controls.Add(this.checkBox_StartMiningWhenIdle); + this.groupBox_Misc.Controls.Add(this.checkBox_ShowDriverVersionWarning); + this.groupBox_Misc.Location = new System.Drawing.Point(357, 6); + this.groupBox_Misc.Name = "groupBox_Misc"; + this.groupBox_Misc.Size = new System.Drawing.Size(229, 330); + this.groupBox_Misc.TabIndex = 391; + this.groupBox_Misc.TabStop = false; + this.groupBox_Misc.Text = "Misc:"; + // + // checkBox_AutoStartMining + // + this.checkBox_AutoStartMining.AutoSize = true; + this.checkBox_AutoStartMining.Location = new System.Drawing.Point(6, 19); + this.checkBox_AutoStartMining.Name = "checkBox_AutoStartMining"; + this.checkBox_AutoStartMining.Size = new System.Drawing.Size(102, 17); + this.checkBox_AutoStartMining.TabIndex = 315; + this.checkBox_AutoStartMining.Text = "Autostart Mining"; + this.checkBox_AutoStartMining.UseVisualStyleBackColor = true; + // + // checkBox_HideMiningWindows + // + this.checkBox_HideMiningWindows.AutoSize = true; + this.checkBox_HideMiningWindows.Location = new System.Drawing.Point(6, 39); + this.checkBox_HideMiningWindows.Name = "checkBox_HideMiningWindows"; + this.checkBox_HideMiningWindows.Size = new System.Drawing.Size(123, 17); + this.checkBox_HideMiningWindows.TabIndex = 315; + this.checkBox_HideMiningWindows.Text = "HideMiningWindows"; + this.checkBox_HideMiningWindows.UseVisualStyleBackColor = true; + // + // checkBox_MinimizeToTray + // + this.checkBox_MinimizeToTray.AutoSize = true; + this.checkBox_MinimizeToTray.Location = new System.Drawing.Point(6, 61); + this.checkBox_MinimizeToTray.Name = "checkBox_MinimizeToTray"; + this.checkBox_MinimizeToTray.Size = new System.Drawing.Size(100, 17); + this.checkBox_MinimizeToTray.TabIndex = 316; + this.checkBox_MinimizeToTray.Text = "MinimizeToTray"; + this.checkBox_MinimizeToTray.UseVisualStyleBackColor = true; + // + // checkBox_DisableDetectionNVidia6X + // + this.checkBox_DisableDetectionNVidia6X.AutoSize = true; + this.checkBox_DisableDetectionNVidia6X.Location = new System.Drawing.Point(6, 83); + this.checkBox_DisableDetectionNVidia6X.Name = "checkBox_DisableDetectionNVidia6X"; + this.checkBox_DisableDetectionNVidia6X.Size = new System.Drawing.Size(151, 17); + this.checkBox_DisableDetectionNVidia6X.TabIndex = 317; + this.checkBox_DisableDetectionNVidia6X.Text = "DisableDetectionNVidia6X"; + this.checkBox_DisableDetectionNVidia6X.UseVisualStyleBackColor = true; + // + // checkBox_DisableDetectionNVidia5X + // + this.checkBox_DisableDetectionNVidia5X.AutoSize = true; + this.checkBox_DisableDetectionNVidia5X.Location = new System.Drawing.Point(6, 105); + this.checkBox_DisableDetectionNVidia5X.Name = "checkBox_DisableDetectionNVidia5X"; + this.checkBox_DisableDetectionNVidia5X.Size = new System.Drawing.Size(151, 17); + this.checkBox_DisableDetectionNVidia5X.TabIndex = 317; + this.checkBox_DisableDetectionNVidia5X.Text = "DisableDetectionNVidia5X"; + this.checkBox_DisableDetectionNVidia5X.UseVisualStyleBackColor = true; + // + // pictureBox_NVIDIAP0State + // + this.pictureBox_NVIDIAP0State.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_NVIDIAP0State.Location = new System.Drawing.Point(205, 281); + this.pictureBox_NVIDIAP0State.Name = "pictureBox_NVIDIAP0State"; + this.pictureBox_NVIDIAP0State.Size = new System.Drawing.Size(18, 18); + this.pictureBox_NVIDIAP0State.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_NVIDIAP0State.TabIndex = 364; + this.pictureBox_NVIDIAP0State.TabStop = false; + // + // pictureBox_DisableWindowsErrorReporting + // + this.pictureBox_DisableWindowsErrorReporting.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DisableWindowsErrorReporting.Location = new System.Drawing.Point(205, 259); + this.pictureBox_DisableWindowsErrorReporting.Name = "pictureBox_DisableWindowsErrorReporting"; + this.pictureBox_DisableWindowsErrorReporting.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DisableWindowsErrorReporting.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DisableWindowsErrorReporting.TabIndex = 364; + this.pictureBox_DisableWindowsErrorReporting.TabStop = false; + // + // pictureBox_ShowDriverVersionWarning + // + this.pictureBox_ShowDriverVersionWarning.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_ShowDriverVersionWarning.Location = new System.Drawing.Point(205, 237); + this.pictureBox_ShowDriverVersionWarning.Name = "pictureBox_ShowDriverVersionWarning"; + this.pictureBox_ShowDriverVersionWarning.Size = new System.Drawing.Size(18, 18); + this.pictureBox_ShowDriverVersionWarning.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_ShowDriverVersionWarning.TabIndex = 364; + this.pictureBox_ShowDriverVersionWarning.TabStop = false; + // + // pictureBox_StartMiningWhenIdle + // + this.pictureBox_StartMiningWhenIdle.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_StartMiningWhenIdle.Location = new System.Drawing.Point(205, 215); + this.pictureBox_StartMiningWhenIdle.Name = "pictureBox_StartMiningWhenIdle"; + this.pictureBox_StartMiningWhenIdle.Size = new System.Drawing.Size(18, 18); + this.pictureBox_StartMiningWhenIdle.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_StartMiningWhenIdle.TabIndex = 364; + this.pictureBox_StartMiningWhenIdle.TabStop = false; + // + // pictureBox_AutoScaleBTCValues + // + this.pictureBox_AutoScaleBTCValues.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_AutoScaleBTCValues.Location = new System.Drawing.Point(205, 193); + this.pictureBox_AutoScaleBTCValues.Name = "pictureBox_AutoScaleBTCValues"; + this.pictureBox_AutoScaleBTCValues.Size = new System.Drawing.Size(18, 18); + this.pictureBox_AutoScaleBTCValues.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_AutoScaleBTCValues.TabIndex = 364; + this.pictureBox_AutoScaleBTCValues.TabStop = false; + // + // pictureBox_DisableDetectionAMD + // + this.pictureBox_DisableDetectionAMD.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DisableDetectionAMD.Location = new System.Drawing.Point(205, 171); + this.pictureBox_DisableDetectionAMD.Name = "pictureBox_DisableDetectionAMD"; + this.pictureBox_DisableDetectionAMD.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DisableDetectionAMD.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DisableDetectionAMD.TabIndex = 364; + this.pictureBox_DisableDetectionAMD.TabStop = false; + // + // pictureBox_DisableDetectionNVidia2X + // + this.pictureBox_DisableDetectionNVidia2X.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DisableDetectionNVidia2X.Location = new System.Drawing.Point(205, 149); + this.pictureBox_DisableDetectionNVidia2X.Name = "pictureBox_DisableDetectionNVidia2X"; + this.pictureBox_DisableDetectionNVidia2X.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DisableDetectionNVidia2X.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DisableDetectionNVidia2X.TabIndex = 364; + this.pictureBox_DisableDetectionNVidia2X.TabStop = false; + // + // pictureBox_DisableDetectionNVidia3X + // + this.pictureBox_DisableDetectionNVidia3X.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DisableDetectionNVidia3X.Location = new System.Drawing.Point(205, 127); + this.pictureBox_DisableDetectionNVidia3X.Name = "pictureBox_DisableDetectionNVidia3X"; + this.pictureBox_DisableDetectionNVidia3X.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DisableDetectionNVidia3X.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DisableDetectionNVidia3X.TabIndex = 364; + this.pictureBox_DisableDetectionNVidia3X.TabStop = false; + // + // pictureBox_DisableDetectionNVidia5X + // + this.pictureBox_DisableDetectionNVidia5X.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DisableDetectionNVidia5X.Location = new System.Drawing.Point(205, 105); + this.pictureBox_DisableDetectionNVidia5X.Name = "pictureBox_DisableDetectionNVidia5X"; + this.pictureBox_DisableDetectionNVidia5X.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DisableDetectionNVidia5X.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DisableDetectionNVidia5X.TabIndex = 364; + this.pictureBox_DisableDetectionNVidia5X.TabStop = false; + // + // pictureBox_DisableDetectionNVidia6X + // + this.pictureBox_DisableDetectionNVidia6X.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DisableDetectionNVidia6X.Location = new System.Drawing.Point(205, 83); + this.pictureBox_DisableDetectionNVidia6X.Name = "pictureBox_DisableDetectionNVidia6X"; + this.pictureBox_DisableDetectionNVidia6X.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DisableDetectionNVidia6X.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DisableDetectionNVidia6X.TabIndex = 364; + this.pictureBox_DisableDetectionNVidia6X.TabStop = false; + // + // pictureBox_AutoStartMining + // + this.pictureBox_AutoStartMining.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_AutoStartMining.Location = new System.Drawing.Point(205, 19); + this.pictureBox_AutoStartMining.Name = "pictureBox_AutoStartMining"; + this.pictureBox_AutoStartMining.Size = new System.Drawing.Size(18, 18); + this.pictureBox_AutoStartMining.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_AutoStartMining.TabIndex = 364; + this.pictureBox_AutoStartMining.TabStop = false; + // + // pictureBox_MinimizeToTray + // + this.pictureBox_MinimizeToTray.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_MinimizeToTray.Location = new System.Drawing.Point(205, 61); + this.pictureBox_MinimizeToTray.Name = "pictureBox_MinimizeToTray"; + this.pictureBox_MinimizeToTray.Size = new System.Drawing.Size(18, 18); + this.pictureBox_MinimizeToTray.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_MinimizeToTray.TabIndex = 364; + this.pictureBox_MinimizeToTray.TabStop = false; + // + // pictureBox_HideMiningWindows + // + this.pictureBox_HideMiningWindows.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_HideMiningWindows.Location = new System.Drawing.Point(205, 39); + this.pictureBox_HideMiningWindows.Name = "pictureBox_HideMiningWindows"; + this.pictureBox_HideMiningWindows.Size = new System.Drawing.Size(18, 18); + this.pictureBox_HideMiningWindows.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_HideMiningWindows.TabIndex = 364; + this.pictureBox_HideMiningWindows.TabStop = false; + // + // checkBox_DisableDetectionNVidia3X + // + this.checkBox_DisableDetectionNVidia3X.AutoSize = true; + this.checkBox_DisableDetectionNVidia3X.Location = new System.Drawing.Point(6, 127); + this.checkBox_DisableDetectionNVidia3X.Name = "checkBox_DisableDetectionNVidia3X"; + this.checkBox_DisableDetectionNVidia3X.Size = new System.Drawing.Size(151, 17); + this.checkBox_DisableDetectionNVidia3X.TabIndex = 318; + this.checkBox_DisableDetectionNVidia3X.Text = "DisableDetectionNVidia3X"; + this.checkBox_DisableDetectionNVidia3X.UseVisualStyleBackColor = true; + // + // checkBox_DisableDetectionNVidia2X + // + this.checkBox_DisableDetectionNVidia2X.AutoSize = true; + this.checkBox_DisableDetectionNVidia2X.Location = new System.Drawing.Point(6, 149); + this.checkBox_DisableDetectionNVidia2X.Name = "checkBox_DisableDetectionNVidia2X"; + this.checkBox_DisableDetectionNVidia2X.Size = new System.Drawing.Size(151, 17); + this.checkBox_DisableDetectionNVidia2X.TabIndex = 319; + this.checkBox_DisableDetectionNVidia2X.Text = "DisableDetectionNVidia2X"; + this.checkBox_DisableDetectionNVidia2X.UseVisualStyleBackColor = true; + // + // checkBox_DisableDetectionAMD + // + this.checkBox_DisableDetectionAMD.AutoSize = true; + this.checkBox_DisableDetectionAMD.Location = new System.Drawing.Point(6, 171); + this.checkBox_DisableDetectionAMD.Name = "checkBox_DisableDetectionAMD"; + this.checkBox_DisableDetectionAMD.Size = new System.Drawing.Size(131, 17); + this.checkBox_DisableDetectionAMD.TabIndex = 320; + this.checkBox_DisableDetectionAMD.Text = "DisableDetectionAMD"; + this.checkBox_DisableDetectionAMD.UseVisualStyleBackColor = true; + // + // checkBox_NVIDIAP0State + // + this.checkBox_NVIDIAP0State.AutoSize = true; + this.checkBox_NVIDIAP0State.Location = new System.Drawing.Point(6, 281); + this.checkBox_NVIDIAP0State.Name = "checkBox_NVIDIAP0State"; + this.checkBox_NVIDIAP0State.Size = new System.Drawing.Size(100, 17); + this.checkBox_NVIDIAP0State.TabIndex = 326; + this.checkBox_NVIDIAP0State.Text = "NVIDIAP0State"; + this.checkBox_NVIDIAP0State.UseVisualStyleBackColor = true; + // + // checkBox_AutoScaleBTCValues + // + this.checkBox_AutoScaleBTCValues.AutoSize = true; + this.checkBox_AutoScaleBTCValues.Location = new System.Drawing.Point(6, 193); + this.checkBox_AutoScaleBTCValues.Name = "checkBox_AutoScaleBTCValues"; + this.checkBox_AutoScaleBTCValues.Size = new System.Drawing.Size(128, 17); + this.checkBox_AutoScaleBTCValues.TabIndex = 321; + this.checkBox_AutoScaleBTCValues.Text = "AutoScaleBTCValues"; + this.checkBox_AutoScaleBTCValues.UseVisualStyleBackColor = true; + // + // checkBox_DisableWindowsErrorReporting + // + this.checkBox_DisableWindowsErrorReporting.AutoSize = true; + this.checkBox_DisableWindowsErrorReporting.Location = new System.Drawing.Point(6, 259); + this.checkBox_DisableWindowsErrorReporting.Name = "checkBox_DisableWindowsErrorReporting"; + this.checkBox_DisableWindowsErrorReporting.Size = new System.Drawing.Size(173, 17); + this.checkBox_DisableWindowsErrorReporting.TabIndex = 324; + this.checkBox_DisableWindowsErrorReporting.Text = "DisableWindowsErrorReporting"; + this.checkBox_DisableWindowsErrorReporting.UseVisualStyleBackColor = true; + // + // checkBox_StartMiningWhenIdle + // + this.checkBox_StartMiningWhenIdle.AutoSize = true; + this.checkBox_StartMiningWhenIdle.Location = new System.Drawing.Point(6, 215); + this.checkBox_StartMiningWhenIdle.Name = "checkBox_StartMiningWhenIdle"; + this.checkBox_StartMiningWhenIdle.Size = new System.Drawing.Size(125, 17); + this.checkBox_StartMiningWhenIdle.TabIndex = 322; + this.checkBox_StartMiningWhenIdle.Text = "StartMiningWhenIdle"; + this.checkBox_StartMiningWhenIdle.UseVisualStyleBackColor = true; + // + // checkBox_ShowDriverVersionWarning + // + this.checkBox_ShowDriverVersionWarning.AutoSize = true; + this.checkBox_ShowDriverVersionWarning.Location = new System.Drawing.Point(6, 237); + this.checkBox_ShowDriverVersionWarning.Name = "checkBox_ShowDriverVersionWarning"; + this.checkBox_ShowDriverVersionWarning.Size = new System.Drawing.Size(156, 17); + this.checkBox_ShowDriverVersionWarning.TabIndex = 323; + this.checkBox_ShowDriverVersionWarning.Text = "ShowDriverVersionWarning"; + this.checkBox_ShowDriverVersionWarning.UseVisualStyleBackColor = true; + // + // groupBox_Logging + // + this.groupBox_Logging.Controls.Add(this.label_LogMaxFileSize); + this.groupBox_Logging.Controls.Add(this.textBox_LogMaxFileSize); + this.groupBox_Logging.Controls.Add(this.checkBox_LogToFile); + this.groupBox_Logging.Controls.Add(this.pictureBox_DebugConsole); + this.groupBox_Logging.Controls.Add(this.pictureBox_LogMaxFileSize); + this.groupBox_Logging.Controls.Add(this.pictureBox_LogToFile); + this.groupBox_Logging.Controls.Add(this.checkBox_DebugConsole); + this.groupBox_Logging.Location = new System.Drawing.Point(6, 240); + this.groupBox_Logging.Name = "groupBox_Logging"; + this.groupBox_Logging.Size = new System.Drawing.Size(345, 70); + this.groupBox_Logging.TabIndex = 388; + this.groupBox_Logging.TabStop = false; + this.groupBox_Logging.Text = "Logging:"; + // + // label_LogMaxFileSize + // + this.label_LogMaxFileSize.AutoSize = true; + this.label_LogMaxFileSize.Location = new System.Drawing.Point(175, 19); + this.label_LogMaxFileSize.Name = "label_LogMaxFileSize"; + this.label_LogMaxFileSize.Size = new System.Drawing.Size(84, 13); + this.label_LogMaxFileSize.TabIndex = 357; + this.label_LogMaxFileSize.Text = "LogMaxFileSize:"; + // + // textBox_LogMaxFileSize + // + this.textBox_LogMaxFileSize.Location = new System.Drawing.Point(175, 40); + this.textBox_LogMaxFileSize.Name = "textBox_LogMaxFileSize"; + this.textBox_LogMaxFileSize.Size = new System.Drawing.Size(160, 20); + this.textBox_LogMaxFileSize.TabIndex = 334; + // + // checkBox_LogToFile + // + this.checkBox_LogToFile.AutoSize = true; + this.checkBox_LogToFile.Location = new System.Drawing.Point(6, 19); + this.checkBox_LogToFile.Name = "checkBox_LogToFile"; + this.checkBox_LogToFile.Size = new System.Drawing.Size(72, 17); + this.checkBox_LogToFile.TabIndex = 327; + this.checkBox_LogToFile.Text = "Log to file"; + this.checkBox_LogToFile.UseVisualStyleBackColor = true; + // + // pictureBox_DebugConsole + // + this.pictureBox_DebugConsole.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DebugConsole.Location = new System.Drawing.Point(130, 42); + this.pictureBox_DebugConsole.Name = "pictureBox_DebugConsole"; + this.pictureBox_DebugConsole.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DebugConsole.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DebugConsole.TabIndex = 364; + this.pictureBox_DebugConsole.TabStop = false; + // + // pictureBox_LogMaxFileSize + // + this.pictureBox_LogMaxFileSize.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_LogMaxFileSize.Location = new System.Drawing.Point(317, 19); + this.pictureBox_LogMaxFileSize.Name = "pictureBox_LogMaxFileSize"; + this.pictureBox_LogMaxFileSize.Size = new System.Drawing.Size(18, 18); + this.pictureBox_LogMaxFileSize.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_LogMaxFileSize.TabIndex = 364; + this.pictureBox_LogMaxFileSize.TabStop = false; + // + // pictureBox_LogToFile + // + this.pictureBox_LogToFile.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_LogToFile.Location = new System.Drawing.Point(130, 19); + this.pictureBox_LogToFile.Name = "pictureBox_LogToFile"; + this.pictureBox_LogToFile.Size = new System.Drawing.Size(18, 18); + this.pictureBox_LogToFile.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_LogToFile.TabIndex = 364; + this.pictureBox_LogToFile.TabStop = false; + // + // checkBox_DebugConsole + // + this.checkBox_DebugConsole.AutoSize = true; + this.checkBox_DebugConsole.Location = new System.Drawing.Point(6, 42); + this.checkBox_DebugConsole.Name = "checkBox_DebugConsole"; + this.checkBox_DebugConsole.Size = new System.Drawing.Size(96, 17); + this.checkBox_DebugConsole.TabIndex = 313; + this.checkBox_DebugConsole.Text = "DebugConsole"; + this.checkBox_DebugConsole.UseVisualStyleBackColor = true; + // + // groupBox_Main + // + this.groupBox_Main.Controls.Add(this.pictureBox_WorkerName); + this.groupBox_Main.Controls.Add(this.pictureBox_MinProfit); + this.groupBox_Main.Controls.Add(this.pictureBox_ServiceLocation); + this.groupBox_Main.Controls.Add(this.pictureBox_Info_BitcoinAddress); + this.groupBox_Main.Controls.Add(this.textBox_MinProfit); + this.groupBox_Main.Controls.Add(this.label_BitcoinAddress); + this.groupBox_Main.Controls.Add(this.label_MinProfit); + this.groupBox_Main.Controls.Add(this.label_WorkerName); + this.groupBox_Main.Controls.Add(this.label_ServiceLocation); + this.groupBox_Main.Controls.Add(this.comboBox_ServiceLocation); + this.groupBox_Main.Controls.Add(this.textBox_BitcoinAddress); + this.groupBox_Main.Controls.Add(this.textBox_WorkerName); + this.groupBox_Main.Location = new System.Drawing.Point(6, 6); + this.groupBox_Main.Name = "groupBox_Main"; + this.groupBox_Main.Size = new System.Drawing.Size(345, 152); + this.groupBox_Main.TabIndex = 386; + this.groupBox_Main.TabStop = false; + this.groupBox_Main.Text = "Main:"; + // + // pictureBox_WorkerName + // + this.pictureBox_WorkerName.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_WorkerName.Location = new System.Drawing.Point(130, 59); + this.pictureBox_WorkerName.Name = "pictureBox_WorkerName"; + this.pictureBox_WorkerName.Size = new System.Drawing.Size(18, 18); + this.pictureBox_WorkerName.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_WorkerName.TabIndex = 364; + this.pictureBox_WorkerName.TabStop = false; + // + // pictureBox_MinProfit + // + this.pictureBox_MinProfit.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_MinProfit.Location = new System.Drawing.Point(229, 103); + this.pictureBox_MinProfit.Name = "pictureBox_MinProfit"; + this.pictureBox_MinProfit.Size = new System.Drawing.Size(18, 18); + this.pictureBox_MinProfit.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_MinProfit.TabIndex = 364; + this.pictureBox_MinProfit.TabStop = false; + // + // pictureBox_ServiceLocation + // + this.pictureBox_ServiceLocation.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_ServiceLocation.Location = new System.Drawing.Point(302, 59); + this.pictureBox_ServiceLocation.Name = "pictureBox_ServiceLocation"; + this.pictureBox_ServiceLocation.Size = new System.Drawing.Size(18, 18); + this.pictureBox_ServiceLocation.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_ServiceLocation.TabIndex = 364; + this.pictureBox_ServiceLocation.TabStop = false; + // + // pictureBox_Info_BitcoinAddress + // + this.pictureBox_Info_BitcoinAddress.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_Info_BitcoinAddress.Location = new System.Drawing.Point(308, 16); + this.pictureBox_Info_BitcoinAddress.Name = "pictureBox_Info_BitcoinAddress"; + this.pictureBox_Info_BitcoinAddress.Size = new System.Drawing.Size(18, 18); + this.pictureBox_Info_BitcoinAddress.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_Info_BitcoinAddress.TabIndex = 364; + this.pictureBox_Info_BitcoinAddress.TabStop = false; + // + // textBox_MinProfit + // + this.textBox_MinProfit.Location = new System.Drawing.Point(10, 123); + this.textBox_MinProfit.Name = "textBox_MinProfit"; + this.textBox_MinProfit.Size = new System.Drawing.Size(237, 20); + this.textBox_MinProfit.TabIndex = 334; + // + // label_BitcoinAddress + // + this.label_BitcoinAddress.AutoSize = true; + this.label_BitcoinAddress.Location = new System.Drawing.Point(10, 16); + this.label_BitcoinAddress.Name = "label_BitcoinAddress"; + this.label_BitcoinAddress.Size = new System.Drawing.Size(80, 13); + this.label_BitcoinAddress.TabIndex = 355; + this.label_BitcoinAddress.Text = "BitcoinAddress:"; + // + // label_MinProfit + // + this.label_MinProfit.AutoSize = true; + this.label_MinProfit.Location = new System.Drawing.Point(10, 103); + this.label_MinProfit.Name = "label_MinProfit"; + this.label_MinProfit.Size = new System.Drawing.Size(115, 13); + this.label_MinProfit.TabIndex = 357; + this.label_MinProfit.Text = "Minimum Profit ($/day):"; + // + // label_WorkerName + // + this.label_WorkerName.AutoSize = true; + this.label_WorkerName.Location = new System.Drawing.Point(10, 59); + this.label_WorkerName.Name = "label_WorkerName"; + this.label_WorkerName.Size = new System.Drawing.Size(73, 13); + this.label_WorkerName.TabIndex = 354; + this.label_WorkerName.Text = "WorkerName:"; + // + // label_ServiceLocation + // + this.label_ServiceLocation.AutoSize = true; + this.label_ServiceLocation.Location = new System.Drawing.Point(160, 59); + this.label_ServiceLocation.Name = "label_ServiceLocation"; + this.label_ServiceLocation.Size = new System.Drawing.Size(87, 13); + this.label_ServiceLocation.TabIndex = 363; + this.label_ServiceLocation.Text = "ServiceLocation:"; + // + // comboBox_ServiceLocation + // + this.comboBox_ServiceLocation.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_ServiceLocation.FormattingEnabled = true; + this.comboBox_ServiceLocation.Items.AddRange(new object[] { + "Europe - Amsterdam", + "USA - San Jose", + "China - Hong Kong", + "Japan - Tokyo"}); + this.comboBox_ServiceLocation.Location = new System.Drawing.Point(160, 80); + this.comboBox_ServiceLocation.Name = "comboBox_ServiceLocation"; + this.comboBox_ServiceLocation.Size = new System.Drawing.Size(160, 21); + this.comboBox_ServiceLocation.TabIndex = 330; + // + // textBox_BitcoinAddress + // + this.textBox_BitcoinAddress.Location = new System.Drawing.Point(10, 36); + this.textBox_BitcoinAddress.Name = "textBox_BitcoinAddress"; + this.textBox_BitcoinAddress.Size = new System.Drawing.Size(316, 20); + this.textBox_BitcoinAddress.TabIndex = 329; + // + // textBox_WorkerName + // + this.textBox_WorkerName.Location = new System.Drawing.Point(10, 80); + this.textBox_WorkerName.Name = "textBox_WorkerName"; + this.textBox_WorkerName.Size = new System.Drawing.Size(139, 20); + this.textBox_WorkerName.TabIndex = 339; + // + // groupBox_Localization + // + this.groupBox_Localization.Controls.Add(this.label_Language); + this.groupBox_Localization.Controls.Add(this.pictureBox5); + this.groupBox_Localization.Controls.Add(this.pictureBox_displayCurrency); + this.groupBox_Localization.Controls.Add(this.pictureBox_Language); + this.groupBox_Localization.Controls.Add(this.comboBox_Language); + this.groupBox_Localization.Controls.Add(this.currencyConverterCombobox); + this.groupBox_Localization.Controls.Add(this.label_displayCurrency); + this.groupBox_Localization.Location = new System.Drawing.Point(6, 164); + this.groupBox_Localization.Name = "groupBox_Localization"; + this.groupBox_Localization.Size = new System.Drawing.Size(345, 70); + this.groupBox_Localization.TabIndex = 385; + this.groupBox_Localization.TabStop = false; + this.groupBox_Localization.Text = "Localization:"; + // + // label_Language + // + this.label_Language.AutoSize = true; + this.label_Language.Location = new System.Drawing.Point(6, 16); + this.label_Language.Name = "label_Language"; + this.label_Language.Size = new System.Drawing.Size(58, 13); + this.label_Language.TabIndex = 358; + this.label_Language.Text = "Language:"; + // + // pictureBox5 + // + this.pictureBox5.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox5.Location = new System.Drawing.Point(-59, 59); + this.pictureBox5.Name = "pictureBox5"; + this.pictureBox5.Size = new System.Drawing.Size(18, 18); + this.pictureBox5.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox5.TabIndex = 364; + this.pictureBox5.TabStop = false; + // + // pictureBox_displayCurrency + // + this.pictureBox_displayCurrency.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_displayCurrency.Location = new System.Drawing.Point(315, 16); + this.pictureBox_displayCurrency.Name = "pictureBox_displayCurrency"; + this.pictureBox_displayCurrency.Size = new System.Drawing.Size(18, 18); + this.pictureBox_displayCurrency.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_displayCurrency.TabIndex = 364; + this.pictureBox_displayCurrency.TabStop = false; + // + // pictureBox_Language + // + this.pictureBox_Language.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_Language.Location = new System.Drawing.Point(178, 16); + this.pictureBox_Language.Name = "pictureBox_Language"; + this.pictureBox_Language.Size = new System.Drawing.Size(18, 18); + this.pictureBox_Language.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_Language.TabIndex = 364; + this.pictureBox_Language.TabStop = false; + // + // comboBox_Language + // + this.comboBox_Language.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_Language.FormattingEnabled = true; + this.comboBox_Language.Location = new System.Drawing.Point(6, 36); + this.comboBox_Language.Name = "comboBox_Language"; + this.comboBox_Language.Size = new System.Drawing.Size(190, 21); + this.comboBox_Language.TabIndex = 328; + // + // currencyConverterCombobox + // + this.currencyConverterCombobox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.currencyConverterCombobox.FormattingEnabled = true; + this.currencyConverterCombobox.Items.AddRange(new object[] { + "AUD", + "BGN", + "BRL", + "CAD", + "CHF", + "CNY", + "CZK", + "DKK", + "EUR", + "GBP", + "HKD", + "HRK", + "HUF", + "IDR", + "ILS", + "INR", + "JPY", + "KRW", + "MXN", + "MYR", + "NOK", + "NZD", + "PHP", + "PLN", + "RON", + "RUB", + "SEK", + "SGD", + "THB", + "TRY", + "USD", + "ZAR"}); + this.currencyConverterCombobox.Location = new System.Drawing.Point(212, 36); + this.currencyConverterCombobox.Name = "currencyConverterCombobox"; + this.currencyConverterCombobox.Size = new System.Drawing.Size(121, 21); + this.currencyConverterCombobox.Sorted = true; + this.currencyConverterCombobox.TabIndex = 381; + this.currencyConverterCombobox.SelectedIndexChanged += new System.EventHandler(this.currencyConverterCombobox_SelectedIndexChanged); + // + // label_displayCurrency + // + this.label_displayCurrency.AutoSize = true; + this.label_displayCurrency.Location = new System.Drawing.Point(212, 16); + this.label_displayCurrency.Name = "label_displayCurrency"; + this.label_displayCurrency.Size = new System.Drawing.Size(89, 13); + this.label_displayCurrency.TabIndex = 382; + this.label_displayCurrency.Text = "Display Currency:"; + // + // tabPageAdvanced + // + this.tabPageAdvanced.Controls.Add(this.groupBox_Miners); + this.tabPageAdvanced.Controls.Add(this.groupBoxBenchmarkTimeLimits); + this.tabPageAdvanced.Location = new System.Drawing.Point(4, 22); + this.tabPageAdvanced.Name = "tabPageAdvanced"; + this.tabPageAdvanced.Padding = new System.Windows.Forms.Padding(3); + this.tabPageAdvanced.Size = new System.Drawing.Size(604, 354); + this.tabPageAdvanced.TabIndex = 2; + this.tabPageAdvanced.Text = "Advanced"; + this.tabPageAdvanced.UseVisualStyleBackColor = true; + // + // groupBox_Miners + // + this.groupBox_Miners.Controls.Add(this.pictureBox_SwitchMinSecondsFixed); + this.groupBox_Miners.Controls.Add(this.pictureBox_MinerRestartDelayMS); + this.groupBox_Miners.Controls.Add(this.pictureBox_APIBindPortStart); + this.groupBox_Miners.Controls.Add(this.pictureBox_SwitchMinSecondsDynamic); + this.groupBox_Miners.Controls.Add(this.pictureBox_ethminerDefaultBlockHeight); + this.groupBox_Miners.Controls.Add(this.pictureBox_DagGeneration); + this.groupBox_Miners.Controls.Add(this.pictureBox_CPU0_ForceCPUExtension); + this.groupBox_Miners.Controls.Add(this.pictureBox_MinerAPIQueryInterval); + this.groupBox_Miners.Controls.Add(this.pictureBox_SwitchMinSecondsAMD); + this.groupBox_Miners.Controls.Add(this.pictureBox_MinIdleSeconds); + this.groupBox_Miners.Controls.Add(this.comboBox_DagLoadMode); + this.groupBox_Miners.Controls.Add(this.label_DagGeneration); + this.groupBox_Miners.Controls.Add(this.comboBox_CPU0_ForceCPUExtension); + this.groupBox_Miners.Controls.Add(this.label_CPU0_ForceCPUExtension); + this.groupBox_Miners.Controls.Add(this.label_MinIdleSeconds); + this.groupBox_Miners.Controls.Add(this.label_SwitchMinSecondsFixed); + this.groupBox_Miners.Controls.Add(this.label_SwitchMinSecondsDynamic); + this.groupBox_Miners.Controls.Add(this.label_MinerAPIQueryInterval); + this.groupBox_Miners.Controls.Add(this.label_MinerRestartDelayMS); + this.groupBox_Miners.Controls.Add(this.textBox_SwitchMinSecondsAMD); + this.groupBox_Miners.Controls.Add(this.label_APIBindPortStart); + this.groupBox_Miners.Controls.Add(this.textBox_ethminerDefaultBlockHeight); + this.groupBox_Miners.Controls.Add(this.label_ethminerDefaultBlockHeight); + this.groupBox_Miners.Controls.Add(this.textBox_APIBindPortStart); + this.groupBox_Miners.Controls.Add(this.label_SwitchMinSecondsAMD); + this.groupBox_Miners.Controls.Add(this.textBox_MinIdleSeconds); + this.groupBox_Miners.Controls.Add(this.textBox_SwitchMinSecondsFixed); + this.groupBox_Miners.Controls.Add(this.textBox_SwitchMinSecondsDynamic); + this.groupBox_Miners.Controls.Add(this.textBox_MinerRestartDelayMS); + this.groupBox_Miners.Controls.Add(this.textBox_MinerAPIQueryInterval); + this.groupBox_Miners.Location = new System.Drawing.Point(6, 6); + this.groupBox_Miners.Name = "groupBox_Miners"; + this.groupBox_Miners.Size = new System.Drawing.Size(592, 192); + this.groupBox_Miners.TabIndex = 389; + this.groupBox_Miners.TabStop = false; + this.groupBox_Miners.Text = "Miners:"; + // + // pictureBox_SwitchMinSecondsFixed + // + this.pictureBox_SwitchMinSecondsFixed.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_SwitchMinSecondsFixed.Location = new System.Drawing.Point(563, 15); + this.pictureBox_SwitchMinSecondsFixed.Name = "pictureBox_SwitchMinSecondsFixed"; + this.pictureBox_SwitchMinSecondsFixed.Size = new System.Drawing.Size(18, 18); + this.pictureBox_SwitchMinSecondsFixed.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_SwitchMinSecondsFixed.TabIndex = 385; + this.pictureBox_SwitchMinSecondsFixed.TabStop = false; + // + // pictureBox_MinerRestartDelayMS + // + this.pictureBox_MinerRestartDelayMS.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_MinerRestartDelayMS.Location = new System.Drawing.Point(363, 15); + this.pictureBox_MinerRestartDelayMS.Name = "pictureBox_MinerRestartDelayMS"; + this.pictureBox_MinerRestartDelayMS.Size = new System.Drawing.Size(18, 18); + this.pictureBox_MinerRestartDelayMS.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_MinerRestartDelayMS.TabIndex = 385; + this.pictureBox_MinerRestartDelayMS.TabStop = false; + // + // pictureBox_APIBindPortStart + // + this.pictureBox_APIBindPortStart.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_APIBindPortStart.Location = new System.Drawing.Point(563, 59); + this.pictureBox_APIBindPortStart.Name = "pictureBox_APIBindPortStart"; + this.pictureBox_APIBindPortStart.Size = new System.Drawing.Size(18, 18); + this.pictureBox_APIBindPortStart.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_APIBindPortStart.TabIndex = 385; + this.pictureBox_APIBindPortStart.TabStop = false; + // + // pictureBox_SwitchMinSecondsDynamic + // + this.pictureBox_SwitchMinSecondsDynamic.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_SwitchMinSecondsDynamic.Location = new System.Drawing.Point(363, 59); + this.pictureBox_SwitchMinSecondsDynamic.Name = "pictureBox_SwitchMinSecondsDynamic"; + this.pictureBox_SwitchMinSecondsDynamic.Size = new System.Drawing.Size(18, 18); + this.pictureBox_SwitchMinSecondsDynamic.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_SwitchMinSecondsDynamic.TabIndex = 385; + this.pictureBox_SwitchMinSecondsDynamic.TabStop = false; + // + // pictureBox_ethminerDefaultBlockHeight + // + this.pictureBox_ethminerDefaultBlockHeight.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_ethminerDefaultBlockHeight.Location = new System.Drawing.Point(363, 102); + this.pictureBox_ethminerDefaultBlockHeight.Name = "pictureBox_ethminerDefaultBlockHeight"; + this.pictureBox_ethminerDefaultBlockHeight.Size = new System.Drawing.Size(18, 18); + this.pictureBox_ethminerDefaultBlockHeight.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_ethminerDefaultBlockHeight.TabIndex = 385; + this.pictureBox_ethminerDefaultBlockHeight.TabStop = false; + // + // pictureBox_DagGeneration + // + this.pictureBox_DagGeneration.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_DagGeneration.Location = new System.Drawing.Point(363, 146); + this.pictureBox_DagGeneration.Name = "pictureBox_DagGeneration"; + this.pictureBox_DagGeneration.Size = new System.Drawing.Size(18, 18); + this.pictureBox_DagGeneration.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_DagGeneration.TabIndex = 385; + this.pictureBox_DagGeneration.TabStop = false; + // + // pictureBox_CPU0_ForceCPUExtension + // + this.pictureBox_CPU0_ForceCPUExtension.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_CPU0_ForceCPUExtension.Location = new System.Drawing.Point(168, 146); + this.pictureBox_CPU0_ForceCPUExtension.Name = "pictureBox_CPU0_ForceCPUExtension"; + this.pictureBox_CPU0_ForceCPUExtension.Size = new System.Drawing.Size(18, 18); + this.pictureBox_CPU0_ForceCPUExtension.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_CPU0_ForceCPUExtension.TabIndex = 385; + this.pictureBox_CPU0_ForceCPUExtension.TabStop = false; + // + // pictureBox_MinerAPIQueryInterval + // + this.pictureBox_MinerAPIQueryInterval.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_MinerAPIQueryInterval.Location = new System.Drawing.Point(168, 102); + this.pictureBox_MinerAPIQueryInterval.Name = "pictureBox_MinerAPIQueryInterval"; + this.pictureBox_MinerAPIQueryInterval.Size = new System.Drawing.Size(18, 18); + this.pictureBox_MinerAPIQueryInterval.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_MinerAPIQueryInterval.TabIndex = 385; + this.pictureBox_MinerAPIQueryInterval.TabStop = false; + // + // pictureBox_SwitchMinSecondsAMD + // + this.pictureBox_SwitchMinSecondsAMD.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_SwitchMinSecondsAMD.Location = new System.Drawing.Point(168, 59); + this.pictureBox_SwitchMinSecondsAMD.Name = "pictureBox_SwitchMinSecondsAMD"; + this.pictureBox_SwitchMinSecondsAMD.Size = new System.Drawing.Size(18, 18); + this.pictureBox_SwitchMinSecondsAMD.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_SwitchMinSecondsAMD.TabIndex = 385; + this.pictureBox_SwitchMinSecondsAMD.TabStop = false; + // + // pictureBox_MinIdleSeconds + // + this.pictureBox_MinIdleSeconds.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_MinIdleSeconds.Location = new System.Drawing.Point(168, 15); + this.pictureBox_MinIdleSeconds.Name = "pictureBox_MinIdleSeconds"; + this.pictureBox_MinIdleSeconds.Size = new System.Drawing.Size(18, 18); + this.pictureBox_MinIdleSeconds.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_MinIdleSeconds.TabIndex = 385; + this.pictureBox_MinIdleSeconds.TabStop = false; + // + // comboBox_DagLoadMode + // + this.comboBox_DagLoadMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_DagLoadMode.FormattingEnabled = true; + this.comboBox_DagLoadMode.Items.AddRange(new object[] { + "Automatic", + "SSE2", + "AVX", + "AVX2"}); + this.comboBox_DagLoadMode.Location = new System.Drawing.Point(209, 165); + this.comboBox_DagLoadMode.Name = "comboBox_DagLoadMode"; + this.comboBox_DagLoadMode.Size = new System.Drawing.Size(172, 21); + this.comboBox_DagLoadMode.TabIndex = 383; + // + // label_DagGeneration + // + this.label_DagGeneration.AutoSize = true; + this.label_DagGeneration.Location = new System.Drawing.Point(209, 149); + this.label_DagGeneration.Name = "label_DagGeneration"; + this.label_DagGeneration.Size = new System.Drawing.Size(87, 13); + this.label_DagGeneration.TabIndex = 384; + this.label_DagGeneration.Text = "Dag Load Mode:"; + // + // comboBox_CPU0_ForceCPUExtension + // + this.comboBox_CPU0_ForceCPUExtension.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_CPU0_ForceCPUExtension.FormattingEnabled = true; + this.comboBox_CPU0_ForceCPUExtension.Items.AddRange(new object[] { + "Automatic", + "AVX2_AES", + "AVX2", + "AVX_AES", + "AVX", + "AES", + "SSE2"}); + this.comboBox_CPU0_ForceCPUExtension.Location = new System.Drawing.Point(9, 165); + this.comboBox_CPU0_ForceCPUExtension.Name = "comboBox_CPU0_ForceCPUExtension"; + this.comboBox_CPU0_ForceCPUExtension.Size = new System.Drawing.Size(177, 21); + this.comboBox_CPU0_ForceCPUExtension.TabIndex = 379; + this.comboBox_CPU0_ForceCPUExtension.SelectedIndexChanged += new System.EventHandler(this.comboBox_CPU0_ForceCPUExtension_SelectedIndexChanged); + // + // label_CPU0_ForceCPUExtension + // + this.label_CPU0_ForceCPUExtension.AutoSize = true; + this.label_CPU0_ForceCPUExtension.Location = new System.Drawing.Point(9, 149); + this.label_CPU0_ForceCPUExtension.Name = "label_CPU0_ForceCPUExtension"; + this.label_CPU0_ForceCPUExtension.Size = new System.Drawing.Size(105, 13); + this.label_CPU0_ForceCPUExtension.TabIndex = 382; + this.label_CPU0_ForceCPUExtension.Text = "ForceCPUExtension:"; + // + // label_MinIdleSeconds + // + this.label_MinIdleSeconds.AutoSize = true; + this.label_MinIdleSeconds.Location = new System.Drawing.Point(9, 15); + this.label_MinIdleSeconds.Name = "label_MinIdleSeconds"; + this.label_MinIdleSeconds.Size = new System.Drawing.Size(86, 13); + this.label_MinIdleSeconds.TabIndex = 356; + this.label_MinIdleSeconds.Text = "MinIdleSeconds:"; + // + // label_SwitchMinSecondsFixed + // + this.label_SwitchMinSecondsFixed.AutoSize = true; + this.label_SwitchMinSecondsFixed.Location = new System.Drawing.Point(409, 15); + this.label_SwitchMinSecondsFixed.Name = "label_SwitchMinSecondsFixed"; + this.label_SwitchMinSecondsFixed.Size = new System.Drawing.Size(126, 13); + this.label_SwitchMinSecondsFixed.TabIndex = 366; + this.label_SwitchMinSecondsFixed.Text = "SwitchMinSecondsFixed:"; + // + // label_SwitchMinSecondsDynamic + // + this.label_SwitchMinSecondsDynamic.AutoSize = true; + this.label_SwitchMinSecondsDynamic.Location = new System.Drawing.Point(209, 59); + this.label_SwitchMinSecondsDynamic.Name = "label_SwitchMinSecondsDynamic"; + this.label_SwitchMinSecondsDynamic.Size = new System.Drawing.Size(142, 13); + this.label_SwitchMinSecondsDynamic.TabIndex = 378; + this.label_SwitchMinSecondsDynamic.Text = "SwitchMinSecondsDynamic:"; + // + // label_MinerAPIQueryInterval + // + this.label_MinerAPIQueryInterval.AutoSize = true; + this.label_MinerAPIQueryInterval.Location = new System.Drawing.Point(9, 100); + this.label_MinerAPIQueryInterval.Name = "label_MinerAPIQueryInterval"; + this.label_MinerAPIQueryInterval.Size = new System.Drawing.Size(116, 13); + this.label_MinerAPIQueryInterval.TabIndex = 376; + this.label_MinerAPIQueryInterval.Text = "MinerAPIQueryInterval:"; + // + // label_MinerRestartDelayMS + // + this.label_MinerRestartDelayMS.AutoSize = true; + this.label_MinerRestartDelayMS.Location = new System.Drawing.Point(209, 15); + this.label_MinerRestartDelayMS.Name = "label_MinerRestartDelayMS"; + this.label_MinerRestartDelayMS.Size = new System.Drawing.Size(113, 13); + this.label_MinerRestartDelayMS.TabIndex = 375; + this.label_MinerRestartDelayMS.Text = "MinerRestartDelayMS:"; + // + // textBox_SwitchMinSecondsAMD + // + this.textBox_SwitchMinSecondsAMD.Location = new System.Drawing.Point(9, 78); + this.textBox_SwitchMinSecondsAMD.Name = "textBox_SwitchMinSecondsAMD"; + this.textBox_SwitchMinSecondsAMD.Size = new System.Drawing.Size(177, 20); + this.textBox_SwitchMinSecondsAMD.TabIndex = 342; + // + // label_APIBindPortStart + // + this.label_APIBindPortStart.AutoSize = true; + this.label_APIBindPortStart.Location = new System.Drawing.Point(409, 59); + this.label_APIBindPortStart.Name = "label_APIBindPortStart"; + this.label_APIBindPortStart.Size = new System.Drawing.Size(118, 13); + this.label_APIBindPortStart.TabIndex = 357; + this.label_APIBindPortStart.Text = "API Bind port pool start:"; + // + // textBox_ethminerDefaultBlockHeight + // + this.textBox_ethminerDefaultBlockHeight.Location = new System.Drawing.Point(209, 121); + this.textBox_ethminerDefaultBlockHeight.Name = "textBox_ethminerDefaultBlockHeight"; + this.textBox_ethminerDefaultBlockHeight.Size = new System.Drawing.Size(172, 20); + this.textBox_ethminerDefaultBlockHeight.TabIndex = 333; + // + // label_ethminerDefaultBlockHeight + // + this.label_ethminerDefaultBlockHeight.AutoSize = true; + this.label_ethminerDefaultBlockHeight.Location = new System.Drawing.Point(209, 100); + this.label_ethminerDefaultBlockHeight.Name = "label_ethminerDefaultBlockHeight"; + this.label_ethminerDefaultBlockHeight.Size = new System.Drawing.Size(142, 13); + this.label_ethminerDefaultBlockHeight.TabIndex = 361; + this.label_ethminerDefaultBlockHeight.Text = "ethminerDefaultBlockHeight:"; + // + // textBox_APIBindPortStart + // + this.textBox_APIBindPortStart.Location = new System.Drawing.Point(409, 78); + this.textBox_APIBindPortStart.Name = "textBox_APIBindPortStart"; + this.textBox_APIBindPortStart.Size = new System.Drawing.Size(172, 20); + this.textBox_APIBindPortStart.TabIndex = 334; + // + // label_SwitchMinSecondsAMD + // + this.label_SwitchMinSecondsAMD.AutoSize = true; + this.label_SwitchMinSecondsAMD.Location = new System.Drawing.Point(9, 59); + this.label_SwitchMinSecondsAMD.Name = "label_SwitchMinSecondsAMD"; + this.label_SwitchMinSecondsAMD.Size = new System.Drawing.Size(125, 13); + this.label_SwitchMinSecondsAMD.TabIndex = 362; + this.label_SwitchMinSecondsAMD.Text = "SwitchMinSecondsAMD:"; + // + // textBox_MinIdleSeconds + // + this.textBox_MinIdleSeconds.Location = new System.Drawing.Point(9, 33); + this.textBox_MinIdleSeconds.Name = "textBox_MinIdleSeconds"; + this.textBox_MinIdleSeconds.Size = new System.Drawing.Size(177, 20); + this.textBox_MinIdleSeconds.TabIndex = 335; + // + // textBox_SwitchMinSecondsFixed + // + this.textBox_SwitchMinSecondsFixed.Location = new System.Drawing.Point(409, 33); + this.textBox_SwitchMinSecondsFixed.Name = "textBox_SwitchMinSecondsFixed"; + this.textBox_SwitchMinSecondsFixed.Size = new System.Drawing.Size(172, 20); + this.textBox_SwitchMinSecondsFixed.TabIndex = 332; + // + // textBox_SwitchMinSecondsDynamic + // + this.textBox_SwitchMinSecondsDynamic.Location = new System.Drawing.Point(209, 78); + this.textBox_SwitchMinSecondsDynamic.Name = "textBox_SwitchMinSecondsDynamic"; + this.textBox_SwitchMinSecondsDynamic.Size = new System.Drawing.Size(172, 20); + this.textBox_SwitchMinSecondsDynamic.TabIndex = 337; + // + // textBox_MinerRestartDelayMS + // + this.textBox_MinerRestartDelayMS.Location = new System.Drawing.Point(209, 33); + this.textBox_MinerRestartDelayMS.Name = "textBox_MinerRestartDelayMS"; + this.textBox_MinerRestartDelayMS.Size = new System.Drawing.Size(172, 20); + this.textBox_MinerRestartDelayMS.TabIndex = 340; + // + // textBox_MinerAPIQueryInterval + // + this.textBox_MinerAPIQueryInterval.Location = new System.Drawing.Point(9, 121); + this.textBox_MinerAPIQueryInterval.Name = "textBox_MinerAPIQueryInterval"; + this.textBox_MinerAPIQueryInterval.Size = new System.Drawing.Size(177, 20); + this.textBox_MinerAPIQueryInterval.TabIndex = 341; + // + // groupBoxBenchmarkTimeLimits + // + this.groupBoxBenchmarkTimeLimits.Controls.Add(this.benchmarkLimitControlNVIDIA); + this.groupBoxBenchmarkTimeLimits.Controls.Add(this.benchmarkLimitControlCPU); + this.groupBoxBenchmarkTimeLimits.Controls.Add(this.benchmarkLimitControlAMD); + this.groupBoxBenchmarkTimeLimits.Location = new System.Drawing.Point(6, 204); + this.groupBoxBenchmarkTimeLimits.Name = "groupBoxBenchmarkTimeLimits"; + this.groupBoxBenchmarkTimeLimits.Size = new System.Drawing.Size(592, 144); + this.groupBoxBenchmarkTimeLimits.TabIndex = 388; + this.groupBoxBenchmarkTimeLimits.TabStop = false; + this.groupBoxBenchmarkTimeLimits.Text = "Benchmark Time Limits:"; + // + // tabPageDevicesAlgos + // + this.tabPageDevicesAlgos.Controls.Add(this.devicesListViewEnableControl1); + this.tabPageDevicesAlgos.Controls.Add(this.algorithmSettingsControl1); + this.tabPageDevicesAlgos.Controls.Add(this.groupBoxAlgorithmSettings); + this.tabPageDevicesAlgos.Controls.Add(this.buttonAllProfit); + this.tabPageDevicesAlgos.Controls.Add(this.buttonSelectedProfit); + this.tabPageDevicesAlgos.Location = new System.Drawing.Point(4, 22); + this.tabPageDevicesAlgos.Name = "tabPageDevicesAlgos"; + this.tabPageDevicesAlgos.Padding = new System.Windows.Forms.Padding(3); + this.tabPageDevicesAlgos.Size = new System.Drawing.Size(604, 354); + this.tabPageDevicesAlgos.TabIndex = 1; + this.tabPageDevicesAlgos.Text = "Devices/Algorithms"; + this.tabPageDevicesAlgos.UseVisualStyleBackColor = true; + // + // groupBoxAlgorithmSettings + // + this.groupBoxAlgorithmSettings.Controls.Add(this.algorithmsListView1); + this.groupBoxAlgorithmSettings.Location = new System.Drawing.Point(7, 142); + this.groupBoxAlgorithmSettings.Name = "groupBoxAlgorithmSettings"; + this.groupBoxAlgorithmSettings.Size = new System.Drawing.Size(351, 206); + this.groupBoxAlgorithmSettings.TabIndex = 395; + this.groupBoxAlgorithmSettings.TabStop = false; + this.groupBoxAlgorithmSettings.Text = "Algorithm settings for selected device:"; + // + // buttonAllProfit + // + this.buttonAllProfit.Location = new System.Drawing.Point(364, 6); + this.buttonAllProfit.Name = "buttonAllProfit"; + this.buttonAllProfit.Size = new System.Drawing.Size(226, 23); + this.buttonAllProfit.TabIndex = 394; + this.buttonAllProfit.Text = "Check All Profitability"; + this.buttonAllProfit.UseVisualStyleBackColor = true; + this.buttonAllProfit.Click += new System.EventHandler(this.buttonAllProfit_Click); + // + // buttonSelectedProfit + // + this.buttonSelectedProfit.Location = new System.Drawing.Point(364, 35); + this.buttonSelectedProfit.Name = "buttonSelectedProfit"; + this.buttonSelectedProfit.Size = new System.Drawing.Size(226, 23); + this.buttonSelectedProfit.TabIndex = 393; + this.buttonSelectedProfit.Text = "Check Selected Profitability"; + this.buttonSelectedProfit.UseVisualStyleBackColor = true; + this.buttonSelectedProfit.Click += new System.EventHandler(this.buttonSelectedProfit_Click); + // + // buttonSaveClose + // + this.buttonSaveClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonSaveClose.Location = new System.Drawing.Point(371, 397); + this.buttonSaveClose.Name = "buttonSaveClose"; + this.buttonSaveClose.Size = new System.Drawing.Size(110, 23); + this.buttonSaveClose.TabIndex = 44; + this.buttonSaveClose.Text = "&Save and Close"; + this.buttonSaveClose.UseVisualStyleBackColor = true; + this.buttonSaveClose.Click += new System.EventHandler(this.buttonSaveClose_Click); + // + // buttonDefaults + // + this.buttonDefaults.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonDefaults.Location = new System.Drawing.Point(290, 397); + this.buttonDefaults.Name = "buttonDefaults"; + this.buttonDefaults.Size = new System.Drawing.Size(75, 23); + this.buttonDefaults.TabIndex = 43; + this.buttonDefaults.Text = "&Defaults"; + this.buttonDefaults.UseVisualStyleBackColor = true; + this.buttonDefaults.Click += new System.EventHandler(this.buttonDefaults_Click); + // + // buttonCloseNoSave + // + this.buttonCloseNoSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCloseNoSave.Location = new System.Drawing.Point(487, 397); + this.buttonCloseNoSave.Name = "buttonCloseNoSave"; + this.buttonCloseNoSave.Size = new System.Drawing.Size(135, 23); + this.buttonCloseNoSave.TabIndex = 45; + this.buttonCloseNoSave.Text = "&Close without Saving"; + this.buttonCloseNoSave.UseVisualStyleBackColor = true; + this.buttonCloseNoSave.Click += new System.EventHandler(this.buttonCloseNoSave_Click); + // +<<<<<<< HEAD +======= + // benchmarkLimitControlNVIDIA + // + this.benchmarkLimitControlNVIDIA.GroupName = "NVIDIA"; + this.benchmarkLimitControlNVIDIA.Location = new System.Drawing.Point(9, 17); + this.benchmarkLimitControlNVIDIA.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); + this.benchmarkLimitControlNVIDIA.Name = "benchmarkLimitControlNVIDIA"; + this.benchmarkLimitControlNVIDIA.Size = new System.Drawing.Size(177, 121); + this.benchmarkLimitControlNVIDIA.TabIndex = 4; + this.benchmarkLimitControlNVIDIA.TimeLimits = null; + // + // benchmarkLimitControlCPU + // + this.benchmarkLimitControlCPU.GroupName = "CPU"; + this.benchmarkLimitControlCPU.Location = new System.Drawing.Point(209, 17); + this.benchmarkLimitControlCPU.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); + this.benchmarkLimitControlCPU.Name = "benchmarkLimitControlCPU"; + this.benchmarkLimitControlCPU.Size = new System.Drawing.Size(177, 121); + this.benchmarkLimitControlCPU.TabIndex = 3; + this.benchmarkLimitControlCPU.TimeLimits = null; + // + // benchmarkLimitControlAMD + // + this.benchmarkLimitControlAMD.GroupName = "AMD"; + this.benchmarkLimitControlAMD.Location = new System.Drawing.Point(409, 17); + this.benchmarkLimitControlAMD.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1); + this.benchmarkLimitControlAMD.Name = "benchmarkLimitControlAMD"; + this.benchmarkLimitControlAMD.Size = new System.Drawing.Size(177, 121); + this.benchmarkLimitControlAMD.TabIndex = 5; + this.benchmarkLimitControlAMD.TimeLimits = null; + // + // devicesListViewEnableControl1 + // + this.devicesListViewEnableControl1.AutoSaveChange = true; + this.devicesListViewEnableControl1.BenchmarkCalculation = null; + this.devicesListViewEnableControl1.FirstColumnText = "Enabled"; + this.devicesListViewEnableControl1.IsInBenchmark = false; + this.devicesListViewEnableControl1.IsMining = false; + this.devicesListViewEnableControl1.Location = new System.Drawing.Point(6, 6); + this.devicesListViewEnableControl1.Name = "devicesListViewEnableControl1"; + this.devicesListViewEnableControl1.SaveToGeneralConfig = false; + this.devicesListViewEnableControl1.SetAllEnabled = false; + this.devicesListViewEnableControl1.Size = new System.Drawing.Size(352, 130); + this.devicesListViewEnableControl1.TabIndex = 397; + // + // algorithmSettingsControl1 + // + this.algorithmSettingsControl1.Location = new System.Drawing.Point(363, 64); + this.algorithmSettingsControl1.Name = "algorithmSettingsControl1"; + this.algorithmSettingsControl1.Size = new System.Drawing.Size(238, 278); + this.algorithmSettingsControl1.TabIndex = 396; + // + // algorithmsListView1 + // + this.algorithmsListView1.BenchmarkCalculation = null; + this.algorithmsListView1.ComunicationInterface = null; + this.algorithmsListView1.IsInBenchmark = false; + this.algorithmsListView1.Location = new System.Drawing.Point(6, 15); + this.algorithmsListView1.Name = "algorithmsListView1"; + this.algorithmsListView1.Size = new System.Drawing.Size(339, 191); + this.algorithmsListView1.TabIndex = 2; + // + // checkBox_AMD_DisableAMDTempControl + // + this.checkBox_AMD_DisableAMDTempControl.AutoSize = true; + this.checkBox_AMD_DisableAMDTempControl.Location = new System.Drawing.Point(6, 303); + this.checkBox_AMD_DisableAMDTempControl.Name = "checkBox_AMD_DisableAMDTempControl"; + this.checkBox_AMD_DisableAMDTempControl.Size = new System.Drawing.Size(145, 17); + this.checkBox_AMD_DisableAMDTempControl.TabIndex = 388; + this.checkBox_AMD_DisableAMDTempControl.Text = "DisableAMDTempControl"; + this.checkBox_AMD_DisableAMDTempControl.UseVisualStyleBackColor = true; + // + // pictureBox_AMD_DisableAMDTempControl + // + this.pictureBox_AMD_DisableAMDTempControl.Image = global::NiceHashMiner.Properties.Resources.info_black_18; + this.pictureBox_AMD_DisableAMDTempControl.Location = new System.Drawing.Point(205, 303); + this.pictureBox_AMD_DisableAMDTempControl.Name = "pictureBox_AMD_DisableAMDTempControl"; + this.pictureBox_AMD_DisableAMDTempControl.Size = new System.Drawing.Size(18, 18); + this.pictureBox_AMD_DisableAMDTempControl.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.pictureBox_AMD_DisableAMDTempControl.TabIndex = 387; + this.pictureBox_AMD_DisableAMDTempControl.TabStop = false; + // +>>>>>>> ExtraLaunchParamsRefactor + // Form_Settings + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(634, 432); + this.Controls.Add(this.buttonDefaults); + this.Controls.Add(this.buttonSaveClose); + this.Controls.Add(this.tabControlGeneral); + this.Controls.Add(this.buttonCloseNoSave); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "Form_Settings"; + this.Text = "Settings"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormSettings_FormClosing); + this.Resize += new System.EventHandler(this.Form_Settings_Resize); + this.tabControlGeneral.ResumeLayout(false); + this.tabPageGeneral.ResumeLayout(false); + this.groupBox_Misc.ResumeLayout(false); + this.groupBox_Misc.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_NVIDIAP0State)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableWindowsErrorReporting)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ShowDriverVersionWarning)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_StartMiningWhenIdle)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AutoScaleBTCValues)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionAMD)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia2X)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia3X)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia5X)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DisableDetectionNVidia6X)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AutoStartMining)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinimizeToTray)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_HideMiningWindows)).EndInit(); + this.groupBox_Logging.ResumeLayout(false); + this.groupBox_Logging.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DebugConsole)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_LogMaxFileSize)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_LogToFile)).EndInit(); + this.groupBox_Main.ResumeLayout(false); + this.groupBox_Main.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_WorkerName)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinProfit)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ServiceLocation)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_Info_BitcoinAddress)).EndInit(); + this.groupBox_Localization.ResumeLayout(false); + this.groupBox_Localization.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_displayCurrency)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_Language)).EndInit(); + this.tabPageAdvanced.ResumeLayout(false); + this.groupBox_Miners.ResumeLayout(false); + this.groupBox_Miners.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchMinSecondsFixed)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinerRestartDelayMS)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_APIBindPortStart)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchMinSecondsDynamic)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_ethminerDefaultBlockHeight)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_DagGeneration)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_CPU0_ForceCPUExtension)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinerAPIQueryInterval)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_SwitchMinSecondsAMD)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_MinIdleSeconds)).EndInit(); + this.groupBoxBenchmarkTimeLimits.ResumeLayout(false); + this.tabPageDevicesAlgos.ResumeLayout(false); + this.groupBoxAlgorithmSettings.ResumeLayout(false); +<<<<<<< HEAD +======= + ((System.ComponentModel.ISupportInitialize)(this.pictureBox_AMD_DisableAMDTempControl)).EndInit(); +>>>>>>> ExtraLaunchParamsRefactor + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button buttonSaveClose; + private System.Windows.Forms.Button buttonDefaults; + private System.Windows.Forms.Button buttonCloseNoSave; + private System.Windows.Forms.TabControl tabControlGeneral; + private System.Windows.Forms.TabPage tabPageGeneral; + private System.Windows.Forms.Label label_displayCurrency; + private System.Windows.Forms.ComboBox currencyConverterCombobox; + private System.Windows.Forms.TextBox textBox_LogMaxFileSize; + private System.Windows.Forms.TextBox textBox_WorkerName; + private System.Windows.Forms.TextBox textBox_BitcoinAddress; + private System.Windows.Forms.CheckBox checkBox_LogToFile; + private System.Windows.Forms.Label label_Language; + private System.Windows.Forms.ComboBox comboBox_Language; + private System.Windows.Forms.Label label_LogMaxFileSize; + private System.Windows.Forms.ComboBox comboBox_ServiceLocation; + private System.Windows.Forms.Label label_ServiceLocation; + private System.Windows.Forms.Label label_WorkerName; + private System.Windows.Forms.Label label_BitcoinAddress; + private System.Windows.Forms.CheckBox checkBox_DebugConsole; + private System.Windows.Forms.TabPage tabPageDevicesAlgos; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.GroupBox groupBox_Main; + private System.Windows.Forms.GroupBox groupBox_Localization; + private System.Windows.Forms.GroupBox groupBox_Logging; + private System.Windows.Forms.TextBox textBox_MinProfit; + private System.Windows.Forms.Label label_MinProfit; + private System.Windows.Forms.TabPage tabPageAdvanced; + private System.Windows.Forms.GroupBox groupBox_Miners; + private System.Windows.Forms.Label label_MinIdleSeconds; + private System.Windows.Forms.Label label_SwitchMinSecondsFixed; + private System.Windows.Forms.Label label_SwitchMinSecondsDynamic; + private System.Windows.Forms.Label label_MinerAPIQueryInterval; + private System.Windows.Forms.Label label_MinerRestartDelayMS; + private System.Windows.Forms.TextBox textBox_SwitchMinSecondsAMD; + private System.Windows.Forms.Label label_APIBindPortStart; + private System.Windows.Forms.TextBox textBox_ethminerDefaultBlockHeight; + private System.Windows.Forms.Label label_ethminerDefaultBlockHeight; + private System.Windows.Forms.TextBox textBox_APIBindPortStart; + private System.Windows.Forms.Label label_SwitchMinSecondsAMD; + private System.Windows.Forms.TextBox textBox_MinIdleSeconds; + private System.Windows.Forms.TextBox textBox_SwitchMinSecondsFixed; + private System.Windows.Forms.TextBox textBox_SwitchMinSecondsDynamic; + private System.Windows.Forms.TextBox textBox_MinerRestartDelayMS; + private System.Windows.Forms.TextBox textBox_MinerAPIQueryInterval; + private System.Windows.Forms.GroupBox groupBoxBenchmarkTimeLimits; + private System.Windows.Forms.GroupBox groupBox_Misc; + private System.Windows.Forms.CheckBox checkBox_HideMiningWindows; + private System.Windows.Forms.CheckBox checkBox_MinimizeToTray; + private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVidia6X; + private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVidia5X; + private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVidia3X; + private System.Windows.Forms.CheckBox checkBox_DisableDetectionNVidia2X; + private System.Windows.Forms.CheckBox checkBox_DisableDetectionAMD; + private System.Windows.Forms.CheckBox checkBox_NVIDIAP0State; + private System.Windows.Forms.CheckBox checkBox_AutoScaleBTCValues; + private System.Windows.Forms.CheckBox checkBox_DisableWindowsErrorReporting; + private System.Windows.Forms.CheckBox checkBox_StartMiningWhenIdle; + private System.Windows.Forms.CheckBox checkBox_ShowDriverVersionWarning; + private System.Windows.Forms.ComboBox comboBox_CPU0_ForceCPUExtension; + private System.Windows.Forms.Label label_CPU0_ForceCPUExtension; + private System.Windows.Forms.ComboBox comboBox_DagLoadMode; + private System.Windows.Forms.Label label_DagGeneration; + private Components.AlgorithmSettingsControl algorithmSettingsControl1; + private System.Windows.Forms.GroupBox groupBoxAlgorithmSettings; + private Components.AlgorithmsListView algorithmsListView1; + private System.Windows.Forms.Button buttonAllProfit; + private System.Windows.Forms.Button buttonSelectedProfit; + private Components.BenchmarkLimitControl benchmarkLimitControlNVIDIA; + private Components.BenchmarkLimitControl benchmarkLimitControlCPU; + private Components.BenchmarkLimitControl benchmarkLimitControlAMD; + private System.Windows.Forms.PictureBox pictureBox_Info_BitcoinAddress; + private System.Windows.Forms.PictureBox pictureBox_NVIDIAP0State; + private System.Windows.Forms.PictureBox pictureBox_DisableWindowsErrorReporting; + private System.Windows.Forms.PictureBox pictureBox_ShowDriverVersionWarning; + private System.Windows.Forms.PictureBox pictureBox_StartMiningWhenIdle; + private System.Windows.Forms.PictureBox pictureBox_AutoScaleBTCValues; + private System.Windows.Forms.PictureBox pictureBox_DisableDetectionAMD; + private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVidia2X; + private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVidia3X; + private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVidia5X; + private System.Windows.Forms.PictureBox pictureBox_DisableDetectionNVidia6X; + private System.Windows.Forms.PictureBox pictureBox_MinimizeToTray; + private System.Windows.Forms.PictureBox pictureBox_HideMiningWindows; + private System.Windows.Forms.PictureBox pictureBox_DebugConsole; + private System.Windows.Forms.PictureBox pictureBox_LogMaxFileSize; + private System.Windows.Forms.PictureBox pictureBox_LogToFile; + private System.Windows.Forms.PictureBox pictureBox_WorkerName; + private System.Windows.Forms.PictureBox pictureBox_MinProfit; + private System.Windows.Forms.PictureBox pictureBox_ServiceLocation; + private System.Windows.Forms.PictureBox pictureBox5; + private System.Windows.Forms.PictureBox pictureBox_displayCurrency; + private System.Windows.Forms.PictureBox pictureBox_Language; + private Components.DevicesListViewEnableControl devicesListViewEnableControl1; + private System.Windows.Forms.PictureBox pictureBox_MinIdleSeconds; + private System.Windows.Forms.PictureBox pictureBox_SwitchMinSecondsAMD; + private System.Windows.Forms.PictureBox pictureBox_CPU0_ForceCPUExtension; + private System.Windows.Forms.PictureBox pictureBox_MinerAPIQueryInterval; + private System.Windows.Forms.PictureBox pictureBox_SwitchMinSecondsFixed; + private System.Windows.Forms.PictureBox pictureBox_MinerRestartDelayMS; + private System.Windows.Forms.PictureBox pictureBox_APIBindPortStart; + private System.Windows.Forms.PictureBox pictureBox_SwitchMinSecondsDynamic; + private System.Windows.Forms.PictureBox pictureBox_ethminerDefaultBlockHeight; + private System.Windows.Forms.PictureBox pictureBox_DagGeneration; + private System.Windows.Forms.CheckBox checkBox_AutoStartMining; + private System.Windows.Forms.PictureBox pictureBox_AutoStartMining; + private System.Windows.Forms.CheckBox checkBox_AMD_DisableAMDTempControl; + private System.Windows.Forms.PictureBox pictureBox_AMD_DisableAMDTempControl; + + } +} \ No newline at end of file diff --git a/NiceHashMiner/Forms/Form_Settings.cs b/NiceHashMiner/Forms/Form_Settings.cs index 6e3627d..2e8547b 100644 --- a/NiceHashMiner/Forms/Form_Settings.cs +++ b/NiceHashMiner/Forms/Form_Settings.cs @@ -1,7 +1,10 @@ using NiceHashMiner.Configs; +using NiceHashMiner.Configs.Data; using NiceHashMiner.Devices; using NiceHashMiner.Enums; using NiceHashMiner.Miners; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; using System; using System.Collections.Generic; using System.Data; @@ -34,19 +37,16 @@ private set { ComputeDevice _selectedComputeDevice; - // deep copy initial state if we want to discard changes - private GeneralConfig _generalConfigBackup; - private Dictionary _benchmarkConfigsBackup; - public Form_Settings() { InitializeComponent(); + this.Icon = NiceHashMiner.Properties.Resources.logo; //ret = 1; // default IsChange = false; IsChangeSaved = false; - _benchmarkConfigsBackup = MemoryHelper.DeepClone(ConfigManager.Instance.BenchmarkConfigs); - _generalConfigBackup = MemoryHelper.DeepClone(ConfigManager.Instance.GeneralConfig); + // backup settings + ConfigManager.CreateBackup(); // initialize form InitializeFormTranslations(); @@ -65,6 +65,13 @@ public Form_Settings() { //algorithmsListView1.RemoveRatioRates(); + // set first device selected { + if (ComputeDeviceManager.Avaliable.AllAvaliableDevices.Count > 0) { + _selectedComputeDevice = ComputeDeviceManager.Avaliable.AllAvaliableDevices[0]; + algorithmsListView1.SetAlgorithms(_selectedComputeDevice, _selectedComputeDevice.Enabled); + groupBoxAlgorithmSettings.Text = String.Format(International.GetText("FormSettings_AlgorithmsSettings"), _selectedComputeDevice.Name); + } + // At the very end set to true _isInitFinished = true; } @@ -97,6 +104,12 @@ private void InitializeToolTip() { toolTip1.SetToolTip(this.checkBox_MinimizeToTray, International.GetText("Form_Settings_ToolTip_checkBox_MinimizeToTray")); toolTip1.SetToolTip(this.pictureBox_MinimizeToTray, International.GetText("Form_Settings_ToolTip_checkBox_MinimizeToTray")); + + toolTip1.SetToolTip(this.checkBox_Use3rdPartyMiners, International.GetText("Form_Settings_General_3rdparty_ToolTip")); + toolTip1.SetToolTip(this.pictureBox_Use3rdPartyMiners, International.GetText("Form_Settings_General_3rdparty_ToolTip")); + + toolTip1.SetToolTip(this.checkBox_AllowMultipleInstances, International.GetText("Form_Settings_General_AllowMultipleInstances_ToolTip")); + toolTip1.SetToolTip(this.pictureBox_AllowMultipleInstances, International.GetText("Form_Settings_General_AllowMultipleInstances_ToolTip")); toolTip1.SetToolTip(this.textBox_SwitchMinSecondsFixed, International.GetText("Form_Settings_ToolTip_SwitchMinSecondsFixed")); @@ -135,15 +148,9 @@ private void InitializeToolTip() { benchmarkLimitControlNVIDIA.SetToolTip(ref toolTip1, "NVIDIA GPUs"); benchmarkLimitControlAMD.SetToolTip(ref toolTip1, "AMD GPUs"); - toolTip1.SetToolTip(this.checkBox_DisableDetectionNVidia6X, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA6.x")); - toolTip1.SetToolTip(this.checkBox_DisableDetectionNVidia5X, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA5.x")); - toolTip1.SetToolTip(this.checkBox_DisableDetectionNVidia3X, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA3.x")); - toolTip1.SetToolTip(this.checkBox_DisableDetectionNVidia2X, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA2.x")); + toolTip1.SetToolTip(this.checkBox_DisableDetectionNVIDIA, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA")); toolTip1.SetToolTip(this.checkBox_DisableDetectionAMD, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "AMD")); - toolTip1.SetToolTip(this.pictureBox_DisableDetectionNVidia6X, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA6.x")); - toolTip1.SetToolTip(this.pictureBox_DisableDetectionNVidia5X, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA5.x")); - toolTip1.SetToolTip(this.pictureBox_DisableDetectionNVidia3X, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA3.x")); - toolTip1.SetToolTip(this.pictureBox_DisableDetectionNVidia2X, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA2.x")); + toolTip1.SetToolTip(this.pictureBox_DisableDetectionNVIDIA, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "NVIDIA")); toolTip1.SetToolTip(this.pictureBox_DisableDetectionAMD, String.Format(International.GetText("Form_Settings_ToolTip_checkBox_DisableDetection"), "AMD")); toolTip1.SetToolTip(this.checkBox_AutoScaleBTCValues, International.GetText("Form_Settings_ToolTip_checkBox_AutoScaleBTCValues")); @@ -172,6 +179,11 @@ private void InitializeToolTip() { toolTip1.SetToolTip(this.checkBox_NVIDIAP0State, International.GetText("Form_Settings_ToolTip_checkBox_NVIDIAP0State")); toolTip1.SetToolTip(this.pictureBox_NVIDIAP0State, International.GetText("Form_Settings_ToolTip_checkBox_NVIDIAP0State")); + + + toolTip1.SetToolTip(this.checkBox_AutoStartMining, International.GetText("Form_Settings_ToolTip_checkBox_AutoStartMining")); + toolTip1.SetToolTip(this.pictureBox_AutoStartMining, International.GetText("Form_Settings_ToolTip_checkBox_AutoStartMining")); + toolTip1.SetToolTip(this.textBox_ethminerDefaultBlockHeight, International.GetText("Form_Settings_ToolTip_ethminerDefaultBlockHeight")); toolTip1.SetToolTip(this.label_ethminerDefaultBlockHeight, International.GetText("Form_Settings_ToolTip_ethminerDefaultBlockHeight")); @@ -186,6 +198,21 @@ private void InitializeToolTip() { toolTip1.SetToolTip(label_CPU0_ForceCPUExtension, International.GetText("Form_Settings_ToolTip_CPU_ForceCPUExtension")); toolTip1.SetToolTip(pictureBox_CPU0_ForceCPUExtension, International.GetText("Form_Settings_ToolTip_CPU_ForceCPUExtension")); + // amd disable temp control + toolTip1.SetToolTip(checkBox_AMD_DisableAMDTempControl, International.GetText("Form_Settings_ToolTip_DisableAMDTempControl")); + toolTip1.SetToolTip(pictureBox_AMD_DisableAMDTempControl, International.GetText("Form_Settings_ToolTip_DisableAMDTempControl")); + + // disable default optimizations + toolTip1.SetToolTip(checkBox_DisableDefaultOptimizations, International.GetText("Form_Settings_ToolTip_DisableDefaultOptimizations")); + toolTip1.SetToolTip(pictureBox_DisableDefaultOptimizations, International.GetText("Form_Settings_ToolTip_DisableDefaultOptimizations")); + + // internet connection mining check + toolTip1.SetToolTip(checkBox_IdleWhenNoInternetAccess, International.GetText("Form_Settings_ToolTip_ContinueMiningIfNoInternetAccess")); + toolTip1.SetToolTip(pictureBox_IdleWhenNoInternetAccess, International.GetText("Form_Settings_ToolTip_ContinueMiningIfNoInternetAccess")); + + toolTip1.SetToolTip(pictureBox_SwitchProfitabilityThreshold, International.GetText("Form_Settings_ToolTip_SwitchProfitabilityThreshold")); + toolTip1.SetToolTip(label_SwitchProfitabilityThreshold, International.GetText("Form_Settings_ToolTip_SwitchProfitabilityThreshold")); + this.Text = International.GetText("Form_Settings_Title"); algorithmSettingsControl1.InitLocale(toolTip1); @@ -203,20 +230,20 @@ private void InitializeFormTranslations() { private void InitializeGeneralTabTranslations() { checkBox_DebugConsole.Text = International.GetText("Form_Settings_General_DebugConsole"); + checkBox_AutoStartMining.Text = International.GetText("Form_Settings_General_AutoStartMining"); checkBox_HideMiningWindows.Text = International.GetText("Form_Settings_General_HideMiningWindows"); checkBox_MinimizeToTray.Text = International.GetText("Form_Settings_General_MinimizeToTray"); - checkBox_DisableDetectionNVidia6X.Text = String.Format(International.GetText("Form_Settings_General_DisableDetection"), "NVIDIA6.x"); - checkBox_DisableDetectionNVidia5X.Text = String.Format(International.GetText("Form_Settings_General_DisableDetection"), "NVIDIA5.x"); - checkBox_DisableDetectionNVidia3X.Text = String.Format(International.GetText("Form_Settings_General_DisableDetection"), "NVIDIA3.x"); - checkBox_DisableDetectionNVidia2X.Text = String.Format(International.GetText("Form_Settings_General_DisableDetection"), "NVIDIA2.x"); + checkBox_DisableDetectionNVIDIA.Text = String.Format(International.GetText("Form_Settings_General_DisableDetection"), "NVIDIA"); checkBox_DisableDetectionAMD.Text = String.Format(International.GetText("Form_Settings_General_DisableDetection"), "AMD"); checkBox_AutoScaleBTCValues.Text = International.GetText("Form_Settings_General_AutoScaleBTCValues"); checkBox_StartMiningWhenIdle.Text = International.GetText("Form_Settings_General_StartMiningWhenIdle"); checkBox_ShowDriverVersionWarning.Text = International.GetText("Form_Settings_General_ShowDriverVersionWarning"); checkBox_DisableWindowsErrorReporting.Text = International.GetText("Form_Settings_General_DisableWindowsErrorReporting"); - //checkBox_UseNewSettingsPage.Text = International.GetText("Form_Settings_General_UseNewSettingsPage"); + checkBox_Use3rdPartyMiners.Text = International.GetText("Form_Settings_General_3rdparty_Text"); checkBox_NVIDIAP0State.Text = International.GetText("Form_Settings_General_NVIDIAP0State"); checkBox_LogToFile.Text = International.GetText("Form_Settings_General_LogToFile"); + checkBox_AMD_DisableAMDTempControl.Text = International.GetText("Form_Settings_General_DisableAMDTempControl"); + checkBox_AllowMultipleInstances.Text = International.GetText("Form_Settings_General_AllowMultipleInstances_Text"); label_Language.Text = International.GetText("Form_Settings_General_Language") + ":"; label_BitcoinAddress.Text = International.GetText("BitcoinAddress") + ":"; @@ -270,6 +297,11 @@ private void InitializeGeneralTabTranslations() { buttonAllProfit.Text = International.GetText("FormSettings_Tab_Devices_Algorithms_Check_ALLProfitability"); buttonSelectedProfit.Text = International.GetText("FormSettings_Tab_Devices_Algorithms_Check_SingleProfitability"); + + checkBox_DisableDefaultOptimizations.Text = International.GetText("Form_Settings_Text_DisableDefaultOptimizations"); + checkBox_IdleWhenNoInternetAccess.Text = International.GetText("Form_Settings_Text_ContinueMiningIfNoInternetAccess"); + + label_SwitchProfitabilityThreshold.Text = International.GetText("Form_Settings_General_SwitchProfitabilityThreshold"); } private void InitializeGeneralTabCallbacks() { @@ -277,10 +309,7 @@ private void InitializeGeneralTabCallbacks() { { this.checkBox_AutoScaleBTCValues.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); this.checkBox_DisableDetectionAMD.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); - this.checkBox_DisableDetectionNVidia2X.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); - this.checkBox_DisableDetectionNVidia3X.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); - this.checkBox_DisableDetectionNVidia5X.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); - this.checkBox_DisableDetectionNVidia6X.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); + this.checkBox_DisableDetectionNVIDIA.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); this.checkBox_MinimizeToTray.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); this.checkBox_HideMiningWindows.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); this.checkBox_DebugConsole.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); @@ -289,6 +318,8 @@ private void InitializeGeneralTabCallbacks() { this.checkBox_StartMiningWhenIdle.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); this.checkBox_NVIDIAP0State.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); this.checkBox_LogToFile.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); + this.checkBox_AutoStartMining.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); + this.checkBox_AllowMultipleInstances.CheckedChanged += new System.EventHandler(this.GeneralCheckBoxes_CheckedChanged); } // Add EventHandler for all the general tab's textboxes { @@ -326,7 +357,7 @@ private void InitializeGeneralTabCallbacks() { } // CPU exceptions - comboBox_CPU0_ForceCPUExtension.SelectedIndex = (int)ConfigManager.Instance.GeneralConfig.ForceCPUExtension; + comboBox_CPU0_ForceCPUExtension.SelectedIndex = (int)ConfigManager.GeneralConfig.ForceCPUExtension; comboBox_CPU0_ForceCPUExtension.SelectedIndexChanged += comboBox_CPU0_ForceCPUExtension_SelectedIndexChanged; // fill dag dropdown comboBox_DagLoadMode.Items.Clear(); @@ -334,53 +365,56 @@ private void InitializeGeneralTabCallbacks() { comboBox_DagLoadMode.Items.Add(MinerEtherum.GetDagGenerationString((DagGenerationType)i)); } // set selected - comboBox_DagLoadMode.SelectedIndex = (int)ConfigManager.Instance.GeneralConfig.EthminerDagGenerationType; + comboBox_DagLoadMode.SelectedIndex = (int)ConfigManager.GeneralConfig.EthminerDagGenerationType; } private void InitializeGeneralTabFieldValuesReferences() { // Checkboxes set checked value { - checkBox_DebugConsole.Checked = ConfigManager.Instance.GeneralConfig.DebugConsole; - checkBox_HideMiningWindows.Checked = ConfigManager.Instance.GeneralConfig.HideMiningWindows; - checkBox_MinimizeToTray.Checked = ConfigManager.Instance.GeneralConfig.MinimizeToTray; - checkBox_DisableDetectionNVidia6X.Checked = ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia6X; - checkBox_DisableDetectionNVidia5X.Checked = ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia5X; - checkBox_DisableDetectionNVidia3X.Checked = ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia3X; - checkBox_DisableDetectionNVidia2X.Checked = ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia2X; - checkBox_DisableDetectionAMD.Checked = ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionAMD; - checkBox_AutoScaleBTCValues.Checked = ConfigManager.Instance.GeneralConfig.AutoScaleBTCValues; - checkBox_StartMiningWhenIdle.Checked = ConfigManager.Instance.GeneralConfig.StartMiningWhenIdle; - checkBox_ShowDriverVersionWarning.Checked = ConfigManager.Instance.GeneralConfig.ShowDriverVersionWarning; - checkBox_DisableWindowsErrorReporting.Checked = ConfigManager.Instance.GeneralConfig.DisableWindowsErrorReporting; - checkBox_NVIDIAP0State.Checked = ConfigManager.Instance.GeneralConfig.NVIDIAP0State; - checkBox_LogToFile.Checked = ConfigManager.Instance.GeneralConfig.LogToFile; + checkBox_DebugConsole.Checked = ConfigManager.GeneralConfig.DebugConsole; + checkBox_AutoStartMining.Checked = ConfigManager.GeneralConfig.AutoStartMining; + checkBox_HideMiningWindows.Checked = ConfigManager.GeneralConfig.HideMiningWindows; + checkBox_MinimizeToTray.Checked = ConfigManager.GeneralConfig.MinimizeToTray; + checkBox_DisableDetectionNVIDIA.Checked = ConfigManager.GeneralConfig.DeviceDetection.DisableDetectionNVIDIA; + checkBox_DisableDetectionAMD.Checked = ConfigManager.GeneralConfig.DeviceDetection.DisableDetectionAMD; + checkBox_AutoScaleBTCValues.Checked = ConfigManager.GeneralConfig.AutoScaleBTCValues; + checkBox_StartMiningWhenIdle.Checked = ConfigManager.GeneralConfig.StartMiningWhenIdle; + checkBox_ShowDriverVersionWarning.Checked = ConfigManager.GeneralConfig.ShowDriverVersionWarning; + checkBox_DisableWindowsErrorReporting.Checked = ConfigManager.GeneralConfig.DisableWindowsErrorReporting; + checkBox_NVIDIAP0State.Checked = ConfigManager.GeneralConfig.NVIDIAP0State; + checkBox_LogToFile.Checked = ConfigManager.GeneralConfig.LogToFile; + checkBox_AMD_DisableAMDTempControl.Checked = ConfigManager.GeneralConfig.DisableAMDTempControl; + checkBox_DisableDefaultOptimizations.Checked = ConfigManager.GeneralConfig.DisableDefaultOptimizations; + checkBox_IdleWhenNoInternetAccess.Checked = ConfigManager.GeneralConfig.IdleWhenNoInternetAccess; + this.checkBox_Use3rdPartyMiners.Checked = ConfigManager.GeneralConfig.Use3rdPartyMiners == Use3rdPartyMiners.YES; + this.checkBox_AllowMultipleInstances.Checked = ConfigManager.GeneralConfig.AllowMultipleInstances; } // Textboxes { - textBox_BitcoinAddress.Text = ConfigManager.Instance.GeneralConfig.BitcoinAddress; - textBox_WorkerName.Text = ConfigManager.Instance.GeneralConfig.WorkerName; - textBox_SwitchMinSecondsFixed.Text = ConfigManager.Instance.GeneralConfig.SwitchMinSecondsFixed.ToString(); - textBox_SwitchMinSecondsDynamic.Text = ConfigManager.Instance.GeneralConfig.SwitchMinSecondsDynamic.ToString(); - textBox_SwitchMinSecondsAMD.Text = ConfigManager.Instance.GeneralConfig.SwitchMinSecondsAMD.ToString(); - textBox_MinerAPIQueryInterval.Text = ConfigManager.Instance.GeneralConfig.MinerAPIQueryInterval.ToString(); - textBox_MinerRestartDelayMS.Text = ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS.ToString(); - textBox_MinIdleSeconds.Text = ConfigManager.Instance.GeneralConfig.MinIdleSeconds.ToString(); - textBox_LogMaxFileSize.Text = ConfigManager.Instance.GeneralConfig.LogMaxFileSize.ToString(); - textBox_ethminerDefaultBlockHeight.Text = ConfigManager.Instance.GeneralConfig.ethminerDefaultBlockHeight.ToString(); - textBox_APIBindPortStart.Text = ConfigManager.Instance.GeneralConfig.ApiBindPortPoolStart.ToString(); - textBox_MinProfit.Text = ConfigManager.Instance.GeneralConfig.MinimumProfit.ToString("F2").Replace(',', '.'); // force comma; + textBox_BitcoinAddress.Text = ConfigManager.GeneralConfig.BitcoinAddress; + textBox_WorkerName.Text = ConfigManager.GeneralConfig.WorkerName; + textBox_SwitchMinSecondsFixed.Text = ConfigManager.GeneralConfig.SwitchMinSecondsFixed.ToString(); + textBox_SwitchMinSecondsDynamic.Text = ConfigManager.GeneralConfig.SwitchMinSecondsDynamic.ToString(); + textBox_SwitchMinSecondsAMD.Text = ConfigManager.GeneralConfig.SwitchMinSecondsAMD.ToString(); + textBox_MinerAPIQueryInterval.Text = ConfigManager.GeneralConfig.MinerAPIQueryInterval.ToString(); + textBox_MinerRestartDelayMS.Text = ConfigManager.GeneralConfig.MinerRestartDelayMS.ToString(); + textBox_MinIdleSeconds.Text = ConfigManager.GeneralConfig.MinIdleSeconds.ToString(); + textBox_LogMaxFileSize.Text = ConfigManager.GeneralConfig.LogMaxFileSize.ToString(); + textBox_ethminerDefaultBlockHeight.Text = ConfigManager.GeneralConfig.ethminerDefaultBlockHeight.ToString(); + textBox_APIBindPortStart.Text = ConfigManager.GeneralConfig.ApiBindPortPoolStart.ToString(); + textBox_MinProfit.Text = ConfigManager.GeneralConfig.MinimumProfit.ToString("F2").Replace(',', '.'); // force comma; + textBox_SwitchProfitabilityThreshold.Text = ConfigManager.GeneralConfig.SwitchProfitabilityThreshold.ToString("F2").Replace(',', '.'); // force comma; } // set custom control referances { - benchmarkLimitControlCPU.TimeLimits = ConfigManager.Instance.GeneralConfig.BenchmarkTimeLimits.CPU; - benchmarkLimitControlNVIDIA.TimeLimits = ConfigManager.Instance.GeneralConfig.BenchmarkTimeLimits.NVIDIA; - benchmarkLimitControlAMD.TimeLimits = ConfigManager.Instance.GeneralConfig.BenchmarkTimeLimits.AMD; + benchmarkLimitControlCPU.TimeLimits = ConfigManager.GeneralConfig.BenchmarkTimeLimits.CPU; + benchmarkLimitControlNVIDIA.TimeLimits = ConfigManager.GeneralConfig.BenchmarkTimeLimits.NVIDIA; + benchmarkLimitControlAMD.TimeLimits = ConfigManager.GeneralConfig.BenchmarkTimeLimits.AMD; // here we want all devices - devicesListViewEnableControl1.SetComputeDevices(ComputeDevice.AllAvaliableDevices); - devicesListViewEnableControl1.AutoSaveChange = false; + devicesListViewEnableControl1.SetComputeDevices(ComputeDeviceManager.Avaliable.AllAvaliableDevices); devicesListViewEnableControl1.SetAlgorithmsListView(algorithmsListView1); devicesListViewEnableControl1.IsSettingsCopyEnabled = true; } @@ -397,10 +431,10 @@ private void InitializeGeneralTabFieldValuesReferences() { // ComboBox { - comboBox_Language.SelectedIndex = (int)ConfigManager.Instance.GeneralConfig.Language; - comboBox_ServiceLocation.SelectedIndex = ConfigManager.Instance.GeneralConfig.ServiceLocation; + comboBox_Language.SelectedIndex = (int)ConfigManager.GeneralConfig.Language; + comboBox_ServiceLocation.SelectedIndex = ConfigManager.GeneralConfig.ServiceLocation; - currencyConverterCombobox.SelectedItem = ConfigManager.Instance.GeneralConfig.DisplayCurrency; + currencyConverterCombobox.SelectedItem = ConfigManager.GeneralConfig.DisplayCurrency; } } @@ -415,15 +449,9 @@ private void InitializeGeneralTab() { #region Tab Devices private void InitializeDevicesTab() { - InitializeDevicesTabTranslations(); InitializeDevicesCallbacks(); } - private void InitializeDevicesTabTranslations() { - //deviceSettingsControl1.InitLocale(toolTip1); - } - - private void InitializeDevicesCallbacks() { devicesListViewEnableControl1.SetDeviceSelectionChangedCallback(devicesListView1_ItemSelectionChanged); } @@ -433,118 +461,127 @@ private void InitializeDevicesCallbacks() { #endregion // Initializations - // TODO - #region Evaluate to be removed - private bool ParseStringToInt32(ref TextBox textBox) { - int configInt; // dummy variable - if (!Int32.TryParse(textBox.Text, out configInt)) { - MessageBox.Show(International.GetText("Form_Settings_ParseIntMsg"), - International.GetText("Form_Settings_ParseIntTitle"), - MessageBoxButtons.OK, MessageBoxIcon.Warning); - textBox.Focus(); - return false; - } + #region Form Callbacks - return true; + #region Tab General + private void GeneralCheckBoxes_CheckedChanged(object sender, EventArgs e) { + if (!_isInitFinished) return; + // indicate there has been a change + IsChange = true; + ConfigManager.GeneralConfig.DebugConsole = checkBox_DebugConsole.Checked; + ConfigManager.GeneralConfig.AutoStartMining = checkBox_AutoStartMining.Checked; + ConfigManager.GeneralConfig.HideMiningWindows = checkBox_HideMiningWindows.Checked; + ConfigManager.GeneralConfig.MinimizeToTray = checkBox_MinimizeToTray.Checked; + ConfigManager.GeneralConfig.DeviceDetection.DisableDetectionNVIDIA = checkBox_DisableDetectionNVIDIA.Checked; + ConfigManager.GeneralConfig.DeviceDetection.DisableDetectionAMD = checkBox_DisableDetectionAMD.Checked; + ConfigManager.GeneralConfig.AutoScaleBTCValues = checkBox_AutoScaleBTCValues.Checked; + ConfigManager.GeneralConfig.StartMiningWhenIdle = checkBox_StartMiningWhenIdle.Checked; + ConfigManager.GeneralConfig.ShowDriverVersionWarning = checkBox_ShowDriverVersionWarning.Checked; + ConfigManager.GeneralConfig.DisableWindowsErrorReporting = checkBox_DisableWindowsErrorReporting.Checked; + ConfigManager.GeneralConfig.NVIDIAP0State = checkBox_NVIDIAP0State.Checked; + ConfigManager.GeneralConfig.LogToFile = checkBox_LogToFile.Checked; + ConfigManager.GeneralConfig.IdleWhenNoInternetAccess = checkBox_IdleWhenNoInternetAccess.Checked; + ConfigManager.GeneralConfig.AllowMultipleInstances = checkBox_AllowMultipleInstances.Checked; } - private bool ParseStringToInt64(ref TextBox textBox) { - long configInt; // dummy variable - if (!Int64.TryParse(textBox.Text, out configInt)) { - MessageBox.Show(International.GetText("Form_Settings_ParseIntMsg"), - International.GetText("Form_Settings_ParseIntTitle"), - MessageBoxButtons.OK, MessageBoxIcon.Warning); - textBox.Focus(); - return false; - } + private void checkBox_AMD_DisableAMDTempControl_CheckedChanged(object sender, EventArgs e) { + if (!_isInitFinished) return; - return true; + // indicate there has been a change + IsChange = true; + ConfigManager.GeneralConfig.DisableAMDTempControl = checkBox_AMD_DisableAMDTempControl.Checked; + foreach (var cDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + if (cDev.DeviceType == DeviceType.AMD) { + foreach (var algorithm in cDev.GetAlgorithmSettings()) { + if (algorithm.NiceHashID != AlgorithmType.DaggerHashimoto) { + algorithm.ExtraLaunchParameters += AmdGpuDevice.TemperatureParam; + algorithm.ExtraLaunchParameters = ExtraLaunchParametersParser.ParseForMiningPair( + new MiningPair(cDev, algorithm), algorithm.NiceHashID, DeviceType.AMD, false); + } + } + } + } } - #endregion // Evaluate to be removed - - #region Form Callbacks - #region Tab General - private void GeneralCheckBoxes_CheckedChanged(object sender, EventArgs e) { + private void checkBox_DisableDefaultOptimizations_CheckedChanged(object sender, EventArgs e) { if (!_isInitFinished) return; + // indicate there has been a change IsChange = true; - ConfigManager.Instance.GeneralConfig.DebugConsole = checkBox_DebugConsole.Checked; - ConfigManager.Instance.GeneralConfig.HideMiningWindows = checkBox_HideMiningWindows.Checked; - ConfigManager.Instance.GeneralConfig.MinimizeToTray = checkBox_MinimizeToTray.Checked; - ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia6X = checkBox_DisableDetectionNVidia6X.Checked; - ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia5X = checkBox_DisableDetectionNVidia5X.Checked; - ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia3X = checkBox_DisableDetectionNVidia3X.Checked; - ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionNVidia2X = checkBox_DisableDetectionNVidia2X.Checked; - ConfigManager.Instance.GeneralConfig.DeviceDetection.DisableDetectionAMD = checkBox_DisableDetectionAMD.Checked; - ConfigManager.Instance.GeneralConfig.AutoScaleBTCValues = checkBox_AutoScaleBTCValues.Checked; - ConfigManager.Instance.GeneralConfig.StartMiningWhenIdle = checkBox_StartMiningWhenIdle.Checked; - ConfigManager.Instance.GeneralConfig.ShowDriverVersionWarning = checkBox_ShowDriverVersionWarning.Checked; - ConfigManager.Instance.GeneralConfig.DisableWindowsErrorReporting = checkBox_DisableWindowsErrorReporting.Checked; - ConfigManager.Instance.GeneralConfig.NVIDIAP0State = checkBox_NVIDIAP0State.Checked; - ConfigManager.Instance.GeneralConfig.LogToFile = checkBox_LogToFile.Checked; + ConfigManager.GeneralConfig.DisableDefaultOptimizations = checkBox_DisableDefaultOptimizations.Checked; + if (ConfigManager.GeneralConfig.DisableDefaultOptimizations) { + foreach (var cDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + foreach (var algorithm in cDev.GetAlgorithmSettings()) { + algorithm.ExtraLaunchParameters = ""; + if (cDev.DeviceType == DeviceType.AMD && algorithm.NiceHashID != AlgorithmType.DaggerHashimoto) { + algorithm.ExtraLaunchParameters += AmdGpuDevice.TemperatureParam; + algorithm.ExtraLaunchParameters = ExtraLaunchParametersParser.ParseForMiningPair( + new MiningPair(cDev, algorithm), algorithm.NiceHashID, cDev.DeviceType, false); + } + } + } + } else { + foreach (var cDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + if (cDev.DeviceType == DeviceType.CPU) continue; // cpu has no defaults + var deviceDefaultsAlgoSettings = GroupAlgorithms.CreateForDeviceList(cDev); + foreach (var defaultAlgoSettings in deviceDefaultsAlgoSettings) { + var toSetAlgo = cDev.GetAlgorithm(defaultAlgoSettings.MinerBaseType, defaultAlgoSettings.NiceHashID); + if (toSetAlgo != null) { + toSetAlgo.ExtraLaunchParameters = defaultAlgoSettings.ExtraLaunchParameters; + toSetAlgo.ExtraLaunchParameters = ExtraLaunchParametersParser.ParseForMiningPair( + new MiningPair(cDev, toSetAlgo), toSetAlgo.NiceHashID, cDev.DeviceType, false); + } + } + } + } } private void GeneralTextBoxes_Leave(object sender, EventArgs e) { if (!_isInitFinished) return; IsChange = true; - ConfigManager.Instance.GeneralConfig.BitcoinAddress = textBox_BitcoinAddress.Text.Trim(); - ConfigManager.Instance.GeneralConfig.WorkerName = textBox_WorkerName.Text.Trim(); - // TODO IMPORTANT fix this - // int's only settings - keypress handles only ints should be safe. If string empty or null focus and alert - // after number init set new value text back because it can be out of bounds - // try to refactor this mess - if (!ParseStringToInt32(ref textBox_SwitchMinSecondsFixed)) return; - ConfigManager.Instance.GeneralConfig.SwitchMinSecondsFixed = Int32.Parse(textBox_SwitchMinSecondsFixed.Text); - textBox_SwitchMinSecondsFixed.Text = ConfigManager.Instance.GeneralConfig.SwitchMinSecondsFixed.ToString(); - - if (!ParseStringToInt32(ref textBox_SwitchMinSecondsDynamic)) return; - ConfigManager.Instance.GeneralConfig.SwitchMinSecondsDynamic = Int32.Parse(textBox_SwitchMinSecondsDynamic.Text); - textBox_SwitchMinSecondsDynamic.Text = ConfigManager.Instance.GeneralConfig.SwitchMinSecondsDynamic.ToString(); - - if (!ParseStringToInt32(ref textBox_SwitchMinSecondsAMD)) return; - ConfigManager.Instance.GeneralConfig.SwitchMinSecondsAMD = Int32.Parse(textBox_SwitchMinSecondsAMD.Text); - textBox_SwitchMinSecondsAMD.Text = ConfigManager.Instance.GeneralConfig.SwitchMinSecondsAMD.ToString(); - - if (!ParseStringToInt32(ref textBox_MinerAPIQueryInterval)) return; - ConfigManager.Instance.GeneralConfig.MinerAPIQueryInterval = Int32.Parse(textBox_MinerAPIQueryInterval.Text); - textBox_MinerAPIQueryInterval.Text = ConfigManager.Instance.GeneralConfig.MinerAPIQueryInterval.ToString(); - - if (!ParseStringToInt32(ref textBox_MinerRestartDelayMS)) return; - ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS = Int32.Parse(textBox_MinerRestartDelayMS.Text); - textBox_MinerRestartDelayMS.Text = ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS.ToString(); - - if (!ParseStringToInt32(ref textBox_MinIdleSeconds)) return; - ConfigManager.Instance.GeneralConfig.MinIdleSeconds = Int32.Parse(textBox_MinIdleSeconds.Text); - textBox_MinIdleSeconds.Text = ConfigManager.Instance.GeneralConfig.MinIdleSeconds.ToString(); - - if (!ParseStringToInt64(ref textBox_LogMaxFileSize)) return; - ConfigManager.Instance.GeneralConfig.LogMaxFileSize = Int64.Parse(textBox_LogMaxFileSize.Text); - textBox_LogMaxFileSize.Text = ConfigManager.Instance.GeneralConfig.LogMaxFileSize.ToString(); - - if (!ParseStringToInt32(ref textBox_ethminerDefaultBlockHeight)) return; - ConfigManager.Instance.GeneralConfig.ethminerDefaultBlockHeight = Int32.Parse(textBox_ethminerDefaultBlockHeight.Text); - textBox_ethminerDefaultBlockHeight.Text = ConfigManager.Instance.GeneralConfig.ethminerDefaultBlockHeight.ToString(); - - if (!ParseStringToInt32(ref textBox_APIBindPortStart)) return; - ConfigManager.Instance.GeneralConfig.ApiBindPortPoolStart = Int32.Parse(textBox_APIBindPortStart.Text); - textBox_APIBindPortStart.Text = ConfigManager.Instance.GeneralConfig.ApiBindPortPoolStart.ToString(); - - ConfigManager.Instance.GeneralConfig.MinimumProfit = Double.Parse(textBox_MinProfit.Text, CultureInfo.InvariantCulture); - textBox_MinProfit.Text = ConfigManager.Instance.GeneralConfig.MinimumProfit.ToString("F2").Replace(',', '.'); // force comma + ConfigManager.GeneralConfig.BitcoinAddress = textBox_BitcoinAddress.Text.Trim(); + ConfigManager.GeneralConfig.WorkerName = textBox_WorkerName.Text.Trim(); + + ConfigManager.GeneralConfig.SwitchMinSecondsFixed = Helpers.ParseInt(textBox_SwitchMinSecondsFixed.Text); + ConfigManager.GeneralConfig.SwitchMinSecondsDynamic = Helpers.ParseInt(textBox_SwitchMinSecondsDynamic.Text); + ConfigManager.GeneralConfig.SwitchMinSecondsAMD = Helpers.ParseInt(textBox_SwitchMinSecondsAMD.Text); + ConfigManager.GeneralConfig.MinerAPIQueryInterval = Helpers.ParseInt(textBox_MinerAPIQueryInterval.Text); + ConfigManager.GeneralConfig.MinerRestartDelayMS = Helpers.ParseInt(textBox_MinerRestartDelayMS.Text); + ConfigManager.GeneralConfig.MinIdleSeconds = Helpers.ParseInt(textBox_MinIdleSeconds.Text); + ConfigManager.GeneralConfig.LogMaxFileSize = Helpers.ParseLong(textBox_LogMaxFileSize.Text); + ConfigManager.GeneralConfig.ethminerDefaultBlockHeight = Helpers.ParseInt(textBox_ethminerDefaultBlockHeight.Text); + ConfigManager.GeneralConfig.ApiBindPortPoolStart = Helpers.ParseInt(textBox_APIBindPortStart.Text); + // min profit + ConfigManager.GeneralConfig.MinimumProfit = Helpers.ParseDouble(textBox_MinProfit.Text); + ConfigManager.GeneralConfig.SwitchProfitabilityThreshold = Helpers.ParseDouble(textBox_SwitchProfitabilityThreshold.Text); + + // Fix bounds + ConfigManager.GeneralConfig.FixSettingBounds(); + // update strings + textBox_MinProfit.Text = ConfigManager.GeneralConfig.MinimumProfit.ToString("F2").Replace(',', '.'); // force comma + textBox_SwitchProfitabilityThreshold.Text = ConfigManager.GeneralConfig.SwitchProfitabilityThreshold.ToString("F2").Replace(',', '.'); // force comma + textBox_SwitchMinSecondsFixed.Text = ConfigManager.GeneralConfig.SwitchMinSecondsFixed.ToString(); + textBox_SwitchMinSecondsDynamic.Text = ConfigManager.GeneralConfig.SwitchMinSecondsDynamic.ToString(); + textBox_SwitchMinSecondsAMD.Text = ConfigManager.GeneralConfig.SwitchMinSecondsAMD.ToString(); + textBox_MinerAPIQueryInterval.Text = ConfigManager.GeneralConfig.MinerAPIQueryInterval.ToString(); + textBox_MinerRestartDelayMS.Text = ConfigManager.GeneralConfig.MinerRestartDelayMS.ToString(); + textBox_MinIdleSeconds.Text = ConfigManager.GeneralConfig.MinIdleSeconds.ToString(); + textBox_LogMaxFileSize.Text = ConfigManager.GeneralConfig.LogMaxFileSize.ToString(); + textBox_ethminerDefaultBlockHeight.Text = ConfigManager.GeneralConfig.ethminerDefaultBlockHeight.ToString(); + textBox_APIBindPortStart.Text = ConfigManager.GeneralConfig.ApiBindPortPoolStart.ToString(); } private void GeneralComboBoxes_Leave(object sender, EventArgs e) { if (!_isInitFinished) return; IsChange = true; - ConfigManager.Instance.GeneralConfig.Language = (LanguageType)comboBox_Language.SelectedIndex; - ConfigManager.Instance.GeneralConfig.ServiceLocation = comboBox_ServiceLocation.SelectedIndex; - ConfigManager.Instance.GeneralConfig.EthminerDagGenerationType = (DagGenerationType)comboBox_DagLoadMode.SelectedIndex; + ConfigManager.GeneralConfig.Language = (LanguageType)comboBox_Language.SelectedIndex; + ConfigManager.GeneralConfig.ServiceLocation = comboBox_ServiceLocation.SelectedIndex; + ConfigManager.GeneralConfig.EthminerDagGenerationType = (DagGenerationType)comboBox_DagLoadMode.SelectedIndex; } private void comboBox_CPU0_ForceCPUExtension_SelectedIndexChanged(object sender, EventArgs e) { ComboBox cmbbox = (ComboBox)sender; - ConfigManager.Instance.GeneralConfig.ForceCPUExtension = (CPUExtensionType)cmbbox.SelectedIndex; + ConfigManager.GeneralConfig.ForceCPUExtension = (CPUExtensionType)cmbbox.SelectedIndex; } #endregion //Tab General @@ -555,38 +592,11 @@ private void devicesListView1_ItemSelectionChanged(object sender, ListViewItemSe algorithmSettingsControl1.Deselect(); // show algorithms - _selectedComputeDevice = ComputeDevice.GetCurrentlySelectedComputeDevice(e.ItemIndex, ShowUniqueDeviceList); - algorithmsListView1.SetAlgorithms(_selectedComputeDevice, _selectedComputeDevice.ComputeDeviceEnabledOption.IsEnabled); + _selectedComputeDevice = ComputeDeviceManager.Avaliable.GetCurrentlySelectedComputeDevice(e.ItemIndex, ShowUniqueDeviceList); + algorithmsListView1.SetAlgorithms(_selectedComputeDevice, _selectedComputeDevice.Enabled); groupBoxAlgorithmSettings.Text = String.Format(International.GetText("FormSettings_AlgorithmsSettings"), _selectedComputeDevice.Name); } - // TODO IMPORTANT get back to this div thing - static double[] div = new double[] { - 1000000, // 0 (MH/s) Scrypt - 1000000000000, // 1 (TH/s) SHA256 - 1000000, // 2 (MH/s) ScryptNf - 1000000, // 3 (MH/s) X11 - 1000000, // 4 (MH/s) X13 - 1000000, // 5 (MH/s) Keccak - 1000000, // 6 (MH/s) X15 - 1000000, // 7 (MH/s) Nist5 - 1000000, // 8 (MH/s) NeoScrypt - 1000000, // 9 (MH/s) Lyra2RE - 1000000, // 10 (MH/s) WhirlpoolX - 1000000, // 11 (MH/s) Qubit - 1000000, // 12 (MH/s) Quark - 1000, // 13 (kH/s) Axiom - 1000000, // 14 (MH/s) Lyra2REv2 - 1000, // 15 (kH/s) ScryptJaneNf16 - 1000000000, // 16 (GH/s) Blake256r8 - 1000000000, // 17 (GH/s) Blake256r14 - 1000000000, // 18 (GH/s) Blake256r8vnl - 1000, // 19 (kH/s) Hodl - 1000000, // 20 (MH/s) Daggerhashimoto - 1000000000, // 21 (GH/s) Decred - 1000, // 22 (kH/s) CryptoNight - 1000000 }; // 999 (MH/s) Ethereum - private void buttonSelectedProfit_Click(object sender, EventArgs e) { if (_selectedComputeDevice == null) { MessageBox.Show(International.GetText("FormSettings_ButtonProfitSingle"), @@ -594,10 +604,10 @@ private void buttonSelectedProfit_Click(object sender, EventArgs e) { MessageBoxButtons.OK); return; } - var url = "https://www.nicehash.com/?p=calc&name=" + _selectedComputeDevice.Name; - foreach (var algorithm in _selectedComputeDevice.DeviceBenchmarkConfig.AlgorithmSettings.Values) { + var url = Links.NHM_Profit_Check + _selectedComputeDevice.Name; + foreach (var algorithm in _selectedComputeDevice.GetAlgorithmSettingsFastest()) { var id = (int)algorithm.NiceHashID; - url += "&speed" + id + "=" + (algorithm.BenchmarkSpeed / div[id]).ToString("F2", System.Globalization.CultureInfo.InvariantCulture); + url += "&speed" + id + "=" + ProfitabilityCalculator.GetFormatedSpeed(algorithm.BenchmarkSpeed, algorithm.NiceHashID).ToString("F2", System.Globalization.CultureInfo.InvariantCulture); } url += "&nhmver=" + Application.ProductVersion.ToString(); // Add version info url += "&cost=1&power=1"; // Set default power and cost to 1 @@ -605,11 +615,10 @@ private void buttonSelectedProfit_Click(object sender, EventArgs e) { } private void buttonAllProfit_Click(object sender, EventArgs e) { - var url = "https://www.nicehash.com/?p=calc&name=CUSTOM"; + var url = Links.NHM_Profit_Check + "CUSTOM"; Dictionary total = new Dictionary(); - - foreach (var curCDev in ComputeDevice.AllAvaliableDevices) { - foreach (var algorithm in curCDev.DeviceBenchmarkConfig.AlgorithmSettings.Values) { + foreach (var curCDev in ComputeDeviceManager.Avaliable.AllAvaliableDevices) { + foreach (var algorithm in curCDev.GetAlgorithmSettingsFastest()) { if (total.ContainsKey(algorithm.NiceHashID)) { total[algorithm.NiceHashID] += algorithm.BenchmarkSpeed; } else { @@ -619,7 +628,7 @@ private void buttonAllProfit_Click(object sender, EventArgs e) { } foreach (var algorithm in total) { var id = (int)algorithm.Key; - url += "&speed" + id + "=" + (algorithm.Value / div[id]).ToString("F2", System.Globalization.CultureInfo.InvariantCulture); + url += "&speed" + id + "=" + ProfitabilityCalculator.GetFormatedSpeed(algorithm.Value, algorithm.Key).ToString("F2", System.Globalization.CultureInfo.InvariantCulture); } url += "&nhmver=" + Application.ProductVersion.ToString(); // Add version info url += "&cost=1&power=1"; // Set default power and cost to 1 @@ -642,9 +651,9 @@ private void buttonDefaults_Click(object sender, EventArgs e) { if (result == System.Windows.Forms.DialogResult.Yes) { IsChange = true; IsChangeSaved = true; - ConfigManager.Instance.GeneralConfig.SetDefaults(); + ConfigManager.GeneralConfig.SetDefaults(); - International.Initialize(ConfigManager.Instance.GeneralConfig.Language); + International.Initialize(ConfigManager.GeneralConfig.Language); InitializeGeneralTabFieldValuesReferences(); InitializeGeneralTabTranslations(); } @@ -679,36 +688,41 @@ private void FormSettings_FormClosing(object sender, FormClosingEventArgs e) { } // check restart parameters change - IsRestartNeeded = ConfigManager.Instance.GeneralConfig.DebugConsole != _generalConfigBackup.DebugConsole - || ConfigManager.Instance.GeneralConfig.NVIDIAP0State != _generalConfigBackup.NVIDIAP0State - || ConfigManager.Instance.GeneralConfig.LogToFile != _generalConfigBackup.LogToFile - || ConfigManager.Instance.GeneralConfig.SwitchMinSecondsFixed != _generalConfigBackup.SwitchMinSecondsFixed - || ConfigManager.Instance.GeneralConfig.SwitchMinSecondsAMD != _generalConfigBackup.SwitchMinSecondsAMD - || ConfigManager.Instance.GeneralConfig.SwitchMinSecondsDynamic != _generalConfigBackup.SwitchMinSecondsDynamic - || ConfigManager.Instance.GeneralConfig.MinerAPIQueryInterval != _generalConfigBackup.MinerAPIQueryInterval; + IsRestartNeeded = ConfigManager.IsRestartNeeded(); if (IsChangeSaved) { - devicesListViewEnableControl1.SaveOptions(); - ConfigManager.Instance.GeneralConfig.Commit(); - ConfigManager.Instance.CommitBenchmarks(); - International.Initialize(ConfigManager.Instance.GeneralConfig.Language); - } else if (IsChange) { - ConfigManager.Instance.GeneralConfig = _generalConfigBackup; - ConfigManager.Instance.BenchmarkConfigs = _benchmarkConfigsBackup; - ConfigManager.Instance.SetDeviceBenchmarkReferences(); + ConfigManager.GeneralConfigFileCommit(); + ConfigManager.CommitBenchmarks(); + International.Initialize(ConfigManager.GeneralConfig.Language); + } else { + ConfigManager.RestoreBackup(); } } private void currencyConverterCombobox_SelectedIndexChanged(object sender, EventArgs e) { - //Helpers.ConsolePrint("CurrencyConverter", "Currency Set to: " + currencyConverterCombobox.SelectedItem); var Selected = currencyConverterCombobox.SelectedItem.ToString(); - ConfigManager.Instance.GeneralConfig.DisplayCurrency = Selected; + ConfigManager.GeneralConfig.DisplayCurrency = Selected; } - #endregion Form Callbacks + #endregion Form Callbacks + + private void tabControlGeneral_Selected(object sender, TabControlEventArgs e) { + // set first device selected { + if (ComputeDeviceManager.Avaliable.AllAvaliableDevices.Count > 0) { + algorithmSettingsControl1.Deselect(); + } + } - private void Form_Settings_Resize(object sender, EventArgs e) { - pictureBox_MinProfit.Location = new Point(label_MinProfit.Location.X + label_MinProfit.Size.Width, pictureBox_MinProfit.Location.Y); + private void checkBox_Use3rdPartyMiners_CheckedChanged(object sender, EventArgs e) { + if (!_isInitFinished) return; + if (this.checkBox_Use3rdPartyMiners.Checked) { + // Show TOS + Form tos = new Form_3rdParty_TOS(); + tos.ShowDialog(this); + this.checkBox_Use3rdPartyMiners.Checked = ConfigManager.GeneralConfig.Use3rdPartyMiners == Use3rdPartyMiners.YES; + } else { + ConfigManager.GeneralConfig.Use3rdPartyMiners = Use3rdPartyMiners.NO; + } } } diff --git a/NiceHashMiner/Forms/Form_Settings.resx b/NiceHashMiner/Forms/Form_Settings.resx index 4c08298..1fcca13 100644 --- a/NiceHashMiner/Forms/Form_Settings.resx +++ b/NiceHashMiner/Forms/Form_Settings.resx @@ -112,1220 +112,15 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + 17, 17 - + 25 - - - - AAABAAQAEBAAAAEAIABoBAAARgAAAAAAAAABACAAGd4AAK4EAAAgIAAAAQAgAKgQAADH4gAAMDAAAAEA - IACoJQAAb/MAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAQQFGhdFVoMogKHNMZvE8DGawu4ofZ3JFD9PfAECAxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAACFkRWhz6/6/xCyv7/QMr+/0HK/v9Dyv7/RMv+/0XL/v8/uOb6FDpIeAAAAAAAAAAAAAAAAAAA - AAAAAAACImqFtEHK/f9Gz/7/Qcr+/0HF9/85p9D/O6nS/0fI+P9KzP7/S8z+/0vM/f8iW3CjAAAAAAAA - AAAAAAAAGk1gi0XO/f9Gz/7/RMXw/yFec/8mZn7/NpCx/ziQsf8uaYD/MGqB/0/H9P9Tzv7/Us79/xk/ - TXgAAAAAAwoMJDu87PxByv7/Pr3s/0Z4gf9Pzfb/Tc/+/1DO/v9Tz/7/V8/+/1bI9P88c4r/Wcn0/1zR - /v9QueL3AgQFFhpSZ4tAyv7/NqjR/yt8mf9Jzfz/TtT+/1PU/v9X0P7/XNH+/2DS/v9j0/7/ZdH6/1GR - rf9dud3/ZdP+/yFGVHgrh6rNQsr+/0XL/f85n8T/Ts7+/1TS/v9e1f7/X9L+/2XT/v9r1f7/b9b+/3LW - /v9ntNP/c9f9/3HW/v9CgJi6NKHK7EPL/v9HzP7/TM39/2XT/P9x0vX/bM/1/2jU/v9w1v7/fNPz/4PY - 9/+C2fz/gtr9/4Ha/v9/2v7/WJ242TWhyutFy/7/T8z7/3DP9P9sxe3/WbXm/0iq4/9Zuuv/VLPm/0yr - 4/9fuef/csjv/4LV9f+R3v3/jt7+/2Oft9gth6nJSMz+/1bE9P9FpeD/Io3Z/y+X3P87qeX/edb6/3/U - 9v8zpOX/KpLa/yiQ2f9HqOP/l9v5/57i/v9ahZe3G1BkhEnM/v9Qyfr/Nqfm/zqx6/9CvPH/V8z3/4Xb - /v+S3/7/Tcn3/0G47v84sOv/UK/m/7Xn/v+x5///N0pTcwMJCx5Gvev6Vs/7/0zK+f8qpej/W8Ty/4nb - +P+M3f7/nOH+/5De+P9IuO7/M6ro/07N/P/J7P3/rNDg9AMEBBIAAAAAHElaflnQ/f+D2ff/l932/6fm - +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 - AAAHETRBlzq04f5Bzf7/R8/+/0HL/v9Ayv7/Qcr+/0HK/v9Cyv7/Qsr+/0PL/v9Ey/7/RMv+/0XL/v9F - y/7/Rsv+/0bL/v9Gy/7/OaXO+AwjLHsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAADxtVasRAx/r/Qcr+/0HM/v9J0f7/Qcr+/0HK/v9Cyv7/Q8r+/0PL/v9Ey/7/Rcv+/0bL/v9G - y/7/R8z+/0jM/v9IzP7/Scz+/0nM/v9JzP7/RcHw/xY9TKUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAocWW/HQMr9/0HK/v9By/7/Ss7+/0PQ/v9Byv7/Qsr+/0PL/f89uOX/MpW5/y6Eo/8w - hqX/N5q+/0S+7P9KzP7/S8z+/0vN/v9Mzf7/TM3+/03N/v9Mzf7/Ssf2/xc+TaYAAAABAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAFEBOp0DM/P9BzP7/Q8v+/0rO/v9Ez/7/Qs7+/0HG+P8qfZv/EjA6/wkND/8T - KjP/Gj1K/xs9Sv8WKzP/EhUZ/x9ATf85jq7/Tsz7/0/O/v9Qzv7/UM7+/1DO/v9Qzv7/TMTx/w8nMH4A - AAAAAAAAAAAAAAAAAAAAAAAAAAgUGl1Bvu3/R8/+/0nQ/v9I0P7/Qs/+/0TP/v9Ircz/Eysu/xc8Sf8y - ja7/RcTz/0rM/v9Lzf7/Tc3+/07N/v9KwOz/Ooqo/yM9Sf8lQU3/SrTc/1TP/v9Uz/7/VM/+/1TP/v9U - z/7/Rq3U+QMHCTcAAAAAAAAAAAAAAAAAAAAMK4Wm6ELL/v9By/7/Qcz+/0HM/v9Cy/7/QZqy/3NSNv9M - p7z/SM/9/0rO/v9Lzf7/Tc3+/0/N/v9Qzv7/Us7+/1PP/v9Vz/7/Vc36/0GPrf8mN0H/SqfL/1nQ/v9Z - 0P7/WdD+/1jQ/v9Y0P7/K2Z8ygAAAAEAAAAAAAAAAAsjK3c/yPz/QMr+/0DK/v9Byv7/Qsr+/zObwf8Y - OD3/WMfp/1LT/v9L0P7/TdH+/0/R/v9Qzv7/Us7+/1TP/v9Wz/7/V9D+/1nQ/v9a0P7/XNH+/1O33P8w - RlL/VLbc/17R/v9e0f7/XdH+/13R/v9WxO7/Bg4RTgAAAAAAAAABJnmY30DK/v9Ayv7/Qcr+/0LK/v9A - wPD/FDVA/0G86f9K0P7/TND+/07W/v9Q1P7/UtP+/1TQ/v9Wz/7/WND+/1rQ/v9c0f7/XtH+/1/S/v9h - 0v7/YtL+/1m53f87WWj/YtH6/2PT/v9j0/7/YtL+/2HS/v8rXHC4AAAAAAEDBDo7vOz/QMr+/0HK/v8w - mLz/K4Sj/yFfdf83n8T/Scz+/0zR/v9O0v7/Udb+/1PV/v9W1f7/V9H+/1rQ/v9c0f7/X9H+/2HS/v9j - 0/7/ZdP+/2bT/v9n1P7/aNT+/1abt/9Qi6T/VJm1/1yy1P9o1P7/ZtP+/0+mx/kAAAAUDi46fkDK/v9B - yv7/Qsr+/0PL/v9BwvP/J2yE/0K45P9LzP7/TtD+/1HS/v9U1f7/V9b+/1zV/v9b0f7/XtH+/2HS/v9k - 0/7/ZtP+/2jU/v9q1P7/bNX+/23V/v9u1f7/Zbnb/1iPqP9u0/v/b9b+/27V/v9s1f7/adH5/wgPElQb - VmyvQMr+/0HK/v9Dy/7/RMv+/0bL/v9Hyfr/MH+a/03N/v9Qzv7/U9H+/1bS/v9a0/7/adX+/1/S/v9j - 0/7/ZtP+/2nU/v9s1f7/btX+/3DW/v9y1/7/dNf+/3XX/v9hm7T/dtj+/3bY/v911/7/dNf+/3PX/v9x - 1v7/HTlDhiRxj9BByv3/Qsr+/0TL/v9Gy/7/SMz+/0rM/v9KxvP/T87+/23T9/9yz/H/Y9H6/3PQ8v9g - 0v3/ZNP+/2fU/v9r1f7/btX+/3TS9v+C1/X/dNH1/4zb9v981/r/fNn+/3vT9v992f7/fdn+/3zZ/v97 - 2f7/edj+/3fY/v8vVmWnKX+g4UHK/v9Dy/7/Rcv+/0fM/v9JzP7/TM3+/0/O/v9Szv7/etn6/3LQ8v9x - 1fr/ccrt/2TT/f9o1P7/bNX+/3DW/v901/7/cs3x/4TX9/930fX/it/6/4ja+v+E2/7/hdv+/4Xb/v+F - 2/7/hNv+/4Lb/v+A2v7/ftn+/zpmd7gpgKHhQsr+/0TL/v9Gy/7/SMz+/0vM/v9ZzPj/b9L2/3LR9f92 - 0PT/bMjv/2jF7v9cuOf/Zcjx/2rN9P9w0vn/c9H2/3PN8v9sw+r/Y73s/3PI7v9yzPL/gNPz/4bX9f+L - 2fb/i9v6/43d/v+M3f7/it3+/4jc/v+F2/7/Pmd4uCZ1k9JDy/7/Rcv+/0fL/v9KzP7/Xsv1/3vT9f9u - y/P/Z8Hs/2C55/9Ur+L/RaTf/zmd3/80md3/NZre/2K+6v9Hpd3/M5jd/zaa3f89oOD/S6jf/1iz5P9k - vOj/aMXw/3LO9f+D1PP/ktz6/5Tf/v+S3/7/kN7+/4zd/v85XGqqHl10s0TL/v9Gy/7/SMz+/0vM/v9q - xe7/Wbjq/06r4P8xltv/IYzZ/yKN2f88ndv/Lpfe/z2j3/9kw+//dtL3/3HK8f9lvuj/MZrg/zab3/8w - lNj/IYzZ/yOO2v89ndn/VLLo/1687P+P1/X/neH+/5vh/v+Y4P7/lN/+/ytBS4oSNkSDRMv+/0fL/v9J - zP7/TM39/1q16P87nt//Pp7c/yGM2f8hjdn/IY7a/z2k4f8uqOr/Tbnr/3rZ/v+A2v7/htv+/4XX9/80 - rOj/Mafp/zWb3P8hjtr/IY3Z/yyT2f88nt3/P6Hg/4nR9P+m5P//o+P//6Di//+c4f7/EBgbWgMKDEFD - w/T/R8z+/0rM/v9Ozf7/Urnr/zCX3v84oOL/OqHe/y+Y2f8lktj/QbXr/znB+v9cx/H/f9r+/4Xb/v+L - 3f7/kd79/0S/8P83v/j/OaPf/yqV2P8zm9v/Qafi/y6Y3/86nN3/pd/6/7Dm//+t5f//qeT//4m91P0A - AAAaAAAABi+IquZIzP7/S83+/0/O/v9Szfz/RrLl/y+v7/8zuPT/QMP4/07M+/9Nz/7/UtL+/23O8v+D - 2/7/itz+/5De/v+X4P7/Yczz/07Q/v9Qz/3/SMn6/zq/9/8xtPL/Na7t/5TQ7f+96v//uur//7fp//+y - 6P//WHWBwQAAAAAAAAAAEjRBgUnM/f9Mzf7/UM7+/1bJ9f89wvn/P8T4/zyu5/8ypeT/Mafk/3LY+f96 - 3v//e9Hy/4fc/v+O3v7/ld/+/5zh/v+C1fP/c93//1nD7/8wpuT/NKfk/0G47P87xPv/V8f0/8Pq/P/F - 7P//wOv//7fm+v8VGx5aAAAAAAAAAAABAgMUN5m97k3N/v9Rzv7/YNP8/1DR/v9bzPT/JqTp/yen6/8r - qen/nuf9/6Tq/v+A0fL/it3+/5Lf/v+Z4P7/oeP//5vb8/+e6P//c87z/yep7P8mpur/Pa/o/1jU//9Q - 0f7/yO39/9Du///K7f//dIuW2AAAAAQAAAAAAAAAAAAAAAAOJi9sTMj3/1HO/v9t2P3/d97+/4ji/v9y - zPH/R7bq/0q36f+67///v/H+/4LT9P+N3f7/ld/+/53h/v+m5P//q+H1/7zw//+V2/X/PLPq/1S76/+I - 2/j/f+D//4Df/f/e8/7/2/L//8Lc6f4RExVGAAAAAAAAAAAAAAAAAAAAAAAAAAQjXHG3Us7+/1fP/f9t - zO//mNzy/7Xs/f+/8f//w/P//8L0///B9f//suz5/5ve9P+X4P7/nd/7/67m9f+/8/3/wfX//8P0///C - 8///u/D//6zm+P+k3PD/0+r2/+73///m9P3/QkhMkgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAxMy - fZrVV8/+/1vR/v9h0f3/qOf5/5fb8f+g4/f/quj1/5nh9v+f5Pb/ltzz/5ng/v+e3/v/p+Ty/7Dn9v+s - 4fH/wPf+/8Tm9P+16PX/3PH5//f6///6/P//+Pv+/2xvcrwAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAIEBRs0fJjTXNH+/2HS/v+t7Pr/g9by/5jl+v+S3vH/gdr+/4nc/v+R3v7/muH+/6Pj//+t - 5f//uOj//7Dg9P+x8/v/1e/7/7Dn8v/e9Pr//f3///39/f91dXW9AAAACwAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAECAxEoWm2xXsz2/3jV9v9y0/j/hdv3/4TX8/+B2v7/idz+/5He/v+a - 4f7/o+P//63m//+46f//vej7/7Dl8v/V7/v/zuv1/+j0+v/r6+z+UFBQlwAAAAYAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQIypiSpe16GzV/f9z1/7/etj+/4Ha/v+J - 3P7/kd7+/5ng/v+i4/7/rOX//7fp///B7P//zO7//9jx///j8vz/mp+i3BkZGUkAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEOGC43ckeGnthx - yu3/gNr+/4fc/v+P3v7/mOD+/6Di//+q5f7/tOj+/77r//+01eX+eIiRyyIlJ2MAAAAFAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAwQGBy8cMDdvN1lmnkt0hb1YgpTMXIOTy1Z1g7pEWWKZIywwaAICAyMAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gB///AAH//gAAf/gAAB/wAAAP4AAAB+AAAAfA - AAADgAAAAYAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGA - AAABgAAAAcAAAAPAAAAH4AAAB/AAAA/4AAAf/AAAf/8AAP//wAf/KAAAADAAAABgAAAAAQAgAAAAAAAA - JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIFBgUPMDwKBQ8TOAQMDmQDCg2AAwoNjQMKDYsD - Cw18BAwPWwYSFysOKzYIAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEJHyZmHVlwpSRxjtwpgaL/MZnB/ziw3P88 - vu//PsT2/z7E9v89u+z/N6vY/y+Tuv8pfp7/I2yI0RpRZZcBAwNYAAAAEgAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkCBogvTKLrPg9wPD+PsX4/0DK/v9A - y///QMr//0HK/v9Byv7/Qcr+/0HK/v9Byv7/Qcr+/0LK//9Cy///Qsv9/0HF9v8+v+/8JXKO8wEGB5gA - AAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMFBQAAAAAAAAAAJBVDUpspg6D/Q9P//03S//9A - y/7/QMr+/0DK/v9Ayv7/Qcr+/0HK/v9Byv7/Qcr+/0HK/v9Cy/7/Qsv+/0PL/v9Dy/7/Q8v+/0TL/v9E - y/7/R9L//0PJ+/8lbIf/EjZDeAAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAEDA95LY6x7z3B7v9C - 0///RM/+/0nN/v9Ayv7/Qcr+/0HK/v9Byv7/Qcr+/0LK/v9Cy/7/Q8v+/0PL/v9Dy/7/RMv+/0TL/v9E - y/7/Rcv+/0XL/v9Gy/7/Rsv+/0bM/v9Hzv//QLnm/yp4lt8AAABQAAAAAAAAAQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwwnML84 - r9z/Qs///0HN/v9Azv7/TtL+/0PN/v9Byv7/Qcr+/0HK/v9Byv7/Qsv+/0LL/v9Dy/7/RMv+/0TL/v9E - y/7/RMv+/0XL/v9Gy/7/Rsv+/0fM/v9HzP7/R8z+/0fM/v9HzP7/R8z+/0nP//8zkbT/CyAofAAAAAEA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAbHl111T/D9f9Czf//Qcv+/0HM/v9Gzv7/TNT+/0HM/v9Byv7/Qcr+/0LL/v9Dy/7/Q8v+/0TL/v9E - y/7/RMv+/0XL/v9Gy/7/R8z+/0fM/v9HzP7/R8z+/0jM/v9JzP7/Scz+/0nM/v9KzP7/Ss3+/0rN/v9M - 0///P6/Z/xtKXLEAAAAHGEFRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAABkaUmb4Q8///0HK/v9Byv7/Qcv+/0LM/v9O0f7/Q9L+/0HL/v9Cyv7/Qsv+/0PL/v9E - y/7/RMv+/0XL/v9Fy/7/Rsz+/0fM/v9HzP7/SMz+/0jM/v9JzP7/Ssz+/0rN/v9Kzf7/S83+/0vN/v9L - zf7/TM3+/0zN/v9Mzf7/TM3+/0jC8f8TMz/IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAFx9geN9E1f//Qcv+/0HL/v9By/7/Qcz+/03O/v9H0f7/QtH+/0LL/v9C - y/7/Rc3//0bU//8+vOn/NJzB/y6Gpf8oc4z/Jmh//yZpgf8reJL/M4qr/zyjyf9GxfP/TtX//03O//9M - zf7/Ts3+/03N/v9Ozf7/Ts7+/07O/v9Ozv7/Ts7+/07Q//9KxPL/GD9OugAAAAcAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAQOEgAAAAAAFD9NyD/H9/9Bzf7/Qcz+/0HM/v9DzP7/Uc/+/0bR/v9C - 0P7/Q8/+/0PL/v9H0///NqrS/xY+S/8MFxz/CgsO/wgDAv8IAAD/CQAA/wsCAf8MAwP/DgkK/xIUGP8W - ICb/JFZm/0a85v9Q0///UM7+/1DO/v9Qzv7/UM7+/1HO/v9Rzv7/Uc7+/1HO/v9Rz///Sbvn/xY5RocA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGFBqRO7/p/0HR//9Bzv7/Q87+/0nO/v9P - 0P7/RND+/0PQ/v9D0P7/Q83//zir1P8VP0z/AgAA/wwVGf8VMTv/JGN4/zSSs/8+sNf/Qr/o/0O95/8/ - rNP/No6r/yhfcf8eNT//Fxsg/xEJCv8sYnX/S73n/1PR//9Tz/7/U8/+/1TP/v9Uz/7/VM/+/1TP/v9U - z/7/VNH//zqQsf8CBgdAAAAAAAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAEA9ocn7TND//0zQ/v9N - 0/7/S9P+/0jS/v9D0f7/Q9L+/0PQ/v9U1f//RH6C/xMaEP8KFBf/K32Z/z6y3P9Jzv//TNL//0zQ//9N - z///Ts///07P//9Q0P//UdH//1PU//9QzPr/R6/W/zR1jP8YFRf/HiUr/z6Oq/9Z2v//VtD+/1bQ/v9W - 0P7/VtD+/1bQ/v9W0P7/VdD+/1jW//8vcovxAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyBheb1C - yvr/Q87+/0LN/v9AzP7/Qs7+/0LP/v9Cz/7/Q8v+/0XH9/9qcGT/hEEZ/0Nzbf9Jz/7/Sc///0rM/v9K - zf7/TM3+/03N/v9Nzv7/UM7+/1DO/v9Sz/7/Us/+/1TP/v9Uz/7/Vc/+/1fT//9Uy/f/LE1c/x8YHP84 - c4r/WdH//1nR/v9Z0P7/WdD+/1nQ/v9Z0P7/WdD+/1jQ/v9Z0v//GDxImQAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAARDOfyP9Ay///QMr+/0HK/v9Byv7/Qcr+/0LK/v9Dy/7/RM///x1OW/9APiP/c6m2/2Tf//9M - 0v//S9L+/0zS/v9N0f7/Ts/+/0/O/v9Qzv7/Us7+/1PP/v9Uz/7/VdD+/1bQ/v9X0P7/WND+/1nR/v9a - 0f//W9P//0KIpP8kIif/P3qR/1/Y//9c0f7/XdL+/1zS/v9c0v7/XNH+/1zR/v9b0f7/P5Cv8gsaHxkA - AAAAAAAAAAAAAAAAAAAAF0ZX50LR//9Ayv7/QMr+/0HK/v9Byv7/Qsr+/0PL/v9F0P//HFFj/woQE/9D - stb/Wtf+/1LT/v9L0P7/TdD+/07R/v9P0v7/UdL+/1HO/v9Sz/7/VM/+/1XP/v9W0P7/WND+/1nQ/v9a - 0f7/W9H+/1zR/v9d0f7/XdL+/1/S/v9Qqcr/KSct/0iSrf9i1///YNL+/2DS/v9g0v7/YNL+/1/S/v9f - 0v7/Wcjy/xAlLIwAAAAAAgECAAAAAAAAAABJN6/c/0HM//9Ayv7/Qcr+/0HK/v9Cyv7/Q8v+/0TL/v8y - l7v/ChIV/zimzP9K1P//SdH+/0vQ/v9N0/7/T9b+/1DU/v9R0/7/U9P+/1TQ/v9Vz/7/VtD+/1jQ/v9Z - 0P7/W9H+/1zR/v9d0f7/XtH+/1/S/v9g0v7/YdL+/2LT/v9k1///TZSv/y4sMv9aut7/ZNT+/2TT/v9j - 0/7/Y9P+/2LT/v9i0/7/ZNn//zJuhf8AAAADAAAAAAAAAAAYSFyjQc3//0DK/v9Byv7/Qcr+/0TR//9G - 1f//RtD//0fS//8PKC//M5Gz/0nP//9Kz/7/TNL+/03R/v9O2P7/Udj+/1LV/v9U1v7/VdT+/1fR/v9X - 0P7/WdH+/1vR/v9c0f7/XtL+/1/S/v9g0/7/YtP+/2LT/v9k0/7/ZdT+/2XU/v9m1P7/aNj//0yIov9C - ZHX/Z9P9/2nZ//9q3f//aNf//2bU/v9l1P7/ZdX//2DM9v8AAABrAAAAAAAAABAriKvUQMr//0HK/v9B - yv7/Q87//yNyi/8VQk//KHyW/yp8mP8YOkf/R8r7/0nM/v9L0P7/TdL+/0/S/v9R1f7/Utb+/1TV/v9V - 1v7/WNb+/1jR/v9a0P7/XNH+/17R/v9f0v7/YNL+/2LT/v9j0/7/ZdP+/2bU/v9o1P7/aNT+/2nV/v9q - 1f7/atX+/2vS+/9BVGL/X7TU/1CHnv9DYG7/WanH/2vY//9q1f7/aNT+/2vb//8oU2PGAAAAAA8uOiAx - nMT7Qcr+/0HK/v9Byv7/Qsv+/0XP//9DzP//OqzV/yFcb/8mZ33/StD//0vN/v9Mzv7/T9P+/1HS/v9S - 1f7/VNb+/1bW/v9Y1/7/WNT+/1vR/v9d0f7/X9L+/2DT/v9i0/7/ZNT+/2bU/v9o1P7/adX+/2vV/v9r - 1f7/bNb+/27W/v9u1v7/b9b+/2/W/v9RfJH/V4+o/2nD5v9v2f//cNj//27W/v9t1v7/bdb+/2zX//9N - mrjiAAAAFxQ+TUg3q9f/Qcr+/0HK/v9Cy/7/Q8v+/0TL/v9Fy/7/R8v+/0jP//8qc4v/QrPd/0zN/v9O - zv7/UM/+/1PU/v9U1P7/VtX+/1jW/v9l2P7/ctr+/17S/v9f0v7/YtP+/2PT/v9m1P7/Z9T+/2rV/v9r - 1f7/bNX+/27W/v9v1v7/cdb+/3LX/v9y1/7/dNj//2q+3/9ck6z/dNj+/3TY/v9z1/7/c9f+/3PX/v9x - 1/7/cNb+/2/W/v9fudzzBQkLMhE2Q30+wfP/Qcr+/0HK/v9Dy/7/RMv+/0TL/v9GzP7/R8z+/0nM/v9A - rtf/MYGa/0/R//9Qzv7/Ts7//1HQ//9V0v7/WNP+/1nT//9e0/7/Y9T+/2DS/v9i0/7/ZNP+/2fU/v9p - 1P7/a9X+/23W/v9u1v//cNf//3LX/v9z2P//c9j//3bY/v932f7/euD//1V0hP920/b/edj+/3nY/v94 - 2P7/d9j+/3fZ/v922P7/dNf+/3TY/v9ju97/JkdUSBM8SqVCzv//Qcr+/0LL/v9EzP7/RMz+/0bM/v9H - zP7/SM3+/0rN/v9Lzfz/Ssfz/0/P//9Oz///g9Hs/4DP6v9cz/v/Xs/6/2rH6/9mz/f/YNP+/2TT/v9l - 1P7/Z9T+/2rV/v9s1v7/b9b+/3LV/P92ze7/fM/u/3XZ//+CzOf/jdTs/3zY/P982f7/fdv//3nR8/9+ - 2///ftr+/37a/v992v7/fNr+/3vZ/v972f7/edn+/3jY/v9rxOf/MFdmYxlPY75Cz///Qsr+/0PL/v9E - y/7/Rcv+/0fM/v9HzP7/Ss3+/0vO/v9Nzv7/T87+/1HO/v9Ozf7/meP4/4HY9f9c0Pv/cNb7/5jo//9o - w+b/Y9T//2bU/v9p1P7/a9X+/27V/v9w1v7/c9f+/3HP9P+G3fr/mef//3vZ/v92yeb/lef+/4Ha/f+A - 2v7/gdv+/4Lb/v+C2/7/gtv+/4Lb/v+C2/7/gdv+/4Da/v9/2v7/fdr+/3zZ/v9zzO//M1tqehxYb8xD - z///Q8v+/0PL/v9Fy/7/Rsv+/0fM/v9JzP7/Ss3+/03N/v9Ozv7/UM7//1HP//9Nyvv/n+j9/3nT8v9b - z/v/eNb4/33V+f9cveX/Z9X//2nV/v9s1f7/btb+/3DX/v901/7/dtj+/3LP9P91z/P/gtf5/4be//9z - xeT/lef//4HW+P+G3f//h93//4fd/v+H3f7/iN3+/4fd/v+H3P7/htz+/4Xc/v+E3P7/gtv+/4Hb/v95 - 0fP/Nl1thB1ZcM1Dz///Q8v+/0TL/v9Fy/7/R8z+/0jM/v9KzP7/TM3+/03N/f9Uzvz/XMny/23O8f9u - y+7/h9v6/3HM8f9dyvT/dM/0/2W/7f9bv+j/atT9/2zU/P9u1f3/ddj+/3jY/f931/z/etf8/3bQ9f9k - ver/a8Xw/4HU9f92x+n/ftj7/4bS7/+J1PH/h9Pw/4jY+P+M3f3/jd7+/4ze/v+M3v7/i93+/4rd/v+I - 3f7/h9z+/4bc/v9+0vT/OF9uhRtUacFE0P//RMv+/0TL/v9Gy/7/R8z+/0nM/v9Lzf7/UMr4/3fT9P+E - 2fb/hdr6/3nU+P9xzfX/ZsTy/2LA7/9guen/VbHm/0mq5f9SruP/T6zh/1Gv4/9XtOT/c9P6/2K54v9U - sOT/Uq3h/1Ot4v9KquT/Tq7m/1y25/9hvu//Y8Hw/2zJ9P900Pf/ftj6/4Xa+P+L2fX/jNXy/5Ph//+R - 4P7/kd/+/5Df/v+O3/7/jN7+/4rd/v+B0PD/Ol5tfBZDVKlE0P//RMv+/0XL/v9HzP7/Scz+/0rN/v9N - zP3/ddDy/3fT9/9wzPT/aMXy/2TA7v9ft+P/XbPg/1Sr3P9Kp93/QKLh/zec3/8zmN3/L5fd/y6W3f84 - m9z/c9L4/0yn2P8tlt7/L5bc/zGX3P82m97/O57g/0al3/9Pqdr/W7Lf/2C14f9hu+n/ZsTx/2zK8/9y - 0Pb/h9n3/5DX8/+X4f//l+D+/5Xg/v+U4P7/kd/+/4/f/v+CzOn/PF5saBI3RINCx/n/RMv+/0bL/v9I - zP7/Sc3+/0vN/v9Ry/r/dcnv/2G/7/9auez/VrHi/0Og2v8tlN3/JpDb/yeQ2/8okNj/S6Ta/y6W3f8u - l97/QKPf/1i35/9evOj/e9f7/27G7P9euuf/VrLh/y+X3v8ult3/N5rc/ziZ2P8pktv/JI7b/yeR3P84 - mtz/Uard/1e36/9evO7/ZcPx/4zU8v+d4v//nOL//5vh//+Z4P7/l+D+/5Tf/v+BxeD/OVViTBVBUU87 - st//Rcv+/0bM/v9IzP7/Ssz+/0vN/v9hzvj/XLbp/0ys5f9IqOT/MZDO/yCM2v8hjNn/IY3Z/yGN2v8e - jNn/U63g/y2c4/8uoeb/Vbno/3nZ/v982/7/f9v+/4Tc/v+I3v//iN76/zGe3f8un+X/N5/h/zWa3P8h - jdr/IY3Z/yGM2f8gjNr/JYnN/0up4v9IqeX/T7Dn/3nJ8f+k5P7/ouT//6Hj//+e4///nOL//5rh//+E - xN72GSQoNhdEViI2oMn/Rsv+/0fM/v9JzP7/S83+/0vN/v9q0/v/Sabj/zmc3/83m97/S6fi/x6L2f8h - jtr/IY7a/yKQ2/8fjtr/VLfp/y2r7v8wsvD/XcLt/3vZ/v9/2v7/g9v+/4fc/v+L3f7/kOD//zet4/8u - r/D/N63r/zef3/8ikNv/Io/b/yGO2v8fjNr/P6Df/zye3/83m97/O5/h/3PC7v+s5v//qOX//6bk//+k - 5P//ouP//6Dk//99tMzlAAAAHAAAABMzlbvZR8z+/0jM/v9KzP7/S83+/03O/v9Uzv3/UKzl/y6W3f8t - lt7/R6nm/0ak2/8kjtX/H4/c/x+R3v8fjtf/WMr4/zO9+P87w/r/Zsnv/37a/v+C2/7/htz+/4rd/v+O - 3v7/k9/+/0m96/82wPr/O773/zml4v8gkd7/H5Dd/x+M1/83mNb/T63l/y6X3v8uld3/M5ne/5HT9P+y - 6P//r+f//63m//+r5v//p+X//6jp//9QcX7MAAAAAAAAAAAhYXqtSM7//0jM/v9Kzf7/TM3+/07O/v9Q - zv7/Tr7r/z2h3v8voOX/LaXp/zKs7v9LvO7/S7bj/0uz4v9Kr97/S87//0PL//9Mz/7/b8zw/4Hb/v+F - 2/7/id3+/47e/v+S3/7/l+D+/1zG7f9Gzf//Qsr+/0y86v9KseD/TLTj/1G86v87tfH/Lafq/y6h5v81 - oOH/abPb/73s//+46f//tuj//7Po//+x5///ref//6zq//8NERN8AAAAAAAAAAAAAABWRMLx/0nN//9L - zf7/Tc3+/0/O/v9Sz/7/VND//1O75f84tPH/MLb0/zW++f89wfb/SMj4/0rK+P9L0P7/TtL//1fU//9k - 2P7/dc3v/4Tc/v+I3P7/jd7+/5Df/v+V4P7/muH//3DL7f9b1v//UtP//0zR//9LzPn/Scn4/0LD9v84 - v/j/Mrn2/zGz8v9cvOj/vuj8/8Hs//+/7P//vev//7rr//+36v//uO7//3OYqP8AAAAQAAAAAAAAAAAA - AAAAJGR99EzU//9Mzf7/Ts3+/1DO/v9Sz/7/W8ny/zu+9v83wfr/QMn//1G75/89rOf/L6Xn/zGp6f9Z - vun/atz//3Dd//+B4P7/ds3w/4fc/v+L3f7/kN/+/5Tg/v+Z4f//nuL//4HQ7f933v//bNz//2XM8v82 - rOr/LqXn/zWo6P9Ks+b/R8f4/zrE+/81v/n/bcjs/8rt///G7f//w+3//8Ls//++6///uev//zM/RqMA - AAAAAAAAAAAAAAAAAAAAAwgKW0K44/9Mzf//Ts7+/1DO/v9Uz/3/V834/0LL//9Iz///Srvl/yWg5/8k - ouf/JqTp/yOl6v9pxOz/heT//47l//+U3vb/e9L1/4jc/v+N3v7/kt/+/5fg/v+c4v//ouP//5LW8P+S - 5f7/iOT//3/W9P8lpuv/Jqbp/yWj6P8joOf/Pqze/0rR//9DzP//Rcv//7zl9v/O7///y+7//8ft///D - 7P//krTC/DU/RiEAAAAAAAAAAAAAAAAAAAAABAoLAyx4lM5MzP3/Ts7+/1HP/v9X0P7/Ztj+/1XU//9c - 1///ctT1/x+i6v8oqez/Kavt/ySr7/+C0u//oer//6vt//+Z1ur/gdn9/4rd/v+Q3v7/leD+/5rh//+f - 4///pOT//5/b9P+p6Pv/pOv//57h9v8nre7/Kazu/yiq7P8kpuv/W8Lv/2HZ//9X1f//T9L//8Lu/v/W - 8f//0vD//87u///M8P//XnJ6qQAAAAISERUAAAAAAAAAAAAAAAAAAAAAAA4mL1BGuub8UM///1HP/v9X - 0P7/ed7+/2/c//933v//j+f//2rF7f8xsO3/LrDu/ySv7/+f3fP/t/D//7/y//+Z0ub/ht3//43e/v+R - 3/7/luD+/5zh//+i5P//p+X//6bd9f+57fv/ufD//77t+f8or+7/LbHv/zGx7v9Etuz/juH7/3vf//9x - 3f//b93//9z1///e8///2fH//9n0//+etcL5AAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ - Q1OsT87+/1LP/v9Vz/7/ZdL7/4HT7/+c7P//nun//6zt//+l4vb/l9rz/4/W8v+97vv/wfP//8P1//+5 - 6/j/jNb1/4PR8v+V4P//mOH//5/j//+c3Pj/otrz/7bn9//C9P7/wvT//8f0//+Q1vL/lNrz/57e9f+u - 6vv/o+v//5vq//+G3Pf/tub3/+34///n9f//4/b//7nM1/8mKS1lAAAAAAMGBQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAJWB34FPR//9Vz/7/WND+/1jL+P9wvt7/p+Dx/77y///A8v//wvP//8L0///C - 9v//wvb//8L3///B9///wPj//8L0+v+N1/b/muH//5/i/v+v5/b/wPj//8D3///C9///wvb//8L2///C - 9f//wvP//8Hy//+/8f//tOr5/5bP4//D3ev/9Pr///H6///u+P//4e72/2hvdaEAAAAAFhUZAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAABxMWJDmPr+tY1v//WND+/1zR/v9d1P//Xcz4/5LX8P/L - +v//hM3o/53g9f+/9v7/sOr2/6bn9/+p6ff/q+z4/5/e6v+R3fz/nOL//6Hj//+d3O//rOz2/7Ds9/+1 - 6/f/tOn2/7z0/f++6/b/tt7u/8Dy/P/E8fv/1+nz//r8///9/v//+/3///r8///3/f//iIyR0gAAABIX - FxoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAAAAAAAADA4h6X/XNj//1zR/v9g - 0v7/X9L//6Di9//F9Pv/Zsju/4re/P+59///jdTn/3/Z/f+H2/z/jN38/5He+/+W4P7/nOL//6Pj//+n - 5P3/rub9/7Xn/f+86f3/uOb5/6jr9f/D7vf/0ur5/7bp8//I9v7/7vj9//v8///+/f////7///7///91 - d3jiCAUKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAAAAAAAA - AAAsPI6t61zR/v9g0///XtL//6rm9v+v6PD/bNL6/43g+/+y+f//g8/n/4Hb//+G3P7/jN3+/5Hf/v+X - 4P7/neL//6Pj//+p5v//sOf//7fp//++6///vOj6/6Hq9f+78Pj/4PL//6Hb6P+68/z/7fj8//79//// - ////9vb2/5qZmtEAAAASAAAAAEE/RQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAEAAQAAAAAACA8TIixjd9Zez/v/YtT//33Y+P+C1fD/b9b+/4PZ9/+c4/H/gs7p/4Hb//+G - 3P7/jN3+/5Lf/v+X4P7/neL//6Pk//+p5v//sOf//7jp//+/7P//v+n7/6Df7P+x5PD/4fP//7/j8P/Q - 7/f/8/n9///////f3+D/b29vpAAAABAAAAAAQUBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQIAAAAAAAAAAAAcO0idWLzi+2XT/P9r1v//b9b+/3PX/v92 - 2f//fNr//4Hb/v+G3P7/i93+/5Hf/v+W4P7/neL//6Pj//+p5v//sOf//7fp//++7P//xe3//8/v///W - 8f//3vP//+j2///x+f//8/f7/9LT1vQ3Nzd0AAAAABAQEAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYGACl0kQAAAAAADBofRj19lr5b - ttn/ct3//3TZ//932P7/fNn+/4Hb/v+G3P7/i93+/5Df/v+W4P7/m+L//6Lj//+o5f//ruf//7Xp//+9 - 6///xO3//8vu///S8P//3fX//+v9//+3wMb/hIiLpgAAAC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAkLDwMEBwk/MF5v3WW/4v942///e9r//4Db/v+F3P7/it7+/5Df/v+V4P7/m+L//6Hj//+n - 5f//reb//7Tp//+66///wez//8nv///R8f//rcPO/0xSV7wlISglAAIAAAAAAAAAAAAAS0lMAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAATEwAAAAAAAAAAAAAAADoyWmqZV5u1y2exzu5vuNb/f8zs/47e/v+X - 5P//nOX//6Lm//+o6f//qOL7/6DS5/+ZwtT/mb3N6IOdqcRIUliIAAAAJQAAAAAAAAAAHRogAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgHiMAAAAAAAAAAAAAAAAAAAAACx8zPBw+ - ZHQwM05aXi5GUIM4Ul2cPlpmpkFbaKU8UVuXOkxVfUdaZVRWanQqISgsGQAAAAcAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//gAH/ - /wAA//4AAH//AAD/+AAAH/8AAP/gAAAH/wAA/8AAAAP/AAD/AAAAAP8AAP4AAAAAfwAA/AAAAAB/AAD4 - AAAAAB8AAPgAAAAAHwAA8AAAAAAPAADgAAAAAAcAAMAAAAAABwAAwAAAAAADAADAAAAAAAMAAIAAAAAA - AQAAgAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AQAAgAAAAAABAACAAAAAAAEAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAOAAAAAABwAA8AAAAAAPAAD4 - AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/8AAAAP/AAD/4AAAB/8AAP/wAAAf - /wAA//4AAH//AAD//4AB//8AAA== - - \ No newline at end of file diff --git a/NiceHashMiner/TextBoxKeyPressEvents.cs b/NiceHashMiner/Forms/TextBoxKeyPressEvents.cs similarity index 96% rename from NiceHashMiner/TextBoxKeyPressEvents.cs rename to NiceHashMiner/Forms/TextBoxKeyPressEvents.cs index bfdcc17..6d340c5 100644 --- a/NiceHashMiner/TextBoxKeyPressEvents.cs +++ b/NiceHashMiner/Forms/TextBoxKeyPressEvents.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; namespace NiceHashMiner { @@ -23,7 +21,7 @@ public static void textBoxDoubleOnly_KeyPress(object sender, KeyPressEventArgs e // allow only one zero var textBox = sender as TextBox; string checkText = textBox.Text; - if (e.KeyChar != '.' && textBox.SelectionLength != textBox.Text.Length && IsHandleZero(e, checkText) && !checkText.Contains('.')) { + if (e.KeyChar != '.' && textBox.SelectionLength != textBox.Text.Length && IsHandleZero(e, checkText) && !checkText.Contains(".")) { e.Handled = true; return; } diff --git a/NiceHashMiner/Globals.cs b/NiceHashMiner/Globals.cs index 2364d7f..dd6181f 100644 --- a/NiceHashMiner/Globals.cs +++ b/NiceHashMiner/Globals.cs @@ -5,15 +5,50 @@ namespace NiceHashMiner { public class Globals { + // Constants public static string[] MiningLocation = { "eu", "usa", "hk", "jp" }; + public static readonly string DemoUser = "3DJhaQaKA6oyRaGyDZYdkZcise4b9DrCi2"; + // change this if TOS changes + public static int CURRENT_TOS_VER = 2; + + // Variables public static Dictionary NiceHashData = null; - public static double BitcoinRate; - public static string DemoUser = "34HKWdzLxWBduUfJE9JxaFhoXnfC6gmePG"; + public static double BitcoinUSDRate; public static JsonSerializerSettings JsonSettings = null; public static int ThreadsPerCPU; // quickfix guard for checking internet conection public static bool IsFirstNetworkCheckTimeout = true; public static int FirstNetworkCheckTimeoutTimeMS = 500; public static int FirstNetworkCheckTimeoutTries = 10; + + + public static string GetLocationURL(AlgorithmType AlgorithmType, string miningLocation, NHMConectionType ConectionType) { + if (Globals.NiceHashData != null && Globals.NiceHashData.ContainsKey(AlgorithmType)) { + string name = Globals.NiceHashData[AlgorithmType].name; + int n_port = Globals.NiceHashData[AlgorithmType].port; + int ssl_port = 30000 + n_port; + + // NHMConectionType.NONE + string prefix = ""; + int port = n_port; + if (NHMConectionType.LOCKED == ConectionType) { + return miningLocation; + } + if (NHMConectionType.STRATUM_TCP == ConectionType) { + prefix = "stratum+tcp://"; + } + if (NHMConectionType.STRATUM_SSL == ConectionType) { + prefix = "stratum+ssl://"; + port = ssl_port; + } + + return prefix + + name + + "." + miningLocation + + ".nicehash.com:" + + port; + } + return ""; + } } } \ No newline at end of file diff --git a/NiceHashMiner/Interfaces/IBenchmarkCalculation.cs b/NiceHashMiner/Interfaces/IBenchmarkCalculation.cs new file mode 100644 index 0000000..11e135b --- /dev/null +++ b/NiceHashMiner/Interfaces/IBenchmarkCalculation.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Interfaces { + public interface IBenchmarkCalculation { + void CalcBenchmarkDevicesAlgorithmQueue(); + } +} diff --git a/NiceHashMiner/Interfaces/IBenchmarkComunicator.cs b/NiceHashMiner/Interfaces/IBenchmarkComunicator.cs index 62dcd99..3845872 100644 --- a/NiceHashMiner/Interfaces/IBenchmarkComunicator.cs +++ b/NiceHashMiner/Interfaces/IBenchmarkComunicator.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Interfaces { public interface IBenchmarkComunicator { diff --git a/NiceHashMiner/Interfaces/IListItemCheckColorSetter.cs b/NiceHashMiner/Interfaces/IListItemCheckColorSetter.cs index dc0987b..ad96b0d 100644 --- a/NiceHashMiner/Interfaces/IListItemCheckColorSetter.cs +++ b/NiceHashMiner/Interfaces/IListItemCheckColorSetter.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; namespace NiceHashMiner.Interfaces { diff --git a/NiceHashMiner/Interfaces/IMainFormRatesComunication.cs b/NiceHashMiner/Interfaces/IMainFormRatesComunication.cs index 9a1c854..0115fcd 100644 --- a/NiceHashMiner/Interfaces/IMainFormRatesComunication.cs +++ b/NiceHashMiner/Interfaces/IMainFormRatesComunication.cs @@ -1,15 +1,14 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Interfaces { public interface IMainFormRatesComunication { void ClearRatesALL(); void ClearRates(int groupCount); void AddRateInfo(string groupName, string deviceStringInfo, APIData iAPIData, double paying, bool isApiGetException); - void ShowNotProfitable(); + void ShowNotProfitable(string msg); void HideNotProfitable(); + //void RaiseAlertSharesNotAccepted(string algoName); } } diff --git a/NiceHashMiner/Interfaces/IMinerUpdateIndicator.cs b/NiceHashMiner/Interfaces/IMinerUpdateIndicator.cs index 144507b..9bc6b08 100644 --- a/NiceHashMiner/Interfaces/IMinerUpdateIndicator.cs +++ b/NiceHashMiner/Interfaces/IMinerUpdateIndicator.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Interfaces { public interface IMinerUpdateIndicator { diff --git a/NiceHashMiner/Interfaces/IPathsProperties.cs b/NiceHashMiner/Interfaces/IPathsProperties.cs deleted file mode 100644 index ec2f9d6..0000000 --- a/NiceHashMiner/Interfaces/IPathsProperties.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NiceHashMiner.Interfaces { - public interface IPathsProperties { - string FilePath { get; set; } - string FilePathOld { get; set; } - } -} diff --git a/NiceHashMiner/Miners/ClaymoreBaseMiner.cs b/NiceHashMiner/Miners/ClaymoreBaseMiner.cs new file mode 100644 index 0000000..d8c0ba5 --- /dev/null +++ b/NiceHashMiner/Miners/ClaymoreBaseMiner.cs @@ -0,0 +1,285 @@ +using Newtonsoft.Json; +using NiceHashMiner.Configs; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; +using NiceHashMiner.Net20_backport; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace NiceHashMiner.Miners { + public abstract class ClaymoreBaseMiner : Miner { + + protected int benchmarkTimeWait = 2 * 45; // Ok... this was all wrong + int benchmark_read_count = 0; + double benchmark_sum = 0.0d; + protected readonly string LOOK_FOR_START; + const string LOOK_FOR_END = "h/s"; + + // only dagger change + protected bool ignoreZero = false; + protected double api_read_mult = 1; + + public ClaymoreBaseMiner(string minerDeviceName, string look_FOR_START) + : base(minerDeviceName) { + ConectionType = NHMConectionType.STRATUM_SSL; + LOOK_FOR_START = look_FOR_START.ToLower(); + IsKillAllUsedMinerProcs = true; + } + + protected abstract double DevFee(); + + protected override int GET_MAX_CooldownTimeInMilliseconds() { + return 60 * 1000 * 5; // 5 minute max, whole waiting time 75seconds + } + + private class JsonApiResponse { + public List result { get; set; } + public int id { get; set; } + public object error { get; set; } + } + + protected void KillClaymoreMinerBase(string exeName) { + foreach (Process process in Process.GetProcessesByName(exeName)) { + try { process.Kill(); } catch (Exception e) { Helpers.ConsolePrint(MinerDeviceName, e.ToString()); } + } + } + + public override APIData GetSummary() { + _currentMinerReadStatus = MinerAPIReadStatus.NONE; + APIData ad = new APIData(MiningSetup.CurrentAlgorithmType); + + TcpClient client = null; + JsonApiResponse resp = null; + try { + byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes("{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"miner_getstat1\"}n"); + client = new TcpClient("127.0.0.1", APIPort); + NetworkStream nwStream = client.GetStream(); + nwStream.Write(bytesToSend, 0, bytesToSend.Length); + byte[] bytesToRead = new byte[client.ReceiveBufferSize]; + int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize); + string respStr = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead); + resp = JsonConvert.DeserializeObject(respStr, Globals.JsonSettings); + client.Close(); + //Helpers.ConsolePrint("ClaymoreZcashMiner API back:", respStr); + } catch (Exception ex) { + Helpers.ConsolePrint(this.MinerTAG(), "GetSummary exception: " + ex.Message); + } + + if (resp != null && resp.error == null) { + //Helpers.ConsolePrint("ClaymoreZcashMiner API back:", "resp != null && resp.error == null"); + if (resp.result != null && resp.result.Count > 4) { + //Helpers.ConsolePrint("ClaymoreZcashMiner API back:", "resp.result != null && resp.result.Count > 4"); + var speeds = resp.result[3].Split(';'); + ad.Speed = 0; + foreach (var speed in speeds) { + //Helpers.ConsolePrint("ClaymoreZcashMiner API back:", "foreach (var speed in speeds) {"); + double tmpSpeed = 0; + try { + tmpSpeed = Double.Parse(speed, CultureInfo.InvariantCulture); + } catch { + tmpSpeed = 0; + } + ad.Speed += tmpSpeed; + } + ad.Speed *= api_read_mult; + _currentMinerReadStatus = MinerAPIReadStatus.GOT_READ; + } + if (ad.Speed == 0) { + _currentMinerReadStatus = MinerAPIReadStatus.READ_SPEED_ZERO; + } + // some clayomre miners have this issue reporting negative speeds in that case restart miner + if (ad.Speed < 0) { + Helpers.ConsolePrint(this.MinerTAG(), "Reporting negative speeds will restart..."); + this.Restart(); + } + } + + return ad; + } + + protected override void _Stop(MinerStopType willswitch) { + Stop_cpu_ccminer_sgminer_nheqminer(willswitch); + } + + private bool IsActiveProcess(int pid) { + try { + return Process.GetProcessById(pid) != null; + } catch { + return false; + } + } + + + protected override string GetDevicesCommandString() { + string extraParams = ExtraLaunchParametersParser.ParseForMiningSetup(MiningSetup, DeviceType.AMD); + string deviceStringCommand = " -di "; + List ids = new List(); + foreach (var mPair in MiningSetup.MiningPairs) { + ids.Add(mPair.Device.ID.ToString()); + } + deviceStringCommand += StringHelper.Join("", ids); + + return deviceStringCommand + extraParams; + } + + // benchmark stuff + + protected override void BenchmarkThreadRoutine(object CommandLine) { + Thread.Sleep(ConfigManager.GeneralConfig.MinerRestartDelayMS); + + BenchmarkSignalQuit = false; + BenchmarkSignalHanged = false; + BenchmarkSignalFinnished = false; + BenchmarkException = null; + + try { + Helpers.ConsolePrint("BENCHMARK", "Benchmark starts"); + Helpers.ConsolePrint(MinerTAG(), "Benchmark should end in : " + benchmarkTimeWait + " seconds"); + BenchmarkHandle = BenchmarkStartProcess((string)CommandLine); + BenchmarkHandle.WaitForExit(benchmarkTimeWait + 2); + Stopwatch _benchmarkTimer = new Stopwatch(); + _benchmarkTimer.Reset(); + _benchmarkTimer.Start(); + //BenchmarkThreadRoutineStartSettup(); + // wait a little longer then the benchmark routine if exit false throw + //var timeoutTime = BenchmarkTimeoutInSeconds(BenchmarkTimeInSeconds); + //var exitSucces = BenchmarkHandle.WaitForExit(timeoutTime * 1000); + // don't use wait for it breaks everything + BenchmarkProcessStatus = BenchmarkProcessStatus.Running; + bool keepRunning = true; + while (keepRunning && IsActiveProcess(BenchmarkHandle.Id)) { + //string outdata = BenchmarkHandle.StandardOutput.ReadLine(); + //BenchmarkOutputErrorDataReceivedImpl(outdata); + // terminate process situations + if (_benchmarkTimer.Elapsed.TotalSeconds >= (benchmarkTimeWait + 2) + || BenchmarkSignalQuit + || BenchmarkSignalFinnished + || BenchmarkSignalHanged + || BenchmarkSignalTimedout + || BenchmarkException != null) { + + string imageName = MinerExeName.Replace(".exe", ""); + // maybe will have to KILL process + KillClaymoreMinerBase(imageName); + if (BenchmarkSignalTimedout) { + throw new Exception("Benchmark timedout"); + } + if (BenchmarkException != null) { + throw BenchmarkException; + } + if (BenchmarkSignalQuit) { + throw new Exception("Termined by user request"); + } + if (BenchmarkSignalFinnished) { + break; + } + keepRunning = false; + break; + } else { + // wait a second reduce CPU load + Thread.Sleep(1000); + } + + } + } catch (Exception ex) { + BenchmarkThreadRoutineCatch(ex); + } finally { + BenchmarkAlgorithm.BenchmarkSpeed = 0; + // find latest log file + string latestLogFile = ""; + var dirInfo = new DirectoryInfo(this.WorkingDirectory); + foreach (var file in dirInfo.GetFiles("*_log.txt")) { + latestLogFile = file.Name; + break; + } + // read file log + if (File.Exists(WorkingDirectory + latestLogFile)) { + var lines = File.ReadAllLines(WorkingDirectory + latestLogFile); + var addBenchLines = bench_lines.Count == 0; + foreach (var line in lines) { + if (line != null) { + bench_lines.Add(line); + string lineLowered = line.ToLower(); + if (lineLowered.Contains(LOOK_FOR_START)) { + if (ignoreZero) { + double got = getNumber(lineLowered); + if (got != 0) { + benchmark_sum += got; + ++benchmark_read_count; + } + } else { + benchmark_sum += getNumber(lineLowered); + ++benchmark_read_count; + } + } + } + } + if (benchmark_read_count > 0) { + BenchmarkAlgorithm.BenchmarkSpeed = benchmark_sum / benchmark_read_count; + } + } + BenchmarkThreadRoutineFinish(); + } + } + + protected void CleanAllOldLogs() { + // clean old logs + try { + var dirInfo = new DirectoryInfo(this.WorkingDirectory); + var deleteContains = "_log.txt"; + if (dirInfo != null && dirInfo.Exists) { + foreach (FileInfo file in dirInfo.GetFiles()) { + if (file.Name.Contains(deleteContains)) { + file.Delete(); + } + } + } + } catch { } + } + + // stub benchmarks read from file + protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { + CheckOutdata(outdata); + } + + protected override bool BenchmarkParseLine(string outdata) { + Helpers.ConsolePrint("BENCHMARK", outdata); + return false; + } + + protected double getNumber(string outdata) { + return getNumber(outdata, LOOK_FOR_START, LOOK_FOR_END); + } + + protected double getNumber(string outdata, string LOOK_FOR_START, string LOOK_FOR_END) { + try { + double mult = 1; + int speedStart = outdata.IndexOf(LOOK_FOR_START); + string speed = outdata.Substring(speedStart, outdata.Length - speedStart); + speed = speed.Replace(LOOK_FOR_START, ""); + speed = speed.Substring(0, speed.IndexOf(LOOK_FOR_END)); + + if (speed.Contains("k")) { + mult = 1000; + speed = speed.Replace("k", ""); + } else if (speed.Contains("m")) { + mult = 1000000; + speed = speed.Replace("m", ""); + } + //Helpers.ConsolePrint("speed", speed); + speed = speed.Trim(); + return (Double.Parse(speed, CultureInfo.InvariantCulture) * mult) * (1.0 - DevFee() * 0.01); + } catch (Exception ex) { + Helpers.ConsolePrint("getNumber", ex.Message + " | args => " + outdata + " | " + LOOK_FOR_END + " | " + LOOK_FOR_START); + } + return 0; + } + } +} diff --git a/NiceHashMiner/Miners/ClaymoreCryptoNightMiner.cs b/NiceHashMiner/Miners/ClaymoreCryptoNightMiner.cs new file mode 100644 index 0000000..cb09fba --- /dev/null +++ b/NiceHashMiner/Miners/ClaymoreCryptoNightMiner.cs @@ -0,0 +1,51 @@ +using NiceHashMiner.Configs; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; +using NiceHashMiner.Net20_backport; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace NiceHashMiner.Miners { + public class ClaymoreCryptoNightMiner : ClaymoreBaseMiner { + + const string _LOOK_FOR_START = "hashrate ="; + public ClaymoreCryptoNightMiner() + : base("ClaymoreCryptoNightMiner", _LOOK_FOR_START) { + } + + protected override double DevFee() { + return 2.0; + } + + public override void Start(string url, string btcAdress, string worker) { + string username = GetUsername(btcAdress, worker); + LastCommandLine = " " + GetDevicesCommandString() + " -mport -" + APIPort + " -o " + url + " -u " + username + " -p x -dbg -1"; + ProcessHandle = _Start(); + } + + // benchmark stuff + + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + // clean old logs + CleanAllOldLogs(); + benchmarkTimeWait = time / 3; // 3 times faster than sgminer + + // network workaround + string url = Globals.GetLocationURL(algorithm.NiceHashID, Globals.MiningLocation[ConfigManager.GeneralConfig.ServiceLocation], this.ConectionType); + // demo for benchmark + string username = Globals.DemoUser; + if (ConfigManager.GeneralConfig.WorkerName.Length > 0) + username += "." + ConfigManager.GeneralConfig.WorkerName.Trim(); + + string ret = " " + GetDevicesCommandString() + " -mport -" + APIPort + " -o " + url + " -u " + username + " -p x"; + return ret; + } + + } +} diff --git a/NiceHashMiner/Miners/ClaymoreDual.cs b/NiceHashMiner/Miners/ClaymoreDual.cs new file mode 100644 index 0000000..fb57ab3 --- /dev/null +++ b/NiceHashMiner/Miners/ClaymoreDual.cs @@ -0,0 +1,87 @@ +using NiceHashMiner.Configs; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners { + public class ClaymoreDual : ClaymoreBaseMiner { + + const string _LOOK_FOR_START = "ETH - Total Speed:"; + public ClaymoreDual() + : base("ClaymoreDual", _LOOK_FOR_START) { + ignoreZero = true; + api_read_mult = 1000; + ConectionType = NHMConectionType.STRATUM_TCP; + } + + // eth-only: 1% + // eth-dual-mine: 2% + protected override double DevFee() { + return 1.0; + } + + protected override int GET_MAX_CooldownTimeInMilliseconds() { + return 90 * 1000; // 1.5 minute max, whole waiting time 75seconds + } + + private string GetStartCommand(string url, string btcAdress, string worker) { + string username = GetUsername(btcAdress, worker); + + string dualModeParams = ""; + foreach (var pair in MiningSetup.MiningPairs) { + if (pair.CurrentExtraLaunchParameters.Contains("-dual=")) { + AlgorithmType dual = AlgorithmType.NONE; + string coinP = ""; + if (pair.CurrentExtraLaunchParameters.Contains("Decred")) { + dual = AlgorithmType.Decred; + coinP = " -dcoin dcr "; + } + //if (pair.CurrentExtraLaunchParameters.Contains("Siacoin")) { + // dual = AlgorithmType.; + //} + if (pair.CurrentExtraLaunchParameters.Contains("Lbry")) { + dual = AlgorithmType.Lbry; + coinP = " -dcoin lbc "; + } + if (pair.CurrentExtraLaunchParameters.Contains("Pascal")) { + dual = AlgorithmType.Pascal; + coinP = " -dcoin pasc "; + } + if (dual != AlgorithmType.NONE) { + string urlSecond = Globals.GetLocationURL(dual, Globals.MiningLocation[ConfigManager.GeneralConfig.ServiceLocation], this.ConectionType); + dualModeParams = String.Format(" {0} -dpool {1} -dwal {2}", coinP, urlSecond, username); + break; + } + } + } + return " " + + GetDevicesCommandString() + + String.Format(" -epool {0} -ewal {1} -mport 127.0.0.1:{2} -esm 3 -epsw x -allpools 1", url, username, APIPort) + + dualModeParams; + } + + public override void Start(string url, string btcAdress, string worker) { + string username = GetUsername(btcAdress, worker); + LastCommandLine = GetStartCommand(url, btcAdress, worker) + " -dbg -1"; + ProcessHandle = _Start(); + } + + // benchmark stuff + + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + // clean old logs + CleanAllOldLogs(); + + benchmarkTimeWait = time; + + // network stub + string url = Globals.GetLocationURL(algorithm.NiceHashID, Globals.MiningLocation[ConfigManager.GeneralConfig.ServiceLocation], this.ConectionType); + // demo for benchmark + string ret = GetStartCommand(url, Globals.DemoUser, ConfigManager.GeneralConfig.WorkerName.Trim()); + // local benhcmark + return ret + " -benchmark 1"; + } + + } +} diff --git a/NiceHashMiner/Miners/Equihash/ClaymoreZcashMiner.cs b/NiceHashMiner/Miners/Equihash/ClaymoreZcashMiner.cs new file mode 100644 index 0000000..5e30fd4 --- /dev/null +++ b/NiceHashMiner/Miners/Equihash/ClaymoreZcashMiner.cs @@ -0,0 +1,46 @@ +using Newtonsoft.Json; +using NiceHashMiner.Configs; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; +using NiceHashMiner.Net20_backport; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace NiceHashMiner.Miners { + public class ClaymoreZcashMiner : ClaymoreBaseMiner { + + const string _LOOK_FOR_START = "ZEC - Total Speed:"; + public ClaymoreZcashMiner() + : base("ClaymoreZcashMiner", _LOOK_FOR_START) { + ignoreZero = true; + } + + protected override double DevFee() { + return 2.0; + } + + + public override void Start(string url, string btcAdress, string worker) { + string username = GetUsername(btcAdress, worker); + LastCommandLine = " " + GetDevicesCommandString() + " -mport 127.0.0.1:" + APIPort + " -zpool " + url + " -zwal " + username + " -zpsw x -dbg -1"; + ProcessHandle = _Start(); + } + + // benchmark stuff + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + // clean old logs + CleanAllOldLogs(); + benchmarkTimeWait = time / 3; // 3 times faster than sgminer + + string ret = " -mport 127.0.0.1:" + APIPort + " -benchmark 1 " + GetDevicesCommandString(); + return ret; + } + } +} diff --git a/NiceHashMiner/Miners/Equihash/OptiminerZcashMiner.cs b/NiceHashMiner/Miners/Equihash/OptiminerZcashMiner.cs new file mode 100644 index 0000000..2d6fd0e --- /dev/null +++ b/NiceHashMiner/Miners/Equihash/OptiminerZcashMiner.cs @@ -0,0 +1,146 @@ +using Newtonsoft.Json; +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; +using NiceHashMiner.Net20_backport; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace NiceHashMiner.Miners.Equihash { + public class OptiminerZcashMiner : Miner { + public OptiminerZcashMiner() + : base("OptiminerZcashMiner") { + ConectionType = NHMConectionType.NONE; + } + + private class Stratum { + public string target { get; set; } + public bool connected { get; set; } + public int connection_failures { get; set; } + public string host { get; set; } + public int port { get; set; } + } + + private class JsonApiResponse { + public double uptime; + public Dictionary> solution_rate; + public Dictionary share; + public Dictionary> iteration_rate; + public Stratum stratum; + } + + // give some time or else it will crash + Stopwatch _startAPI = null; + bool _skipAPICheck = true; + int waitSeconds = 30; + + public override void Start(string url, string btcAdress, string worker) { + string username = GetUsername(btcAdress, worker); + LastCommandLine = " " + GetDevicesCommandString() + " -m " + APIPort + " -s " + url + " -u " + username + " -p x"; + ProcessHandle = _Start(); + + // + _startAPI = new Stopwatch(); + _startAPI.Start(); + } + + protected override void _Stop(MinerStopType willswitch) { + Stop_cpu_ccminer_sgminer_nheqminer(willswitch); + } + + protected override int GET_MAX_CooldownTimeInMilliseconds() { + return 60 * 1000 * 5; // 5 minute max, whole waiting time 75seconds + } + + protected override string GetDevicesCommandString() { + string extraParams = ExtraLaunchParametersParser.ParseForMiningSetup(MiningSetup, DeviceType.AMD); + string deviceStringCommand = " -c " + ComputeDeviceManager.Avaliable.AMDOpenCLPlatformNum; + deviceStringCommand += " "; + List ids = new List(); + foreach (var mPair in MiningSetup.MiningPairs) { + ids.Add("-d " + mPair.Device.ID.ToString()); + } + deviceStringCommand += StringHelper.Join(" ", ids); + + return deviceStringCommand + extraParams; + } + + public override APIData GetSummary() { + _currentMinerReadStatus = MinerAPIReadStatus.NONE; + APIData ad = new APIData(MiningSetup.CurrentAlgorithmType); + + if (_skipAPICheck == false) { + JsonApiResponse resp = null; + try { + string DataToSend = GetHttpRequestNHMAgentStrin(""); + string respStr = GetAPIData(APIPort, DataToSend, true); + if (respStr != null && respStr.Contains("{")) { + int start = respStr.IndexOf("{"); + if (start > -1) { + string respStrJSON = respStr.Substring(start); + resp = JsonConvert.DeserializeObject(respStrJSON.Trim(), Globals.JsonSettings); + } + } + //Helpers.ConsolePrint("OptiminerZcashMiner API back:", respStr); + } catch (Exception ex) { + Helpers.ConsolePrint("OptiminerZcashMiner", "GetSummary exception: " + ex.Message); + } + + if (resp != null && resp.solution_rate != null) { + //Helpers.ConsolePrint("OptiminerZcashMiner API back:", "resp != null && resp.error == null"); + const string total_key = "Total"; + const string _5s_key = "5s"; + if (resp.solution_rate.ContainsKey(total_key)) { + var total_solution_rate_dict = resp.solution_rate[total_key]; + if (total_solution_rate_dict != null && total_solution_rate_dict.ContainsKey(_5s_key)) { + ad.Speed = total_solution_rate_dict[_5s_key]; + _currentMinerReadStatus = MinerAPIReadStatus.GOT_READ; + } + } + if (ad.Speed == 0) { + _currentMinerReadStatus = MinerAPIReadStatus.READ_SPEED_ZERO; + } + } + } else if (_skipAPICheck && _startAPI.Elapsed.TotalSeconds > waitSeconds) { + _startAPI.Stop(); + _skipAPICheck = false; + } + + return ad; + } + + // benchmark stuff + + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + int t = time / 9; // sgminer needs 9 times more than this miner so reduce benchmark speed + string ret = " " + GetDevicesCommandString() + " --benchmark " + t; + return ret; + } + protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { + CheckOutdata(outdata); + } + + protected override bool BenchmarkParseLine(string outdata) { + const string FIND = "Benchmark:"; + if (outdata.Contains(FIND)) { + int start = outdata.IndexOf("Benchmark:") + FIND.Length; + string itersAndVars = outdata.Substring(start).Trim(); + var ar = itersAndVars.Split(new char[] { ' ' }); + if (ar.Length >= 4) { + // gets sols/s + BenchmarkAlgorithm.BenchmarkSpeed = Helpers.ParseDouble(ar[2]); + return true; + } + } + return false; + } + + } +} diff --git a/NiceHashMiner/Miners/Equihash/nheqBase.cs b/NiceHashMiner/Miners/Equihash/nheqBase.cs new file mode 100644 index 0000000..704d86a --- /dev/null +++ b/NiceHashMiner/Miners/Equihash/nheqBase.cs @@ -0,0 +1,129 @@ +using Newtonsoft.Json; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Net.Sockets; +using System.Text; + +namespace NiceHashMiner.Miners { + public abstract class nheqBase : Miner { + protected MiningSetup CPU_Setup = new MiningSetup(null); + protected MiningSetup NVIDIA_Setup = new MiningSetup(null); + protected readonly int AMD_OCL_PLATFORM; + protected MiningSetup AMD_Setup = new MiningSetup(null); + + // extra benchmark stuff + protected double curSpeed = 0; + static protected readonly String Iter_PER_SEC = "I/s"; + static protected readonly String Sols_PER_SEC = "Sols/s"; + protected const double SolMultFactor = 1.9; + + private class Result { + public double interval_seconds { get; set; } + public double speed_ips { get; set; } + public double speed_sps { get; set; } + public double accepted_per_minute { get; set; } + public double rejected_per_minute { get; set; } + } + + private class JsonApiResponse { + public string method { get; set; } + public Result result { get; set; } + public object error { get; set; } + } + + public nheqBase(string minerDeviceName) + : base(minerDeviceName) { + AMD_OCL_PLATFORM = ComputeDeviceManager.Avaliable.AMDOpenCLPlatformNum; + } + + public override void InitMiningSetup(MiningSetup miningSetup) { + base.InitMiningSetup(miningSetup); + List CPUs = new List(); + List NVIDIAs = new List(); + List AMDs = new List(); + foreach (var pairs in MiningSetup.MiningPairs) { + if (pairs.Device.DeviceType == DeviceType.CPU) { + CPUs.Add(pairs); + } + if (pairs.Device.DeviceType == DeviceType.NVIDIA) { + NVIDIAs.Add(pairs); + } + if (pairs.Device.DeviceType == DeviceType.AMD) { + AMDs.Add(pairs); + } + } + // reinit + CPU_Setup = new MiningSetup(CPUs); + NVIDIA_Setup = new MiningSetup(NVIDIAs); + AMD_Setup = new MiningSetup(AMDs); + } + + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + // TODO nvidia extras + String ret = "-b " + GetDevicesCommandString(); + return ret; + } + + public override APIData GetSummary() { + _currentMinerReadStatus = MinerAPIReadStatus.NONE; + APIData ad = new APIData(MiningSetup.CurrentAlgorithmType); + + TcpClient client = null; + JsonApiResponse resp = null; + try { + byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes("status\n"); + client = new TcpClient("127.0.0.1", APIPort); + NetworkStream nwStream = client.GetStream(); + nwStream.Write(bytesToSend, 0, bytesToSend.Length); + byte[] bytesToRead = new byte[client.ReceiveBufferSize]; + int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize); + string respStr = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead); + resp = JsonConvert.DeserializeObject(respStr, Globals.JsonSettings); + client.Close(); + } catch (Exception ex) { + Helpers.ConsolePrint("ERROR", ex.Message); + } + + if (resp != null && resp.error == null) { + ad.Speed = resp.result.speed_sps; + _currentMinerReadStatus = MinerAPIReadStatus.GOT_READ; + if (ad.Speed == 0) { + _currentMinerReadStatus = MinerAPIReadStatus.READ_SPEED_ZERO; + } + } + + return ad; + } + + protected override void _Stop(MinerStopType willswitch) { + Stop_cpu_ccminer_sgminer_nheqminer(willswitch); + } + + protected override int GET_MAX_CooldownTimeInMilliseconds() { + return 60 * 1000 * 5; // 5 minute max, whole waiting time 75seconds + } + + protected double getNumber(string outdata, string startF, string remF) { + try { + int speedStart = outdata.IndexOf(startF); + String speed = outdata.Substring(speedStart, outdata.Length - speedStart); + speed = speed.Replace(startF, ""); + speed = speed.Replace(remF, ""); + speed = speed.Trim(); + return Double.Parse(speed, CultureInfo.InvariantCulture); + } catch { + } + return 0; + } + + // benchmark stuff + + protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { + CheckOutdata(outdata); + } + } +} diff --git a/NiceHashMiner/Miners/Equihash/nheqminer.cs b/NiceHashMiner/Miners/Equihash/nheqminer.cs new file mode 100644 index 0000000..aec7ee9 --- /dev/null +++ b/NiceHashMiner/Miners/Equihash/nheqminer.cs @@ -0,0 +1,101 @@ +using Newtonsoft.Json; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net.Sockets; +using System.Text; +using NiceHashMiner.Miners.Grouping; +using System.Diagnostics; +using NiceHashMiner.Miners.Parsing; + +namespace NiceHashMiner.Miners { + public class nheqminer : nheqBase { + public nheqminer() + : base("nheqminer") { + ConectionType = NHMConectionType.NONE; + } + + // CPU aff set from NHM + protected override NiceHashProcess _Start() { + NiceHashProcess P = base._Start(); + if (CPU_Setup.IsInit && P != null) { + var AffinityMask = CPU_Setup.MiningPairs[0].Device.AffinityMask; + if (AffinityMask != 0) { + CPUID.AdjustAffinity(P.Id, AffinityMask); + } + } + + return P; + } + + public override void Start(string url, string btcAdress, string worker) { + string username = GetUsername(btcAdress, worker); + LastCommandLine = GetDevicesCommandString() + " -a " + APIPort + " -l " + url + " -u " + username; + ProcessHandle = _Start(); + } + + + protected override string GetDevicesCommandString() { + string deviceStringCommand = " "; + + if (CPU_Setup.IsInit) { + deviceStringCommand += " " + ExtraLaunchParametersParser.ParseForMiningSetup(CPU_Setup, DeviceType.CPU); + } else { + // disable CPU + deviceStringCommand += " -t 0 "; + } + + if (NVIDIA_Setup.IsInit) { + deviceStringCommand += " -cd "; + foreach (var nvidia_pair in NVIDIA_Setup.MiningPairs) { + deviceStringCommand += nvidia_pair.Device.ID + " "; + } + deviceStringCommand += " " + ExtraLaunchParametersParser.ParseForMiningSetup(NVIDIA_Setup, DeviceType.NVIDIA); + } + + if (AMD_Setup.IsInit) { + deviceStringCommand += " -op " + AMD_OCL_PLATFORM.ToString(); + deviceStringCommand += " -od "; + foreach (var amd_pair in AMD_Setup.MiningPairs) { + deviceStringCommand += amd_pair.Device.ID + " "; + } + deviceStringCommand += " " + ExtraLaunchParametersParser.ParseForMiningSetup(AMD_Setup, DeviceType.AMD); + } + + return deviceStringCommand; + } + + // benchmark stuff + protected override Process BenchmarkStartProcess(string CommandLine) { + Process BenchmarkHandle = base.BenchmarkStartProcess(CommandLine); + + if (CPU_Setup.IsInit && BenchmarkHandle != null) { + var AffinityMask = CPU_Setup.MiningPairs[0].Device.AffinityMask; + if (AffinityMask != 0) { + CPUID.AdjustAffinity(BenchmarkHandle.Id, AffinityMask); + } + } + + return BenchmarkHandle; + } + + protected override bool BenchmarkParseLine(string outdata) { + + if (outdata.Contains(Iter_PER_SEC)) { + curSpeed = getNumber(outdata, "Speed: ", Iter_PER_SEC) * SolMultFactor; + } + if (outdata.Contains(Sols_PER_SEC)) { + var sols = getNumber(outdata, "Speed: ", Sols_PER_SEC); + if (sols > 0) { + BenchmarkAlgorithm.BenchmarkSpeed = curSpeed; + return true; + } + } + return false; + } + + } +} diff --git a/NiceHashMiner/Miners/Grouping/GroupMiner.cs b/NiceHashMiner/Miners/Grouping/GroupMiner.cs new file mode 100644 index 0000000..de29c90 --- /dev/null +++ b/NiceHashMiner/Miners/Grouping/GroupMiner.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NiceHashMiner.Enums; +using NiceHashMiner.Devices; +using NiceHashMiner.Configs; +using NiceHashMiner.Net20_backport; + +namespace NiceHashMiner.Miners.Grouping { + public class GroupMiner { + public Miner Miner { get; protected set; } + public string DevicesInfoString { get; private set; } + public AlgorithmType AlgorithmType { get; private set; } + // for now used only for dagger identification AMD or NVIDIA + public DeviceType DeviceType { get; private set; } + public double CurrentRate { get; set; } + public string Key { get; private set; } + + // , string miningLocation, string btcAdress, string worker + public GroupMiner(List miningPairs, string key) { + AlgorithmType = AlgorithmType.NONE; + DevicesInfoString = "N/A"; + CurrentRate = 0; + Key = key; + if (miningPairs.Count > 0) { + // sort pairs by device id + miningPairs.Sort((a, b) => a.Device.ID - b.Device.ID); + // init name scope + { + List deviceNames = new List(); + foreach (var pair in miningPairs) { + deviceNames.Add(pair.Device.NameCount); + } + DevicesInfoString = "{ " + StringHelper.Join(", ", deviceNames) + " }"; + } + // init miner + { + var mPair = miningPairs[0]; + DeviceType = mPair.Device.DeviceType; + Miner = MinerFactory.CreateMiner(mPair.Device, mPair.Algorithm); + if(Miner != null) { + Miner.InitMiningSetup(new MiningSetup(miningPairs)); + AlgorithmType = mPair.Algorithm.NiceHashID; + } + } + } + } + + public void Stop() { + if (Miner != null && Miner.IsRunning) { + Miner.Stop(MinerStopType.SWITCH); + // wait before going on + System.Threading.Thread.Sleep(ConfigManager.GeneralConfig.MinerRestartDelayMS); + } + CurrentRate = 0; + } + + public void End() { + if (Miner != null) { + Miner.End(); + } + CurrentRate = 0; + } + + public void Start(string miningLocation, string btcAdress, string worker) { + if(Miner.IsRunning) { + return; + } + // Wait before new start + System.Threading.Thread.Sleep(ConfigManager.GeneralConfig.MinerRestartDelayMS); + + string locationURL = Globals.GetLocationURL(AlgorithmType, miningLocation, Miner.ConectionType); + Miner.Start(locationURL, btcAdress, worker); + } + } +} diff --git a/NiceHashMiner/Miners/Grouping/GroupSetupUtils.cs b/NiceHashMiner/Miners/Grouping/GroupSetupUtils.cs new file mode 100644 index 0000000..e78a3b6 --- /dev/null +++ b/NiceHashMiner/Miners/Grouping/GroupSetupUtils.cs @@ -0,0 +1,178 @@ +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Net20_backport; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Grouping { + public static class GroupSetupUtils { + static readonly string TAG = "GroupSetupUtils"; + public static bool IsAlgoMiningCapable(Algorithm algo) { + return algo != null && algo.Enabled && algo.BenchmarkSpeed > 0; + } + + public static Tuple getDeviceMiningStatus(ComputeDevice device) { + DeviceMiningStatus status = DeviceMiningStatus.CanMine; + if (device == null) { // C# is null happy + status = DeviceMiningStatus.DeviceNull; + } else if (device.Enabled == false) { + status = DeviceMiningStatus.Disabled; + } else { + bool hasEnabledAlgo = false; + foreach (Algorithm algo in device.GetAlgorithmSettings()) { + hasEnabledAlgo |= IsAlgoMiningCapable(algo) && MinerPaths.IsValidMinerPath(algo.MinerBinaryPath); + } + if (hasEnabledAlgo == false) { + status = DeviceMiningStatus.NoEnabledAlgorithms; + } + } + return new Tuple(device, status); + } + + private static Tuple, List>> GetMiningAndNonMiningDevices(List devices) { + List> nonMiningDevStatuses = new List>(); + List miningDevices = new List(); + foreach (var dev in devices) { + var devStatus = getDeviceMiningStatus(dev); + if (devStatus.Item2 == DeviceMiningStatus.CanMine) { + miningDevices.Add(new MiningDevice(dev)); + } else { + nonMiningDevStatuses.Add(devStatus); + } + } + return new Tuple, List>>(miningDevices, nonMiningDevStatuses); + } + + private static string GetDisabledDeviceStatusString(Tuple devStatusTuple) { + var dev = devStatusTuple.Item1; + var status = devStatusTuple.Item2; + if (DeviceMiningStatus.DeviceNull == status) { + return "Passed Device is NULL"; + } else if (DeviceMiningStatus.Disabled == status) { + return "DISABLED: " + dev.GetFullName(); + } else if (DeviceMiningStatus.NoEnabledAlgorithms == status) { + return "No Enabled Algorithms: " + dev.GetFullName(); + } + return "Invalid status Passed"; + } + private static void LogMiningNonMiningStatuses(List enabledDevices, List> disabledDevicesStatuses) { + // print statuses + if (disabledDevicesStatuses.Count > 0) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(""); + stringBuilder.AppendLine("Disabled Devices:"); + foreach (var deviceStatus in disabledDevicesStatuses) { + stringBuilder.AppendLine("\t" + GetDisabledDeviceStatusString(deviceStatus)); + } + Helpers.ConsolePrint(TAG, stringBuilder.ToString()); + } + if (enabledDevices.Count > 0) { + // print enabled + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(""); + stringBuilder.AppendLine("Enabled Devices for Mining session:"); + foreach (var miningDevice in enabledDevices) { + var device = miningDevice.Device; + stringBuilder.AppendLine(String.Format("\tENABLED ({0})", device.GetFullName())); + foreach (var algo in device.GetAlgorithmSettings()) { + var isEnabled = IsAlgoMiningCapable(algo) && MinerPaths.IsValidMinerPath(algo.MinerBinaryPath); + stringBuilder.AppendLine(String.Format("\t\tALGORITHM {0} ({1})", + isEnabled ? "ENABLED " : "DISABLED", // ENABLED/DISABLED + algo.AlgorithmStringID)); + } + } + Helpers.ConsolePrint(TAG, stringBuilder.ToString()); + } + } + + public static List GetMiningDevices(List devices, bool log) { + var miningNonMiningDevs = GetMiningAndNonMiningDevices(devices); + if(log) { + LogMiningNonMiningStatuses(miningNonMiningDevs.Item1, miningNonMiningDevs.Item2); + } + return miningNonMiningDevs.Item1; + } + + // avarage passed in benchmark values + public static void AvarageSpeeds(List miningDevs) { + // calculate avarage speeds, to ensure mining stability + // device name, algo key, algos refs list + Dictionary allAvaragers = new Dictionary(); + + // init empty avarager + foreach (var device in miningDevs) { + string devName = device.Device.Name; + allAvaragers[devName] = new AvaragerGroup(); + } + // fill avarager + foreach (var device in miningDevs) { + string devName = device.Device.Name; + // add UUID + allAvaragers[devName].UUIDsList.Add(device.Device.UUID); + allAvaragers[devName].AddAlgorithms(device.Algorithms); + } + // calculate and set new AvarageSpeeds for miningDeviceReferences + foreach (var curAvaragerKvp in allAvaragers) { + AvaragerGroup curAvarager = curAvaragerKvp.Value; + var calculatedAvaragers = curAvarager.CalculateAvarages(); + foreach (var uuid in curAvarager.UUIDsList) { + int minerDevIndex = miningDevs.FindIndex((dev) => dev.Device.UUID == uuid); + if (minerDevIndex > -1) { + foreach (var avgKvp in calculatedAvaragers) { + string algo_id = avgKvp.Key; + double avaragedSpeed = avgKvp.Value; + int index = miningDevs[minerDevIndex].Algorithms.FindIndex((a) => a.AlgorithmStringID == algo_id); + if(index > -1) { + miningDevs[minerDevIndex].Algorithms[index].AvaragedSpeed = avaragedSpeed; + } + } + } + } + } + } + + } + + class SpeedSumCount { + public double speed = 0; + public int count = 0; + public double GetAvarage() { + if (count > 0) { + return speed / (double)count; + } + return 0; + } + } + + class AvaragerGroup { + public string DeviceName; + public List UUIDsList = new List(); + // algo_id, speed_sum, speed_count + public Dictionary BenchmarkSums = new Dictionary(); + public Dictionary CalculateAvarages() { + Dictionary ret = new Dictionary(); + foreach (var kvp in this.BenchmarkSums) { + string algo_id = kvp.Key; + SpeedSumCount ssc = kvp.Value; + ret[algo_id] = ssc.GetAvarage(); + } + return ret; + } + + public void AddAlgorithms(List algos) { + foreach (var algo in algos) { + var algo_id = algo.AlgorithmStringID; + if (BenchmarkSums.ContainsKey(algo_id) == false) { + var ssc = new SpeedSumCount(); + ssc.count = 1; + ssc.speed = algo.BenchmarkSpeed; + BenchmarkSums[algo_id] = ssc; + } else { + BenchmarkSums[algo_id].count++; + BenchmarkSums[algo_id].speed += algo.BenchmarkSpeed; + } + } + } + } +} diff --git a/NiceHashMiner/Miners/Grouping/GroupingLogic.cs b/NiceHashMiner/Miners/Grouping/GroupingLogic.cs new file mode 100644 index 0000000..e74e9d9 --- /dev/null +++ b/NiceHashMiner/Miners/Grouping/GroupingLogic.cs @@ -0,0 +1,37 @@ +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Grouping { + public static class GroupingLogic { + + public static bool ShouldGroup(MiningPair a, MiningPair b) { + bool canGroup = IsGroupableMinerBaseType(a) && IsGroupableMinerBaseType(b); + // group if same bin path and same algo type + if (canGroup && IsSameBinPath(a, b) && IsSameAlgorithmType(a, b) && IsNotCpuGroups(a, b) && IsSameDeviceType(a, b)) { + return true; + } + return false; + } + + private static bool IsNotCpuGroups(MiningPair a, MiningPair b) { + return a.Device.DeviceType != DeviceType.CPU && b.Device.DeviceType != DeviceType.CPU; + } + + private static bool IsSameBinPath(MiningPair a, MiningPair b) { + return a.Algorithm.MinerBinaryPath == b.Algorithm.MinerBinaryPath; + } + private static bool IsSameAlgorithmType(MiningPair a, MiningPair b) { + return a.Algorithm.NiceHashID == b.Algorithm.NiceHashID; + } + private static bool IsSameDeviceType(MiningPair a, MiningPair b) { + return a.Device.DeviceType == b.Device.DeviceType; + } + private static bool IsGroupableMinerBaseType(MiningPair a) { + return a.Algorithm.MinerBaseType != MinerBaseType.cpuminer + && a.Algorithm.MinerBaseType != MinerBaseType.XmrStackCPU; + } + } +} diff --git a/NiceHashMiner/Miners/Grouping/MinerPaths.cs b/NiceHashMiner/Miners/Grouping/MinerPaths.cs new file mode 100644 index 0000000..612c976 --- /dev/null +++ b/NiceHashMiner/Miners/Grouping/MinerPaths.cs @@ -0,0 +1,205 @@ +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Grouping +{ + /// + /// MinerPaths, used just to store miners paths strings. Only one instance needed + /// + public static class MinerPaths + { + + public static class Data { + // root binary folder + private const string _bin = @"bin"; + /// + /// ccminers + /// + public const string ccminer_decred = _bin + @"\ccminer_decred\ccminer.exe"; + public const string ccminer_nanashi = _bin + @"\ccminer_nanashi\ccminer.exe"; + public const string ccminer_neoscrypt = _bin + @"\ccminer_neoscrypt\ccminer.exe"; + public const string ccminer_sp = _bin + @"\ccminer_sp\ccminer.exe"; + public const string ccminer_tpruvot = _bin + @"\ccminer_tpruvot\ccminer.exe"; + public const string ccminer_cryptonight = _bin + @"\ccminer_cryptonight\ccminer.exe"; + public const string ccminer_x11gost = _bin + @"\ccminer_x11gost\ccminer.exe"; + + /// + /// ethminers + /// + public const string ethminer = _bin + @"\ethminer\ethminer.exe"; + + /// + /// sgminers + /// + public const string sgminer_5_6_0_general = _bin + @"\sgminer-5-6-0-general\sgminer.exe"; + public const string sgminer_gm = _bin + @"\sgminer-gm\sgminer.exe"; + + public const string nheqminer = _bin + @"\nheqminer_v0.4b\nheqminer.exe"; + public const string excavator = _bin + @"\excavator\excavator.exe"; + + public const string XmrStackCPUMiner = _bin + @"\xmr-stak-cpu\xmr-stak-cpu.exe"; + + public const string NONE = ""; + + // root binary folder + private const string _bin_3rdparty = @"bin_3rdparty"; + public const string ClaymoreZcashMiner = _bin_3rdparty + @"\claymore_zcash\ZecMiner64.exe"; + public const string ClaymoreCryptoNightMiner = _bin_3rdparty + @"\claymore_cryptonight\NsGpuCNMiner.exe"; + public const string OptiminerZcashMiner = _bin_3rdparty + @"\optiminer_zcash_win\Optiminer.exe"; + public const string ClaymoreDual = _bin_3rdparty + @"\claymore_dual\EthDcrMiner64.exe"; + } + + // NEW START + //////////////////////////////////////////// + // Pure functions + //public static bool IsMinerAlgorithmAvaliable(List algos, MinerBaseType minerBaseType, AlgorithmType algorithmType) { + // return algos.FindIndex((a) => a.MinerBaseType == minerBaseType && a.NiceHashID == algorithmType) > -1; + //} + + public static string GetPathFor(MinerBaseType minerBaseType, AlgorithmType algoType, DeviceGroupType devGroupType) { + switch (minerBaseType) { + case MinerBaseType.ccminer: + return NVIDIA_GROUPS.ccminer_path(algoType, devGroupType); + case MinerBaseType.sgminer: + return AMD_GROUP.sgminer_path(algoType); + case MinerBaseType.nheqminer: + return Data.nheqminer; + case MinerBaseType.ethminer: + return Data.ethminer; + case MinerBaseType.ClaymoreAMD: + return AMD_GROUP.ClaymorePath(algoType); + case MinerBaseType.OptiminerAMD: + return Data.OptiminerZcashMiner; + case MinerBaseType.excavator: + return Data.excavator; + case MinerBaseType.XmrStackCPU: + return Data.XmrStackCPUMiner; + case MinerBaseType.ccminer_alexis: + return NVIDIA_GROUPS.ccminer_unstable_path(algoType, devGroupType); + case MinerBaseType.experimental: + return EXPERIMENTAL.GetPath(algoType, devGroupType); + } + return Data.NONE; + } + + public static string GetPathFor(ComputeDevice computeDevice, Algorithm algorithm /*, Options: MinerPathsConfig*/) { + if (computeDevice == null || algorithm == null) { + return Data.NONE; + } + + return GetPathFor( + algorithm.MinerBaseType, + algorithm.NiceHashID, + computeDevice.DeviceGroupType + ); + } + + public static bool IsValidMinerPath(string minerPath) { + // TODO make a list of valid miner paths and check that instead + return minerPath != null && Data.NONE != minerPath && minerPath != ""; + } + + /** + * InitAlgorithmsMinerPaths gets and sets miner paths + */ + public static List GetAndInitAlgorithmsMinerPaths(List algos, ComputeDevice computeDevice/*, Options: MinerPathsConfig*/) { + var retAlgos = algos.FindAll((a) => a != null).ConvertAll((a) => { + a.MinerBinaryPath = GetPathFor(computeDevice, a/*, Options*/); + return a; + }); + + return retAlgos; + } + // NEW END + + ////// private stuff from here on + static class NVIDIA_GROUPS { + public static string ccminer_sm21_or_sm3x(AlgorithmType algorithmType) { + if (AlgorithmType.Decred == algorithmType) { + return Data.ccminer_decred; + } + if (AlgorithmType.CryptoNight == algorithmType) { + return Data.ccminer_cryptonight; + } + return Data.ccminer_tpruvot; + } + + public static string ccminer_sm5x_or_sm6x(AlgorithmType algorithmType) { + if (AlgorithmType.Decred == algorithmType) { + return Data.ccminer_decred; + } + if (AlgorithmType.NeoScrypt == algorithmType) { + return Data.ccminer_neoscrypt; + } + if (AlgorithmType.Lyra2RE == algorithmType || AlgorithmType.Lyra2REv2 == algorithmType) { + return Data.ccminer_nanashi; + } + if (AlgorithmType.CryptoNight == algorithmType) { + return Data.ccminer_cryptonight; + } + if (AlgorithmType.Lbry == algorithmType || AlgorithmType.X11Gost == algorithmType) { + return Data.ccminer_tpruvot; + } + + return Data.ccminer_sp; + } + public static string ccminer_path(AlgorithmType algorithmType, DeviceGroupType nvidiaGroup) { + // sm21 and sm3x have same settings + if (nvidiaGroup == DeviceGroupType.NVIDIA_2_1 || nvidiaGroup == DeviceGroupType.NVIDIA_3_x) { + return NVIDIA_GROUPS.ccminer_sm21_or_sm3x(algorithmType); + } + // sm5x and sm6x have same settings + if (nvidiaGroup == DeviceGroupType.NVIDIA_5_x || nvidiaGroup == DeviceGroupType.NVIDIA_6_x) { + return NVIDIA_GROUPS.ccminer_sm5x_or_sm6x(algorithmType); + } + // TODO wrong case? + return Data.NONE; // should not happen + } + + public static string ccminer_unstable_path(AlgorithmType algorithmType, DeviceGroupType nvidiaGroup) { + // sm5x and sm6x have same settings + if (nvidiaGroup == DeviceGroupType.NVIDIA_5_x || nvidiaGroup == DeviceGroupType.NVIDIA_6_x) { + if (AlgorithmType.X11Gost == algorithmType) { + return Data.ccminer_x11gost; + } + } + // TODO wrong case? + return Data.NONE; // should not happen + } + } + + static class AMD_GROUP { + public static string sgminer_path(AlgorithmType type) { + if (AlgorithmType.CryptoNight == type || AlgorithmType.DaggerHashimoto == type) { + return Data.sgminer_gm; + } + return Data.sgminer_5_6_0_general; + } + + public static string ClaymorePath(AlgorithmType type) { + if(AlgorithmType.Equihash == type) { + return Data.ClaymoreZcashMiner; + } else if(AlgorithmType.CryptoNight == type) { + return Data.ClaymoreCryptoNightMiner; + } else if (AlgorithmType.DaggerHashimoto == type) { + return Data.ClaymoreDual; + } + return Data.NONE; // should not happen + } + } + + // unstable miners, NVIDIA for now + static class EXPERIMENTAL { + public static string GetPath(AlgorithmType algoType, DeviceGroupType devGroupType) { + if (devGroupType == DeviceGroupType.NVIDIA_6_x) { + return NVIDIA_GROUPS.ccminer_path(algoType, devGroupType); + } + return Data.NONE; // should not happen + } + } + } +} diff --git a/NiceHashMiner/Miners/Grouping/MiningDevice.cs b/NiceHashMiner/Miners/Grouping/MiningDevice.cs new file mode 100644 index 0000000..c5ec15a --- /dev/null +++ b/NiceHashMiner/Miners/Grouping/MiningDevice.cs @@ -0,0 +1,157 @@ +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Grouping { + public class MiningDevice { + + // switch testing quick and dirty, runtime versions +#if (SWITCH_TESTING) + static List testingAlgos = new List() { + //AlgorithmType.X13, + //AlgorithmType.Keccak, + //AlgorithmType.X15, + //AlgorithmType.Nist5, + //AlgorithmType.NeoScrypt, + AlgorithmType.Lyra2RE, + //AlgorithmType.WhirlpoolX, + //AlgorithmType.Qubit, + //AlgorithmType.Quark, + //AlgorithmType.Lyra2REv2, + //AlgorithmType.Blake256r8, + //AlgorithmType.Blake256r14, + //AlgorithmType.Blake256r8vnl, + AlgorithmType.Hodl, + //AlgorithmType.DaggerHashimoto, + //AlgorithmType.Decred, + AlgorithmType.CryptoNight, + //AlgorithmType.Lbry, + AlgorithmType.Equihash + }; + static int next = -1; + public static void SetNextTest() { + ++next; + if (next >= testingAlgos.Count) next = 0; + var mostProfitKeyName = AlgorithmNiceHashNames.GetName(testingAlgos[next]); + Helpers.ConsolePrint("SWITCH_TESTING", String.Format("Setting most MostProfitKey to {0}", mostProfitKeyName)); + } + + static bool ForceNone = false; + // globals testing variables + static int seconds = 20; + public static int SMAMinerCheckInterval = seconds * 1000; // 30s + public static bool ForcePerCardMiners = false; +#endif + + public MiningDevice(ComputeDevice device) { + Device = device; + foreach (var algo in Device.GetAlgorithmSettings()) { + bool isAlgoMiningCapable = GroupSetupUtils.IsAlgoMiningCapable(algo); + bool isValidMinerPath = MinerPaths.IsValidMinerPath(algo.MinerBinaryPath); + if (isAlgoMiningCapable && isValidMinerPath) { + Algorithms.Add(algo); + } + } + MostProfitableAlgorithmType = AlgorithmType.NONE; + MostProfitableMinerBaseType = MinerBaseType.NONE; + } + public ComputeDevice Device { get; private set; } + public List Algorithms = new List(); + + public string GetMostProfitableString() { + return + Enum.GetName(typeof(MinerBaseType), MostProfitableMinerBaseType) + + "_" + + Enum.GetName(typeof(AlgorithmType), MostProfitableAlgorithmType); + } + + public AlgorithmType MostProfitableAlgorithmType { get; private set; } + public MinerBaseType MostProfitableMinerBaseType { get; private set; } + // prev state + public AlgorithmType PrevProfitableAlgorithmType { get; private set; } + public MinerBaseType PrevProfitableMinerBaseType { get; private set; } + + private int GetMostProfitableIndex() { + return Algorithms.FindIndex((a) => a.NiceHashID == MostProfitableAlgorithmType && a.MinerBaseType == MostProfitableMinerBaseType); + } + + private int GetPrevProfitableIndex() { + return Algorithms.FindIndex((a) => a.NiceHashID == PrevProfitableAlgorithmType && a.MinerBaseType == PrevProfitableMinerBaseType); + } + + public double GetCurrentMostProfitValue { + get { + int mostProfitableIndex = GetMostProfitableIndex(); + if (mostProfitableIndex > -1) { + return Algorithms[mostProfitableIndex].CurrentProfit; + } + return 0; + } + } + + public double GetPrevMostProfitValue { + get { + int mostProfitableIndex = GetPrevProfitableIndex(); + if (mostProfitableIndex > -1) { + return Algorithms[mostProfitableIndex].CurrentProfit; + } + return 0; + } + } + + public MiningPair GetMostProfitablePair() { + return new MiningPair(this.Device, Algorithms[GetMostProfitableIndex()]); + } + + public bool HasProfitableAlgo() { + return GetMostProfitableIndex() > -1; + } + + public void RestoreOldProfitsState() { + // restore last state + MostProfitableAlgorithmType = PrevProfitableAlgorithmType; + MostProfitableMinerBaseType = PrevProfitableMinerBaseType; + } + + public void CalculateProfits(Dictionary NiceHashData) { + // save last state + PrevProfitableAlgorithmType = MostProfitableAlgorithmType; + PrevProfitableMinerBaseType = MostProfitableMinerBaseType; + // assume none is profitable + MostProfitableAlgorithmType = AlgorithmType.NONE; + MostProfitableMinerBaseType = MinerBaseType.NONE; + // calculate new profits + foreach (var algo in Algorithms) { + AlgorithmType key = algo.NiceHashID; + if (NiceHashData.ContainsKey(key)) { + algo.CurNhmSMADataVal = NiceHashData[key].paying; + algo.CurrentProfit = algo.CurNhmSMADataVal * algo.AvaragedSpeed * 0.000000001; + } else { + algo.CurrentProfit = 0; + } + } + // find max paying value and save key + double maxProfit = 0; + foreach (var algo in Algorithms) { + if (maxProfit < algo.CurrentProfit) { + maxProfit = algo.CurrentProfit; + MostProfitableAlgorithmType = algo.NiceHashID; + MostProfitableMinerBaseType = algo.MinerBaseType; + } + } +#if (SWITCH_TESTING) + var devName = Device.GetFullName(); + // set new most profit + if (Algorithms.ContainsKey(testingAlgos[next])) { + MostProfitableKey = testingAlgos[next]; + } else if(ForceNone) { + MostProfitableKey = AlgorithmType.NONE; + } + var mostProfitKeyName = AlgorithmNiceHashNames.GetName(MostProfitableKey); + Helpers.ConsolePrint("SWITCH_TESTING", String.Format("Setting device {0} to {1}", devName, mostProfitKeyName)); +#endif + } + } +} diff --git a/NiceHashMiner/Miners/Grouping/MiningPair.cs b/NiceHashMiner/Miners/Grouping/MiningPair.cs new file mode 100644 index 0000000..26543ab --- /dev/null +++ b/NiceHashMiner/Miners/Grouping/MiningPair.cs @@ -0,0 +1,17 @@ +using NiceHashMiner.Devices; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Grouping { + public class MiningPair { + public readonly ComputeDevice Device; + public readonly Algorithm Algorithm; + public string CurrentExtraLaunchParameters; + public MiningPair(ComputeDevice d, Algorithm a) { + this.Device = d; + this.Algorithm = a; + this.CurrentExtraLaunchParameters = Algorithm.ExtraLaunchParameters; + } + } +} diff --git a/NiceHashMiner/Miners/Grouping/MiningSetup.cs b/NiceHashMiner/Miners/Grouping/MiningSetup.cs new file mode 100644 index 0000000..60082c3 --- /dev/null +++ b/NiceHashMiner/Miners/Grouping/MiningSetup.cs @@ -0,0 +1,27 @@ +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Grouping { + public class MiningSetup { + public List MiningPairs { get; private set; } + public string MinerPath { get; private set; } + public string MinerName { get; private set; } + public AlgorithmType CurrentAlgorithmType { get; private set; } + public bool IsInit { get; private set; } + + public MiningSetup(List miningPairs) { + this.IsInit = false; + this.CurrentAlgorithmType = AlgorithmType.NONE; + if (miningPairs != null && miningPairs.Count > 0) { + this.MiningPairs = miningPairs; + this.MiningPairs.Sort((a, b) => a.Device.ID - b.Device.ID); + this.MinerName = miningPairs[0].Algorithm.MinerName; + this.CurrentAlgorithmType = miningPairs[0].Algorithm.NiceHashID; + this.MinerPath = miningPairs[0].Algorithm.MinerBinaryPath; + this.IsInit = MinerPaths.IsValidMinerPath(this.MinerPath); + } + } + } +} diff --git a/NiceHashMiner/Miners/ManagerPrivate/CpuGroupMiner.cs b/NiceHashMiner/Miners/ManagerPrivate/CpuGroupMiner.cs deleted file mode 100644 index 5c91c54..0000000 --- a/NiceHashMiner/Miners/ManagerPrivate/CpuGroupMiner.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NiceHashMiner.Miners { - using NiceHashMiner.Enums; - using NiceHashMiner.Devices; - using NiceHashMiner.Configs; - // typedefs - using GroupedDevices = SortedSet; - using GroupedDevicesKey = SortedSet>; - - public partial class MinersManager { - private class CpuGroupMiner : GroupMiners { - - public CpuGroupMiner(GroupedDevices deviceUUIDSet, cpuminer miner) - : base(deviceUUIDSet) { - _miners.Add(miner); - } - } - } -} diff --git a/NiceHashMiner/Miners/ManagerPrivate/GroupMiners.cs b/NiceHashMiner/Miners/ManagerPrivate/GroupMiners.cs deleted file mode 100644 index 7200eea..0000000 --- a/NiceHashMiner/Miners/ManagerPrivate/GroupMiners.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NiceHashMiner.Miners { - using NiceHashMiner.Enums; - using NiceHashMiner.Devices; - using NiceHashMiner.Configs; - // typedefs - using GroupedDevices = SortedSet; - using GroupedDevicesKey = SortedSet>; - - public partial class MinersManager { - // for switching different miners for different algorithms - private class GroupMiners { - public Miner CurrentWorkingMiner { get; protected set; } - public string DevicesInfoString { get; private set; } - - protected List _miners; - protected SortedSet _deviceNames; - protected string[] _deviceUUIDs; - protected DeviceGroupType _deviceGroupType = DeviceGroupType.NONE; - - public GroupMiners(GroupedDevices deviceUUIDSet) { - _miners = new List(); - _deviceNames = new SortedSet(); - foreach (var uuid in deviceUUIDSet) { - var tmpCdev = ComputeDevice.GetDeviceWithUUID(uuid); - _deviceNames.Add(tmpCdev.NameCount); - if (_deviceGroupType == DeviceGroupType.NONE) { - _deviceGroupType = tmpCdev.DeviceGroupType; - } - } - // init device uuids - _deviceUUIDs = deviceUUIDSet.ToArray(); - // init DevicesInfoString - string[] _deviceNamesCount = new string[_deviceNames.Count]; - { - int i = 0; - foreach (var devName in _deviceNames) { - _deviceNamesCount[i++] = - ComputeDevice.GetEnabledDeviceNameCount(devName).ToString() - + " * " + devName; - } - } - - DevicesInfoString = "{ " + string.Join(", ", _deviceNames) + " }"; - } - - private void StopMiner(Miner miner) { - if (miner.IsRunning) { - miner.Stop(MinerStopType.SWITCH); - // wait 0.5 seconds before going on - System.Threading.Thread.Sleep(ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS); - } - } - - public void Stop() { - foreach (var miner in _miners) { - StopMiner(miner); - } - } - - public void End() { - foreach (var miner in _miners) { - miner.End(); - } - } - - public void StartAlgorihtm(Algorithm algorithm, string miningLocation, string worker) { - bool containsSupportedMiner = false; - Miner startSwitchMiner = null; - var algorithmType = algorithm.NiceHashID; - foreach (var miner in _miners) { - if (miner.IsSupportedMinerAlgorithms(algorithmType)) { - containsSupportedMiner = true; - startSwitchMiner = miner; - break; - } - } - // check if contains miner if not create one - if (!containsSupportedMiner && _deviceGroupType != DeviceGroupType.CPU) { - startSwitchMiner = CreateMiner(_deviceGroupType, algorithmType); - startSwitchMiner.SetCDevs(_deviceUUIDs); - _miners.Add(startSwitchMiner); - } - - // hanlde CurrentWorkingMiner change - if (CurrentWorkingMiner != null && CurrentWorkingMiner != startSwitchMiner) { - StopMiner(CurrentWorkingMiner); - CurrentWorkingMiner = startSwitchMiner; - } else { - CurrentWorkingMiner = startSwitchMiner; - } - SwitchMinerAlgorithm(ref startSwitchMiner, algorithm, miningLocation, worker); - } - - private void SwitchMinerAlgorithm(ref Miner m, Algorithm algorithm, string miningLocation, string worker) { - // if is running and the current algorithm is the same skip - if (m.IsRunning && m.CurrentAlgorithmType == algorithm.NiceHashID) { - return; - } - - if (m.CurrentAlgorithmType != AlgorithmType.NONE && m.CurrentAlgorithmType != AlgorithmType.INVALID) { - m.Stop(MinerStopType.SWITCH); - // wait 0.5 seconds before going on - System.Threading.Thread.Sleep(ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS); - } - - var MaxProfitKey = algorithm.NiceHashID; - - // Wait before new start - System.Threading.Thread.Sleep(ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS); - - m.Start(algorithm, - "stratum+tcp://" - + Globals.NiceHashData[MaxProfitKey].name - + "." + miningLocation - + ".nicehash.com:" - + Globals.NiceHashData[MaxProfitKey].port, worker); - } - - } - } -} diff --git a/NiceHashMiner/Miners/ManagerPrivate/SwitchTesting.cs b/NiceHashMiner/Miners/ManagerPrivate/SwitchTesting.cs deleted file mode 100644 index 6b35513..0000000 --- a/NiceHashMiner/Miners/ManagerPrivate/SwitchTesting.cs +++ /dev/null @@ -1,65 +0,0 @@ -using NiceHashMiner.Enums; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - - -#if (SWITCH_TESTING) -namespace NiceHashMiner.Miners { - using NiceHashMiner.Devices; - using PerDeviceProifitDictionary = Dictionary>; - public partial class MinersManager { - // globals testing variables - static int seconds = 60; - public static int SMAMinerCheckInterval = seconds * 1000; // 30s - public static bool ForcePerCardMiners = false; - - - private class SwitchTesting : BaseLazySingleton { - - readonly string TAG; - // dev names - Dictionary _curStepCheck; - Dictionary> _allAvaliableAlgoKeys; - const double MOST_PROFIT_REPLACE_VAL = 500000.0d; - - protected SwitchTesting() { - TAG = this.GetType().Name; - - _curStepCheck = new Dictionary(); - _allAvaliableAlgoKeys = new Dictionary>(); - - foreach (var cDev in ComputeDevice.AllAvaliableDevices) { - _curStepCheck[cDev.UUID] = 0; - //_allAvaliableAlgoKeys[cDev.Name] = new List(cDev.DeviceBenchmarkConfig.AlgorithmSettings.Keys); - _allAvaliableAlgoKeys[cDev.UUID] = new List(new[] { AlgorithmType.DaggerHashimoto, AlgorithmType.Lyra2RE }); - } - } - - public void SetNext(ref PerDeviceProifitDictionary devProfits, List enabledDevices) { - - foreach (var cDev in enabledDevices) { - var devUUID = cDev.UUID; - var curStepCheckIndex = _curStepCheck[devUUID]; - var _mostProfitKey = _allAvaliableAlgoKeys[devUUID][curStepCheckIndex]; - var mostProfitKeyName = AlgorithmNiceHashNames.GetName(_mostProfitKey); - Helpers.ConsolePrint(TAG, String.Format("Setting most MostProfitKey to {0}", mostProfitKeyName)); - - // set new most profit - Helpers.ConsolePrint(TAG, String.Format("Setting device {0} to {1}", devUUID, mostProfitKeyName)); - devProfits[devUUID][_mostProfitKey] = MOST_PROFIT_REPLACE_VAL; - - ++curStepCheckIndex; - if (curStepCheckIndex >= _allAvaliableAlgoKeys[devUUID].Count) curStepCheckIndex = 0; - _curStepCheck[devUUID] = curStepCheckIndex; - } - - - } - - } - } -} -#endif \ No newline at end of file diff --git a/NiceHashMiner/Miners/Miner.cs b/NiceHashMiner/Miners/Miner.cs index 5e12af1..5d42949 100644 --- a/NiceHashMiner/Miners/Miner.cs +++ b/NiceHashMiner/Miners/Miner.cs @@ -13,8 +13,12 @@ using NiceHashMiner.Enums; using NiceHashMiner.Miners; using NiceHashMiner.Interfaces; +using NiceHashMiner.Miners.Grouping; -using Timer = System.Windows.Forms.Timer; +using Timer = System.Timers.Timer; +using System.Timers; +using NiceHashMiner.Net20_backport; +using System.IO; namespace NiceHashMiner { @@ -23,6 +27,11 @@ public class APIData public AlgorithmType AlgorithmID; public string AlgorithmName; public double Speed; + public APIData(AlgorithmType algorithmID) { + this.AlgorithmID = algorithmID; + this.AlgorithmName = AlgorithmNiceHashNames.GetName(algorithmID); + this.Speed = 0.0; + } } // @@ -37,38 +46,29 @@ public abstract class Miner { // MINER_ID_COUNT used to identify miners creation protected static long MINER_ID_COUNT { get; private set; } + + public NHMConectionType ConectionType { get; protected set; } // used to identify miner instance protected readonly long MINER_ID; private string _minetTag = null; - public string MinerDeviceName { get; private set; } + public string MinerDeviceName { get; set; } protected int APIPort { get; private set; } // if miner has no API bind port for reading curentlly only CryptoNight on ccminer public bool IsAPIReadException { get; protected set; } - protected List CDevs; - public DeviceType DeviceType { get; private set; } - + public bool IsNeverHideMiningWindow { get; protected set; } // mining algorithm stuff - public AlgorithmType CurrentAlgorithmType { get; protected set; } - private Algorithm _currentMiningAlgorithm; - protected Algorithm CurrentMiningAlgorithm { - get { return _currentMiningAlgorithm; } - set { - if (value == null) { - CurrentAlgorithmType = AlgorithmType.NONE; - } else { - CurrentAlgorithmType = value.NiceHashID; - } - _currentMiningAlgorithm = value; - } - } - public double CurrentRate; + protected bool IsInit { get; private set; } + protected MiningSetup MiningSetup { get; set; } + // sgminer/zcash claymore workaround + protected bool IsKillAllUsedMinerProcs { get; set; } public bool IsRunning { get; protected set; } - protected string Path; + protected string Path { get; private set; } protected string LastCommandLine { get; set; } // TODO check this protected double PreviousTotalMH; // the defaults will be - protected string WorkingDirectory; + protected string WorkingDirectory { get; private set; } + protected string MinerExeName { get; private set; } protected NiceHashProcess ProcessHandle; private MinerPID_Data _currentPidData; private List _allPidData = new List(); @@ -79,31 +79,19 @@ protected Algorithm CurrentMiningAlgorithm { Stopwatch BenchmarkTimeOutStopWatch = null; public bool BenchmarkSignalTimedout = false; protected bool BenchmarkSignalFinnished; - IBenchmarkComunicator BenchmarkComunicator; - private bool OnBenchmarkCompleteCalled = false; - protected AlgorithmType CurrentBenchmarkAlgorithmType { get; private set; } - private Algorithm _benchmarkAlgorithm; - protected Algorithm BenchmarkAlgorithm { - get { return _benchmarkAlgorithm; } - set { - if (value == null) { - CurrentBenchmarkAlgorithmType = AlgorithmType.NONE; - } else { - CurrentBenchmarkAlgorithmType = value.NiceHashID; - } - _benchmarkAlgorithm = value; - } - } - public BenchmarkProcessStatus BenchmarkProcessStatus { get; private set; } - private string BenchmarkProcessPath; - private Process BenchmarkHandle = null; + protected IBenchmarkComunicator BenchmarkComunicator; + protected bool OnBenchmarkCompleteCalled = false; + protected Algorithm BenchmarkAlgorithm { get; set; } + public BenchmarkProcessStatus BenchmarkProcessStatus { get; protected set; } + protected string BenchmarkProcessPath { get; set; } + protected Process BenchmarkHandle { get; set; } protected Exception BenchmarkException = null; protected int BenchmarkTimeInSeconds; - - protected bool _isEthMinerExit = false; - protected AlgorithmType[] _supportedMinerAlgorithms; + string benchmarkLogPath = ""; + protected List bench_lines; + // TODO maybe set for individual miner cooldown/retries logic variables // this replaces MinerAPIGraceSeconds(AMD) private const int _MIN_CooldownTimeInMilliseconds = 5 * 1000; // 5 seconds @@ -116,56 +104,80 @@ protected Algorithm BenchmarkAlgorithm { protected MinerAPIReadStatus _currentMinerReadStatus { get; set; } private int _currentCooldownTimeInSeconds = _MIN_CooldownTimeInMilliseconds; private int _currentCooldownTimeInSecondsLeft = _MIN_CooldownTimeInMilliseconds; - private int _isCooldownCheckTimerAliveCount = 0; private const int IS_COOLDOWN_CHECK_TIMER_ALIVE_CAP = 15; + private bool NeedsRestart = false; + + private bool isEnded = false; - public Miner(DeviceType deviceType, string minerDeviceName) + public Miner(string minerDeviceName) { + ConectionType = NHMConectionType.STRATUM_TCP; + MiningSetup = new MiningSetup(null); + IsInit = false; MINER_ID = MINER_ID_COUNT++; - CDevs = new List(); - DeviceType = deviceType; + MinerDeviceName = minerDeviceName; - //WorkingDirectory = @"bin\dlls"; WorkingDirectory = ""; - CurrentAlgorithmType = AlgorithmType.NONE; - CurrentRate = 0; IsRunning = false; PreviousTotalMH = 0.0; LastCommandLine = ""; - InitSupportedMinerAlgorithms(); - - APIPort = MinersApiPortsManager.Instance.GetAvaliablePort(); IsAPIReadException = false; + IsNeverHideMiningWindow = false; + IsKillAllUsedMinerProcs = false; _MAX_CooldownTimeInMilliseconds = GET_MAX_CooldownTimeInMilliseconds(); - // cool down init - _cooldownCheckTimer = new Timer() { - Interval = _MIN_CooldownTimeInMilliseconds - }; - _cooldownCheckTimer.Tick += MinerCoolingCheck_Tick; // Helpers.ConsolePrint(MinerTAG(), "NEW MINER CREATED"); } ~Miner() { // free the port - MinersApiPortsManager.Instance.RemovePort(APIPort); + MinersApiPortsManager.RemovePort(APIPort); Helpers.ConsolePrint(MinerTAG(), "MINER DESTROYED"); } - virtual public void SetCDevs(string[] deviceUUIDs) { - foreach (var uuid in deviceUUIDs) { - CDevs.Add(ComputeDevice.GetDeviceWithUUID(uuid)); + protected void SetWorkingDirAndProgName(string fullPath) { + this.WorkingDirectory = ""; + this.Path = fullPath; + int lastIndex = fullPath.LastIndexOf("\\") + 1; + if(lastIndex > 0) { + this.WorkingDirectory = fullPath.Substring(0, lastIndex); + this.MinerExeName = fullPath.Substring(lastIndex); + } + } + + private void SetAPIPort() { + if (IsInit) { + var minerBase = MiningSetup.MiningPairs[0].Algorithm.MinerBaseType; + var algoType = MiningSetup.MiningPairs[0].Algorithm.NiceHashID; + var path = MiningSetup.MinerPath; + var reservedPorts = MinersSettingsManager.GetPortsListFor(minerBase, path, algoType); + APIPort = -1; // not set + foreach (var reservedPort in reservedPorts) { + if (MinersApiPortsManager.IsPortAvaliable(reservedPort)) { + APIPort = reservedPort; + break; + } + } + if (APIPort == -1) { + APIPort = MinersApiPortsManager.GetAvaliablePort(); + } } - // sort devices by id - CDevs.Sort((a, b) => a.ID - b.ID); } - public void ClearCDevs() { - CDevs.Clear(); + virtual public void InitMiningSetup(MiningSetup miningSetup) { + MiningSetup = miningSetup; + IsInit = MiningSetup.IsInit; + SetAPIPort(); + SetWorkingDirAndProgName(MiningSetup.MinerPath); + } + + public void InitBenchmarkSetup(MiningPair benchmarkPair) { + InitMiningSetup(new MiningSetup(new List() { benchmarkPair })); + BenchmarkAlgorithm = benchmarkPair.Algorithm; } // TAG for identifying miner @@ -173,13 +185,13 @@ public string MinerTAG() { if (_minetTag == null) { const string MASK = "{0}-MINER_ID({1})-DEVICE_IDs({2})"; // no devices set - if (CDevs.Count == 0) { + if (!IsInit) { return String.Format(MASK, MinerDeviceName, MINER_ID, "NOT_SET"); } // contains ids - List ids = new List(); - foreach (var cdevs in CDevs) ids.Add(cdevs.ID); - _minetTag = String.Format(MASK, MinerDeviceName, MINER_ID, string.Join(",", ids)); + List ids = new List(); + foreach (var cdevs in MiningSetup.MiningPairs) ids.Add(cdevs.Device.ID.ToString()); + _minetTag = String.Format(MASK, MinerDeviceName, MINER_ID, StringHelper.Join(",", ids)); } return _minetTag; } @@ -195,25 +207,6 @@ public string ProcessTag() { return ProcessTag(_currentPidData); } - public bool IsSupportedMinerAlgorithms(AlgorithmType algorithmType) { - foreach (var supportedType in _supportedMinerAlgorithms) { - if (supportedType == algorithmType) return true; - } - return false; - } - - protected abstract void InitSupportedMinerAlgorithms(); - - /// - /// GetOptimizedMinerPath returns optimized miner path based on algorithm type and device codename. - /// Device codename is a quickfix for sgminer, other miners don't use it - /// - /// determines what miner path to return - /// sgminer extra - /// sgminer extra - /// - abstract public string GetOptimizedMinerPath(AlgorithmType algorithmType, string devCodename = "", bool isOptimized = true); - public void KillAllUsedMinerProcesses() { List toRemovePidData = new List(); Helpers.ConsolePrint(MinerTAG(), "Trying to kill all miner processes for this instance:"); @@ -222,7 +215,11 @@ public void KillAllUsedMinerProcesses() { Process process = Process.GetProcessById(PidData.PID); if (process != null && PidData.minerBinPath.Contains(process.ProcessName)) { Helpers.ConsolePrint(MinerTAG(), String.Format("Trying to kill {0}", ProcessTag(PidData))); - try { process.Kill(); } catch (Exception e) { + try { + process.Kill(); + process.Close(); + process.WaitForExit(1000 * 60 * 1); + } catch (Exception e) { Helpers.ConsolePrint(MinerTAG(), String.Format("Exception killing {0}, exMsg {1}", ProcessTag(PidData), e.Message)); } } @@ -235,59 +232,40 @@ public void KillAllUsedMinerProcesses() { _allPidData.RemoveAll( x => toRemovePidData.Contains(x)); } - abstract public void Start(Algorithm miningAlgorithm, string url, string username); + abstract public void Start(string url, string btcAdress, string worker); + protected string GetUsername(string btcAdress, string worker) { + if (worker.Length > 0) { + return btcAdress + "." + worker; + } + return btcAdress; + } abstract protected void _Stop(MinerStopType willswitch); - virtual public void Stop(MinerStopType willswitch = MinerStopType.SWITCH, bool needsRestart = false) + virtual public void Stop(MinerStopType willswitch = MinerStopType.SWITCH) { - _cooldownCheckTimer.Stop(); - if (!needsRestart) { - _Stop(willswitch); - PreviousTotalMH = 0.0; - IsRunning = false; - } else { - //_currentMinerReadStatus = MinerAPIReadStatus.RESTART; - Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Manually closed, will restart"); - Restart(); - } + if (_cooldownCheckTimer != null) _cooldownCheckTimer.Stop(); + _Stop(willswitch); + PreviousTotalMH = 0.0; + IsRunning = false; } public void End() { + isEnded = true; Stop(MinerStopType.FORCE_END); - CurrentAlgorithmType = AlgorithmType.NONE; - CurrentRate = 0; - } - - protected void ChangeToNextAvaliablePort() { - // change to new port - var oldApiPort = APIPort; - var newApiPort = MinersApiPortsManager.Instance.GetAvaliablePort(); - // check if update last command port - if (UpdateBindPortCommand(oldApiPort, newApiPort)) { - Helpers.ConsolePrint(MinerTAG(), String.Format("Changing miner port from {0} to {1}", - oldApiPort.ToString(), - newApiPort.ToString())); - // free old set new - MinersApiPortsManager.Instance.RemovePort(oldApiPort); - APIPort = newApiPort; - } else { // release new - MinersApiPortsManager.Instance.RemovePort(newApiPort); - } } - protected void Stop_cpu_ccminer_sgminer(MinerStopType willswitch) { + protected void Stop_cpu_ccminer_sgminer_nheqminer(MinerStopType willswitch) { if (IsRunning) { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Shutting down miner"); } - if (willswitch != MinerStopType.FORCE_END) ChangeToNextAvaliablePort(); if (ProcessHandle != null) { try { ProcessHandle.Kill(); } catch { } ProcessHandle.Close(); ProcessHandle = null; // sgminer needs to be removed and kill by PID - if (DeviceType == DeviceType.AMD) KillAllUsedMinerProcesses(); + if (IsKillAllUsedMinerProcs) KillAllUsedMinerProcesses(); } } @@ -295,10 +273,10 @@ virtual protected string GetDevicesCommandString() { string deviceStringCommand = " "; List ids = new List(); - foreach (var cdev in CDevs) { - ids.Add(cdev.ID.ToString()); + foreach (var mPair in MiningSetup.MiningPairs) { + ids.Add(mPair.Device.ID.ToString()); } - deviceStringCommand += string.Join(",", ids); + deviceStringCommand += StringHelper.Join(",", ids); return deviceStringCommand; } @@ -306,24 +284,23 @@ virtual protected string GetDevicesCommandString() { #region BENCHMARK DE-COUPLED Decoupled benchmarking routines public int BenchmarkTimeoutInSeconds(int timeInSeconds) { - if (CurrentBenchmarkAlgorithmType == AlgorithmType.DaggerHashimoto) { + if (BenchmarkAlgorithm.NiceHashID == AlgorithmType.DaggerHashimoto) { return 5 * 60 + 120; // 5 minutes plus two minutes } - if (CurrentBenchmarkAlgorithmType == AlgorithmType.CryptoNight) { + if (BenchmarkAlgorithm.NiceHashID == AlgorithmType.CryptoNight) { return 5 * 60 + 120; // 5 minutes plus two minutes } return timeInSeconds + 120; // wait time plus two minutes } - abstract protected string BenchmarkCreateCommandLine(ComputeDevice benchmarkDevice, Algorithm algorithm, int time); + // TODO remove algorithm + abstract protected string BenchmarkCreateCommandLine(Algorithm algorithm, int time); // The benchmark config and algorithm must guarantee that they are compatible with miner // we guarantee algorithm is supported // we will not have empty benchmark configs, all benchmark configs will have device list - virtual public void BenchmarkStart(ComputeDevice benchmarkDevice, Algorithm algorithm, int time, IBenchmarkComunicator benchmarkComunicator) { - + virtual public void BenchmarkStart(int time, IBenchmarkComunicator benchmarkComunicator) { BenchmarkComunicator = benchmarkComunicator; - BenchmarkAlgorithm = algorithm; BenchmarkTimeInSeconds = time; BenchmarkSignalFinnished = true; // check and kill @@ -331,27 +308,45 @@ virtual public void BenchmarkStart(ComputeDevice benchmarkDevice, Algorithm algo OnBenchmarkCompleteCalled = false; BenchmarkTimeOutStopWatch = null; - string CommandLine = BenchmarkCreateCommandLine(benchmarkDevice, algorithm, time); + + try { + if (!Directory.Exists("logs")) { + Directory.CreateDirectory("logs"); + } + } catch { } + bench_lines = new List(); + benchmarkLogPath = String.Format("{0}Log_{1}_{2}", Logger._logPath, MiningSetup.MiningPairs[0].Device.UUID, MiningSetup.MiningPairs[0].Algorithm.AlgorithmStringID); + + string CommandLine = BenchmarkCreateCommandLine(BenchmarkAlgorithm, time); Thread BenchmarkThread = new Thread(BenchmarkThreadRoutine); BenchmarkThread.Start(CommandLine); } virtual protected Process BenchmarkStartProcess(string CommandLine) { + Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; Helpers.ConsolePrint(MinerTAG(), "Starting benchmark: " + CommandLine); Process BenchmarkHandle = new Process(); - - BenchmarkHandle.StartInfo.FileName = GetOptimizedMinerPath(BenchmarkAlgorithm.NiceHashID); - // TODO sgminer quickfix + BenchmarkHandle.StartInfo.FileName = MiningSetup.MinerPath; + // sgminer quickfix if (this is sgminer) { BenchmarkProcessPath = "cmd / " + BenchmarkHandle.StartInfo.FileName; BenchmarkHandle.StartInfo.FileName = "cmd"; } else { BenchmarkProcessPath = BenchmarkHandle.StartInfo.FileName; Helpers.ConsolePrint(MinerTAG(), "Using miner: " + BenchmarkHandle.StartInfo.FileName); + BenchmarkHandle.StartInfo.WorkingDirectory = WorkingDirectory; + } + // set sys variables + if (MinersSettingsManager.MinerSystemVariables.ContainsKey(Path)) { + foreach (var kvp in MinersSettingsManager.MinerSystemVariables[Path]) { + string envName = kvp.Key; + string envValue = kvp.Value; + BenchmarkHandle.StartInfo.EnvironmentVariables[envName] = envValue; + } } BenchmarkHandle.StartInfo.Arguments = (string)CommandLine; @@ -361,27 +356,27 @@ virtual protected Process BenchmarkStartProcess(string CommandLine) { BenchmarkHandle.StartInfo.CreateNoWindow = true; BenchmarkHandle.OutputDataReceived += BenchmarkOutputErrorDataReceived; BenchmarkHandle.ErrorDataReceived += BenchmarkOutputErrorDataReceived; + BenchmarkHandle.Exited += BenchmarkHandle_Exited; if (!BenchmarkHandle.Start()) return null; + _currentPidData = new MinerPID_Data(); + _currentPidData.minerBinPath = BenchmarkHandle.StartInfo.FileName; + _currentPidData.PID = BenchmarkHandle.Id; + _allPidData.Add(_currentPidData); + return BenchmarkHandle; } - - private string ElapsedTimeString(long timeMillies) { - if (timeMillies < 1000) { - return timeMillies.ToString() + " milliseconds"; - } else if (timeMillies < 60 * 1000) { - return (timeMillies / 1000).ToString() + " seconds"; - } - return (timeMillies / (60 * 1000)).ToString() + " minutes"; + void BenchmarkHandle_Exited(object sender, EventArgs e) { + BenchmarkSignalFinnished = true; } private void BenchmarkOutputErrorDataReceived(object sender, DataReceivedEventArgs e) { if (BenchmarkTimeOutStopWatch == null) { BenchmarkTimeOutStopWatch = new Stopwatch(); BenchmarkTimeOutStopWatch.Start(); - } else if (BenchmarkTimeOutStopWatch.ElapsedMilliseconds > BenchmarkTimeoutInSeconds(BenchmarkTimeInSeconds) * 1000) { + } else if (BenchmarkTimeOutStopWatch.Elapsed.TotalSeconds > BenchmarkTimeoutInSeconds(BenchmarkTimeInSeconds)) { BenchmarkTimeOutStopWatch.Stop(); BenchmarkSignalTimedout = true; } @@ -403,6 +398,8 @@ private void BenchmarkOutputErrorDataReceived(object sender, DataReceivedEventAr protected abstract void BenchmarkOutputErrorDataReceivedImpl(string outdata); protected void CheckOutdata(string outdata) { + //Helpers.ConsolePrint("BENCHMARK" + benchmarkLogPath, outdata); + bench_lines.Add(outdata); // ccminer, cpuminer if (outdata.Contains("Cuda error")) BenchmarkException = new Exception("CUDA error"); @@ -426,41 +423,58 @@ protected void CheckOutdata(string outdata) { } } - //protected double BenchmarkParseLine_cpu_ccminer_extra(string outdata) { - // // parse line - // if (outdata.Contains("Benchmark: ") && outdata.Contains("/s")) { - // int i = outdata.IndexOf("Benchmark:"); - // int k = outdata.IndexOf("/s"); - // string hashspeed = outdata.Substring(i + 11, k - i - 9); - // Helpers.ConsolePrint("BENCHMARK", "Final Speed: " + hashspeed); + public void InvokeBenchmarkSignalQuit() { + KillAllUsedMinerProcesses(); + } - // // save speed - // int b = hashspeed.IndexOf(" "); - // double spd = Double.Parse(hashspeed.Substring(0, b), CultureInfo.InvariantCulture); - // if (hashspeed.Contains("kH/s")) - // spd *= 1000; - // else if (hashspeed.Contains("MH/s")) - // spd *= 1000000; - // else if (hashspeed.Contains("GH/s")) - // spd *= 1000000000; + protected double BenchmarkParseLine_cpu_ccminer_extra(string outdata) { + // parse line + if (outdata.Contains("Benchmark: ") && outdata.Contains("/s")) { + int i = outdata.IndexOf("Benchmark:"); + int k = outdata.IndexOf("/s"); + string hashspeed = outdata.Substring(i + 11, k - i - 9); + Helpers.ConsolePrint("BENCHMARK", "Final Speed: " + hashspeed); - // return spd; - // } - // return 0.0d; - //} + // save speed + int b = hashspeed.IndexOf(" "); + if (b < 0) { + int stub; + for (int _i = hashspeed.Length - 1; _i >= 0; --_i ) { + if (Int32.TryParse(hashspeed[_i].ToString(), out stub)) { + b = _i; + break; + } + } + } + if (b >= 0) { + string speedStr = hashspeed.Substring(0, b); + double spd = Helpers.ParseDouble(speedStr); + if (hashspeed.Contains("kH/s")) + spd *= 1000; + else if (hashspeed.Contains("MH/s")) + spd *= 1000000; + else if (hashspeed.Contains("GH/s")) + spd *= 1000000000; + + return spd; + } + } + return 0.0d; + } // killing proccesses can take time - public void EndBenchmarkProcces() { - if (BenchmarkHandle != null && BenchmarkProcessStatus != BenchmarkProcessStatus.Killing) { + virtual public void EndBenchmarkProcces() { + if (BenchmarkHandle != null && BenchmarkProcessStatus != BenchmarkProcessStatus.Killing && BenchmarkProcessStatus != BenchmarkProcessStatus.DoneKilling) { BenchmarkProcessStatus = BenchmarkProcessStatus.Killing; try { - Helpers.ConsolePrint("BENCHMARK", String.Format("Trying to kill benchmark process {0} algorithm {1}", BenchmarkProcessPath, BenchmarkAlgorithm.NiceHashName)); + Helpers.ConsolePrint("BENCHMARK", String.Format("Trying to kill benchmark process {0} algorithm {1}", BenchmarkProcessPath, BenchmarkAlgorithm.AlgorithmName)); BenchmarkHandle.Kill(); BenchmarkHandle.Close(); + KillAllUsedMinerProcesses(); } catch { } finally { BenchmarkProcessStatus = BenchmarkProcessStatus.DoneKilling; - Helpers.ConsolePrint("BENCHMARK", String.Format("Benchmark process {0} algorithm {1} KILLED", BenchmarkProcessPath, BenchmarkAlgorithm.NiceHashName)); + Helpers.ConsolePrint("BENCHMARK", String.Format("Benchmark process {0} algorithm {1} KILLED", BenchmarkProcessPath, BenchmarkAlgorithm.AlgorithmName)); //BenchmarkHandle = null; } } @@ -472,8 +486,47 @@ virtual protected void BenchmarkThreadRoutineStartSettup() { BenchmarkHandle.BeginOutputReadLine(); } + protected void BenchmarkThreadRoutineCatch(Exception ex) { + BenchmarkAlgorithm.BenchmarkSpeed = 0; + + Helpers.ConsolePrint(MinerTAG(), "Benchmark Exception: " + ex.Message); + if (BenchmarkComunicator != null && !OnBenchmarkCompleteCalled) { + OnBenchmarkCompleteCalled = true; + BenchmarkComunicator.OnBenchmarkComplete(false, GetFinalBenchmarkString()); + } + } + + protected virtual string GetFinalBenchmarkString() { + return BenchmarkSignalTimedout ? International.GetText("Benchmark_Timedout") : International.GetText("Benchmark_Terminated"); + } + + protected void BenchmarkThreadRoutineFinish() { + BenchmarkProcessStatus status = BenchmarkProcessStatus.Finished; + + if (BenchmarkAlgorithm.BenchmarkSpeed > 0) { + status = BenchmarkProcessStatus.Success; + } + + using (StreamWriter sw = File.AppendText(benchmarkLogPath)) { + foreach (var line in bench_lines) { + sw.WriteLine(line); + } + } + BenchmarkProcessStatus = status; + Helpers.ConsolePrint("BENCHMARK", "Final Speed: " + Helpers.FormatSpeedOutput(BenchmarkAlgorithm.BenchmarkSpeed)); + Helpers.ConsolePrint("BENCHMARK", "Benchmark ends"); + if (BenchmarkComunicator != null && !OnBenchmarkCompleteCalled) { + OnBenchmarkCompleteCalled = true; + bool isOK = BenchmarkProcessStatus.Success == status; + string msg = GetFinalBenchmarkString(); + BenchmarkComunicator.OnBenchmarkComplete(isOK, isOK ? "" : msg); + } + } + + + virtual protected void BenchmarkThreadRoutine(object CommandLine) { - Thread.Sleep(ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS); + Thread.Sleep(ConfigManager.GeneralConfig.MinerRestartDelayMS); BenchmarkSignalQuit = false; BenchmarkSignalHanged = false; @@ -507,21 +560,9 @@ virtual protected void BenchmarkThreadRoutine(object CommandLine) { //break; } } catch (Exception ex) { - BenchmarkAlgorithm.BenchmarkSpeed = 0; - - Helpers.ConsolePrint(MinerTAG(), "Benchmark Exception: " + ex.Message); - if (BenchmarkComunicator != null && !OnBenchmarkCompleteCalled) { - OnBenchmarkCompleteCalled = true; - BenchmarkComunicator.OnBenchmarkComplete(false, BenchmarkSignalTimedout ? International.GetText("Benchmark_Timedout") : International.GetText("Benchmark_Terminated")); - } + BenchmarkThreadRoutineCatch(ex); } finally { - BenchmarkProcessStatus = BenchmarkProcessStatus.Success; - Helpers.ConsolePrint("BENCHMARK", "Final Speed: " + Helpers.FormatSpeedOutput(BenchmarkAlgorithm.BenchmarkSpeed)); - Helpers.ConsolePrint("BENCHMARK", "Benchmark ends"); - if (BenchmarkComunicator != null && !OnBenchmarkCompleteCalled) { - OnBenchmarkCompleteCalled = true; - BenchmarkComunicator.OnBenchmarkComplete(true, "Success"); - } + BenchmarkThreadRoutineFinish(); } } @@ -531,6 +572,11 @@ virtual protected void BenchmarkThreadRoutine(object CommandLine) { virtual protected NiceHashProcess _Start() { + // never start when ended + if (isEnded) { + return null; + } + PreviousTotalMH = 0.0; if (LastCommandLine.Length == 0) return null; @@ -540,12 +586,27 @@ virtual protected NiceHashProcess _Start() { P.StartInfo.WorkingDirectory = WorkingDirectory; } + if (MinersSettingsManager.MinerSystemVariables.ContainsKey(Path)) { + foreach (var kvp in MinersSettingsManager.MinerSystemVariables[Path]) { + string envName = kvp.Key; + string envValue = kvp.Value; + P.StartInfo.EnvironmentVariables[envName] = envValue; + } + } P.StartInfo.FileName = Path; P.ExitEvent = Miner_Exited; P.StartInfo.Arguments = LastCommandLine; - P.StartInfo.CreateNoWindow = ConfigManager.Instance.GeneralConfig.HideMiningWindows; + if (IsNeverHideMiningWindow) { + P.StartInfo.CreateNoWindow = false; + if (ConfigManager.GeneralConfig.HideMiningWindows) { + P.StartInfo.WindowStyle = ProcessWindowStyle.Minimized; + P.StartInfo.UseShellExecute = true; + } + } else { + P.StartInfo.CreateNoWindow = ConfigManager.GeneralConfig.HideMiningWindows; + } P.StartInfo.UseShellExecute = false; try @@ -577,71 +638,53 @@ virtual protected NiceHashProcess _Start() protected void StartCoolDownTimerChecker() { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Starting cooldown checker"); + if (_cooldownCheckTimer != null && _cooldownCheckTimer.Enabled) _cooldownCheckTimer.Stop(); + // cool down init + _cooldownCheckTimer = new Timer() { + Interval = _MIN_CooldownTimeInMilliseconds + }; + _cooldownCheckTimer.Elapsed += MinerCoolingCheck_Tick; _cooldownCheckTimer.Start(); _currentCooldownTimeInSeconds = _MIN_CooldownTimeInMilliseconds; _currentCooldownTimeInSecondsLeft = _currentCooldownTimeInSeconds; _currentMinerReadStatus = MinerAPIReadStatus.NONE; - _isCooldownCheckTimerAliveCount = 0; - } - - - virtual protected void Miner_Exited() { - //bool willswitch = _isEthMinerExit ? false : true; - //Stop(willswitch, true); - - Stop(MinerStopType.END, true); } - //virtual protected void ethMiner_Exited() - //{ - // Stop(false); - //} - protected abstract bool UpdateBindPortCommand(int oldPort, int newPort); - protected bool UpdateBindPortCommand_ccminer_cpuminer(int oldPort, int newPort) { - // --api-bind= - const string MASK = "--api-bind={0}"; - var oldApiBindStr = String.Format(MASK, oldPort); - var newApiBindStr = String.Format(MASK, newPort); - if (LastCommandLine != null && LastCommandLine.Contains(oldApiBindStr)) { - LastCommandLine = LastCommandLine.Replace(oldApiBindStr, newApiBindStr); - return true; - } - return false; + virtual protected void Miner_Exited() { + ScheduleRestart(5000); } - private void Restart() { - Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Restarting miner.."); - Stop(MinerStopType.END); // stop miner first - System.Threading.Thread.Sleep(ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS); - ProcessHandle = _Start(); // start with old command line + protected void ScheduleRestart(int ms) { + var RestartInMS = ConfigManager.GeneralConfig.MinerRestartDelayMS > ms ? + ConfigManager.GeneralConfig.MinerRestartDelayMS : ms; + Helpers.ConsolePrint(MinerTAG(), ProcessTag() + String.Format(" Miner_Exited Will restart in {0} ms", RestartInMS)); + _currentMinerReadStatus = MinerAPIReadStatus.RESTART; + NeedsRestart = true; + _currentCooldownTimeInSecondsLeft = RestartInMS; } - protected void FillAlgorithm(string aname, ref APIData AD) { - if (CurrentMiningAlgorithm.MinerName.Equals(aname)) { - AD.AlgorithmID = CurrentMiningAlgorithm.NiceHashID; - AD.AlgorithmName = CurrentMiningAlgorithm.NiceHashName; + protected void Restart() { + if (!isEnded) { + Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Restarting miner.."); + Stop(MinerStopType.END); // stop miner first + System.Threading.Thread.Sleep(ConfigManager.GeneralConfig.MinerRestartDelayMS); + ProcessHandle = _Start(); // start with old command line } } - protected string GetAPIData(int port, string cmd) + protected string GetAPIData(int port, string DataToSend, bool exitHack = false) { string ResponseFromServer = null; try { TcpClient tcpc = new TcpClient("127.0.0.1", port); - string DataToSend = "GET /" + cmd + " HTTP/1.1\r\n" + - "Host: 127.0.0.1\r\n" + - "User-Agent: NiceHashMiner/" + Application.ProductVersion + "\r\n" + - "\r\n"; - - if (DeviceType == DeviceType.AMD /*MinerDeviceName.Equals("AMD_OpenCL")*/) - DataToSend = cmd; byte[] BytesToSend = ASCIIEncoding.ASCII.GetBytes(DataToSend); tcpc.Client.Send(BytesToSend); byte[] IncomingBuffer = new byte[5000]; + int prevOffset = -1; int offset = 0; bool fin = false; @@ -650,13 +693,24 @@ protected string GetAPIData(int port, string cmd) int r = tcpc.Client.Receive(IncomingBuffer, offset, 5000 - offset, SocketFlags.None); for (int i = offset; i < offset + r; i++) { - if (IncomingBuffer[i] == 0x7C || IncomingBuffer[i] == 0x00) - { + if (IncomingBuffer[i] == 0x7C || IncomingBuffer[i] == 0x00) { fin = true; break; } + // Not working + //if (IncomingBuffer[i] == 0x5d || IncomingBuffer[i] == 0x5e) { + // fin = true; + // break; + //} } offset += r; + if (exitHack) { + if (prevOffset == offset) { + fin = true; + break; + } + prevOffset = offset; + } } tcpc.Close(); @@ -666,8 +720,7 @@ protected string GetAPIData(int port, string cmd) } catch (Exception ex) { - return null; - } catch { // all + Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " GetAPIData reason: " + ex.Message); return null; } @@ -676,12 +729,22 @@ protected string GetAPIData(int port, string cmd) public abstract APIData GetSummary(); + protected string GetHttpRequestNHMAgentStrin(string cmd) { + return "GET /" + cmd + " HTTP/1.1\r\n" + + "Host: 127.0.0.1\r\n" + + "User-Agent: NiceHashMiner/" + Application.ProductVersion + "\r\n" + + "\r\n"; + } + protected APIData GetSummaryCPU_CCMINER() { string resp; + // TODO aname string aname = null; - APIData ad = new APIData(); + APIData ad = new APIData(MiningSetup.CurrentAlgorithmType); - resp = GetAPIData(APIPort, "summary"); + string DataToSend = GetHttpRequestNHMAgentStrin("summary"); + + resp = GetAPIData(APIPort, DataToSend); if (resp == null) { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " summary is null"); _currentMinerReadStatus = MinerAPIReadStatus.NONE; @@ -705,7 +768,6 @@ protected APIData GetSummaryCPU_CCMINER() { } _currentMinerReadStatus = MinerAPIReadStatus.GOT_READ; - FillAlgorithm(aname, ref ad); // check if speed zero if (ad.Speed == 0) _currentMinerReadStatus = MinerAPIReadStatus.READ_SPEED_ZERO; @@ -718,18 +780,13 @@ protected APIData GetSummaryCPU_CCMINER() { /// decrement time for half current half time, if less then min ammend /// private void CoolDown() { - _currentCooldownTimeInSeconds /= 2; - if (_currentCooldownTimeInSeconds < _MIN_CooldownTimeInMilliseconds) { + if (_currentCooldownTimeInSeconds > _MIN_CooldownTimeInMilliseconds) { _currentCooldownTimeInSeconds = _MIN_CooldownTimeInMilliseconds; - if (_isCooldownCheckTimerAliveCount == 0) { - _isCooldownCheckTimerAliveCount = IS_COOLDOWN_CHECK_TIMER_ALIVE_CAP; - Helpers.ConsolePrint(MinerTAG(), String.Format("{0} Cooling DOWN, cool time is {1} ms", ProcessTag(), _currentCooldownTimeInSeconds.ToString())); - } - --_isCooldownCheckTimerAliveCount; - } else { - Helpers.ConsolePrint(MinerTAG(), String.Format("{0} Cooling DOWN, cool time is {1} ms", ProcessTag(), _currentCooldownTimeInSeconds.ToString())); + Helpers.ConsolePrint(MinerTAG(), String.Format("{0} Reseting cool time = {1} ms", ProcessTag(), _MIN_CooldownTimeInMilliseconds.ToString())); + _currentMinerReadStatus = MinerAPIReadStatus.NONE; } } + /// /// increment time for half current half time, if more then max set restart /// @@ -743,11 +800,18 @@ private void CoolUp() { } } - private void MinerCoolingCheck_Tick(object sender, EventArgs e) { - _currentCooldownTimeInSecondsLeft -= _cooldownCheckTimer.Interval; + private void MinerCoolingCheck_Tick(object sender, ElapsedEventArgs e) { + if (isEnded) { + End(); + return; + } + _currentCooldownTimeInSecondsLeft -= (int)_cooldownCheckTimer.Interval; // if times up if (_currentCooldownTimeInSecondsLeft <= 0) { - if (_currentMinerReadStatus == MinerAPIReadStatus.GOT_READ) { + if (NeedsRestart) { + NeedsRestart = false; + Restart(); + } else if (_currentMinerReadStatus == MinerAPIReadStatus.GOT_READ) { CoolDown(); } else if (_currentMinerReadStatus == MinerAPIReadStatus.READ_SPEED_ZERO) { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " READ SPEED ZERO, will cool up"); diff --git a/NiceHashMiner/Miners/MinerEtherumCUDA.cs b/NiceHashMiner/Miners/MinerEtherumCUDA.cs deleted file mode 100644 index e5e0c10..0000000 --- a/NiceHashMiner/Miners/MinerEtherumCUDA.cs +++ /dev/null @@ -1,55 +0,0 @@ -using NiceHashMiner.Configs; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NiceHashMiner.Miners { - public class MinerEtherumCUDA : MinerEtherum { - - // reference to all MinerEtherumCUDA make sure to clear this after miner Stop - // we make sure only ONE instance of MinerEtherumCUDA is running - private static List MinerEtherumCUDAList = new List(); - - public MinerEtherumCUDA() - : base(DeviceType.NVIDIA, "MinerEtherumCUDA", "NVIDIA") { - MinerEtherumCUDAList.Add(this); - } - - ~MinerEtherumCUDA() { - // remove from list - MinerEtherumCUDAList.Remove(this); - } - - public override void Start(Algorithm miningAlgorithm, string url, string username) { - Helpers.ConsolePrint(MinerTAG(), "Starting MinerEtherumCUDA, checking existing MinerEtherumCUDA to stop"); - foreach (var ethminer in MinerEtherumCUDAList) { - if (ethminer.MINER_ID != MINER_ID && (ethminer.IsRunning || ethminer.IsPaused)) { - Helpers.ConsolePrint(MinerTAG(), String.Format("Will end {0} {1}",ethminer.MinerTAG(), ethminer.ProcessTag())); - ethminer.End(); - System.Threading.Thread.Sleep(ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS); - } - } - base.Start(miningAlgorithm, url, username); - } - - protected override string GetStartCommandStringPart(Algorithm miningAlgorithm, string url, string username) { - return " --cuda" - + " " + miningAlgorithm.ExtraLaunchParameters - + " -S " + url.Substring(14) - + " -O " + username + ":" + Algorithm.PasswordDefault - + " --api-port " + APIPort.ToString() - + " --cuda-devices "; - } - - protected override string GetBenchmarkCommandStringPart(ComputeDevice benchmarkDevice, Algorithm algorithm) { - return " --benchmark-warmup 40 --benchmark-trial 20" - + " " + algorithm.ExtraLaunchParameters - + " --cuda --cuda-devices "; - } - - } -} diff --git a/NiceHashMiner/Miners/MinerEtherumOCL.cs b/NiceHashMiner/Miners/MinerEtherumOCL.cs deleted file mode 100644 index 79c5bfe..0000000 --- a/NiceHashMiner/Miners/MinerEtherumOCL.cs +++ /dev/null @@ -1,63 +0,0 @@ -using NiceHashMiner.Configs; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NiceHashMiner.Miners { - - // TODO for NOW ONLY AMD - // AMD or TODO it could be something else - public class MinerEtherumOCL : MinerEtherum { - - // reference to all MinerEtherumOCL make sure to clear this after miner Stop - // we make sure only ONE instance of MinerEtherumOCL is running - private static List MinerEtherumOCLList = new List(); - - private readonly int GPUPlatformNumber; - - public MinerEtherumOCL() - : base(DeviceType.AMD, "MinerEtherumOCL", "AMD OpenCL") { - GPUPlatformNumber = ComputeDeviceQueryManager.Instance.AMDOpenCLPlatformNum; - } - - ~MinerEtherumOCL() { - // remove from list - MinerEtherumOCLList.Remove(this); - } - - public override void Start(Algorithm miningAlgorithm, string url, string username) { - Helpers.ConsolePrint(MinerTAG(), "Starting MinerEtherumOCL, checking existing MinerEtherumOCL to stop"); - foreach (var ethminer in MinerEtherumOCLList) { - if (ethminer.MINER_ID != MINER_ID && (ethminer.IsRunning || ethminer.IsPaused)) { - Helpers.ConsolePrint(MinerTAG(), String.Format("Will end {0} {1}", ethminer.MinerTAG(), ethminer.ProcessTag())); - ethminer.End(); - System.Threading.Thread.Sleep(ConfigManager.Instance.GeneralConfig.MinerRestartDelayMS); - } - } - base.Start(miningAlgorithm, url, username); - } - - protected override string GetStartCommandStringPart(Algorithm miningAlgorithm, string url, string username) { - // set directory - WorkingDirectory = ""; - return " --opencl --opencl-platform " + GPUPlatformNumber - + " " + miningAlgorithm.ExtraLaunchParameters - + " -S " + url.Substring(14) - + " -O " + username + ":" + Algorithm.PasswordDefault - + " --api-port " + APIPort.ToString() - + " --opencl-devices "; - } - - protected override string GetBenchmarkCommandStringPart(ComputeDevice benchmarkDevice, Algorithm algorithm) { - return " --opencl --opencl-platform " + GPUPlatformNumber - + " " + algorithm.ExtraLaunchParameters - + " --benchmark-warmup 40 --benchmark-trial 20" - + " --opencl-devices "; - } - - } -} diff --git a/NiceHashMiner/Miners/MinerFactory.cs b/NiceHashMiner/Miners/MinerFactory.cs new file mode 100644 index 0000000..6d385ff --- /dev/null +++ b/NiceHashMiner/Miners/MinerFactory.cs @@ -0,0 +1,72 @@ +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Equihash; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners { + public class MinerFactory { + + private static Miner CreateEthminer(DeviceType deviceType) { + if (DeviceType.AMD == deviceType) { + return new MinerEtherumOCL(); + } else if(DeviceType.NVIDIA == deviceType) { + return new MinerEtherumCUDA(); + } + return null; + } + + private static Miner CreateClaymore(AlgorithmType algorithmType) { + if (AlgorithmType.Equihash == algorithmType) { + return new ClaymoreZcashMiner(); + } else if (AlgorithmType.CryptoNight == algorithmType) { + return new ClaymoreCryptoNightMiner(); + } else if (AlgorithmType.DaggerHashimoto == algorithmType) { + return new ClaymoreDual(); + } + return null; + } + + private static Miner CreateExperimental(DeviceType deviceType, AlgorithmType algorithmType) { + if (AlgorithmType.NeoScrypt == algorithmType && DeviceType.NVIDIA == deviceType) { + return new ccminer(); + } + return null; + } + + public static Miner CreateMiner(DeviceType deviceType, AlgorithmType algorithmType, MinerBaseType minerBaseType) { + switch (minerBaseType) { + case MinerBaseType.ccminer: + return new ccminer(); + case MinerBaseType.sgminer: + return new sgminer(); + case MinerBaseType.nheqminer: + return new nheqminer(); + case MinerBaseType.ethminer: + return CreateEthminer(deviceType); + case MinerBaseType.ClaymoreAMD: + return CreateClaymore(algorithmType); + case MinerBaseType.OptiminerAMD: + return new OptiminerZcashMiner(); + case MinerBaseType.excavator: + return new excavator(); + case MinerBaseType.XmrStackCPU: + return new XmrStackCPUMiner(); + case MinerBaseType.ccminer_alexis: + return new ccminer(); + case MinerBaseType.experimental: + return CreateExperimental(deviceType, algorithmType); + } + return null; + } + + // create miner creates new miners based on device type and algorithm/miner path + public static Miner CreateMiner(ComputeDevice device, Algorithm algorithm) { + if (device != null && algorithm != null) { + return CreateMiner(device.DeviceType, algorithm.NiceHashID, algorithm.MinerBaseType); + } + return null; + } + } +} diff --git a/NiceHashMiner/Miners/MinerPaths.cs b/NiceHashMiner/Miners/MinerPaths.cs deleted file mode 100644 index 8e53f7c..0000000 --- a/NiceHashMiner/Miners/MinerPaths.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace NiceHashMiner.Miners -{ - /// - /// MinerPaths, used just to store miners paths strings. Only one instance needed - /// - public static class MinerPaths - { - // root binary folder - private const string _bin = @"bin"; - /// - /// ccminers - /// - public const string ccminer_decred = _bin + @"\ccminer_decred.exe"; - public const string ccminer_nanashi = _bin + @"\ccminer_nanashi.exe"; - public const string ccminer_neoscrypt = _bin + @"\ccminer_neoscrypt.exe"; - public const string ccminer_sp = _bin + @"\ccminer_sp.exe"; - public const string ccminer_tpruvot = _bin + @"\ccminer_tpruvot.exe"; - public const string ccminer_cryptonight = _bin + @"\ccminer_cryptonight.exe"; - /// - /// cpuminers opt new - /// - public const string cpuminer_opt_AVX = _bin + @"\cpuminer_opt_AVX.exe"; - public const string cpuminer_opt_AVX2 = _bin + @"\cpuminer_opt_AVX2.exe"; - public const string cpuminer_opt_SSE2 = _bin + @"\cpuminer_opt_SSE2.exe"; - public const string cpuminer_opt_AES = _bin + @"\cpuminer_opt_AES.exe"; // TODO check - /// - /// ethminers - /// - public const string ethminer = _bin + @"\ethminer.exe"; - - /// - /// sgminers - /// - public const string sgminer_5_1_0_optimized = _bin + @"\sgminer-5-1-0-optimized\sgminer.exe"; - public const string sgminer_5_1_1_optimized = _bin + @"\sgminer-5-1-1-optimized\sgminer.exe"; - public const string sgminer_5_4_0_general = _bin + @"\sgminer-5-4-0-general\sgminer.exe"; - public const string sgminer_5_4_0_tweaked = _bin + @"\sgminer-5-4-0-tweaked\sgminer.exe"; - - } -} diff --git a/NiceHashMiner/Miners/MinersApiPortsManager.cs b/NiceHashMiner/Miners/MinersApiPortsManager.cs index f1412f5..3a1fa64 100644 --- a/NiceHashMiner/Miners/MinersApiPortsManager.cs +++ b/NiceHashMiner/Miners/MinersApiPortsManager.cs @@ -1,21 +1,16 @@ using NiceHashMiner.Configs; using NiceHashMiner.Enums; +using NiceHashMiner.Net20_backport; using System; using System.Collections.Generic; -using System.Linq; using System.Net.NetworkInformation; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.Miners { - public class MinersApiPortsManager : BaseLazySingleton { - private HashSet _usedPorts; - - protected MinersApiPortsManager() { - _usedPorts = new HashSet(); - } + public static class MinersApiPortsManager { + private static HashSet _usedPorts = new HashSet(); - private bool IsPortAvaliable(int port) { + public static bool IsPortAvaliable(int port) { bool isAvailable = true; IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); @@ -42,18 +37,18 @@ private bool IsPortAvaliable(int port) { return isAvailable; } - public int GetAvaliablePort() { - int port = ConfigManager.Instance.GeneralConfig.ApiBindPortPoolStart; + public static int GetAvaliablePort() { + int port = ConfigManager.GeneralConfig.ApiBindPortPoolStart; int newPortEnd = port + 3000; for (; port < newPortEnd; ++port) { - if (IsPortAvaliable(port) && _usedPorts.Add(port)) { + if (MinersSettingsManager.AllReservedPorts.Contains(port) == false && IsPortAvaliable(port) && _usedPorts.Add(port)) { break; } } return port; } - public void RemovePort(int port) { + public static void RemovePort(int port) { _usedPorts.Remove(port); } } diff --git a/NiceHashMiner/Miners/MinersManager.cs b/NiceHashMiner/Miners/MinersManager.cs index e2839b3..d294813 100644 --- a/NiceHashMiner/Miners/MinersManager.cs +++ b/NiceHashMiner/Miners/MinersManager.cs @@ -1,656 +1,68 @@ -using NiceHashMiner.Configs; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; -using System; -using System.Collections; +using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; -using System.Diagnostics; - -namespace NiceHashMiner.Miners { - // typedefs - using DeviceSubsetList = List>; - using PerDeviceProifitDictionary = Dictionary>; - using PerDeviceSpeedDictionary = Dictionary>; - - using GroupedDevices = SortedSet; - using AllGroupedDevices = List>; - using NiceHashMiner.Interfaces; - using System.Windows.Forms; - - - - public partial class MinersManager : BaseLazySingleton { - - // temporary varibales for current session - PerDeviceSpeedDictionary _perDeviceSpeedDictionary; - string _miningLocation; - string _worker; - string _btcAdress; - - string _workerBtcStringWorker; - - readonly DeviceGroupType[] _nvidiaTypes = new DeviceGroupType[] { - DeviceGroupType.NVIDIA_2_1, - DeviceGroupType.NVIDIA_3_x, - DeviceGroupType.NVIDIA_5_x, - DeviceGroupType.NVIDIA_6_x - }; - - readonly DeviceGroupType[] _gpuTypes = new DeviceGroupType[] { - DeviceGroupType.AMD_OpenCL, - DeviceGroupType.NVIDIA_2_1, - DeviceGroupType.NVIDIA_3_x, - DeviceGroupType.NVIDIA_5_x, - DeviceGroupType.NVIDIA_6_x - }; - - // these miners are just used for binary path checking - public readonly Dictionary MinerPathChecker; - - // ccminers intensity checking - public readonly Dictionary> CCMinersIntensitiesBoundries = new Dictionary>() { - { MinerPaths.ccminer_decred, Tuple.Create(8.0, 25.0) }, - { MinerPaths.ccminer_nanashi, Tuple.Create(8.0, 25.0) }, - { MinerPaths.ccminer_tpruvot, Tuple.Create(8.0, 25.0) }, - { MinerPaths.ccminer_neoscrypt, Tuple.Create(8.0, 31.0) }, - { MinerPaths.ccminer_sp, Tuple.Create(8.0, 31.0) }, - }; - - // GroupDevices hash code doesn't work correctly use string instead - //Dictionary _groupedDevicesMiners; - Dictionary _groupedDevicesMiners; - List _enabledDevices; - AllGroupedDevices _previousAllGroupedDevices; - AllGroupedDevices _currentAllGroupedDevices; - - IMainFormRatesComunication _mainFormRatesComunication; - - private Timer _preventSleepTimer; - // check internet connection - private Timer _internetCheckTimer; - - // we save cpu miners string group name - Dictionary _cpuMiners = new Dictionary(); - - private bool IsProfitable = true; - - readonly string TAG; - - readonly string DOUBLE_FORMAT = "F12"; - - private bool IsCurrentlyIdle = true; - - protected MinersManager() { - TAG = this.GetType().Name; - _preventSleepTimer = new Timer(); - _preventSleepTimer.Tick += PreventSleepTimer_Tick; - // sleep time is minimal 1 minute - _preventSleepTimer.Interval = 20 * 1000; // leave this interval, it works - - // set internet checking - _internetCheckTimer = new Timer(); - _internetCheckTimer.Tick += InternetCheckTimer_Tick; - _internetCheckTimer.Interval = 1000 * 60 * 5; - - // path checker - Helpers.ConsolePrint(TAG, "Creating MinerPathChecker miners"); - MinerPathChecker = new Dictionary(); - foreach (var gpuGroup in _gpuTypes) { - MinerPathChecker.Add(gpuGroup, CreateMiner(gpuGroup, AlgorithmType.NONE)); - } - } - - private void InternetCheckTimer_Tick(object sender, EventArgs e) { - //if () { - - //} else { - - //} - } - - private void PreventSleepTimer_Tick(object sender, EventArgs e) { - // when mining keep system awake, prevent sleep - Helpers.PreventSleep(); - } +using System.IO; - public void AddCpuMiner(cpuminer miner, int deviceID, string deviceName) { - _cpuMiners.Add(miner.MinerDeviceName, miner); - } +using NiceHashMiner.Interfaces; +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; - public void StopAllMiners() { - IsCurrentlyIdle = true; - if (_groupedDevicesMiners != null) { - foreach (var kv in _groupedDevicesMiners) { - kv.Value.End(); - } - } - if (_mainFormRatesComunication != null) { - _mainFormRatesComunication.ClearRatesALL(); - } +namespace NiceHashMiner.Miners { + using NiceHashMiner.Miners.Grouping; + using NiceHashMiner.Miners.Equihash; + public static class MinersManager { - // restroe/enable sleep - _preventSleepTimer.Stop(); - Helpers.AllowMonitorPowerdownAndSleep(); - } + private static MiningSession CurMiningSession; - public void StopAllMinersNonProfitable() { - IsCurrentlyIdle = true; - if (_groupedDevicesMiners != null) { - foreach (var kv in _groupedDevicesMiners) { - kv.Value.End(); - } - } - if (_mainFormRatesComunication != null) { - _mainFormRatesComunication.ClearRates(-1); - } + public static void StopAllMiners() { + if (CurMiningSession != null) CurMiningSession.StopAllMiners(); + CurMiningSession = null; } - public string GetActiveMinersGroup() { - if (IsCurrentlyIdle) { - return "IDLE"; - } - - string ActiveMinersGroup = ""; - - //get unique miner groups like CPU, NVIDIA, AMD,... - HashSet UniqueMinerGroups = new HashSet(); - foreach (var curDevice in ComputeDevice.AllAvaliableDevices) { - if (curDevice.Enabled) { - UniqueMinerGroups.Add(curDevice.DeviceGroupString); - } - } - if (UniqueMinerGroups.Count > 0 && IsProfitable) { - ActiveMinersGroup = string.Join("/", UniqueMinerGroups); - } - - return ActiveMinersGroup; + public static void StopAllMinersNonProfitable() { + if (CurMiningSession != null) CurMiningSession.StopAllMinersNonProfitable(); } - public static Miner GetCpuMiner(string groupName) { - if (Instance._cpuMiners.Count > 0) { - return Instance._cpuMiners[groupName]; + public static string GetActiveMinersGroup() { + if (CurMiningSession != null) { + return CurMiningSession.GetActiveMinersGroup(); } - return null; + // if no session it is idle + return "IDLE"; } - // create miner creates new miners, except cpuminer, those are saves and called from GetCpuMiner() - public static Miner CreateMiner(DeviceGroupType deviceGroupType, AlgorithmType algorithmType) { - if (AlgorithmType.DaggerHashimoto == algorithmType) { - if (DeviceGroupType.AMD_OpenCL == deviceGroupType) { - return new MinerEtherumOCL(); - } else { - return new MinerEtherumCUDA(); - } - } else { - switch (deviceGroupType) { - case DeviceGroupType.AMD_OpenCL: - return new sgminer(); - case DeviceGroupType.NVIDIA_2_1: - return new ccminer_sm21(); - case DeviceGroupType.NVIDIA_3_x: - return new ccminer_sm3x(); - case DeviceGroupType.NVIDIA_5_x: - return new ccminer_sm5x(); - case DeviceGroupType.NVIDIA_6_x: - return new ccminer_sm6x(); - } - } - - return null; - } - - private string CalcGroupedDevicesKey(GroupedDevices group) { - return string.Join(", ", group); - } - - public double GetTotalRate() { - double TotalRate = 0; - if (_currentAllGroupedDevices != null) { - foreach (var group in _currentAllGroupedDevices) { - var groupMiners = _groupedDevicesMiners[CalcGroupedDevicesKey(group)]; - TotalRate += groupMiners.CurrentWorkingMiner.CurrentRate; - } - } - - return TotalRate; + public static double GetTotalRate() { + if (CurMiningSession != null) return CurMiningSession.GetTotalRate(); + return 0; } - public bool StartInitialize(IMainFormRatesComunication mainFormRatesComunication, + public static bool StartInitialize(IMainFormRatesComunication mainFormRatesComunication, string miningLocation, string worker, string btcAdress) { - _mainFormRatesComunication = mainFormRatesComunication; - _miningLocation = miningLocation; - _worker = worker; - _btcAdress = btcAdress; - - if (_worker.Length > 0) - _workerBtcStringWorker = _btcAdress + "." + _worker; - else - _workerBtcStringWorker = _btcAdress; - - _perDeviceSpeedDictionary = GetEnabledDeviceTypeSpeeds(); - //_groupedDevicesMiners = new Dictionary(); - _groupedDevicesMiners = new Dictionary(); - _enabledDevices = new List(); - _currentAllGroupedDevices = new AllGroupedDevices(); + + CurMiningSession = new MiningSession(ComputeDeviceManager.Avaliable.AllAvaliableDevices, + mainFormRatesComunication, miningLocation, worker, btcAdress); - // assume profitable - IsProfitable = true; - - - // this checks if there are enabled devices and enabled algorithms - bool isMiningEnabled = false; - - foreach (var cdev in ComputeDevice.AllAvaliableDevices) { - if (cdev.Enabled) { - _enabledDevices.Add(cdev); - // check if in CPU group and add the saved CPU miners - if (cdev.DeviceGroupType == DeviceGroupType.CPU) { - GroupedDevices gdevs = new GroupedDevices(); - gdevs.Add(cdev.UUID); - cpuminer miner = _cpuMiners[cdev.Group]; - CpuGroupMiner cpuGroupMiner = new CpuGroupMiner(gdevs, miner); - _groupedDevicesMiners.Add(CalcGroupedDevicesKey(gdevs), cpuGroupMiner); - } - // check if any algorithm enabled - if(!isMiningEnabled) { - foreach (var algorithm in cdev.DeviceBenchmarkConfig.AlgorithmSettings) { - if (!algorithm.Value.Skip) { - isMiningEnabled = true; - break; - } - } - } - - } - } - - if (isMiningEnabled) { - _preventSleepTimer.Start(); - } - - IsCurrentlyIdle = !isMiningEnabled; - - return isMiningEnabled; - } - - /// - /// GetEnabledDeviceTypeBenchmarks calculates currently enabled ComputeDevice benchmark speeds. - /// If there are more cards of the same model it multiplies the speeds by it's count - /// - /// - PerDeviceSpeedDictionary GetEnabledDeviceTypeSpeeds() { - PerDeviceSpeedDictionary perDeviceTypeBenchmarks = new PerDeviceSpeedDictionary(); - - // init algorithms count 0 - foreach (var curCDev in ComputeDevice.AllAvaliableDevices) { - if (curCDev.Enabled) { - Dictionary cumulativeSpeeds = new Dictionary(); - var deviceConfig = curCDev.DeviceBenchmarkConfig; - foreach (var kvp in deviceConfig.AlgorithmSettings) { - var key = kvp.Key; - cumulativeSpeeds[key] = 0; - } - perDeviceTypeBenchmarks[curCDev.UUID] = cumulativeSpeeds; - } - } - // set enabled algorithm count per device counts - foreach (var curCDev in ComputeDevice.AllAvaliableDevices) { - if (curCDev.Enabled) { - Dictionary cumulativeSpeeds = perDeviceTypeBenchmarks[curCDev.UUID]; - var deviceConfig = curCDev.DeviceBenchmarkConfig; - foreach (var kvp in deviceConfig.AlgorithmSettings) { - var key = kvp.Key; - var algorithm = kvp.Value; - // check dagger RAM SIZE - if (algorithm.Skip - || (algorithm.NiceHashID == AlgorithmType.DaggerHashimoto && !curCDev.IsEtherumCapale)) { - // for now set to negative value as not profitable - cumulativeSpeeds[key]--; - } else { - cumulativeSpeeds[key]++; - } - } - } - } - // calculate benchmarks - foreach (var curCDev in ComputeDevice.AllAvaliableDevices) { - if (curCDev.Enabled) { - Dictionary cumulativeSpeeds = perDeviceTypeBenchmarks[curCDev.UUID]; - var deviceConfig = curCDev.DeviceBenchmarkConfig; - foreach (var kvp in deviceConfig.AlgorithmSettings) { - var key = kvp.Key; - var algorithm = kvp.Value; - // instead of cumulative speeds get just if enabled or not count x > 0 => enabled; x < 0 => disabled - if (cumulativeSpeeds[key] > 0) { - cumulativeSpeeds[key] = algorithm.BenchmarkSpeed; - } else { - cumulativeSpeeds[key] = -1 * algorithm.BenchmarkSpeed; - } - } - } - } - - return perDeviceTypeBenchmarks; + return CurMiningSession.IsMiningEnabled; } - - PerDeviceProifitDictionary GetEnabledDeviceProifitDictionary(PerDeviceSpeedDictionary speedDict, Dictionary NiceHashData) { - PerDeviceProifitDictionary profitDict = new PerDeviceProifitDictionary(); - - // log stuff - int MAX_NAME_LEN = "daggerhashimoto".Length; - int MAX_SPEED_LEN = 15; - StringBuilder stringBuilderFull = new StringBuilder(); - stringBuilderFull.AppendLine("Current device profits:"); - - foreach (var nameBenchKvp in speedDict) { - var deviceUUID = nameBenchKvp.Key; - var curDevProfits = new Dictionary(); - StringBuilder stringBuilderDevice = new StringBuilder(); - stringBuilderDevice.AppendLine(String.Format("\tProfits for {0} ({1}):", deviceUUID, ComputeDevice.GetNameForUUID(deviceUUID))); - AlgorithmType mostProfitKey = AlgorithmType.NONE; - double mostProfitAlgoVal = -1; - foreach (var algoSpeedKvp in nameBenchKvp.Value) { - // Log stuff and calculation - string name = AlgorithmNiceHashNames.GetName(algoSpeedKvp.Key); - string namePreaty = name + new String(' ', MAX_NAME_LEN - name.Length); - bool isEnabled = algoSpeedKvp.Value > 0; - double nhmSMADataVal = NiceHashData[algoSpeedKvp.Key].paying; - // TODO what is the constant at the end? - double algoProfit = algoSpeedKvp.Value * nhmSMADataVal * 0.000000001; - - // calculate - if (isEnabled) { - curDevProfits.Add(algoSpeedKvp.Key, algoProfit); - if (mostProfitAlgoVal < algoProfit) { - mostProfitKey = algoSpeedKvp.Key; - mostProfitAlgoVal = algoProfit; - } - } else { - // if disabled make unprofitable - curDevProfits.Add(algoSpeedKvp.Key, -1000000); - algoProfit *= -1; // make bigger then 0 for logging reasons - } - // log stuff - string speedStr = algoSpeedKvp.Value.ToString("F3"); - string speedPreaty = new String(' ', MAX_SPEED_LEN - speedStr.Length) + speedStr; - stringBuilderDevice.AppendLine(String.Format("\t\t{0}\t:\tPROFIT = {1} ({2}, SPEED = {3}, NHSMA = {4})", - namePreaty, // Name - algoProfit.ToString(DOUBLE_FORMAT), // Profit - isEnabled ? "ENABLED " : "DISABLED", // ENABLED/DISABLED - speedPreaty, // Speed - nhmSMADataVal.ToString(DOUBLE_FORMAT) // NiceHashData - )); - } - // add profits - profitDict.Add(deviceUUID, curDevProfits); - // log stuff - stringBuilderDevice.AppendLine(String.Format("\t\tMOST PROFITABLE (ENABLED) ALGO: {0}, PROFIT: {1}", - AlgorithmNiceHashNames.GetName(mostProfitKey), - mostProfitAlgoVal.ToString(DOUBLE_FORMAT))); - stringBuilderFull.AppendLine(stringBuilderDevice.ToString()); - } - - Helpers.ConsolePrint(TAG, stringBuilderFull.ToString()); - return profitDict; - } - - #region Groupping logic - private bool IsAlgorithmSettingsSame(Algorithm a, Algorithm b) { - return a.NiceHashID == b.NiceHashID -#if (SWITCH_TESTING) - && (!ForcePerCardMiners) // this will force individual miners -#endif - && SafeStrCompare(a.ExtraLaunchParameters, b.ExtraLaunchParameters); - } - - private bool SafeStrCompare(string a, string b) { - if (string.IsNullOrEmpty(a) == true && string.IsNullOrEmpty(a) == string.IsNullOrEmpty(b)) return true; - return a == b; - } - - private bool IsNvidiaDevice(ComputeDevice a) { - foreach (var type in _nvidiaTypes) { - if (a.DeviceGroupType == type) return true; - } + public static bool IsMiningEnabled() { + if (CurMiningSession != null) return CurMiningSession.IsMiningEnabled; return false; } - // checks if dagger algo, same settings and if compute platform is same - private bool IsDaggerAndSameComputePlatform(ComputeDevice a, ComputeDevice b) { - return a.MostProfitableAlgorithm.NiceHashID == AlgorithmType.DaggerHashimoto - && IsAlgorithmSettingsSame(a.MostProfitableAlgorithm, b.MostProfitableAlgorithm) - // check if both etherum capable - && a.IsEtherumCapale && b.IsEtherumCapale - // compute platforms must be same - && (IsNvidiaDevice(a) == IsNvidiaDevice(b)); - } - - private bool IsNotCpuGroups(ComputeDevice a, ComputeDevice b) { - return a.DeviceGroupType != DeviceGroupType.CPU && b.DeviceGroupType != DeviceGroupType.CPU; - } - - // this will not check Ethminer path - private bool IsSameBinPath(ComputeDevice a, ComputeDevice b) { - // same group uses same Miner class and therefore same binary path for same algorithm - bool sameGroup = a.DeviceGroupType == b.DeviceGroupType; - if (!sameGroup) { - var a_algoType = a.MostProfitableAlgorithm.NiceHashID; - var b_algoType = b.MostProfitableAlgorithm.NiceHashID; - // a and b algorithm settings should be the same if we call this function - return MinerPathChecker[a.DeviceGroupType].GetOptimizedMinerPath(a_algoType, a.Codename, a.IsOptimizedVersion) - == MinerPathChecker[b.DeviceGroupType].GetOptimizedMinerPath(b_algoType, b.Codename, b.IsOptimizedVersion); - } - - return true; - } - - // we don't want to group CPU devices - private bool IsGroupBinaryAndAlgorithmSame(ComputeDevice a, ComputeDevice b) { - return IsNotCpuGroups(a, b) - && IsAlgorithmSettingsSame(a.MostProfitableAlgorithm, b.MostProfitableAlgorithm) - && IsSameBinPath(a, b); - } - #endregion //Groupping logic - - private string GetDevProfitString(string deviceName, Dictionary deviceProfits) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine(String.Format("\tProfits for {0}:", deviceName)); - // TODO make parameter - int MAX_NAME_LEN = "daggerhashimoto".Length; - foreach (var kvp in deviceProfits) { - string name = AlgorithmNiceHashNames.GetName(kvp.Key); - string namePreaty = name + new String(' ', MAX_NAME_LEN - name.Length); - stringBuilder.AppendLine(String.Format("\t\t{0}\t:\t{1},", - namePreaty, - kvp.Value.ToString(DOUBLE_FORMAT))); - } - - return stringBuilder.ToString(); - } - - private string GetProfitsSummery(PerDeviceProifitDictionary devProfits) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine("Current device profits:"); - foreach (var kvp in devProfits) { - stringBuilder.AppendLine(GetDevProfitString(kvp.Key, kvp.Value)); - } - return stringBuilder.ToString(); - } /// /// SwichMostProfitable should check the best combination for most profit. - /// Calculate profit for each supported algorithm per device group. - /// Build from ground up compatible devices and algorithms. - /// See #region Groupping logic - /// Device groups are CPU, AMD_OpenCL and NVIDIA CUDA SM.x.x. - /// NVIDIA SMx.x should be paired separately except for daggerhashimoto. + /// Calculate profit for each supported algorithm per device and group. /// /// - public void SwichMostProfitableGroupUpMethod(Dictionary NiceHashData) { - var devProfits = GetEnabledDeviceProifitDictionary(_perDeviceSpeedDictionary, NiceHashData); - -#if (SWITCH_TESTING) - SwitchTesting.Instance.SetNext(ref devProfits, _enabledDevices); -#endif - double CurrentProfit = 0.0d; - // calculate most profitable algorithm per enabled device - foreach (var cdev in _enabledDevices) { - var curDevProfits = devProfits[cdev.UUID]; - double maxProfit = double.MinValue; - AlgorithmType maxAlgorithmTypeKey = AlgorithmType.NONE; - var algorithmSettings = cdev.DeviceBenchmarkConfig.AlgorithmSettings; - - foreach (var kvpTypeProfit in curDevProfits) { - if (algorithmSettings.ContainsKey(kvpTypeProfit.Key) - && !algorithmSettings[kvpTypeProfit.Key].Skip - && kvpTypeProfit.Value > 0.0d - && maxProfit < kvpTypeProfit.Value) { - // extra check if current device can't handle dagger - if (AlgorithmType.DaggerHashimoto == kvpTypeProfit.Key && !cdev.IsEtherumCapale) { - continue; - } - maxProfit = kvpTypeProfit.Value; - maxAlgorithmTypeKey = kvpTypeProfit.Key; - } - } - if(maxAlgorithmTypeKey == AlgorithmType.NONE) { - cdev.MostProfitableAlgorithm = null; - } else { - cdev.MostProfitableAlgorithm - = algorithmSettings[maxAlgorithmTypeKey]; - // add most profitable to cumulative profit - CurrentProfit += maxProfit; - } - } - - // now if profitable check - // TODO FOR NOW USD ONLY - var currentProfitUSD = (CurrentProfit * Globals.BitcoinRate); - Helpers.ConsolePrint(TAG, "Current Global profit: " + currentProfitUSD.ToString("F8") + " USD/Day"); - if (ConfigManager.Instance.GeneralConfig.MinimumProfit > 0 - && currentProfitUSD < ConfigManager.Instance.GeneralConfig.MinimumProfit) { - IsProfitable = false; - IsCurrentlyIdle = true; - _mainFormRatesComunication.ShowNotProfitable(); - // return don't group - StopAllMinersNonProfitable(); - Helpers.ConsolePrint(TAG, "Current Global profit: NOT PROFITABLE MinProfit " + ConfigManager.Instance.GeneralConfig.MinimumProfit.ToString("F8") + " USD/Day"); - return; - } else { - IsProfitable = true; - IsCurrentlyIdle = false; - _mainFormRatesComunication.HideNotProfitable(); - string profitabilityInfo = ConfigManager.Instance.GeneralConfig.MinimumProfit == 0 ? "mine always regardless of profit" : ConfigManager.Instance.GeneralConfig.MinimumProfit.ToString("F8") + " USD/Day"; - Helpers.ConsolePrint(TAG, "Current Global profit: IS PROFITABLE MinProfit " + profitabilityInfo); - } - - // group devices with same supported algorithms - _previousAllGroupedDevices = _currentAllGroupedDevices; - _currentAllGroupedDevices = new AllGroupedDevices(); - Dictionary newGroupAndAlgorithm = new Dictionary(); - for (int first = 0; first < _enabledDevices.Count; ++first) { - var firstDev = _enabledDevices[first]; - // skip if no algorithm is profitable - if (firstDev.MostProfitableAlgorithm == null) { - Helpers.ConsolePrint("SwichMostProfitableGroupUpMethod", String.Format("Device {0}, MostProfitableAlgorithm == null", firstDev.Name)); - continue; - } - // check if is in group - bool isInGroup = false; - foreach (var groupedDevices in _currentAllGroupedDevices) { - if (groupedDevices.Contains(firstDev.UUID)) { - isInGroup = true; - break; - } - } - if (isInGroup) continue; - - var newGroup = new GroupedDevices(); - newGroup.Add(firstDev.UUID); - for (int second = first + 1; second < _enabledDevices.Count; ++second) { - var secondDev = _enabledDevices[second]; - // check if we should group - if(IsDaggerAndSameComputePlatform(firstDev, secondDev) - || IsGroupBinaryAndAlgorithmSame(firstDev, secondDev)) { - newGroup.Add(secondDev.UUID); - } - } - - _currentAllGroupedDevices.Add(newGroup); - newGroupAndAlgorithm.Add(newGroup, firstDev.MostProfitableAlgorithm); - } - - // stop groupes that aren't in current group devices - foreach (var curPrevGroup in _previousAllGroupedDevices) { - var curPrevGroupKey = CalcGroupedDevicesKey(curPrevGroup); - bool contains = false; - foreach (var curCheckGroup in _currentAllGroupedDevices) { - var curCheckGroupKey = CalcGroupedDevicesKey(curCheckGroup); - if (curPrevGroupKey == curCheckGroupKey) { - contains = true; - break; - } - } - if (!contains) { - _groupedDevicesMiners[curPrevGroupKey].Stop(); - } - } - // switch to newGroupAndAlgorithm most profitable algorithm - foreach (var kvpGroupAlgorithm in newGroupAndAlgorithm) { - var group = kvpGroupAlgorithm.Key; - var algorithm = kvpGroupAlgorithm.Value; - - GroupMiners currentGroupMiners; - // try find if it doesn't exist create new - string groupStringKey = CalcGroupedDevicesKey(group); - if (!_groupedDevicesMiners.TryGetValue(groupStringKey, out currentGroupMiners)) { - currentGroupMiners = new GroupMiners(group); - _groupedDevicesMiners.Add(groupStringKey, currentGroupMiners); - } - currentGroupMiners.StartAlgorihtm(algorithm, _miningLocation, _workerBtcStringWorker); - } - - // stats quick fix code - if (_currentAllGroupedDevices.Count != _previousAllGroupedDevices.Count) { - MinerStatsCheck(NiceHashData); - } + public static void SwichMostProfitableGroupUpMethod(Dictionary NiceHashData) { + if (CurMiningSession != null) CurMiningSession.SwichMostProfitableGroupUpMethod(NiceHashData); } - public void MinerStatsCheck(Dictionary NiceHashData) { - _mainFormRatesComunication.ClearRates(_currentAllGroupedDevices.Count); - foreach (var group in _currentAllGroupedDevices) { - var groupMiners = _groupedDevicesMiners[CalcGroupedDevicesKey(group)]; - Miner m = groupMiners.CurrentWorkingMiner; - - // skip if not running - if (!m.IsRunning) continue; - - APIData AD = m.GetSummary(); - if (AD == null) { - Helpers.ConsolePrint(m.MinerTAG(), "GetSummary returned null.."); - } - // set rates - if (NiceHashData != null && AD != null) { - m.CurrentRate = NiceHashData[AD.AlgorithmID].paying * AD.Speed * 0.000000001; - } else { - m.CurrentRate = 0; - // set empty - AD = new APIData() { - AlgorithmID = m.CurrentAlgorithmType, - AlgorithmName = AlgorithmNiceHashNames.GetName(m.CurrentAlgorithmType), - Speed = 0.0d - }; - } - - // Update GUI - _mainFormRatesComunication.AddRateInfo(m.MinerTAG(), groupMiners.DevicesInfoString, AD, m.CurrentRate, m.IsAPIReadException); - } + public static void MinerStatsCheck(Dictionary NiceHashData) { + if (CurMiningSession != null) CurMiningSession.MinerStatsCheck(NiceHashData); } - - } } diff --git a/NiceHashMiner/Miners/MinersSettingsManager.cs b/NiceHashMiner/Miners/MinersSettingsManager.cs new file mode 100644 index 0000000..c02c6d4 --- /dev/null +++ b/NiceHashMiner/Miners/MinersSettingsManager.cs @@ -0,0 +1,151 @@ +using NiceHashMiner.Configs.ConfigJsonFile; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners { + public static class MinersSettingsManager { + + class MinerReservedPortsFile : ConfigFile>>>> { + public MinerReservedPortsFile() + : base(FOLDERS.CONFIG, "MinerReservedPorts.json", "MinerReservedPorts_old.json") { + } + } + + // {miner path : {envName : envValue} } + class MinerSystemVariablesFile : ConfigFile>> { + public MinerSystemVariablesFile() : base(FOLDERS.CONFIG, "MinerSystemVariables.json", "MinerSystemVariables_old.json") {} + } + + private static Dictionary>>> MinerReservedPorts = new Dictionary>>>(); + public static List AllReservedPorts = new List(); + + public static Dictionary> MinerSystemVariables = new Dictionary>(); + + public static void Init() { + ExtraLaunchParameters.InitializePackages(); + InitMinerReservedPortsFile(); + InitMinerSystemVariablesFile(); + } + + public static List GetPortsListFor(MinerBaseType minerBaseType, string path, AlgorithmType algorithmType) { + if (MinerReservedPorts != null && MinerReservedPorts.ContainsKey(minerBaseType)) { + if (MinerReservedPorts[minerBaseType] != null && MinerReservedPorts[minerBaseType].ContainsKey(path)) { + if (MinerReservedPorts[minerBaseType][path] != null && MinerReservedPorts[minerBaseType][path].ContainsKey(algorithmType)) { + if (MinerReservedPorts[minerBaseType][path][algorithmType] != null) { + return MinerReservedPorts[minerBaseType][path][algorithmType]; + } + } + } + } + + return new List(); + } + + public static void InitMinerReservedPortsFile() { + MinerReservedPortsFile file = new MinerReservedPortsFile(); + MinerReservedPorts = new Dictionary>>>(); + if (file.IsFileExists()) { + var read = file.ReadFile(); + if (read != null) { + MinerReservedPorts = read; + } + } + try { + for (MinerBaseType type = (MinerBaseType.NONE + 1); type < MinerBaseType.END; ++type) { + if (MinerReservedPorts.ContainsKey(type) == false) { + MinerReservedPorts[type] = new Dictionary>>(); + } + } + for (DeviceGroupType devGroupType = (DeviceGroupType.NONE + 1); devGroupType < DeviceGroupType.LAST; ++devGroupType) { + var minerAlgosForGroup = GroupAlgorithms.CreateDefaultsForGroup(devGroupType); + if (minerAlgosForGroup != null) { + foreach (var mbaseKvp in minerAlgosForGroup) { + MinerBaseType minerBaseType = mbaseKvp.Key; + if (MinerReservedPorts.ContainsKey(minerBaseType)) { + var algos = mbaseKvp.Value; + foreach (var algo in algos) { + var algoType = algo.NiceHashID; + var path = MinerPaths.GetPathFor(minerBaseType, algoType, devGroupType); + var isPathValid = path != MinerPaths.Data.NONE; + if (isPathValid && MinerReservedPorts[minerBaseType].ContainsKey(path) == false) { + MinerReservedPorts[minerBaseType][path] = new Dictionary>(); + } + if (isPathValid && MinerReservedPorts[minerBaseType][path] != null && MinerReservedPorts[minerBaseType][path].ContainsKey(algoType) == false) { + MinerReservedPorts[minerBaseType][path][algoType] = new List(); + } + } + } + } + } + } + file.Commit(MinerReservedPorts); + // set all reserved + foreach (var paths in MinerReservedPorts.Values) { + foreach (var algos in paths.Values) { + foreach (var ports in algos.Values) { + foreach (int port in ports) { + AllReservedPorts.Add(port); + } + } + } + } + } catch { + } + } + + public static void InitMinerSystemVariablesFile() { + MinerSystemVariablesFile file = new MinerSystemVariablesFile(); + MinerSystemVariables = new Dictionary>(); + bool isFileInit = false; + if (file.IsFileExists()) { + var read = file.ReadFile(); + if (read != null) { + isFileInit = true; + MinerSystemVariables = read; + } + } + if (!isFileInit) { + // general AMD defaults scope + { + List minerPaths = new List() { + MinerPaths.Data.sgminer_5_6_0_general, + MinerPaths.Data.sgminer_gm, + MinerPaths.Data.ClaymoreCryptoNightMiner, + MinerPaths.Data.ClaymoreZcashMiner, + MinerPaths.Data.OptiminerZcashMiner + }; + foreach (var minerPath in minerPaths) { + MinerSystemVariables[minerPath] = new Dictionary() { + { "GPU_MAX_ALLOC_PERCENT", "100" }, + { "GPU_USE_SYNC_OBJECTS", "1" }, + { "GPU_SINGLE_ALLOC_PERCENT", "100" }, + { "GPU_MAX_HEAP_SIZE", "100" }, + { "GPU_FORCE_64BIT_PTR", "1" } + }; + } + } + // ClaymoreDual scope + { + MinerSystemVariables[MinerPaths.Data.ClaymoreDual] = new Dictionary() { + { "GPU_MAX_ALLOC_PERCENT", "100" }, + { "GPU_USE_SYNC_OBJECTS", "1" }, + { "GPU_SINGLE_ALLOC_PERCENT", "100" }, + { "GPU_MAX_HEAP_SIZE", "100" }, + { "GPU_FORCE_64BIT_PTR", "0" } + }; + } + // save defaults + file.Commit(MinerSystemVariables); + } + } + + } +} diff --git a/NiceHashMiner/Miners/MiningSession.cs b/NiceHashMiner/Miners/MiningSession.cs new file mode 100644 index 0000000..f09043a --- /dev/null +++ b/NiceHashMiner/Miners/MiningSession.cs @@ -0,0 +1,446 @@ +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Interfaces; +using System; +using System.Collections.Generic; +using System.Text; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Configs; +using System.IO; +using NiceHashMiner.Net20_backport; + +using Timer = System.Timers.Timer; +using System.Timers; + +namespace NiceHashMiner.Miners { + using GroupedDevices = SortedSet; + public class MiningSession { + const string TAG = "MiningSession"; + const string DOUBLE_FORMAT = "F12"; + + // session varibles fixed + string _miningLocation = ""; + string _btcAdress = ""; + string _worker = ""; + List _miningDevices = new List(); + IMainFormRatesComunication _mainFormRatesComunication; + + // session varibles changing + // GroupDevices hash code doesn't work correctly use string instead + //Dictionary _groupedDevicesMiners; + Dictionary _runningGroupMiners = new Dictionary(); + GroupMiner _ethminerNVIDIAPaused = null; + GroupMiner _ethminerAMDPaused = null; + + + private bool IsProfitable = true; + + private bool IsConnectedToInternet = true; + private bool IsMiningRegardlesOfProfit = true; + + // timers + private Timer _preventSleepTimer; + // check internet connection + private Timer _internetCheckTimer; + + + public bool IsMiningEnabled { + get { + // if this is not empty it means we can mine + return _miningDevices.Count > 0; + } + } + + private bool IsCurrentlyIdle { + get { + return !IsMiningEnabled || !IsConnectedToInternet || !IsProfitable; + } + } + + public MiningSession(List devices, + IMainFormRatesComunication mainFormRatesComunication, + string miningLocation, string worker, string btcAdress) { + // init fixed + _mainFormRatesComunication = mainFormRatesComunication; + _miningLocation = miningLocation; + + _btcAdress = btcAdress; + _worker = worker; + + // initial settup + _miningDevices = GroupSetupUtils.GetMiningDevices(devices, true); + if (_miningDevices.Count > 0) { + GroupSetupUtils.AvarageSpeeds(_miningDevices); + } + + // init timer stuff + _preventSleepTimer = new Timer(); + _preventSleepTimer.Elapsed += PreventSleepTimer_Tick; + // sleep time is minimal 1 minute + _preventSleepTimer.Interval = 20 * 1000; // leave this interval, it works + + // set internet checking + _internetCheckTimer = new Timer(); + _internetCheckTimer.Elapsed += InternetCheckTimer_Tick; + _internetCheckTimer.Interval = 1 * 1000 * 60; // every minute + + // assume profitable + IsProfitable = true; + // assume we have internet + IsConnectedToInternet = true; + + if (IsMiningEnabled) { + _preventSleepTimer.Start(); + _internetCheckTimer.Start(); + } + + IsMiningRegardlesOfProfit = ConfigManager.GeneralConfig.MinimumProfit == 0; + } + + #region Timers stuff + private void InternetCheckTimer_Tick(object sender, EventArgs e) { + if (ConfigManager.GeneralConfig.IdleWhenNoInternetAccess) { + IsConnectedToInternet = Helpers.IsConnectedToInternet(); + } + } + + private void PreventSleepTimer_Tick(object sender, ElapsedEventArgs e) { + // when mining keep system awake, prevent sleep + Helpers.PreventSleep(); + } + + #endregion + + #region Start/Stop + public void StopAllMiners() { + if (_runningGroupMiners != null) { + foreach (var groupMiner in _runningGroupMiners.Values) { + groupMiner.End(); + } + _runningGroupMiners = new Dictionary(); + } + if (_ethminerNVIDIAPaused != null) { + _ethminerNVIDIAPaused.End(); + _ethminerNVIDIAPaused = null; + } + if (_ethminerAMDPaused != null) { + _ethminerAMDPaused.End(); + _ethminerAMDPaused = null; + } + if (_mainFormRatesComunication != null) { + _mainFormRatesComunication.ClearRatesALL(); + } + + // restroe/enable sleep + _preventSleepTimer.Stop(); + _internetCheckTimer.Stop(); + Helpers.AllowMonitorPowerdownAndSleep(); + } + + public void StopAllMinersNonProfitable() { + if (_runningGroupMiners != null) { + foreach (var groupMiner in _runningGroupMiners.Values) { + groupMiner.End(); + } + _runningGroupMiners = new Dictionary(); + } + if (_ethminerNVIDIAPaused != null) { + _ethminerNVIDIAPaused.End(); + _ethminerNVIDIAPaused = null; + } + if (_ethminerAMDPaused != null) { + _ethminerAMDPaused.End(); + _ethminerAMDPaused = null; + } + if (_mainFormRatesComunication != null) { + _mainFormRatesComunication.ClearRates(-1); + } + } + #endregion Start/Stop + + private string CalcGroupedDevicesKey(GroupedDevices group) { + return StringHelper.Join(", ", group); + } + + public string GetActiveMinersGroup() { + if (IsCurrentlyIdle) { + return "IDLE"; + } + + string ActiveMinersGroup = ""; + + //get unique miner groups like CPU, NVIDIA, AMD,... + HashSet UniqueMinerGroups = new HashSet(); + foreach (var miningDevice in _miningDevices) { + //if (miningDevice.MostProfitableKey != AlgorithmType.NONE) { + UniqueMinerGroups.Add(GroupNames.GetNameGeneral(miningDevice.Device.DeviceType)); + //} + } + if (UniqueMinerGroups.Count > 0 && IsProfitable) { + ActiveMinersGroup = StringHelper.Join("/", UniqueMinerGroups); + } + + return ActiveMinersGroup; + } + + public double GetTotalRate() { + double TotalRate = 0; + + if (_runningGroupMiners != null) { + foreach (var groupMiner in _runningGroupMiners.Values) { + TotalRate += groupMiner.CurrentRate; + } + } + + return TotalRate; + } + + // full of state + private bool CheckIfProfitable(double CurrentProfit, bool log = true) { + // TODO FOR NOW USD ONLY + var currentProfitUSD = (CurrentProfit * Globals.BitcoinUSDRate); + IsProfitable = + IsMiningRegardlesOfProfit + || !IsMiningRegardlesOfProfit && currentProfitUSD >= ConfigManager.GeneralConfig.MinimumProfit; + if (log) { + Helpers.ConsolePrint(TAG, "Current Global profit: " + currentProfitUSD.ToString("F8") + " USD/Day"); + if (!IsProfitable) { + Helpers.ConsolePrint(TAG, "Current Global profit: NOT PROFITABLE MinProfit " + ConfigManager.GeneralConfig.MinimumProfit.ToString("F8") + " USD/Day"); + } else { + string profitabilityInfo = IsMiningRegardlesOfProfit ? "mine always regardless of profit" : ConfigManager.GeneralConfig.MinimumProfit.ToString("F8") + " USD/Day"; + Helpers.ConsolePrint(TAG, "Current Global profit: IS PROFITABLE MinProfit " + profitabilityInfo); + } + } + return IsProfitable; + } + + private bool CheckIfShouldMine(double CurrentProfit, bool log = true) { + // if profitable and connected to internet mine + bool shouldMine = CheckIfProfitable(CurrentProfit, log) && IsConnectedToInternet; + if (shouldMine) { + _mainFormRatesComunication.HideNotProfitable(); + } else { + if (!IsConnectedToInternet) { + // change msg + if (log) Helpers.ConsolePrint(TAG, "NO INTERNET!!! Stopping mining."); + _mainFormRatesComunication.ShowNotProfitable(International.GetText("Form_Main_MINING_NO_INTERNET_CONNECTION")); + } else { + _mainFormRatesComunication.ShowNotProfitable(International.GetText("Form_Main_MINING_NOT_PROFITABLE")); + } + // return don't group + StopAllMinersNonProfitable(); + } + return shouldMine; + } + + public void SwichMostProfitableGroupUpMethod(Dictionary NiceHashData, bool log = true) { +#if (SWITCH_TESTING) + MiningDevice.SetNextTest(); +#endif + List profitableDevices = new List(); + double CurrentProfit = 0.0d; + double PrevStateProfit = 0.0d; + foreach (var device in _miningDevices) { + // calculate profits + device.CalculateProfits(NiceHashData); + // check if device has profitable algo + if (device.HasProfitableAlgo()) { + profitableDevices.Add(device.GetMostProfitablePair()); + CurrentProfit += device.GetCurrentMostProfitValue; + PrevStateProfit += device.GetPrevMostProfitValue; + } + } + + // print profit statuses + if (log) { + StringBuilder stringBuilderFull = new StringBuilder(); + stringBuilderFull.AppendLine("Current device profits:"); + foreach (var device in _miningDevices) { + StringBuilder stringBuilderDevice = new StringBuilder(); + stringBuilderDevice.AppendLine(String.Format("\tProfits for {0} ({1}):", device.Device.UUID, device.Device.GetFullName())); + foreach (var algo in device.Algorithms) { + stringBuilderDevice.AppendLine(String.Format("\t\tPROFIT = {0}\t(SPEED = {1}\t\t| NHSMA = {2})\t[{3}]", + algo.CurrentProfit.ToString(DOUBLE_FORMAT), // Profit + algo.AvaragedSpeed, // Speed + algo.CurNhmSMADataVal, // NiceHashData + algo.AlgorithmStringID // Name + )); + } + // most profitable + stringBuilderDevice.AppendLine(String.Format("\t\tMOST PROFITABLE ALGO: {0}, PROFIT: {1}", + device.GetMostProfitableString(), + device.GetCurrentMostProfitValue.ToString(DOUBLE_FORMAT))); + stringBuilderFull.AppendLine(stringBuilderDevice.ToString()); + } + Helpers.ConsolePrint(TAG, stringBuilderFull.ToString()); + } + + // check profit threshold + Helpers.ConsolePrint(TAG, String.Format("PrevStateProfit {0}, CurrentProfit {1}", PrevStateProfit, CurrentProfit)); + if (PrevStateProfit > 0 && CurrentProfit > 0) { + double a = Math.Max(PrevStateProfit, CurrentProfit); + double b = Math.Min(PrevStateProfit, CurrentProfit); + //double percDiff = Math.Abs((PrevStateProfit / CurrentProfit) - 1); + double percDiff = ((a - b)) / b; + if (percDiff < ConfigManager.GeneralConfig.SwitchProfitabilityThreshold) { + // don't switch + Helpers.ConsolePrint(TAG, String.Format("Will NOT switch profit diff is {0}, current threshold {1}", percDiff, ConfigManager.GeneralConfig.SwitchProfitabilityThreshold)); + // RESTORE OLD PROFITS STATE + foreach (var device in _miningDevices) { + device.RestoreOldProfitsState(); + } + return; + } else { + Helpers.ConsolePrint(TAG, String.Format("Will SWITCH profit diff is {0}, current threshold {1}", percDiff, ConfigManager.GeneralConfig.SwitchProfitabilityThreshold)); + } + } + + // check if should mine + // Only check if profitable inside this method when getting SMA data, cheching during mining is not reliable + if (CheckIfShouldMine(CurrentProfit, log) == false) { + return; + } + + // group new miners + Dictionary> newGroupedMiningPairs = new Dictionary>(); + // group devices with same supported algorithms + { + var currentGroupedDevices = new List(); + for (int first = 0; first < profitableDevices.Count; ++first) { + var firstDev = profitableDevices[first].Device; + // check if is in group + bool isInGroup = false; + foreach (var groupedDevices in currentGroupedDevices) { + if (groupedDevices.Contains(firstDev.UUID)) { + isInGroup = true; + break; + } + } + // if device is not in any group create new group and check if other device should group + if (isInGroup == false) { + var newGroup = new GroupedDevices(); + var miningPairs = new List() { profitableDevices[first] }; + newGroup.Add(firstDev.UUID); + for (int second = first + 1; second < profitableDevices.Count; ++second) { + // check if we should group + var firstPair = profitableDevices[first]; + var secondPair = profitableDevices[second]; + if (GroupingLogic.ShouldGroup(firstPair, secondPair)) { + var secondDev = profitableDevices[second].Device; + newGroup.Add(secondDev.UUID); + miningPairs.Add(profitableDevices[second]); + } + } + currentGroupedDevices.Add(newGroup); + newGroupedMiningPairs[CalcGroupedDevicesKey(newGroup)] = miningPairs; + } + } + } + //bool IsMinerStatsCheckUpdate = false; + { + // check which groupMiners should be stopped and which ones should be started and which to keep running + Dictionary toStopGroupMiners = new Dictionary(); + Dictionary toRunNewGroupMiners = new Dictionary(); + // check what to stop/update + foreach (string runningGroupKey in _runningGroupMiners.Keys) { + if (newGroupedMiningPairs.ContainsKey(runningGroupKey) == false) { + // runningGroupKey not in new group definately needs to be stopped and removed from curently running + toStopGroupMiners[runningGroupKey] = _runningGroupMiners[runningGroupKey]; + } else { + // runningGroupKey is contained but needs to check if mining algorithm is changed + var miningPairs = newGroupedMiningPairs[runningGroupKey]; + var newAlgoType = GetMinerPairAlgorithmType(miningPairs); + if(newAlgoType != AlgorithmType.NONE && newAlgoType != AlgorithmType.INVALID) { + // if algoType valid and different from currently running update + if (newAlgoType != _runningGroupMiners[runningGroupKey].AlgorithmType) { + // remove current one and schedule to stop mining + toStopGroupMiners[runningGroupKey] = _runningGroupMiners[runningGroupKey]; + // create new one TODO check if DaggerHashimoto + GroupMiner newGroupMiner = null; + if (newAlgoType == AlgorithmType.DaggerHashimoto) { + if (_ethminerNVIDIAPaused != null && _ethminerNVIDIAPaused.Key == runningGroupKey) { + newGroupMiner = _ethminerNVIDIAPaused; + } + if (_ethminerAMDPaused != null && _ethminerAMDPaused.Key == runningGroupKey) { + newGroupMiner = _ethminerAMDPaused; + } + } + if (newGroupMiner == null) { + newGroupMiner = new GroupMiner(miningPairs, runningGroupKey); + } + toRunNewGroupMiners[runningGroupKey] = newGroupMiner; + } + } + } + } + // check brand new + foreach (var kvp in newGroupedMiningPairs) { + var key = kvp.Key; + var miningPairs = kvp.Value; + if (_runningGroupMiners.ContainsKey(key) == false) { + GroupMiner newGroupMiner = new GroupMiner(miningPairs, key); + toRunNewGroupMiners[key] = newGroupMiner; + } + } + // stop old miners + foreach (var toStop in toStopGroupMiners.Values) { + toStop.Stop(); + _runningGroupMiners.Remove(toStop.Key); + // TODO check if daggerHashimoto and save + if(toStop.AlgorithmType == AlgorithmType.DaggerHashimoto) { + if (toStop.DeviceType == DeviceType.NVIDIA) { + _ethminerNVIDIAPaused = toStop; + } else if (toStop.DeviceType == DeviceType.AMD) { + _ethminerAMDPaused = toStop; + } + } + } + // start new miners + foreach (var toStart in toRunNewGroupMiners.Values) { + toStart.Start(_miningLocation, _btcAdress, _worker); + _runningGroupMiners[toStart.Key] = toStart; + } + } + + // stats quick fix code + //if (_currentAllGroupedDevices.Count != _previousAllGroupedDevices.Count) { + MinerStatsCheck(NiceHashData); + //} + } + + private AlgorithmType GetMinerPairAlgorithmType(List miningPairs) { + if (miningPairs.Count > 0) { + return miningPairs[0].Algorithm.NiceHashID; + } + return AlgorithmType.NONE; + } + + public void MinerStatsCheck(Dictionary NiceHashData) { + double CurrentProfit = 0.0d; + _mainFormRatesComunication.ClearRates(_runningGroupMiners.Count); + foreach (var groupMiners in _runningGroupMiners.Values) { + Miner m = groupMiners.Miner; + + // skip if not running + if (!m.IsRunning) continue; + + APIData AD = m.GetSummary(); + if (AD == null) { + Helpers.ConsolePrint(m.MinerTAG(), "GetSummary returned null.."); + } + // set rates + if (NiceHashData != null && AD != null) { + groupMiners.CurrentRate = NiceHashData[AD.AlgorithmID].paying * AD.Speed * 0.000000001; + } else { + groupMiners.CurrentRate = 0; + // set empty + AD = new APIData(groupMiners.AlgorithmType); + } + CurrentProfit += groupMiners.CurrentRate; + // Update GUI + _mainFormRatesComunication.AddRateInfo(m.MinerTAG(), groupMiners.DevicesInfoString, AD, groupMiners.CurrentRate, m.IsAPIReadException); + } + } + + } +} diff --git a/NiceHashMiner/Miners/Obsolete/cpuminer.cs b/NiceHashMiner/Miners/Obsolete/cpuminer.cs new file mode 100644 index 0000000..0648711 --- /dev/null +++ b/NiceHashMiner/Miners/Obsolete/cpuminer.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Globalization; +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; + +namespace NiceHashMiner.Miners { + public class cpuminer : Miner { + public cpuminer() + : base("cpuminer_CPU") { + } + + protected override int GET_MAX_CooldownTimeInMilliseconds() { + return 3600000; // 1hour + } + + public override void Start(string url, string btcAdress, string worker) { + if(!IsInit) { + Helpers.ConsolePrint(MinerTAG(), "MiningSetup is not initialized exiting Start()"); + return; + } + string username = GetUsername(btcAdress, worker); + + LastCommandLine = "--algo=" + MiningSetup.MinerName + + " --url=" + url + + " --userpass=" + username + ":x " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.CPU) + + " --api-bind=" + APIPort.ToString(); + + ProcessHandle = _Start(); + } + + public override APIData GetSummary() { + return GetSummaryCPU_CCMINER(); + } + + protected override void _Stop(MinerStopType willswitch) { + Stop_cpu_ccminer_sgminer_nheqminer(willswitch); + } + + protected override NiceHashProcess _Start() { + NiceHashProcess P = base._Start(); + + var AffinityMask = MiningSetup.MiningPairs[0].Device.AffinityMask; + if (AffinityMask != 0 && P != null) + CPUID.AdjustAffinity(P.Id, AffinityMask); + + return P; + } + + // new decoupled benchmarking routines + #region Decoupled benchmarking routines + + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + return "--algo=" + algorithm.MinerName + + " --benchmark" + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.CPU) + + " --time-limit " + time.ToString(); + } + + protected override Process BenchmarkStartProcess(string CommandLine) { + Process BenchmarkHandle = base.BenchmarkStartProcess(CommandLine); + + var AffinityMask = MiningSetup.MiningPairs[0].Device.AffinityMask; + if (AffinityMask != 0 && BenchmarkHandle != null) + CPUID.AdjustAffinity(BenchmarkHandle.Id, AffinityMask); + + return BenchmarkHandle; + } + + protected override bool BenchmarkParseLine(string outdata) { + double lastSpeed = 0; + if (double.TryParse(outdata, out lastSpeed)) { + BenchmarkAlgorithm.BenchmarkSpeed = lastSpeed; + return true; + } + return false; + } + + protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { + CheckOutdata(outdata); + } + + #endregion // Decoupled benchmarking routines + } +} diff --git a/NiceHashMiner/Miners/Obsolete/eqm.cs b/NiceHashMiner/Miners/Obsolete/eqm.cs new file mode 100644 index 0000000..6ade6a6 --- /dev/null +++ b/NiceHashMiner/Miners/Obsolete/eqm.cs @@ -0,0 +1,70 @@ +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; + +namespace NiceHashMiner.Miners { + public class eqm : nheqBase { + public eqm() + : base("eqm") { + ConectionType = NHMConectionType.LOCKED; + IsNeverHideMiningWindow = true; + } + + public override void Start(string url, string btcAdress, string worker) { + LastCommandLine = GetDevicesCommandString() + " -a " + APIPort + " -l " + url + " -u " + btcAdress + " -w " + worker; + ProcessHandle = _Start(); + } + + + protected override string GetDevicesCommandString() { + string deviceStringCommand = " "; + + if (CPU_Setup.IsInit) { + deviceStringCommand += "-p " + CPU_Setup.MiningPairs.Count; + deviceStringCommand += " " + ExtraLaunchParametersParser.ParseForMiningSetup(CPU_Setup, DeviceType.CPU); + } else { + // disable CPU + deviceStringCommand += " -t 0 "; + } + + if (NVIDIA_Setup.IsInit) { + deviceStringCommand += " -cd "; + foreach (var nvidia_pair in NVIDIA_Setup.MiningPairs) { + if (nvidia_pair.CurrentExtraLaunchParameters.Contains("-ct")) { + for (int i = 0; i < ExtraLaunchParametersParser.GetEqmCudaThreadCount(nvidia_pair); ++i) { + deviceStringCommand += nvidia_pair.Device.ID + " "; + } + } else { // use default 2 best performance + for (int i = 0; i < 2; ++i) { + deviceStringCommand += nvidia_pair.Device.ID + " "; + } + } + } + // no extra launch params + deviceStringCommand += " " + ExtraLaunchParametersParser.ParseForMiningSetup(NVIDIA_Setup, DeviceType.NVIDIA); + } + + return deviceStringCommand; + } + + // benchmark stuff + const string TOTAL_MES = "Total measured:"; + protected override bool BenchmarkParseLine(string outdata) { + + if (outdata.Contains(TOTAL_MES) && outdata.Contains(Iter_PER_SEC)) { + curSpeed = getNumber(outdata, TOTAL_MES, Iter_PER_SEC) * SolMultFactor; + } + if (outdata.Contains(TOTAL_MES) && outdata.Contains(Sols_PER_SEC)) { + var sols = getNumber(outdata, TOTAL_MES, Sols_PER_SEC); + if (sols > 0) { + BenchmarkAlgorithm.BenchmarkSpeed = curSpeed; + return true; + } + } + return false; + } + } +} diff --git a/NiceHashMiner/Miners/Parsing/ExtraLaunchParameters.cs b/NiceHashMiner/Miners/Parsing/ExtraLaunchParameters.cs new file mode 100644 index 0000000..b73b11f --- /dev/null +++ b/NiceHashMiner/Miners/Parsing/ExtraLaunchParameters.cs @@ -0,0 +1,282 @@ +using NiceHashMiner.Configs.ConfigJsonFile; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Parsing { + class MinerOptionPackageFile : ConfigFile { + public MinerOptionPackageFile(string name) : base(FOLDERS.INTERNALS, String.Format("{0}.json", name), String.Format("{0}.json", name)) { + } + } + public static class ExtraLaunchParameters { + + private static readonly List DEFAULTS = new List() { + new MinerOptionPackage( + MinerType.ccminer, + new List() { + new MinerOption("Intensity", "-i", "--intensity=", "0", MinerOptionFlagType.MultiParam, ",") + }, + new List() + ), + new MinerOptionPackage( + MinerType.ccminer_CryptoNight, + new List() { + new MinerOption("Launch", "-l", "--launch=", "8x20", MinerOptionFlagType.MultiParam, ","), // default is 8x20 + new MinerOption("Bfactor", "", "--bfactor=", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("Bsleep", "", "--bsleep=", "0", MinerOptionFlagType.MultiParam, ",") // TODO check default + }, + new List() + ), + new MinerOptionPackage( + MinerType.ethminer_OCL, + new List() { + new MinerOption("LocalWork", "", "--cl-local-work", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("GlobalWork", "", "--cl-global-work", "0", MinerOptionFlagType.MultiParam, ","), + }, + new List() + ), + new MinerOptionPackage( + MinerType.ethminer_CUDA, + new List() { + new MinerOption("CudaBlockSize", "", "--cuda-block-size", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("CudaGridSize", "", "--cuda-grid-size", "0", MinerOptionFlagType.MultiParam, ","), + }, + new List() + ), + new MinerOptionPackage( + MinerType.sgminer, + new List() { + // SingleParam + new MinerOption("KeccakUnroll", "", "--keccak-unroll", "0", MinerOptionFlagType.SingleParam, ""), + new MinerOption("HamsiExpandBig", "", "--hamsi-expand-big", "4", MinerOptionFlagType.SingleParam, ""), + new MinerOption("Nfactor", "", "--nfactor", "10", MinerOptionFlagType.SingleParam, ""), + // MultiParam TODO IMPORTANT check defaults + new MinerOption("Intensity", "-I", "--intensity", "d", MinerOptionFlagType.MultiParam, ","), // default is "d" check if -1 works + new MinerOption("Xintensity", "-X", "--xintensity", "-1", MinerOptionFlagType.MultiParam, ","), // default none + new MinerOption("Rawintensity", "", "--rawintensity", "-1", MinerOptionFlagType.MultiParam, ","), // default none + new MinerOption("ThreadConcurrency", "", "--thread-concurrency", "-1", MinerOptionFlagType.MultiParam, ","), // default none + new MinerOption("Worksize", "-w", "--worksize", "-1", MinerOptionFlagType.MultiParam, ","), // default none + new MinerOption("GpuThreads", "-g", "--gpu-threads", "1", MinerOptionFlagType.MultiParam, ","), + new MinerOption("LookupGap", "", "--lookup-gap", "-1", MinerOptionFlagType.MultiParam, ","), // default none + // Uni + new MinerOption("RemoveDisabled", "--remove-disabled", "--remove-disabled", "", MinerOptionFlagType.Uni, ""), // default none + }, + // TemperatureOptions + new List() { + new MinerOption("GpuFan", "", "--gpu-fan", "30-60", MinerOptionFlagType.MultiParam, ","), // default none + new MinerOption("TempCutoff", "", "--temp-cutoff", "95", MinerOptionFlagType.MultiParam, ","), + new MinerOption("TempOverheat", "", "--temp-overheat", "85", MinerOptionFlagType.MultiParam, ","), + new MinerOption("TempTarget", "", "--temp-target", "75", MinerOptionFlagType.MultiParam, ","), + new MinerOption("AutoFan", "", "--auto-fan", null, MinerOptionFlagType.Uni, ""), + new MinerOption("AutoGpu", "", "--auto-gpu", null, MinerOptionFlagType.Uni, "") + } + ), + new MinerOptionPackage( + MinerType.cpuminer_opt, + new List() { + new MinerOption("Threads", "-t", "--threads=", "-1", MinerOptionFlagType.MultiParam, ","), // default none + new MinerOption("CpuAffinity", "", "--cpu-affinity", "-1", MinerOptionFlagType.MultiParam, ","), // default none + new MinerOption("CpuPriority", "", "--cpu-priority", "-1", MinerOptionFlagType.MultiParam, ",") // default + }, + new List() + ), + new MinerOptionPackage( + MinerType.nheqminer_CPU, + new List() { + new MinerOption("Threads", "-t", "-t", "-1", MinerOptionFlagType.SingleParam, " "), // default none + }, + new List() + ), + new MinerOptionPackage( + MinerType.nheqminer_CUDA, + new List() { + new MinerOption("Solver_Version", "-cv", "-cv", "0", MinerOptionFlagType.SingleParam, " "), // default 0 + new MinerOption("Solver_Block", "-cb", "-cb", "0", MinerOptionFlagType.MultiParam, " "), // default 0 + new MinerOption("Solver_Thread", "-ct", "-ct", "0", MinerOptionFlagType.MultiParam, " "), // default 0 + }, + new List() + ), + new MinerOptionPackage( + MinerType.eqm_CUDA, + new List() { + new MinerOption("Solver_Mode", "-cm", "-cm", "0", MinerOptionFlagType.MultiParam, " "), // default 0 + }, + new List() + ), + new MinerOptionPackage( + MinerType.ClaymoreZcash, + new List() { + new MinerOption("ClaymoreZcash_a" , "-a", "-a", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreZcash_asm" , "-asm", "-asm", "1", MinerOptionFlagType.MultiParam, ","), + + new MinerOption("ClaymoreZcash_i" , "-i", "-i", "6", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreZcash_wd" , "-wd", "-wd", "1", MinerOptionFlagType.SingleParam, ","), + //new MinerOption(ClaymoreZcash_r , , , , MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreZcash_nofee" , "-nofee", "-nofee", "0", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreZcash_li" , "-li", "-li", "0", MinerOptionFlagType.MultiParam, ","), + + //MinerOptionFlagType.MultiParam might not work corectly due to ADL indexing so use single param to apply to all + new MinerOption("ClaymoreZcash_cclock" , "-cclock", "-cclock", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreZcash_mclock" , "-mclock", "-mclock", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreZcash_powlim" , "-powlim", "-powlim", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreZcash_cvddc" , "-cvddc", "-cvddc", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreZcash_mvddc" , "-mvddc", "-mvddc", "0", MinerOptionFlagType.MultiParam, ","), + }, + new List() { + // temperature stuff + //MinerOptionFlagType.MultiParam might not work corectly due to ADL indexing so use single param to apply to all + new MinerOption("ClaymoreZcash_tt" , "-tt", "-tt", "1", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreZcash_ttli" , "-ttli", "-ttli", "70", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreZcash_tstop" , "-tstop", "-tstop", "0", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreZcash_fanmax" , "-fanmax", "-fanmax", "100", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreZcash_fanmin" , "-fanmin", "-fanmin", "0", MinerOptionFlagType.MultiParam, ","), + } + ), + new MinerOptionPackage( + MinerType.ClaymoreCryptoNight, + new List() { + new MinerOption("ClaymoreCryptoNight_a" , "-a", "-a", "0", MinerOptionFlagType.MultiParam, ""), + new MinerOption("ClaymoreCryptoNight_wd" , "-wd", "-wd", "1", MinerOptionFlagType.SingleParam, ","), + //new MinerOption(ClaymoreCryptoNight_r , , , , MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreCryptoNight_nofee" , "-nofee", "-nofee", "0", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreCryptoNight_li" , "-li", "-li", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreCryptoNight_h" , "-h", "-h", "0", MinerOptionFlagType.MultiParam, ","), + + new MinerOption("ClaymoreCryptoNight_cclock" , "-cclock", "-cclock", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreCryptoNight_mclock" , "-mclock", "-mclock", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreCryptoNight_powlim" , "-powlim", "-powlim", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreCryptoNight_cvddc" , "-cvddc", "-cvddc", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreCryptoNight_mvddc" , "-mvddc", "-mvddc", "0", MinerOptionFlagType.MultiParam, ","), + }, + new List() { + // temperature stuff + //MinerOptionFlagType.MultiParam might not work corectly due to ADL indexing so use single param to apply to all + new MinerOption("ClaymoreCryptoNight_tt" , "-tt", "-tt", "1", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreCryptoNight_tstop" , "-tstop", "-tstop", "0", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreCryptoNight_fanmax" , "-fanmax", "-fanmax", "100", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreCryptoNight_fanmin" , "-fanmin", "-fanmin", "0", MinerOptionFlagType.MultiParam, ","), + } + ), + new MinerOptionPackage( + MinerType.OptiminerZcash, + new List() { + new MinerOption("ForceGenericKernel" , "--force-generic-kernel", "--force-generic-kernel", null, MinerOptionFlagType.Uni, ""), + new MinerOption("ExperimentalKernel" , "--experimental-kernel", "--experimental-kernel", null, MinerOptionFlagType.Uni, ""), + new MinerOption("nodevfee" , "--nodevfee", "--nodevfee", null, MinerOptionFlagType.Uni, ""), + new MinerOption("Intensity" , "-i", "--intensity", "0", MinerOptionFlagType.DuplicateMultiParam, ""), + new MinerOption("PciMode" , "--pci-mode", "--pci-mode", "", MinerOptionFlagType.SingleParam, ""), + }, + new List() + ), + new MinerOptionPackage( + MinerType.excavator, + new List() { + // parameters differ according to algorithm + new MinerOption("parameter1", "-c1", "-c1", "0", MinerOptionFlagType.MultiParam, " "), + new MinerOption("parameter2", "-c2", "-c2", "0", MinerOptionFlagType.MultiParam, " "), + new MinerOption("debug_param", "-f", "-f", "", MinerOptionFlagType.SingleParam, " "), + // Overclocking not supported from NHM + //new MinerOption("Overclocking_os", "-os", "-os", "", MinerOptionFlagType.MultiParam, " "), + //new MinerOption("Overclocking_od", "-od", "-od", "2", MinerOptionFlagType.MultiParam, " "), + }, + new List() + ), + new MinerOptionPackage( + MinerType.ClaymoreDual, + new List() { + new MinerOption("ClaymoreDual_etha" , "-etha", "-etha", "-1", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreDual_ethi" , "-ethi", "-ethi", "8", MinerOptionFlagType.MultiParam, ","), + + new MinerOption("ClaymoreDual_eres" , "-eres", "-eres", "2", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_erate" , "-erate", "-erate", "1", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_estale" , "-estale", "-estale", "1", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_gser" , "-gser", "-gser", "0", MinerOptionFlagType.SingleParam, ","), + + new MinerOption("ClaymoreDual_wd" , "-wd", "-wd", "1", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_retrydelay" , "-retrydelay", "-retrydelay", "20", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_nofee" , "-nofee", "-nofee", "0", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_li" , "-li", "-li", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreDual_lidag" , "-lidag", "-lidag", "0", MinerOptionFlagType.MultiParam, ","), + + //MinerOptionFlagType.MultiParam might not work corectly due to ADL indexing so use single param to apply to all + new MinerOption("ClaymoreDual_cclock" , "-cclock", "-cclock", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreDual_mclock" , "-mclock", "-mclock", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreDual_powlim" , "-powlim", "-powlim", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreDual_cvddc" , "-cvddc", "-cvddc", "0", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreDual_mvddc" , "-mvddc", "-mvddc", "0", MinerOptionFlagType.MultiParam, ","), + + // other and dual mining features + new MinerOption("ClaymoreDual_etht" , "-etht", "-etht", "200", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_allcoins" , "-allcoins", "-allcoins", "", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_r" , "-r", "-r", "0", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_mode" , "-mode", "-mode", "0", MinerOptionFlagType.SingleParam, ","), // this is not well supported in MultiParam + + new MinerOption("ClaymoreDual_ftime" , "-ftime", "-ftime", "0", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_eres" , "-eres", "-eres", "2", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_dpool" , "-dpool", "-dpool", "", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_dwal" , "-dwal", "-dwal", "", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_dpsw" , "-dpsw", "-dpsw", "", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_dcoin" , "-dcoin", "-dcoin", "", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_dcri" , "-dcri", "-dcri", "30", MinerOptionFlagType.MultiParam, ","), + + new MinerOption("ClaymoreDual_dcrt" , "-dcrt", "-dcrt", "5", MinerOptionFlagType.SingleParam, ","), + // v9.0 + new MinerOption("ClaymoreDual_asm" , "-asm", "-asm", "1", MinerOptionFlagType.MultiParam, ","), + }, + new List() { + // temperature stuff + //MinerOptionFlagType.MultiParam might not work corectly due to ADL indexing so use single param to apply to all + new MinerOption("ClaymoreDual_tt" , "-tt", "-tt", "1", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_ttdcr" , "-ttdcr", "-ttdcr", "1", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_ttli" , "-ttli", "-ttli", "70", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_tstop" , "-tstop", "-tstop", "0", MinerOptionFlagType.SingleParam, ","), + new MinerOption("ClaymoreDual_fanmax" , "-fanmax", "-fanmax", "100", MinerOptionFlagType.MultiParam, ","), + new MinerOption("ClaymoreDual_fanmin" , "-fanmin", "-fanmin", "0", MinerOptionFlagType.MultiParam, ","), + } + ), + }; + + private static List MinerOptionPackages = new List(); + + public static void InitializePackages() { + foreach (var pack in DEFAULTS) { + var packageName = String.Format("MinerOptionPackage_{0}", pack.Name); + var packageFile = new MinerOptionPackageFile(packageName); + var readPack = packageFile.ReadFile(); + if (readPack == null) { // read has failed + Helpers.ConsolePrint("ExtraLaunchParameters", "Creating internal params config " + packageName); + MinerOptionPackages.Add(pack); + // create defaults + packageFile.Commit(pack); + } else { + Helpers.ConsolePrint("ExtraLaunchParameters", "Loading internal params config " + packageName); + MinerOptionPackages.Add(readPack); + } + } + var defaultKeys = DEFAULTS.ConvertAll((p) => p.Type); + // extra check if DEFAULTS is missing a key + for (var type = (MinerType.NONE + 1); type < MinerType.END; ++type) { + if (defaultKeys.Contains(type) == false) { + var packageName = String.Format("MinerOptionPackage_{0}", Enum.GetName(typeof(MinerType), type)); + var packageFile = new MinerOptionPackageFile(packageName); + var readPack = packageFile.ReadFile(); + if (readPack != null) { // read has failed + Helpers.ConsolePrint("ExtraLaunchParameters", "Creating internal params config " + packageName); + MinerOptionPackages.Add(readPack); + } + } + } + } + + public static MinerOptionPackage GetMinerOptionPackageForMinerType(MinerType type) { + int index = MinerOptionPackages.FindIndex((p) => p.Type == type); + if(index > -1) { + return MinerOptionPackages[index]; + } + // if none found + return new MinerOptionPackage(MinerType.NONE, new List(), new List()); + } + + } +} diff --git a/NiceHashMiner/Miners/Parsing/ExtraLaunchParametersParser.cs b/NiceHashMiner/Miners/Parsing/ExtraLaunchParametersParser.cs new file mode 100644 index 0000000..ed78156 --- /dev/null +++ b/NiceHashMiner/Miners/Parsing/ExtraLaunchParametersParser.cs @@ -0,0 +1,415 @@ +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Net20_backport; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Parsing { + using MinerOptionType = String; + static class ExtraLaunchParametersParser { + private static readonly string TAG = "ExtraLaunchParametersParser"; + private static readonly string MinerOptionType_NONE = "MinerOptionType_NONE"; + + + private static bool _showLog = true; + + private static void LogParser(string msg) { + if (_showLog) { + Helpers.ConsolePrint(TAG, msg); + } + } + + // exception... + public static int GetEqmCudaThreadCount(MiningPair pair) { + if (pair.CurrentExtraLaunchParameters.Contains("-ct")) { + List eqm_CUDA_Options = new List() { + new MinerOption("CUDA_Solver_Thread", "-ct", "-ct", "1", MinerOptionFlagType.MultiParam, " "), + }; + string parsedStr = Parse(new List() { pair }, eqm_CUDA_Options, true); + try { + int threads = Int32.Parse(parsedStr.Trim().Replace("-ct", "").Trim()); + return threads; + } catch { } + } + return 1; // default + } + + private static bool prevHasIgnoreParam = false; + private static int logCount = 0; + + private static void IgnorePrintLogInit() { + prevHasIgnoreParam = false; + logCount = 0; + } + + private static void IgnorePrintLog(string param, string IGNORE_PARAM, List ignoreLogOpions = null) { + // AMD temp controll is separated and logs stuff that is ignored + bool printIgnore = true; + if (ignoreLogOpions != null) { + foreach (var ignoreOption in ignoreLogOpions) { + if (param.Equals(ignoreOption.ShortName) || param.Equals(ignoreOption.LongName)) { + printIgnore = false; + prevHasIgnoreParam = true; + logCount = 0; + break; + } + } + } + if (printIgnore && !prevHasIgnoreParam) { + LogParser(String.Format(IGNORE_PARAM, param)); + } + if (logCount == 1) { + prevHasIgnoreParam = false; + logCount = 0; + } + ++logCount; + } + + private static string Parse(List MiningPairs, List options, bool useIfDefaults = true, List ignoreLogOpions = null) { + const string IGNORE_PARAM = "Cannot parse \"{0}\", not supported, set to ignore, or wrong extra launch parameter settings"; + List optionsOrder = new List(); + Dictionary> cdevOptions = new Dictionary>(); + Dictionary isOptionDefaults = new Dictionary(); + Dictionary isOptionExist = new Dictionary(); + // init devs options, and defaults + foreach (var pair in MiningPairs) { + var defaults = new Dictionary(); + foreach (var option in options) { + defaults[option.Type] = option.Default; + } + cdevOptions[pair.Device.UUID] = defaults; + } + // init order and params flags, and params list + foreach (var option in options) { + MinerOptionType optionType = option.Type; + optionsOrder.Add(optionType); + + isOptionDefaults[optionType] = true; + isOptionExist[optionType] = false; + } + // parse + foreach (var pair in MiningPairs) { + LogParser(String.Format("ExtraLaunch params \"{0}\" for device UUID {1}", pair.CurrentExtraLaunchParameters, pair.Device.UUID)); + var parameters = pair.CurrentExtraLaunchParameters.Replace("=", "= ").Split(' '); + + IgnorePrintLogInit(); + + + MinerOptionType currentFlag = MinerOptionType_NONE; + foreach (var param in parameters) { + if (param.Equals("")) { // skip + continue; + } else if (currentFlag == MinerOptionType_NONE) { + bool isIngored = true; + foreach (var option in options) { + if (param.Equals(option.ShortName) || param.Equals(option.LongName)) { + isIngored = false; + if (option.FlagType == MinerOptionFlagType.Uni) { + isOptionExist[option.Type] = true; + cdevOptions[pair.Device.UUID][option.Type] = "notNull"; // if Uni param is null it is not present + } else { // Sinlge and Multi param + currentFlag = option.Type; + } + } + } + if (isIngored) { // ignored + IgnorePrintLog(param, IGNORE_PARAM, ignoreLogOpions); + } + } else if (currentFlag != MinerOptionType_NONE) { + isOptionExist[currentFlag] = true; + cdevOptions[pair.Device.UUID][currentFlag] = param; + currentFlag = MinerOptionType_NONE; + } else { // problem + IgnorePrintLog(param, IGNORE_PARAM, ignoreLogOpions); + } + } + } + + string retVal = ""; + + // check if is all defaults + bool isAllDefault = true; + foreach (var pair in MiningPairs) { + foreach (var option in options) { + if (option.Default != cdevOptions[pair.Device.UUID][option.Type]) { + isAllDefault = false; + isOptionDefaults[option.Type] = false; + } + } + } + + if (!isAllDefault || useIfDefaults) { + foreach (var option in options) { + if (!isOptionDefaults[option.Type] || isOptionExist[option.Type] || useIfDefaults) { // if options all default ignore + if(option.FlagType == MinerOptionFlagType.Uni) { + // uni params if one exist use or all must exist? + bool isOptionInUse = false; + foreach (var pair in MiningPairs) { + if (cdevOptions[pair.Device.UUID][option.Type] != null) { + isOptionInUse = true; + break; + } + } + if (isOptionInUse) { + retVal += String.Format(" {0}", option.LongName); + } + } else if(option.FlagType == MinerOptionFlagType.MultiParam) { + List values = new List(); + foreach (var pair in MiningPairs) { + values.Add(cdevOptions[pair.Device.UUID][option.Type]); + } + string MASK = " {0} {1}"; + if(option.LongName.Contains("=")) { + MASK = " {0}{1}"; + } + retVal += String.Format(MASK, option.LongName, StringHelper.Join(option.Separator, values)); + } else if (option.FlagType == MinerOptionFlagType.SingleParam) { + HashSet values = new HashSet(); + foreach (var pair in MiningPairs) { + values.Add(cdevOptions[pair.Device.UUID][option.Type]); + } + string setValue = option.Default; + if (values.Count >= 1) { + // Always take first + setValue = values.First(); + } + string MASK = " {0} {1}"; + if (option.LongName.Contains("=")) { + MASK = " {0}{1}"; + } + retVal += String.Format(MASK, option.LongName, setValue); + } else if (option.FlagType == MinerOptionFlagType.DuplicateMultiParam) { + List values = new List(); + string MASK = " {0} {1}"; + foreach (var pair in MiningPairs) { + values.Add(String.Format(MASK, option.LongName, cdevOptions[pair.Device.UUID][option.Type])); + } + retVal += " " + StringHelper.Join(" ", values); + } + } + } + } + + LogParser(String.Format("Final extra launch params parse \"{0}\"", retVal)); + + return retVal; + } + + public static string ParseForMiningSetup(MiningSetup miningSetup, DeviceType deviceType, bool showLog = true) { + return ParseForMiningPairs( + miningSetup.MiningPairs, + deviceType, showLog); + } + + public static string ParseForMiningPair(MiningPair miningPair, AlgorithmType algorithmType, DeviceType deviceType, bool showLog = true) { + return ParseForMiningPairs( + new List() { miningPair }, + deviceType, showLog); + } + + private static MinerType GetMinerType(DeviceType deviceType, MinerBaseType minerBaseType, AlgorithmType algorithmType) { + //if (MinerBaseType.cpuminer == minerBaseType) { + // return MinerType.cpuminer_opt; + //} + if (MinerBaseType.OptiminerAMD == minerBaseType) { + return MinerType.OptiminerZcash; + } + if (MinerBaseType.sgminer == minerBaseType) { + return MinerType.sgminer; + } + if (MinerBaseType.ccminer == minerBaseType || MinerBaseType.ccminer_alexis == minerBaseType || MinerBaseType.experimental == minerBaseType) { + if (AlgorithmType.CryptoNight == algorithmType) { + return MinerType.ccminer_CryptoNight; + } + return MinerType.ccminer; + } + if (MinerBaseType.ClaymoreAMD == minerBaseType) { + if (AlgorithmType.CryptoNight == algorithmType) { + return MinerType.ClaymoreCryptoNight; + } + if (AlgorithmType.Equihash == algorithmType) { + return MinerType.ClaymoreZcash; + } + if (AlgorithmType.DaggerHashimoto == algorithmType) { + return MinerType.ClaymoreDual; + } + } + if (MinerBaseType.ethminer == minerBaseType) { + if(DeviceType.AMD == deviceType) { + return MinerType.ethminer_OCL; + } + if(DeviceType.NVIDIA == deviceType) { + return MinerType.ethminer_CUDA; + } + } + if (MinerBaseType.nheqminer == minerBaseType) { + if(DeviceType.CPU == deviceType) { + return MinerType.nheqminer_CPU; + } + if(DeviceType.AMD == deviceType) { + return MinerType.nheqminer_AMD; + } + if(DeviceType.NVIDIA == deviceType) { + return MinerType.nheqminer_CUDA; + } + } + if (MinerBaseType.eqm == minerBaseType) { + if(DeviceType.CPU == deviceType) { + return MinerType.eqm_CPU; + } + if(DeviceType.NVIDIA == deviceType) { + return MinerType.eqm_CUDA; + } + } + if (MinerBaseType.excavator == minerBaseType) { + return MinerType.excavator; + } + + return MinerType.NONE; + } + + private static string ParseForMiningPairs(List MiningPairs, DeviceType deviceType, bool showLog = true) { + _showLog = showLog; + + MinerBaseType minerBaseType = MinerBaseType.NONE; + AlgorithmType algorithmType = AlgorithmType.NONE; + if (MiningPairs.Count > 0) { + var algo = MiningPairs[0].Algorithm; + if (algo != null) { + algorithmType = algo.NiceHashID; + minerBaseType = algo.MinerBaseType; + } + } + + MinerType minerType = GetMinerType(deviceType, minerBaseType, algorithmType); + + MinerOptionPackage minerOptionPackage = ExtraLaunchParameters.GetMinerOptionPackageForMinerType(minerType); + + List setMiningPairs = MiningPairs.ConvertAll((mp) => mp); + // handle exceptions and package parsing + // CPU exception + if (deviceType == DeviceType.CPU) { + CheckAndSetCPUPairs(setMiningPairs); + } + // ethminer exception + if (MinerType.ethminer_OCL == minerType || MinerType.ethminer_CUDA == minerType) { + // use if missing compute device for correct mapping + // init fakes workaround + var cdevs_mappings = new List(); + { + int id = -1; + var fakeAlgo = new Algorithm(MinerBaseType.ethminer, AlgorithmType.DaggerHashimoto, "daggerhashimoto"); + foreach (var pair in setMiningPairs) { + while (++id != pair.Device.ID) { + var fakeCdev = new ComputeDevice(id); + cdevs_mappings.Add(new MiningPair(fakeCdev, fakeAlgo)); + } + cdevs_mappings.Add(pair); + } + } + // reset setMiningPairs + setMiningPairs = cdevs_mappings; + } + // sgminer exception handle intensity types + if (MinerType.sgminer == minerType) { + // rawIntensity overrides xintensity, xintensity overrides intensity + var sgminer_intensities = new List() { + new MinerOption("Intensity", "-I", "--intensity", "d", MinerOptionFlagType.MultiParam, ","), // default is "d" check if -1 works + new MinerOption("Xintensity", "-X", "--xintensity", "-1", MinerOptionFlagType.MultiParam, ","), // default none + new MinerOption("Rawintensity", "", "--rawintensity", "-1", MinerOptionFlagType.MultiParam, ","), // default none + }; + var contains_intensity = new Dictionary() { + { "Intensity", false }, + { "Xintensity", false }, + { "Rawintensity", false }, + }; + // check intensity and xintensity, the latter overrides so change accordingly + foreach (var cDev in setMiningPairs) { + foreach (var intensityOption in sgminer_intensities) { + if (!string.IsNullOrEmpty(intensityOption.ShortName) && cDev.CurrentExtraLaunchParameters.Contains(intensityOption.ShortName)) { + cDev.CurrentExtraLaunchParameters = cDev.CurrentExtraLaunchParameters.Replace(intensityOption.ShortName, intensityOption.LongName); + contains_intensity[intensityOption.Type] = true; + } + if (cDev.CurrentExtraLaunchParameters.Contains(intensityOption.LongName)) { + contains_intensity[intensityOption.Type] = true; + } + } + } + // replace + if (contains_intensity["Intensity"] && contains_intensity["Xintensity"]) { + LogParser("Sgminer replacing --intensity with --xintensity"); + foreach (var cDev in setMiningPairs) { + cDev.CurrentExtraLaunchParameters = cDev.CurrentExtraLaunchParameters.Replace("--intensity", "--xintensity"); + } + } + if (contains_intensity["Xintensity"] && contains_intensity["Rawintensity"]) { + LogParser("Sgminer replacing --xintensity with --rawintensity"); + foreach (var cDev in setMiningPairs) { + cDev.CurrentExtraLaunchParameters = cDev.CurrentExtraLaunchParameters.Replace("--xintensity", "--rawintensity"); + } + } + } + + string ret = ""; + string general = Parse(setMiningPairs, minerOptionPackage.GeneralOptions, false, minerOptionPackage.TemperatureOptions); + // temp control and parse + if (ConfigManager.GeneralConfig.DisableAMDTempControl) { + LogParser("DisableAMDTempControl is TRUE, temp control parameters will be ignored"); + ret = general; + } else { + LogParser("AMD parsing temperature control parameters"); + // temp = Parse(setMiningPairs, minerOptionPackage.TemperatureOptions, true, minerOptionPackage.GeneralOptions); + string temp = Parse(setMiningPairs, minerOptionPackage.TemperatureOptions, false, minerOptionPackage.GeneralOptions); + + ret = general + " " + temp; + } + + return ret; + } + + private static void CheckAndSetCPUPairs(List MiningPairs) { + foreach (var pair in MiningPairs) { + var cDev = pair.Device; + // extra thread check + if (pair.CurrentExtraLaunchParameters.Contains("--threads=") || pair.CurrentExtraLaunchParameters.Contains("-t")) { + // nothing + } else { // add threads params mandatory + pair.CurrentExtraLaunchParameters += " -t " + GetThreads(cDev.Threads, pair.Algorithm.LessThreads).ToString(); + } + } + } + + public static int GetThreadsNumber(MiningPair cpuPair) { + var cDev = cpuPair.Device; + var algo = cpuPair.Algorithm; + // extra thread check + if (algo.ExtraLaunchParameters.Contains("--threads=") || algo.ExtraLaunchParameters.Contains("-t")) { + var strings = algo.ExtraLaunchParameters.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + int i = -1; + for (int cur_i = 0; cur_i < strings.Length; ++cur_i) { + if (strings[cur_i] == "--threads=" || strings[cur_i] == "-t") { + i = cur_i + 1; + break; + } + } + if (i > -1 && strings.Length < i) { + int numTr = cDev.Threads; + if (Int32.TryParse(strings[i], out numTr)) { + if (numTr <= cDev.Threads) return numTr; + } + } + } + return GetThreads(cDev.Threads, cpuPair.Algorithm.LessThreads); + } + + private static int GetThreads(int Threads, int LessThreads) { + if (Threads > LessThreads) { + return Threads - LessThreads; + } + return Threads; + } + } +} diff --git a/NiceHashMiner/Miners/Parsing/MinerOption.cs b/NiceHashMiner/Miners/Parsing/MinerOption.cs new file mode 100644 index 0000000..d47dd9d --- /dev/null +++ b/NiceHashMiner/Miners/Parsing/MinerOption.cs @@ -0,0 +1,23 @@ +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Parsing { + public class MinerOption { + public MinerOption(string iType, string iShortName, string iLongName, string iDefault, MinerOptionFlagType iFlagType, string iSeparator) { + this.Type = iType; + this.ShortName = iShortName; + this.LongName = iLongName; + this.Default = iDefault; + this.FlagType = iFlagType; + this.Separator = iSeparator; + } + public string Type; + public string ShortName; + public string LongName; + public string Default; + public MinerOptionFlagType FlagType; + public string Separator; + } +} diff --git a/NiceHashMiner/Miners/Parsing/MinerOptionPackage.cs b/NiceHashMiner/Miners/Parsing/MinerOptionPackage.cs new file mode 100644 index 0000000..f639cbe --- /dev/null +++ b/NiceHashMiner/Miners/Parsing/MinerOptionPackage.cs @@ -0,0 +1,20 @@ +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Miners.Parsing { + public class MinerOptionPackage { + public string Name; + public MinerType Type; + public List GeneralOptions; + public List TemperatureOptions; + + public MinerOptionPackage(MinerType iType, List iGeneralOptions, List iTemperatureOptions) { + this.Type = iType; + this.GeneralOptions = iGeneralOptions; + this.TemperatureOptions = iTemperatureOptions; + this.Name = Enum.GetName(typeof(MinerType), iType); + } + } +} diff --git a/NiceHashMiner/Miners/XmrStackCPUMiner.cs b/NiceHashMiner/Miners/XmrStackCPUMiner.cs new file mode 100644 index 0000000..11736e4 --- /dev/null +++ b/NiceHashMiner/Miners/XmrStackCPUMiner.cs @@ -0,0 +1,324 @@ +using Newtonsoft.Json.Linq; +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Parsing; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Net.Sockets; +using System.Text; + +namespace NiceHashMiner.Miners { + + public class XmrStackCPUMinerConfig { + public XmrStackCPUMinerConfig(int numberOfthreads, string poolAddr, string wallet, int port) { + this.cpu_thread_num = numberOfthreads; + this.pool_address = poolAddr; + this.wallet_address = wallet; + this.httpd_port = port; + } + + public void Inti_cpu_threads_conf(bool low_power_mode, bool no_prefetch, bool affine_to_cpu, bool isHyperThreading) { + cpu_threads_conf = new List(); + if (isHyperThreading) { + for (int i_cpu = 0; i_cpu < cpu_thread_num; ++i_cpu) { + cpu_threads_conf.Add(JObject.FromObject(new { low_power_mode = low_power_mode, no_prefetch = no_prefetch, affine_to_cpu = i_cpu * 2 })); + } + } else { + for (int i_cpu = 0; i_cpu < cpu_thread_num; ++i_cpu) { + if (affine_to_cpu) { + cpu_threads_conf.Add(JObject.FromObject(new { low_power_mode = low_power_mode, no_prefetch = no_prefetch, affine_to_cpu = i_cpu })); + } else { + cpu_threads_conf.Add(JObject.FromObject(new { low_power_mode = low_power_mode, no_prefetch = no_prefetch, affine_to_cpu = false })); + } + } + } + } + + /* + * Number of threads. You can configure them below. Cryptonight uses 2MB of memory, so the optimal setting + * here is the size of your L3 cache divided by 2. Intel mid-to-high end desktop processors have 2MB of L3 + * cache per physical core. Low end cpus can have 1.5 or 1 MB while Xeons can have 2, 2.5 or 3MB per core. + */ + public readonly int cpu_thread_num; + + /* + * Thread configuration for each thread. Make sure it matches the number above. + * low_power_mode - This mode will double the cache usage, and double the single thread performance. It will + * consume much less power (as less cores are working), but will max out at around 80-85% of + * the maximum performance. + * + * no_prefetch - This mode meant for large pages only. It will generate an error if running on slow memory + * Some sytems can gain up to extra 5% here, but sometimes it will have no difference or make + * things slower. + * + * affine_to_cpu - This can be either false (no affinity), or the CPU core number. Note that on hyperthreading + * systems it is better to assign threads to physical cores. On Windows this usually means selecting + * even or odd numbered cpu numbers. For Linux it will be usually the lower CPU numbers, so for a 4 + * physical core CPU you should select cpu numbers 0-3. + * + */ + public List cpu_threads_conf; + //"cpu_threads_conf" : [ + // { "low_power_mode" : false, "no_prefetch" : false, "affine_to_cpu" : 0 }, + // { "low_power_mode" : false, "no_prefetch" : false, "affine_to_cpu" : 1 }, + //], + + /* + * LARGE PAGE SUPPORT + * Lare pages need a properly set up OS. It can be difficult if you are not used to systems administation, + * but the performace results are worth the trouble - you will get around 20% boost. Slow memory mode is + * meant as a backup, you won't get stellar results there. If you are running into trouble, especially + * on Windows, please read the common issues in the README. + * + * By default we will try to allocate large pages. This means you need to "Run As Administrator" on Windows. + * You need to edit your system's group policies to enable locking large pages. Here are the steps from MSDN + * + * 1. On the Start menu, click Run. In the Open box, type gpedit.msc. + * 2. On the Local Group Policy Editor console, expand Computer Configuration, and then expand Windows Settings. + * 3. Expand Security Settings, and then expand Local Policies. + * 4. Select the User Rights Assignment folder. + * 5. The policies will be displayed in the details pane. + * 6. In the pane, double-click Lock pages in memory. + * 7. In the Local Security Setting – Lock pages in memory dialog box, click Add User or Group. + * 8. In the Select Users, Service Accounts, or Groups dialog box, add an account that you will run the miner on + * 9. Reboot for change to take effect. + * + * Windows also tends to fragment memory a lot. If you are running on a system with 4-8GB of RAM you might need + * to switch off all the auto-start applications and reboot to have a large enough chunk of contiguous memory. + * + * On Linux you will need to configure large page support "sudo sysctl -w vm.nr_hugepages=128" and increase your + * ulimit -l. To do do this you need to add following lines to /etc/security/limits.conf - "* soft memlock 262144" + * and "* hard memlock 262144". You can also do it Windows-style and simply run-as-root, but this is NOT + * recommended for security reasons. + * + * Memory locking means that the kernel can't swap out the page to disk - something that is unlikey to happen on a + * command line system that isn't starved of memory. I haven't observed any difference on a CLI Linux system between + * locked and unlocked memory. If that is your setup see option "no_mlck". + */ + + /* + * use_slow_memory defines our behaviour with regards to large pages. There are three possible options here: + * always - Don't even try to use large pages. Always use slow memory. + * warn - We will try to use large pages, but fall back to slow memory if that fails. + * no_mlck - This option is only relevant on Linux, where we can use large pages without locking memory. + * It will never use slow memory, but it won't attempt to mlock + * never - If we fail to allocate large pages we will print an error and exit. + */ + public string use_slow_memory = "warn"; + + /* + * NiceHash mode + * nicehash_nonce - Limit the noce to 3 bytes as required by nicehash. This cuts all the safety margins, and + * if a block isn't found within 30 minutes then you might run into nonce collisions. Number + * of threads in this mode is hard-limited to 32. + */ + public readonly bool nicehash_nonce = true; // + + /* + * pool_address - Pool address should be in the form "pool.supportxmr.com:3333". Only stratum pools are supported. + * wallet_address - Your wallet, or pool login. + * pool_password - Can be empty in most cases or "x". + */ + + public readonly string pool_address; // : "pool.supportxmr.com:3333", + public readonly string wallet_address; + public readonly string pool_password = "x"; + + /* + * Network timeouts. + * Because of the way this client is written it doesn't need to constantly talk (keep-alive) to the server to make + * sure it is there. We detect a buggy / overloaded server by the call timeout. The default values will be ok for + * nearly all cases. If they aren't the pool has most likely overload issues. Low call timeout values are preferable - + * long timeouts mean that we waste hashes on potentially stale jobs. Connection report will tell you how long the + * server usually takes to process our calls. + * + * call_timeout - How long should we wait for a response from the server before we assume it is dead and drop the connection. + * retry_time - How long should we wait before another connection attempt. + * Both values are in seconds. + */ + public int call_timeout = 10; + public int retry_time = 10; + + /* + * Output control. + * Since most people are used to miners printing all the time, that's what we do by default too. This is suboptimal + * really, since you cannot see errors under pages and pages of text and performance stats. Given that we have internal + * performance monitors, there is very little reason to spew out pages of text instead of concise reports. + * Press 'h' (hashrate), 'r' (results) or 'c' (connection) to print reports. + * + * verbose_level - 0 - Don't print anything. + * 1 - Print intro, connection event, disconnect event + * 2 - All of level 1, and new job (block) event if the difficulty is different from the last job + * 3 - All of level 1, and new job (block) event in all cases, result submission event. + * 4 - All of level 3, and automatic hashrate report printing + */ + public int verbose_level = 3; + + /* + * Automatic hashrate report + * + * h_print_time - How often, in seconds, should we print a hashrate report if verbose_level is set to 4. + * This option has no effect if verbose_level is not 4. + */ + public int h_print_time = 60; + + /* + * Built-in web server + * I like checking my hashrate on my phone. Don't you? + * Keep in mind that you will need to set up port forwarding on your router if you want to access it from + * outside of your home network. Ports lower than 1024 on Linux systems will require root. + * + * httpd_port - Port we should listen on. Default, 0, will switch off the server. + */ + public readonly int httpd_port; + + /* + * prefer_ipv4 - IPv6 preference. If the host is available on both IPv4 and IPv6 net, which one should be choose? + * This setting will only be needed in 2020's. No need to worry about it now. + */ + public bool prefer_ipv4 = true; + + } + + public class XmrStackCPUMiner : Miner { + public XmrStackCPUMiner() + : base("XmrStackCPUMiner") { + this.ConectionType = NHMConectionType.NONE; + IsNeverHideMiningWindow = true; + } + + protected override int GET_MAX_CooldownTimeInMilliseconds() { + return 3600000; // 1hour + } + + + private string GetConfigFileName() { + return String.Format("config_{0}.txt", this.MiningSetup.MiningPairs[0].Device.ID); + } + + private void prepareConfigFile(string pool, string wallet) { + if (this.MiningSetup.MiningPairs.Count > 0) { + try { + bool IsHyperThreadingEnabled = this.MiningSetup.MiningPairs[0].CurrentExtraLaunchParameters.Contains("enable_ht=true"); + int numTr = ExtraLaunchParametersParser.GetThreadsNumber(this.MiningSetup.MiningPairs[0]); + if (IsHyperThreadingEnabled) { + numTr /= 2; + } + var config = new XmrStackCPUMinerConfig(numTr, pool, wallet, this.APIPort); + + //config.Inti_cpu_threads_conf(false, false, true, ComputeDeviceManager.Avaliable.IsHyperThreadingEnabled); + config.Inti_cpu_threads_conf(false, false, false, IsHyperThreadingEnabled); + var confJson = JObject.FromObject(config); + string writeStr = confJson.ToString(); + int start = writeStr.IndexOf("{"); + int end = writeStr.LastIndexOf("}"); + writeStr = writeStr.Substring(start + 1, end - 1); + System.IO.File.WriteAllText(WorkingDirectory + GetConfigFileName(), writeStr); + } catch { + } + } + } + + protected override void _Stop(MinerStopType willswitch) { + Stop_cpu_ccminer_sgminer_nheqminer(willswitch); + } + + public override APIData GetSummary() { + string resp; + APIData ad = new APIData(MiningSetup.CurrentAlgorithmType); + + string DataToSend = GetHttpRequestNHMAgentStrin("h"); + + resp = GetAPIData(APIPort, DataToSend); + if (resp == null) { + Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " summary is null"); + _currentMinerReadStatus = MinerAPIReadStatus.NONE; + return null; + } + const string Totals = "Totals:"; + const string Highest = "Highest:"; + int start_i = resp.IndexOf(Totals); + int end_i = resp.IndexOf(Highest); + if (start_i > -1 && end_i > -1) { + string sub_resp = resp.Substring(start_i, end_i); + sub_resp = sub_resp.Replace(Totals, ""); + sub_resp = sub_resp.Replace(Highest, ""); + var strings = sub_resp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var s in strings) { + if (s != "(na)") { + _currentMinerReadStatus = MinerAPIReadStatus.GOT_READ; + ad.Speed = Helpers.ParseDouble(s); + break; + } + } + } + // check if speed zero + if (ad.Speed == 0) _currentMinerReadStatus = MinerAPIReadStatus.READ_SPEED_ZERO; + + return ad; + } + + public override void Start(string url, string btcAdress, string worker) { + if (!IsInit) { + Helpers.ConsolePrint(MinerTAG(), "MiningSetup is not initialized exiting Start()"); + return; + } + string username = GetUsername(btcAdress, worker); + LastCommandLine = GetConfigFileName(); + + prepareConfigFile(url, username); + + ProcessHandle = _Start(); + } + + protected override NiceHashProcess _Start() { + NiceHashProcess P = base._Start(); + + var AffinityMask = MiningSetup.MiningPairs[0].Device.AffinityMask; + if (AffinityMask != 0 && P != null) + CPUID.AdjustAffinity(P.Id, AffinityMask); + + return P; + } + + // doesn't work stubs + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + string url = Globals.GetLocationURL(algorithm.NiceHashID, Globals.MiningLocation[ConfigManager.GeneralConfig.ServiceLocation], this.ConectionType); + prepareConfigFile(url, Globals.DemoUser); + return "benchmark_mode " + GetConfigFileName(); + } + + protected override Process BenchmarkStartProcess(string CommandLine) { + Process BenchmarkHandle = base.BenchmarkStartProcess(CommandLine); + + var AffinityMask = MiningSetup.MiningPairs[0].Device.AffinityMask; + if (AffinityMask != 0 && BenchmarkHandle != null) + CPUID.AdjustAffinity(BenchmarkHandle.Id, AffinityMask); + + return BenchmarkHandle; + } + + protected override bool BenchmarkParseLine(string outdata) { + if (outdata.Contains("Total:")) { + string toParse = outdata.Substring(outdata.IndexOf("Total:")).Replace("Total:", "").Trim(); + var strings = toParse.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var s in strings) { + double lastSpeed = 0; + if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out lastSpeed)) { + Helpers.ConsolePrint("BENCHMARK " + MinerTAG(), "double.TryParse true. Last speed is" + lastSpeed.ToString()); + BenchmarkAlgorithm.BenchmarkSpeed = Helpers.ParseDouble(s); + return true; + } + } + } + return false; + } + + protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { + CheckOutdata(outdata); + } + } +} diff --git a/NiceHashMiner/Miners/ccminer.cs b/NiceHashMiner/Miners/ccminer.cs index ed8164a..7ae9ce9 100644 --- a/NiceHashMiner/Miners/ccminer.cs +++ b/NiceHashMiner/Miners/ccminer.cs @@ -10,12 +10,14 @@ using NiceHashMiner.Configs; using NiceHashMiner.Enums; using NiceHashMiner.Devices; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; namespace NiceHashMiner.Miners { - abstract public class ccminer : Miner + public class ccminer : Miner { - public ccminer(string minerDeviceName) : base(DeviceType.NVIDIA, minerDeviceName) { } + public ccminer() : base("ccminer_NVIDIA") { } // cryptonight benchmark exception int _cryptonightTotalCount = 0; @@ -23,81 +25,62 @@ public ccminer(string minerDeviceName) : base(DeviceType.NVIDIA, minerDeviceName const int _cryptonightTotalDelim = 2; protected override int GET_MAX_CooldownTimeInMilliseconds() { - return 60 * 1000; // 1 minute max, whole waiting time 75seconds - } - - protected string getIntensityString() { - List intensityString = new List(); - bool ignore = true; - foreach (var cdev in CDevs) { - double intensity = cdev.DeviceBenchmarkConfig.AlgorithmSettings[CurrentAlgorithmType].Intensity; - if (intensity < 8.0d) { // all have minimum of 8 - intensityString.Add("0"); - } else { - intensityString.Add(intensity.ToString("F8")); - ignore = false; - } - } - if (!ignore && intensityString.Count > 0) { - return "--intensity="+string.Join(",", intensityString); + if (this.MiningSetup.MinerPath == MinerPaths.Data.ccminer_x11gost) { + return 60 * 1000 * 3; // wait a little longer } - return ""; + return 60 * 1000; // 1 minute max, whole waiting time 75seconds } - public override void Start(Algorithm miningAlgorithm, string url, string username) + public override void Start(string url, string btcAdress, string worker) { - CurrentMiningAlgorithm = miningAlgorithm; - if (miningAlgorithm == null) return; + if (!IsInit) { + Helpers.ConsolePrint(MinerTAG(), "MiningSetup is not initialized exiting Start()"); + return; + } + string username = GetUsername(btcAdress, worker); string algo = ""; string apiBind = ""; - string intensity = ""; - if (CurrentMiningAlgorithm.NiceHashID != AlgorithmType.CryptoNight) { - algo = "--algo=" + miningAlgorithm.MinerName; + if (MiningSetup.CurrentAlgorithmType != AlgorithmType.CryptoNight) { + algo = "--algo=" + MiningSetup.MinerName; apiBind = " --api-bind=" + APIPort.ToString(); - intensity = getIntensityString(); } - IsAPIReadException = CurrentMiningAlgorithm.NiceHashID == AlgorithmType.CryptoNight; + IsAPIReadException = MiningSetup.CurrentAlgorithmType == AlgorithmType.CryptoNight; LastCommandLine = algo + " --url=" + url + - " --userpass=" + username + ":" + Algorithm.PasswordDefault + - apiBind + - " " + miningAlgorithm.ExtraLaunchParameters + - intensity + + " --userpass=" + username + ":x " + + apiBind + " " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.NVIDIA) + " --devices "; LastCommandLine += GetDevicesCommandString(); - Path = GetOptimizedMinerPath(miningAlgorithm.NiceHashID); - ProcessHandle = _Start(); } protected override void _Stop(MinerStopType willswitch) { - Stop_cpu_ccminer_sgminer(willswitch); - } - - protected override bool UpdateBindPortCommand(int oldPort, int newPort) { - return UpdateBindPortCommand_ccminer_cpuminer(oldPort, newPort); + Stop_cpu_ccminer_sgminer_nheqminer(willswitch); } // new decoupled benchmarking routines #region Decoupled benchmarking routines - protected override string BenchmarkCreateCommandLine(ComputeDevice benchmarkDevice, Algorithm algorithm, int time) { + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { string timeLimit = algorithm.NiceHashID == AlgorithmType.CryptoNight ? "" : " --time-limit " + time.ToString(); string CommandLine = " --algo=" + algorithm.MinerName + " --benchmark" + - timeLimit + - " " + algorithm.ExtraLaunchParameters + + timeLimit + " " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.NVIDIA) + " --devices "; CommandLine += GetDevicesCommandString(); - Path = GetOptimizedMinerPath(algorithm.NiceHashID); - // cryptonight exception helper variables _cryptonightTotalCount = BenchmarkTimeInSeconds / _cryptonightTotalDelim; _cryptonightTotal = 0.0d; @@ -138,7 +121,12 @@ protected override bool BenchmarkParseLine(string outdata) { } } - double lastSpeed = 0; + double lastSpeed = BenchmarkParseLine_cpu_ccminer_extra(outdata); + if (lastSpeed > 0.0d) { + BenchmarkAlgorithm.BenchmarkSpeed = lastSpeed; + return true; + } + if (double.TryParse(outdata, out lastSpeed)) { BenchmarkAlgorithm.BenchmarkSpeed = lastSpeed; return true; @@ -154,7 +142,7 @@ protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { public override APIData GetSummary() { // CryptoNight does not have api bind port - if (CurrentAlgorithmType == AlgorithmType.CryptoNight) { + if (MiningSetup.CurrentAlgorithmType == AlgorithmType.CryptoNight) { // check if running if (ProcessHandle == null) { _currentMinerReadStatus = MinerAPIReadStatus.RESTART; @@ -165,28 +153,23 @@ public override APIData GetSummary() { var runningProcess = Process.GetProcessById(ProcessHandle.Id); } catch (ArgumentException ex) { _currentMinerReadStatus = MinerAPIReadStatus.RESTART; - Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Could not read data from CryptoNight"); + Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Could not read data from CryptoNight reason: " + ex.Message); return null; // will restart outside } catch (InvalidOperationException ex) { _currentMinerReadStatus = MinerAPIReadStatus.RESTART; - Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Could not read data from CryptoNight"); + Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Could not read data from CryptoNight reason: " + ex.Message); return null; // will restart outside } - // extra check - if (CurrentMiningAlgorithm == null) { - _currentMinerReadStatus = MinerAPIReadStatus.RESTART; - Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Could not read data from CryptoNight Proccess CurrentMiningAlgorithm is NULL"); - return null; - } var totalSpeed = 0.0d; - foreach (var cdev in CDevs) { - totalSpeed += cdev.DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.CryptoNight].BenchmarkSpeed; + foreach (var miningPair in MiningSetup.MiningPairs) { + var algo = miningPair.Device.GetAlgorithm(MinerBaseType.ccminer, AlgorithmType.CryptoNight); + if (algo != null) { + totalSpeed += algo.BenchmarkSpeed; + } } - APIData CryptoNightData = new APIData(); - CryptoNightData.AlgorithmID = AlgorithmType.CryptoNight; - CryptoNightData.AlgorithmName = "cryptonight"; + APIData CryptoNightData = new APIData(MiningSetup.CurrentAlgorithmType); CryptoNightData.Speed = totalSpeed; _currentMinerReadStatus = MinerAPIReadStatus.GOT_READ; // check if speed zero diff --git a/NiceHashMiner/Miners/ccminer_sm21.cs b/NiceHashMiner/Miners/ccminer_sm21.cs deleted file mode 100644 index 9235e32..0000000 --- a/NiceHashMiner/Miners/ccminer_sm21.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using NiceHashMiner.Configs; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; - -namespace NiceHashMiner.Miners -{ - class ccminer_sm21 : ccminer - { - public ccminer_sm21() : base("NVIDIA2.1") - { - Path = MinerPaths.ccminer_tpruvot; - } - - protected override void InitSupportedMinerAlgorithms() { - var allGroupSupportedList = GroupAlgorithms.GetAlgorithmKeysForGroup(DeviceGroupType.NVIDIA_2_1); - allGroupSupportedList.Remove(AlgorithmType.DaggerHashimoto); - _supportedMinerAlgorithms = allGroupSupportedList.ToArray(); - } - - public override string GetOptimizedMinerPath(AlgorithmType algorithmType, string devCodename, bool isOptimized) { - if (AlgorithmType.Decred == algorithmType) { - return MinerPaths.ccminer_decred; - } - if (AlgorithmType.CryptoNight == algorithmType) { - return MinerPaths.ccminer_cryptonight; - } - return MinerPaths.ccminer_tpruvot; - } - } -} diff --git a/NiceHashMiner/Miners/ccminer_sm3x.cs b/NiceHashMiner/Miners/ccminer_sm3x.cs deleted file mode 100644 index 6aa9f2d..0000000 --- a/NiceHashMiner/Miners/ccminer_sm3x.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using NiceHashMiner.Configs; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; - -namespace NiceHashMiner.Miners -{ - class ccminer_sm3x : ccminer - { - public ccminer_sm3x() : base("NVIDIA3.x") - { - Path = MinerPaths.ccminer_tpruvot; - } - - protected override void InitSupportedMinerAlgorithms() { - var allGroupSupportedList = GroupAlgorithms.GetAlgorithmKeysForGroup(DeviceGroupType.NVIDIA_3_x); - allGroupSupportedList.Remove(AlgorithmType.DaggerHashimoto); - _supportedMinerAlgorithms = allGroupSupportedList.ToArray(); - } - - public override string GetOptimizedMinerPath(AlgorithmType algorithmType, string devCodename, bool isOptimized) { - if (AlgorithmType.Decred == algorithmType) { - return MinerPaths.ccminer_decred; - } - if (AlgorithmType.CryptoNight == algorithmType) { - return MinerPaths.ccminer_cryptonight; - } - return MinerPaths.ccminer_tpruvot; - } - } -} diff --git a/NiceHashMiner/Miners/ccminer_sm5x.cs b/NiceHashMiner/Miners/ccminer_sm5x.cs deleted file mode 100644 index 5096922..0000000 --- a/NiceHashMiner/Miners/ccminer_sm5x.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using NiceHashMiner.Configs; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; - -namespace NiceHashMiner.Miners -{ - class ccminer_sm5x : ccminer - { - public ccminer_sm5x(string minerDeviceName = "NVIDIA5.x") : - base(minerDeviceName) - { - Path = MinerPaths.ccminer_sp; - } - - protected override void InitSupportedMinerAlgorithms() { - var allGroupSupportedList = GroupAlgorithms.GetAlgorithmKeysForGroup(DeviceGroupType.NVIDIA_5_x); - allGroupSupportedList.Remove(AlgorithmType.DaggerHashimoto); - _supportedMinerAlgorithms = allGroupSupportedList.ToArray(); - } - - public override string GetOptimizedMinerPath(AlgorithmType algorithmType, string devCodename, bool isOptimized) { - if (AlgorithmType.Decred == algorithmType) { - return MinerPaths.ccminer_decred; - } - if (AlgorithmType.NeoScrypt == algorithmType) { - return MinerPaths.ccminer_neoscrypt; - } - if (AlgorithmType.Lyra2RE == algorithmType || AlgorithmType.Lyra2REv2 == algorithmType) { - return MinerPaths.ccminer_nanashi; - } - if (AlgorithmType.CryptoNight == algorithmType) { - return MinerPaths.ccminer_cryptonight; - } - - return MinerPaths.ccminer_sp; - } - } -} diff --git a/NiceHashMiner/Miners/ccminer_sm6x.cs b/NiceHashMiner/Miners/ccminer_sm6x.cs deleted file mode 100644 index 7e5f8ae..0000000 --- a/NiceHashMiner/Miners/ccminer_sm6x.cs +++ /dev/null @@ -1,20 +0,0 @@ -using NiceHashMiner.Configs; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NiceHashMiner.Miners { - class ccminer_sm6x : ccminer_sm5x { - public ccminer_sm6x() : - base("NVIDIA6.x") - { - Path = MinerPaths.ccminer_nanashi; - } - - } -} diff --git a/NiceHashMiner/Miners/cpuminer.cs b/NiceHashMiner/Miners/cpuminer.cs deleted file mode 100644 index 5bb9c2a..0000000 --- a/NiceHashMiner/Miners/cpuminer.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using System.Globalization; -using NiceHashMiner.Configs; -using NiceHashMiner.Devices; -using NiceHashMiner.Enums; - -namespace NiceHashMiner.Miners { - public class cpuminer : Miner { - private int Threads; - private ulong AffinityMask; - private string CPUMinerPath; - - public cpuminer(int id, int threads, ulong affinity) - : base(DeviceType.CPU, "CPU" + id.ToString()) { - Threads = threads; - AffinityMask = affinity; - - bool isInitialized = InitializeMinerPaths(); - // if our CPU is supported add it to devices - // TODO if Miner and ComputeDevice decoupling redo this this is going to be at detecting CPUs - if (isInitialized) { - CDevs.Add(new ComputeDevice(0, MinerDeviceName, CPUID.GetCPUName().Trim(), true)); - } - } - - private bool InitializeMinerPaths() { - // this is the order we check and initialize if automatic - CPUExtensionType[] detectOrder = new CPUExtensionType[] { CPUExtensionType.AVX2, CPUExtensionType.AVX, CPUExtensionType.AES, CPUExtensionType.SSE2 }; - - // #1 try to initialize with Configured extension - bool isInitialized = InitializeMinerPaths(ConfigManager.Instance.GeneralConfig.ForceCPUExtension); - // #2 if automatic or does not support then initialize in order - if (isInitialized == false) { - ConfigManager.Instance.GeneralConfig.ForceCPUExtension = CPUExtensionType.Automatic; // set to automatic if not supported - for (int i = 0; i < detectOrder.Length; ++i) { - isInitialized = InitializeMinerPaths(detectOrder[i]); - if (isInitialized) { - break; // stop if initialized - } - } - } - return isInitialized; - } - - public override void SetCDevs(string[] deviceUUIDs) { - // DO NOTHING, CPU MINER DEVICES ARE SET ONLY AT THE BEGINING - } - - protected override int GET_MAX_CooldownTimeInMilliseconds() { - return 60 * 1000; // 1 minute max, whole waiting time 75seconds - } - - protected override void InitSupportedMinerAlgorithms() { - var allGroupSupportedList = GroupAlgorithms.GetAlgorithmKeysForGroup(DeviceGroupType.CPU); - _supportedMinerAlgorithms = allGroupSupportedList.ToArray(); - } - - /// - /// InitializeMinerPaths initializes cpuminer paths based on CPUExtensionType. - /// Make sure to check if extensions enabled. Currently using CPUID fo checking - /// - /// - /// Returns False if CPUExtensionType.Automatic, otherwise True and initializes paths - private bool InitializeMinerPaths(CPUExtensionType type) { - bool isInitialized = false; - // if type not automatic and has extension support set initialized - if (HasExtensionSupport(type)) { - isInitialized = true; - switch (type) { - case CPUExtensionType.SSE2: - CPUMinerPath = MinerPaths.cpuminer_opt_SSE2; - break; - case CPUExtensionType.AVX: - CPUMinerPath = MinerPaths.cpuminer_opt_AVX; - break; - case CPUExtensionType.AVX2: - CPUMinerPath = MinerPaths.cpuminer_opt_AVX2; - break; - case CPUExtensionType.AES: - CPUMinerPath = MinerPaths.cpuminer_opt_AES; - break; - default: // CPUExtensionType.Automatic - break; - } - } - return isInitialized; - } - - public override string GetOptimizedMinerPath(AlgorithmType algorithmType, string devCodename = "", bool isOptimized = false) { - return CPUMinerPath; - } - - /// - /// HasExtensionSupport checks CPU extensions support, if type automatic just return false. - /// - /// - /// False if type Automatic otherwise True if supported - private bool HasExtensionSupport(CPUExtensionType type) { - switch (type) { - case CPUExtensionType.SSE2: - return CPUID.SupportsSSE2() == 1; - case CPUExtensionType.AVX: - return CPUID.SupportsAVX() == 1; - case CPUExtensionType.AVX2: - return CPUID.SupportsAVX2() == 1; - case CPUExtensionType.AES: - return CPUID.SupportsAES() == 1; - default: // CPUExtensionType.Automatic - break; - } - return false; - } - - public override void Start(Algorithm miningAlgorithm, string url, string username) { - // to set miner paths - InitializeMinerPaths(); - - CurrentMiningAlgorithm = miningAlgorithm; - if (ProcessHandle != null) return; // ignore, already running - - if (CDevs.Count == 0 || !CDevs[0].Enabled) return; - - if (miningAlgorithm == null) return; - - Path = GetOptimizedMinerPath(miningAlgorithm.NiceHashID); - - LastCommandLine = "--algo=" + miningAlgorithm.MinerName + - " --url=" + url + - " --userpass=" + username + ":" + Algorithm.PasswordDefault + - " --threads=" + GetThreads(miningAlgorithm.LessThreads).ToString() + - " " + miningAlgorithm.ExtraLaunchParameters + - " --api-bind=" + APIPort.ToString(); - - ProcessHandle = _Start(); - } - - public override APIData GetSummary() { - return GetSummaryCPU_CCMINER(); - } - - protected override void _Stop(MinerStopType willswitch) { - Stop_cpu_ccminer_sgminer(willswitch); - } - - protected override NiceHashProcess _Start() { - NiceHashProcess P = base._Start(); - - if (AffinityMask != 0 && P != null) - CPUID.AdjustAffinity(P.Id, AffinityMask); - - return P; - } - - protected override bool UpdateBindPortCommand(int oldPort, int newPort) { - return UpdateBindPortCommand_ccminer_cpuminer(oldPort, newPort); - } - - private int GetThreads(int LessThreads) { - if (Threads > LessThreads) { - return Threads - LessThreads; - } - return Threads; - } - - // new decoupled benchmarking routines - #region Decoupled benchmarking routines - - protected override string BenchmarkCreateCommandLine(ComputeDevice benchmarkDevice, Algorithm algorithm, int time) { - // to set miner paths - InitializeMinerPaths(); - - Path = GetOptimizedMinerPath(algorithm.NiceHashID); - - return "--algo=" + algorithm.MinerName + - " --benchmark" + - " --threads=" + GetThreads(algorithm.LessThreads).ToString() + - " " + algorithm.ExtraLaunchParameters + - " --time-limit " + time.ToString(); - } - - protected override Process BenchmarkStartProcess(string CommandLine) { - Process BenchmarkHandle = base.BenchmarkStartProcess(CommandLine); - - if (AffinityMask != 0 && BenchmarkHandle != null) - CPUID.AdjustAffinity(BenchmarkHandle.Id, AffinityMask); - - return BenchmarkHandle; - } - - protected override bool BenchmarkParseLine(string outdata) { - double lastSpeed = 0; - if (double.TryParse(outdata, out lastSpeed)) { - BenchmarkAlgorithm.BenchmarkSpeed = lastSpeed; - return true; - } - return false; - } - - protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { - CheckOutdata(outdata); - } - - #endregion // Decoupled benchmarking routines - } -} diff --git a/NiceHashMiner/Miners/ethminer/Ethereum.cs b/NiceHashMiner/Miners/ethminer/Ethereum.cs new file mode 100644 index 0000000..e93547a --- /dev/null +++ b/NiceHashMiner/Miners/ethminer/Ethereum.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.IO; +using Newtonsoft.Json; +using System.Net; +using System.Net.Sockets; +using System.Windows.Forms; +using NiceHashMiner.Configs; +using NiceHashMiner.Miners; +using NiceHashMiner.Miners.Grouping; + +namespace NiceHashMiner +{ + //public class EthminerReader + //{ + // /// + // /// Initialize ethminer instance that listens on certain UDP port for speed and DAG progress reports. You may have multiple instances, + // /// but each one must be listening on another port! + // /// + // /// UDP listening port. + // public EthminerReader(int port) + // { + // bindPort = port; + // } + + // /// + // /// Start listening. + // /// + // public void Start() + // { + // isRunning = true; + // speed = 0; + // DAGprogress = 0; + // lastActiveTime = DateTime.Now; + // ipep = new IPEndPoint(IPAddress.Loopback, bindPort); + // client = new UdpClient(ipep); + // workerTimer = new Timer(); + // workerTimer.Tick += workerTimer_Tick; + // workerTimer.Interval = 50; + // workerTimer.Start(); + // } + + // /// + // /// Stop listening. Call this before application exits or if you are about to restart ethminer reader. + // /// + // public void Stop() + // { + // isRunning = false; + // speed = 0; + // DAGprogress = 0; + // workerTimer.Stop(); + // client.Close(); + // client = null; + // } + + // /// + // /// Get if miner is still running. + // /// + // /// State of miner. + // public bool GetIsRunning() + // { + // return isRunning; + // } + + // /// + // /// Get speed of miner in MH/s. + // /// + // /// Speed of miner in MH/s. + // public double GetSpeed() + // { + // return speed; + // } + + // /// + // /// Get DAG progress in %. It only reports correct progress if ethminer is launched with -D parameter. + // /// + // /// DAG creation progress in %. When mining, this value is 100. + // public uint GetDAGprogress() + // { + // return DAGprogress; + // } + + // /// + // /// Get DateTime when miner sent UDP status packet. + // /// + // /// DateTime of last active time. + // public DateTime GetLastActiveTime() + // { + // return lastActiveTime; + // } + + // public string ByteArrayToString(byte[] ba) + // { + // StringBuilder hex = new StringBuilder(ba.Length * 2); + // foreach (byte b in ba) hex.AppendFormat("{0:x2} ", b); + // return hex.ToString(); + // } + + // #region PRIVATE_PROPERTIES + // private IPEndPoint ipep; + // private UdpClient client; + // private double speed; + // private uint DAGprogress; + // private int bindPort; + // private bool isRunning; + // private Timer workerTimer; + // private DateTime lastActiveTime; + // #endregion + + // #region PRIVATE_METHODS + // private void workerTimer_Tick(object sender, EventArgs e) + // { + // try + // { + // client.Client.Blocking = false; + + // if (isRunning && client.Available > 0) + // { + // byte[] data = client.Receive(ref ipep); + // //Helpers.ConsolePrint("DEBUG", "ByteArray: " + ByteArrayToString(data)); + // speed = BitConverter.ToDouble(data, 0); + // DAGprogress = BitConverter.ToUInt32(data, 8); + // lastActiveTime = DateTime.Now; + // } + // } + // catch (Exception ex) + // { + // Helpers.ConsolePrint("EthminerReader", "Error: " + ex.Message); + // } + // } + + // #endregion + //} + + public static class Ethereum + { + //public static string EtherMinerPath; + public static string CurrentBlockNum; + + static Ethereum() + { + CurrentBlockNum = ""; + } + + public static void GetCurrentBlock(string worker) + { + string ret = NiceHashStats.GetNiceHashAPIData("https://etherchain.org/api/blocks/count", worker); + + if (ret == null) + { + Helpers.ConsolePrint(worker, String.Format("Failed to obtain current block, using default {0}.", ConfigManager.GeneralConfig.ethminerDefaultBlockHeight)); + CurrentBlockNum = ConfigManager.GeneralConfig.ethminerDefaultBlockHeight.ToString(); + } + else + { + ret = ret.Substring(ret.LastIndexOf("count") + 7); + CurrentBlockNum = ret.Substring(0, ret.Length - 3); + } + } + } +} diff --git a/NiceHashMiner/Miners/MinerEtherum.cs b/NiceHashMiner/Miners/ethminer/MinerEtherum.cs similarity index 75% rename from NiceHashMiner/Miners/MinerEtherum.cs rename to NiceHashMiner/Miners/ethminer/MinerEtherum.cs index a31a771..4ba2fac 100644 --- a/NiceHashMiner/Miners/MinerEtherum.cs +++ b/NiceHashMiner/Miners/ethminer/MinerEtherum.cs @@ -3,11 +3,11 @@ using NiceHashMiner.Enums; using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Net.Sockets; using System.Net; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Net20_backport; namespace NiceHashMiner.Miners { @@ -24,33 +24,27 @@ public abstract class MinerEtherum : Miner { protected bool IsPaused = false; - public MinerEtherum(DeviceType deviceType, string minerDeviceName, string blockString) - : base(deviceType, minerDeviceName) { - Path = Ethereum.EtherMinerPath; - _isEthMinerExit = true; + public MinerEtherum(string minerDeviceName, string blockString) + : base(minerDeviceName) { CurrentBlockString = blockString; - DagGenerationType = ConfigManager.Instance.GeneralConfig.EthminerDagGenerationType; + DagGenerationType = ConfigManager.GeneralConfig.EthminerDagGenerationType; } protected override int GET_MAX_CooldownTimeInMilliseconds() { return 90 * 1000; // 1.5 minute max, whole waiting time 75seconds } - protected override void InitSupportedMinerAlgorithms() { - _supportedMinerAlgorithms = new AlgorithmType[] { AlgorithmType.DaggerHashimoto }; - } - - protected abstract string GetStartCommandStringPart(Algorithm miningAlgorithm, string url, string username); - protected abstract string GetBenchmarkCommandStringPart(ComputeDevice benchmarkDevice, Algorithm algorithm); + protected abstract string GetStartCommandStringPart(string url, string username); + protected abstract string GetBenchmarkCommandStringPart(Algorithm algorithm); protected override string GetDevicesCommandString() { string deviceStringCommand = " "; List ids = new List(); - foreach (var cdev in CDevs) { - ids.Add(cdev.ID.ToString()); + foreach (var mPair in MiningSetup.MiningPairs) { + ids.Add(mPair.Device.ID.ToString()); } - deviceStringCommand += string.Join(" ", ids); + deviceStringCommand += StringHelper.Join(" ", ids); // set dag load mode deviceStringCommand += String.Format(" --dag-load-mode {0} ", GetDagGenerationString(DagGenerationType)); if (DagGenerationType == DagGenerationType.Single @@ -75,16 +69,23 @@ public static string GetDagGenerationString(DagGenerationType type) { return "singlekeep"; } - public override void Start(Algorithm miningAlgorithm, string url, string username) { - IsPaused = false; - if (ProcessHandle == null) { - CurrentMiningAlgorithm = miningAlgorithm; - if (miningAlgorithm == null && miningAlgorithm.NiceHashID != AlgorithmType.DaggerHashimoto) { - Helpers.ConsolePrint(MinerTAG(), "Algorithm is null or not DaggerHashimoto"); - return; + public void Start(string url, string btcAdress, string worker, List usedMiners) { + if (!IsInit) { + Helpers.ConsolePrint(MinerTAG(), "MiningSetup is not initialized exiting Start()"); + return; + } + foreach (var ethminer in usedMiners) { + if (ethminer.MINER_ID != MINER_ID && (ethminer.IsRunning || ethminer.IsPaused)) { + Helpers.ConsolePrint(MinerTAG(), String.Format("Will end {0} {1}", ethminer.MinerTAG(), ethminer.ProcessTag())); + ethminer.End(); + System.Threading.Thread.Sleep(ConfigManager.GeneralConfig.MinerRestartDelayMS); } + } - LastCommandLine = GetStartCommandStringPart(miningAlgorithm, url, username) + GetDevicesCommandString(); + IsPaused = false; + if (ProcessHandle == null) { + string username = GetUsername(btcAdress, worker); + LastCommandLine = GetStartCommandStringPart(url, username) + GetDevicesCommandString(); ProcessHandle = _Start(); } else { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Resuming ethminer.."); @@ -93,31 +94,30 @@ public override void Start(Algorithm miningAlgorithm, string url, string usernam } } - protected override string BenchmarkCreateCommandLine(ComputeDevice benchmarkDevice, Algorithm algorithm, int time) { - string CommandLine = GetBenchmarkCommandStringPart(benchmarkDevice, algorithm) + GetDevicesCommandString(); + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + string CommandLine = GetBenchmarkCommandStringPart(algorithm) + GetDevicesCommandString(); Ethereum.GetCurrentBlock(CurrentBlockString); CommandLine += " --benchmark " + Ethereum.CurrentBlockNum; return CommandLine; } - public override void SetCDevs(string[] deviceUUIDs) { - base.SetCDevs(deviceUUIDs); + public override void InitMiningSetup(MiningSetup miningSetup) { + base.InitMiningSetup(miningSetup); // now find the fastest for DAG generation double fastestSpeed = double.MinValue; - foreach (var cdev in CDevs) { - double compareSpeed = cdev.DeviceBenchmarkConfig.AlgorithmSettings[AlgorithmType.DaggerHashimoto].BenchmarkSpeed; + foreach (var mPair in MiningSetup.MiningPairs) { + double compareSpeed = mPair.Algorithm.AvaragedSpeed; if (fastestSpeed < compareSpeed) { - DaggerHashimotoGenerateDevice = cdev; + DaggerHashimotoGenerateDevice = mPair.Device; fastestSpeed = compareSpeed; } } } public override APIData GetSummary() { - APIData ad = new APIData(); + APIData ad = new APIData(MiningSetup.CurrentAlgorithmType); - FillAlgorithm("daggerhashimoto", ref ad); bool ismining; var getSpeedStatus = GetSpeed(out ismining, out ad.Speed); if (GetSpeedStatus.GOT == getSpeedStatus) { @@ -156,7 +156,6 @@ protected override void _Stop(MinerStopType willswitch) { } else if ((IsRunning || IsPaused) && willswitch != MinerStopType.SWITCH) { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Shutting down miner"); } - if (willswitch == MinerStopType.END) ChangeToNextAvaliablePort(); if ((willswitch == MinerStopType.FORCE_END || willswitch == MinerStopType.END) && ProcessHandle != null) { IsPaused = false; // shutting down means it is not paused try { @@ -168,22 +167,6 @@ protected override void _Stop(MinerStopType willswitch) { } } - public override string GetOptimizedMinerPath(AlgorithmType algorithmType, string devCodename, bool isOptimized) { - return Ethereum.EtherMinerPath; - } - - protected override bool UpdateBindPortCommand(int oldPort, int newPort) { - // --api-port - const string MASK = "--api-port {0}"; - var oldApiBindStr = String.Format(MASK, oldPort); - var newApiBindStr = String.Format(MASK, newPort); - if (LastCommandLine != null && LastCommandLine.Contains(oldApiBindStr)) { - LastCommandLine = LastCommandLine.Replace(oldApiBindStr, newApiBindStr); - return true; - } - return false; - } - // benchmark stuff protected override bool BenchmarkParseLine(string outdata) { if (outdata.Contains("min/mean/max:")) { @@ -224,6 +207,7 @@ private void SetEthminerAPI(int port) { /// Call this to start ethminer. If ethminer is already running, nothing happens. /// private void StartMining() { + Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Sending START UDP"); SendUDP(2); IsRunning = true; } @@ -232,6 +216,7 @@ private void StartMining() { /// Call this to stop ethminer. If ethminer is already stopped, nothing happens. /// private void StopMining() { + Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Sending STOP UDP"); SendUDP(1); IsRunning = false; } diff --git a/NiceHashMiner/Miners/ethminer/MinerEtherumCUDA.cs b/NiceHashMiner/Miners/ethminer/MinerEtherumCUDA.cs new file mode 100644 index 0000000..e956adf --- /dev/null +++ b/NiceHashMiner/Miners/ethminer/MinerEtherumCUDA.cs @@ -0,0 +1,54 @@ +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; + +namespace NiceHashMiner.Miners { + public class MinerEtherumCUDA : MinerEtherum { + + // reference to all MinerEtherumCUDA make sure to clear this after miner Stop + // we make sure only ONE instance of MinerEtherumCUDA is running + private static List MinerEtherumCUDAList = new List(); + + public MinerEtherumCUDA() + : base("MinerEtherumCUDA", "NVIDIA") { + MinerEtherumCUDAList.Add(this); + } + + ~MinerEtherumCUDA() { + // remove from list + MinerEtherumCUDAList.Remove(this); + } + + public override void Start(string url, string btcAdress, string worker) { + Helpers.ConsolePrint(MinerTAG(), "Starting MinerEtherumCUDA, checking existing MinerEtherumCUDA to stop"); + base.Start(url, btcAdress, worker, MinerEtherumCUDAList); + } + + protected override string GetStartCommandStringPart(string url, string username) { + return " --cuda" + + " " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.NVIDIA) + + " -S " + url.Substring(14) + + " -O " + username + ":x " + + " --api-port " + APIPort.ToString() + + " --cuda-devices "; + } + + protected override string GetBenchmarkCommandStringPart(Algorithm algorithm) { + return " --benchmark-warmup 40 --benchmark-trial 20" + + " " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.NVIDIA) + + " --cuda --cuda-devices "; + } + + } +} diff --git a/NiceHashMiner/Miners/ethminer/MinerEtherumOCL.cs b/NiceHashMiner/Miners/ethminer/MinerEtherumOCL.cs new file mode 100644 index 0000000..26a9b8e --- /dev/null +++ b/NiceHashMiner/Miners/ethminer/MinerEtherumOCL.cs @@ -0,0 +1,61 @@ +using NiceHashMiner.Configs; +using NiceHashMiner.Devices; +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; + +namespace NiceHashMiner.Miners { + + // TODO for NOW ONLY AMD + // AMD or TODO it could be something else + public class MinerEtherumOCL : MinerEtherum { + + // reference to all MinerEtherumOCL make sure to clear this after miner Stop + // we make sure only ONE instance of MinerEtherumOCL is running + private static List MinerEtherumOCLList = new List(); + + private readonly int GPUPlatformNumber; + + public MinerEtherumOCL() + : base("MinerEtherumOCL", "AMD OpenCL") { + GPUPlatformNumber = ComputeDeviceManager.Avaliable.AMDOpenCLPlatformNum; + MinerEtherumOCLList.Add(this); + } + + ~MinerEtherumOCL() { + // remove from list + MinerEtherumOCLList.Remove(this); + } + + public override void Start(string url, string btcAdress, string worker) { + Helpers.ConsolePrint(MinerTAG(), "Starting MinerEtherumOCL, checking existing MinerEtherumOCL to stop"); + base.Start(url, btcAdress, worker, MinerEtherumOCLList); + } + + protected override string GetStartCommandStringPart(string url, string username) { + return " --opencl --opencl-platform " + GPUPlatformNumber + + " " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.AMD) + + " -S " + url.Substring(14) + + " -O " + username + ":x " + + " --api-port " + APIPort.ToString() + + " --opencl-devices "; + } + + protected override string GetBenchmarkCommandStringPart(Algorithm algorithm) { + return " --opencl --opencl-platform " + GPUPlatformNumber + + " " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.AMD) + + " --benchmark-warmup 40 --benchmark-trial 20" + + " --opencl-devices "; + } + + } +} diff --git a/NiceHashMiner/Miners/excavator.cs b/NiceHashMiner/Miners/excavator.cs new file mode 100644 index 0000000..2f673a1 --- /dev/null +++ b/NiceHashMiner/Miners/excavator.cs @@ -0,0 +1,162 @@ +using Newtonsoft.Json; +using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Net.Sockets; +using System.Text; + +namespace NiceHashMiner.Miners { + public class excavator : Miner { + + private class DeviceStat { + public int id { get; set; } + public string name { get; set; } + public double speed_hps { get; set; } + } + + private class Result { + public bool connected { get; set; } + public double interval_seconds { get; set; } + public double speed_hps { get; set; } + public List devices { get; set; } + public double accepted_per_minute { get; set; } + public double rejected_per_minute { get; set; } + } + + private class JsonApiResponse { + public string method { get; set; } + public Result result { get; set; } + public object error { get; set; } + } + + public excavator() + : base("excavator") { + ConectionType = NHMConectionType.NONE; + IsNeverHideMiningWindow = true; + } + + public override void Start(string url, string btcAdress, string worker) { + string username = GetUsername(btcAdress, worker); + LastCommandLine = GetDevicesCommandString() + " -a " + this.MiningSetup.MinerName + " -p " + APIPort + " -s " + url + " -u " + username + ":x"; + ProcessHandle = _Start(); + } + + protected override string GetDevicesCommandString() { + List CT_MiningPairs = new List(); + string deviceStringCommand = " -cd "; + int default_CT = 1; + if(this.MiningSetup.CurrentAlgorithmType == AlgorithmType.Equihash) { + default_CT = 2; + } + foreach (var nvidia_pair in this.MiningSetup.MiningPairs) { + if (nvidia_pair.CurrentExtraLaunchParameters.Contains("-ct")) { + for (int i = 0; i < ExtraLaunchParametersParser.GetEqmCudaThreadCount(nvidia_pair); ++i) { + deviceStringCommand += nvidia_pair.Device.ID + " "; + CT_MiningPairs.Add(nvidia_pair); + } + } else { // use default default_CT for best performance + for (int i = 0; i < default_CT; ++i) { + deviceStringCommand += nvidia_pair.Device.ID + " "; + CT_MiningPairs.Add(nvidia_pair); + } + } + } + + MiningSetup CT_MiningSetup = new MiningSetup(CT_MiningPairs); + //deviceStringCommand += " " + ExtraLaunchParametersParser.ParseForMiningSetup(this.MiningSetup, DeviceType.NVIDIA); + deviceStringCommand += " " + ExtraLaunchParametersParser.ParseForMiningSetup(CT_MiningSetup, DeviceType.NVIDIA); + + return deviceStringCommand; + } + + // benchmark stuff + + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { + string ret = " -a " + this.MiningSetup.MinerName + " -b " + time + " " + GetDevicesCommandString(); + return ret; + } + + const string TOTAL_MES = "Total measured:"; + protected override bool BenchmarkParseLine(string outdata) { + + if (outdata.Contains(TOTAL_MES)) { + try { + int speedStart = outdata.IndexOf(TOTAL_MES); + string speed = outdata.Substring(speedStart, outdata.Length - speedStart).Replace(TOTAL_MES, ""); + var splitSrs = speed.Trim().Split(' '); + if (splitSrs.Length >= 2) { + string speedStr = splitSrs[0]; + string postfixStr = splitSrs[1]; + double spd = Double.Parse(speedStr, CultureInfo.InvariantCulture); + if (postfixStr.Contains("kH/s")) + spd *= 1000; + else if (postfixStr.Contains("MH/s")) + spd *= 1000000; + else if (postfixStr.Contains("GH/s")) + spd *= 1000000000; + + // wrong benchmark workaround over 3gh/s is considered false + if (this.MiningSetup.CurrentAlgorithmType == AlgorithmType.Pascal + && spd > 3.0d * 1000000000.0d + ) { + return false; + } + + BenchmarkAlgorithm.BenchmarkSpeed = spd; + return true; + } + } catch { + } + } + return false; + } + + public override APIData GetSummary() { + _currentMinerReadStatus = MinerAPIReadStatus.NONE; + APIData ad = new APIData(MiningSetup.CurrentAlgorithmType); + + TcpClient client = null; + JsonApiResponse resp = null; + try { + byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes("status\n"); + client = new TcpClient("127.0.0.1", APIPort); + NetworkStream nwStream = client.GetStream(); + nwStream.Write(bytesToSend, 0, bytesToSend.Length); + byte[] bytesToRead = new byte[client.ReceiveBufferSize]; + int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize); + string respStr = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead); + resp = JsonConvert.DeserializeObject(respStr, Globals.JsonSettings); + client.Close(); + } catch (Exception ex) { + Helpers.ConsolePrint("ERROR", ex.Message); + } + + if (resp != null && resp.error == null) { + ad.Speed = resp.result.speed_hps; + _currentMinerReadStatus = MinerAPIReadStatus.GOT_READ; + if (ad.Speed == 0) { + _currentMinerReadStatus = MinerAPIReadStatus.READ_SPEED_ZERO; + } + } + + return ad; + } + + protected override void _Stop(MinerStopType willswitch) { + Stop_cpu_ccminer_sgminer_nheqminer(willswitch); + } + + protected override int GET_MAX_CooldownTimeInMilliseconds() { + return 60 * 1000 * 5; // 5 minute max, whole waiting time 75seconds + } + + // benchmark stuff + + protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { + CheckOutdata(outdata); + } + } +} diff --git a/NiceHashMiner/Miners/sgminer.cs b/NiceHashMiner/Miners/sgminer.cs index a1be52a..828a0bb 100644 --- a/NiceHashMiner/Miners/sgminer.cs +++ b/NiceHashMiner/Miners/sgminer.cs @@ -11,29 +11,22 @@ using NiceHashMiner.Configs; using NiceHashMiner.Devices; using NiceHashMiner.Enums; +using NiceHashMiner.Miners.Grouping; +using NiceHashMiner.Miners.Parsing; +using System.Threading; namespace NiceHashMiner.Miners { - // TODO IMPORTANT, Intensity not handled correctly - // for now AMD only class sgminer : Miner { private readonly int GPUPlatformNumber; - - // we only group devices that are compatible. for sgminer we have gpucodename and enabled optimized vesrion as mandatory extra parameters - private string CommonGpuCodenameSetting = ""; - private bool EnableOptimizedVersion = true; - - // benchmark helper variables - bool _benchmarkOnce = true; Stopwatch _benchmarkTimer = new Stopwatch(); public sgminer() - : base(DeviceType.AMD, "AMD_OpenCL") - { - Path = MinerPaths.sgminer_5_4_0_general; - EnableOptimizedVersion = true; - GPUPlatformNumber = ComputeDeviceQueryManager.Instance.AMDOpenCLPlatformNum; + : base("sgminer_AMD") + { + GPUPlatformNumber = ComputeDeviceManager.Avaliable.AMDOpenCLPlatformNum; + IsKillAllUsedMinerProcs = true; } // use ONLY for exiting a benchmark @@ -43,48 +36,47 @@ public void KillSGMiner() { } } - protected override int GET_MAX_CooldownTimeInMilliseconds() { - return 90 * 1000; // 1.5 minute max, whole waiting time 75seconds - } - - protected override void InitSupportedMinerAlgorithms() { - var allGroupSupportedList = GroupAlgorithms.GetAlgorithmKeysForGroup(DeviceGroupType.AMD_OpenCL); - allGroupSupportedList.Remove(AlgorithmType.DaggerHashimoto); - _supportedMinerAlgorithms = allGroupSupportedList.ToArray(); + public override void EndBenchmarkProcces() { + if (BenchmarkProcessStatus != BenchmarkProcessStatus.Killing && BenchmarkProcessStatus != BenchmarkProcessStatus.DoneKilling) { + BenchmarkProcessStatus = BenchmarkProcessStatus.Killing; + try { + Helpers.ConsolePrint("BENCHMARK", String.Format("Trying to kill benchmark process {0} algorithm {1}", BenchmarkProcessPath, BenchmarkAlgorithm.AlgorithmName)); + KillSGMiner(); + } catch { } finally { + BenchmarkProcessStatus = BenchmarkProcessStatus.DoneKilling; + Helpers.ConsolePrint("BENCHMARK", String.Format("Benchmark process {0} algorithm {1} KILLED", BenchmarkProcessPath, BenchmarkAlgorithm.AlgorithmName)); + //BenchmarkHandle = null; + } + } } - public override void SetCDevs(string[] deviceUUIDs) { - base.SetCDevs(deviceUUIDs); - // now set extra sgminer settings, first dev is enough because of grouping logic - if(CDevs.Count != 0) { - CommonGpuCodenameSetting = CDevs[0].Codename; - EnableOptimizedVersion = CDevs[0].IsOptimizedVersion; - } + protected override int GET_MAX_CooldownTimeInMilliseconds() { + return 90 * 1000; // 1.5 minute max, whole waiting time 75seconds } protected override void _Stop(MinerStopType willswitch) { - Stop_cpu_ccminer_sgminer(willswitch); + Stop_cpu_ccminer_sgminer_nheqminer(willswitch); } - public override void Start(Algorithm miningAlgorithm, string url, string username) + public override void Start(string url, string btcAdress, string worker) { - CurrentMiningAlgorithm = miningAlgorithm; - if (miningAlgorithm == null) - { - Helpers.ConsolePrint(MinerTAG(), "GetMinerAlgorithm(" + miningAlgorithm.NiceHashID + "): Algo equals to null"); + if (!IsInit) { + Helpers.ConsolePrint(MinerTAG(), "MiningSetup is not initialized exiting Start()"); return; } - - Path = GetOptimizedMinerPath(miningAlgorithm.NiceHashID, CommonGpuCodenameSetting, EnableOptimizedVersion); - WorkingDirectory = Path.Replace("sgminer.exe", ""); - + string username = GetUsername(btcAdress, worker); + LastCommandLine = " --gpu-platform " + GPUPlatformNumber + - " -k " + miningAlgorithm.MinerName + + " -k " + MiningSetup.MinerName + " --url=" + url + - " --userpass=" + username + ":" + Algorithm.PasswordDefault + + " --userpass=" + username + + " -p x " + " --api-listen" + " --api-port=" + APIPort.ToString() + - " " + miningAlgorithm.ExtraLaunchParameters + + " " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.AMD) + " --device "; LastCommandLine += GetDevicesCommandString(); @@ -92,66 +84,33 @@ public override void Start(Algorithm miningAlgorithm, string url, string usernam ProcessHandle = _Start(); } - protected override bool UpdateBindPortCommand(int oldPort, int newPort) { - // --api-port= - const string MASK = "--api-port={0}"; - var oldApiBindStr = String.Format(MASK, oldPort); - var newApiBindStr = String.Format(MASK, newPort); - if (LastCommandLine.Contains(oldApiBindStr)) { - LastCommandLine = LastCommandLine.Replace(oldApiBindStr, newApiBindStr); - return true; - } - return false; - } - - public override string GetOptimizedMinerPath(AlgorithmType type, string gpuCodename, bool isOptimized) { - if (EnableOptimizedVersion) { - if (AlgorithmType.Quark == type || AlgorithmType.Lyra2REv2 == type || AlgorithmType.Qubit == type) { - if (!(gpuCodename.Contains("Hawaii") || gpuCodename.Contains("Pitcairn") || gpuCodename.Contains("Tahiti"))) { - if (!Helpers.InternalCheckIsWow64()) - return MinerPaths.sgminer_5_4_0_general; - - return MinerPaths.sgminer_5_4_0_tweaked; - } - if (AlgorithmType.Quark == type || AlgorithmType.Lyra2REv2 == type) - return MinerPaths.sgminer_5_1_0_optimized; - else - return MinerPaths.sgminer_5_1_1_optimized; - } - } - - return MinerPaths.sgminer_5_4_0_general; - } - // new decoupled benchmarking routines #region Decoupled benchmarking routines - protected override string BenchmarkCreateCommandLine(ComputeDevice benchmarkDevice, Algorithm algorithm, int time) { + protected override string BenchmarkCreateCommandLine(Algorithm algorithm, int time) { string CommandLine; - Path = "cmd"; - string MinerPath = GetOptimizedMinerPath(algorithm.NiceHashID, CommonGpuCodenameSetting, EnableOptimizedVersion); - var nhAlgorithmData = Globals.NiceHashData[algorithm.NiceHashID]; - string url = "stratum+tcp://" + nhAlgorithmData.name + "." + - Globals.MiningLocation[ConfigManager.Instance.GeneralConfig.ServiceLocation] + ".nicehash.com:" + - nhAlgorithmData.port; + string url = Globals.GetLocationURL(algorithm.NiceHashID, Globals.MiningLocation[ConfigManager.GeneralConfig.ServiceLocation], this.ConectionType); - string username = ConfigManager.Instance.GeneralConfig.BitcoinAddress.Trim(); - if (String.IsNullOrEmpty(username) || String.IsNullOrWhiteSpace(username)) { - username = Globals.DemoUser; - } - if (ConfigManager.Instance.GeneralConfig.WorkerName.Length > 0) - username += "." + ConfigManager.Instance.GeneralConfig.WorkerName.Trim(); + // demo for benchmark + string username = Globals.DemoUser; + + if (ConfigManager.GeneralConfig.WorkerName.Length > 0) + username += "." + ConfigManager.GeneralConfig.WorkerName.Trim(); // cd to the cgminer for the process bins - CommandLine = " /C \"cd /d " + MinerPath.Replace("sgminer.exe", "") + " && sgminer.exe " + + CommandLine = " /C \"cd /d " + WorkingDirectory + " && sgminer.exe " + " --gpu-platform " + GPUPlatformNumber + " -k " + algorithm.MinerName + " --url=" + url + - " --userpass=" + username + ":" + Algorithm.PasswordDefault + + " --userpass=" + username + + " -p x " + " --sched-stop " + DateTime.Now.AddSeconds(time).ToString("HH:mm") + " -T --log 10 --log-file dump.txt" + - " " + algorithm.ExtraLaunchParameters + + " " + + ExtraLaunchParametersParser.ParseForMiningSetup( + MiningSetup, + DeviceType.AMD) + " --device "; CommandLine += GetDevicesCommandString(); @@ -162,7 +121,7 @@ protected override string BenchmarkCreateCommandLine(ComputeDevice benchmarkDevi } protected override bool BenchmarkParseLine(string outdata) { - if (outdata.Contains("Average hashrate:") && outdata.Contains("/s")) { + if (outdata.Contains("Average hashrate:") && outdata.Contains("/s") && BenchmarkAlgorithm.NiceHashID != AlgorithmType.DaggerHashimoto) { int i = outdata.IndexOf(": "); int k = outdata.IndexOf("/s"); @@ -179,6 +138,30 @@ protected override bool BenchmarkParseLine(string outdata) { speed *= 1000000; BenchmarkAlgorithm.BenchmarkSpeed = speed; + return true; + } else if (outdata.Contains(String.Format("GPU{0}", MiningSetup.MiningPairs[0].Device.ID)) && outdata.Contains("s):") && BenchmarkAlgorithm.NiceHashID == AlgorithmType.DaggerHashimoto) { + int i = outdata.IndexOf("s):"); + int k = outdata.IndexOf("(avg)"); + + // save speed + string hashSpeed = outdata.Substring(i + 3, k - i + 3).Trim(); + hashSpeed = hashSpeed.Replace("(avg):", ""); + Helpers.ConsolePrint("BENCHMARK", "Final Speed: " + hashSpeed); + + double mult = 1; + if (hashSpeed.Contains("K")) { + hashSpeed = hashSpeed.Replace("K", " "); + mult = 1000; + } else if (hashSpeed.Contains("M")) { + hashSpeed = hashSpeed.Replace("M", " "); + mult = 1000000; + } + + hashSpeed = hashSpeed.Substring(0, hashSpeed.IndexOf(" ")); + double speed = Double.Parse(hashSpeed, CultureInfo.InvariantCulture) * mult; + + BenchmarkAlgorithm.BenchmarkSpeed = speed; + return true; } return false; @@ -197,47 +180,111 @@ protected override void BenchmarkThreadRoutineStartSettup() { if (Globals.NiceHashData[NHDataIndex].paying == 0) { Helpers.ConsolePrint("BENCHMARK", "Skipping sgminer benchmark because there is no work on Nicehash.com " + - "[algo: " + BenchmarkAlgorithm.NiceHashName + "(" + NHDataIndex + ")]"); + "[algo: " + BenchmarkAlgorithm.AlgorithmName + "(" + NHDataIndex + ")]"); throw new Exception("No work can be used for benchmarking"); } _benchmarkTimer.Reset(); _benchmarkTimer.Start(); - // call base - base.BenchmarkThreadRoutineStartSettup(); + // call base, read only outpus + //BenchmarkHandle.BeginOutputReadLine(); } protected override void BenchmarkOutputErrorDataReceivedImpl(string outdata) { - if (_benchmarkTimer.Elapsed.Minutes >= BenchmarkTimeInSeconds + 1 && _benchmarkOnce == true) { - _benchmarkOnce = false; + if (_benchmarkTimer.Elapsed.TotalSeconds >= BenchmarkTimeInSeconds) { string resp = GetAPIData(APIPort, "quit").TrimEnd(new char[] { (char)0 }); Helpers.ConsolePrint("BENCHMARK", "SGMiner Response: " + resp); } - if (_benchmarkTimer.Elapsed.Minutes >= BenchmarkTimeInSeconds + 2) { + if (_benchmarkTimer.Elapsed.TotalSeconds >= BenchmarkTimeInSeconds + 2) { _benchmarkTimer.Stop(); // this is safe in a benchmark KillSGMiner(); BenchmarkSignalHanged = true; } - if (!BenchmarkSignalFinnished) { + if (!BenchmarkSignalFinnished && outdata != null) { CheckOutdata(outdata); } } + protected override string GetFinalBenchmarkString() { + if (BenchmarkAlgorithm.BenchmarkSpeed <= 0) { + Helpers.ConsolePrint("sgminer_GetFinalBenchmarkString", International.GetText("sgminer_precise_try")); + return International.GetText("sgminer_precise_try"); + } + return base.GetFinalBenchmarkString(); + } + + protected override void BenchmarkThreadRoutine(object CommandLine) { + Thread.Sleep(ConfigManager.GeneralConfig.MinerRestartDelayMS * 3); // increase wait for sgminer + + BenchmarkSignalQuit = false; + BenchmarkSignalHanged = false; + BenchmarkSignalFinnished = false; + BenchmarkException = null; + + try { + Helpers.ConsolePrint("BENCHMARK", "Benchmark starts"); + BenchmarkHandle = BenchmarkStartProcess((string)CommandLine); + BenchmarkThreadRoutineStartSettup(); + // wait a little longer then the benchmark routine if exit false throw + //var timeoutTime = BenchmarkTimeoutInSeconds(BenchmarkTimeInSeconds); + //var exitSucces = BenchmarkHandle.WaitForExit(timeoutTime * 1000); + // don't use wait for it breaks everything + BenchmarkProcessStatus = BenchmarkProcessStatus.Running; + while(true) { + string outdata = BenchmarkHandle.StandardOutput.ReadLine(); + BenchmarkOutputErrorDataReceivedImpl(outdata); + // terminate process situations + if (BenchmarkSignalQuit + || BenchmarkSignalFinnished + || BenchmarkSignalHanged + || BenchmarkSignalTimedout + || BenchmarkException != null) { + //EndBenchmarkProcces(); + // this is safe in a benchmark + KillSGMiner(); + if (BenchmarkSignalTimedout) { + throw new Exception("Benchmark timedout"); + } + if (BenchmarkException != null) { + throw BenchmarkException; + } + if (BenchmarkSignalQuit) { + throw new Exception("Termined by user request"); + } + if (BenchmarkSignalHanged) { + throw new Exception("SGMiner is not responding"); + } + if (BenchmarkSignalFinnished) { + break; + } + } else { + // wait a second reduce CPU load + Thread.Sleep(1000); + } + } + } catch (Exception ex) { + BenchmarkThreadRoutineCatch(ex); + } finally { + BenchmarkThreadRoutineFinish(); + } + } + #endregion // Decoupled benchmarking routines // TODO _currentMinerReadStatus public override APIData GetSummary() { string resp; - string aname = null; - APIData ad = new APIData(); + APIData ad = new APIData(MiningSetup.CurrentAlgorithmType); resp = GetAPIData(APIPort, "summary"); if (resp == null) { _currentMinerReadStatus = MinerAPIReadStatus.NONE; return null; } + //// sgminer debug log + //Helpers.ConsolePrint("sgminer-DEBUG_resp", resp); try { // Checks if all the GPUs are Alive first @@ -246,11 +293,13 @@ public override APIData GetSummary() { _currentMinerReadStatus = MinerAPIReadStatus.NONE; return null; } + //// sgminer debug log + //Helpers.ConsolePrint("sgminer-DEBUG_resp2", resp2); string[] checkGPUStatus = resp2.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 1; i < checkGPUStatus.Length - 1; i++) { - if (!checkGPUStatus[i].Contains("Status=Alive")) { + if (checkGPUStatus[i].Contains("Enabled=Y") && !checkGPUStatus[i].Contains("Status=Alive")) { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " GPU " + i + ": Sick/Dead/NoStart/Initialising/Disabled/Rejecting/Unknown"); _currentMinerReadStatus = MinerAPIReadStatus.WAIT; return null; @@ -269,9 +318,6 @@ public override APIData GetSummary() { ad.Speed = Double.Parse(speed[1]) * 1000; - aname = CurrentMiningAlgorithm.MinerName; - - if (total_mh <= PreviousTotalMH) { Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " SGMiner might be stuck as no new hashes are being produced"); Helpers.ConsolePrint(MinerTAG(), ProcessTag() + " Prev Total MH: " + PreviousTotalMH + " .. Current Total MH: " + total_mh); @@ -289,7 +335,6 @@ public override APIData GetSummary() { } _currentMinerReadStatus = MinerAPIReadStatus.GOT_READ; - FillAlgorithm(aname, ref ad); // check if speed zero if (ad.Speed == 0) _currentMinerReadStatus = MinerAPIReadStatus.READ_SPEED_ZERO; diff --git a/NiceHashMiner/Net20_backport/HashSet.cs b/NiceHashMiner/Net20_backport/HashSet.cs new file mode 100644 index 0000000..079cf72 --- /dev/null +++ b/NiceHashMiner/Net20_backport/HashSet.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Net20_backport { + public class HashSet : List { + + public new bool Add(T item) { + if (this.Contains(item) == false) { + base.Add(item); + return true; + } + return false; + } + + public T First() { + if(this.Count >= 1) { + return this[0]; + } + throw new IndexOutOfRangeException(); + } + } +} diff --git a/NiceHashMiner/Net20_backport/SortedSet.cs b/NiceHashMiner/Net20_backport/SortedSet.cs new file mode 100644 index 0000000..3823a71 --- /dev/null +++ b/NiceHashMiner/Net20_backport/SortedSet.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Net20_backport { + public class SortedSet : List { + public new void Add(T item) { + if (this.Contains(item) == false) { + base.Add(item); + base.Sort(); + } + } + } +} diff --git a/NiceHashMiner/Net20_backport/StringHelper.cs b/NiceHashMiner/Net20_backport/StringHelper.cs new file mode 100644 index 0000000..9d585e2 --- /dev/null +++ b/NiceHashMiner/Net20_backport/StringHelper.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Net20_backport { + public static class StringHelper { + public static string Join(string delim, IList values) { + if (values.Count == 1) { + return values[0]; + } + string ret = ""; + if (values.Count > 1) { + for (int i = 0; i < values.Count - 1; ++i) { + ret += values[i] + delim; + } + // append last + ret += values[values.Count - 1]; + } + return ret; + } + + public static bool IsNullOrWhiteSpace(string check) { + if (check == null) { + return true; + } + if (check == " ") { + return true; + } + return false; + } + } +} diff --git a/NiceHashMiner/Net20_backport/Tuple.cs b/NiceHashMiner/Net20_backport/Tuple.cs new file mode 100644 index 0000000..f92d41f --- /dev/null +++ b/NiceHashMiner/Net20_backport/Tuple.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Net20_backport { + public class Tuple { + public T1 Item1 { get; set; } + public T2 Item2 { get; set; } + + public Tuple(T1 i1, T2 i2) { + Item1 = i1; + Item2 = i2; + } + } +} diff --git a/NiceHashMiner/Net20_backport/Tuple3.cs b/NiceHashMiner/Net20_backport/Tuple3.cs new file mode 100644 index 0000000..12d8e07 --- /dev/null +++ b/NiceHashMiner/Net20_backport/Tuple3.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Net20_backport { + public class Tuple3 { + public T1 Item1 { get; set; } + public T2 Item2 { get; set; } + public T3 Item3 { get; set; } + + public Tuple3(T1 i1, T2 i2, T3 i3) { + Item1 = i1; + Item2 = i2; + Item3 = i3; + } + } +} diff --git a/NiceHashMiner/NiceHashMiner.csproj b/NiceHashMiner/NiceHashMiner.csproj index 100456a..cf78307 100644 --- a/NiceHashMiner/NiceHashMiner.csproj +++ b/NiceHashMiner/NiceHashMiner.csproj @@ -9,7 +9,7 @@ Properties NiceHashMiner NiceHashMiner - v4.5 + v2.0 512 true @@ -55,6 +55,9 @@ Resources\logo.ico + + ..\3rdparty\sharpcompress-0.11\LinqBridge.dll + False ..\3rdparty\log4net\log4net.dll @@ -62,13 +65,14 @@ ..\3rdparty\json\Newtonsoft.Json.dll + + ..\3rdparty\sharpcompress-0.11\SharpCompress.dll + - - @@ -76,20 +80,26 @@ - - - - - - + + + + - - - + + + + + + + + + - + + + @@ -97,14 +107,19 @@ - + + + + + + UserControl @@ -153,56 +168,80 @@ Form_Benchmark.cs - - Form - - - Form_Settings.cs - Form Form_ChooseLanguage.cs + + Form + + + Form_3rdParty_TOS.cs + + + Form + + + Form_Settings.cs + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - - Form DriverVersionConfirmationDialog.cs - - - + + - + Form @@ -215,7 +254,7 @@ Form_Loading.cs - + Form @@ -225,18 +264,21 @@ + - + - - - + + + + AlgorithmsListView.cs + Designer AlgorithmSettingsControl.cs @@ -260,12 +302,15 @@ Form_Benchmark.cs - - Form_Settings.cs - Form_ChooseLanguage.cs + + Form_3rdParty_TOS.cs + + + Form_Settings.cs + DriverVersionConfirmationDialog.cs diff --git a/NiceHashMiner/NiceHashStats.cs b/NiceHashMiner/NiceHashStats.cs index d49fb9a..e11c3e2 100644 --- a/NiceHashMiner/NiceHashStats.cs +++ b/NiceHashMiner/NiceHashStats.cs @@ -7,6 +7,9 @@ using Newtonsoft.Json; using NiceHashMiner.Enums; using NiceHashMiner.Miners; +using Newtonsoft.Json.Linq; + + namespace NiceHashMiner { @@ -65,6 +68,11 @@ class nicehash_json public string method; } + class nicehash_json_T { + public T result; + public string method; + } + class nicehash_error { public string error; @@ -80,7 +88,7 @@ class nicehashminer_version public static Dictionary GetAlgorithmRates(string worker) { - string r1 = GetNiceHashAPIData("https://www.nicehash.com/api?method=simplemultialgo.info", worker); + string r1 = GetNiceHashAPIData(Links.NHM_API_info, worker); if (r1 == null) return null; nicehash_json_2 nhjson_current; @@ -103,10 +111,9 @@ public static Dictionary GetAlgorithmRates(string wo } } - public static nicehash_stats GetStats(string btc, int algo, string worker) { - string r1 = GetNiceHashAPIData("https://www.nicehash.com/api?method=stats.provider&addr=" + btc, worker); + string r1 = GetNiceHashAPIData(Links.NHM_API_stats + btc, worker); if (r1 == null) return null; nicehash_json nhjson_current; @@ -132,7 +139,7 @@ public static double GetBalance(string btc, string worker) { double balance = 0; - string r1 = GetNiceHashAPIData("https://www.nicehash.com/api?method=stats.provider&addr=" + btc, worker); + string r1 = GetNiceHashAPIData(Links.NHM_API_stats + btc, worker); if (r1 != null) { nicehash_json nhjson_current; @@ -160,7 +167,7 @@ public static double GetBalance(string btc, string worker) public static string GetVersion(string worker) { - string r1 = GetNiceHashAPIData("https://www.nicehash.com/nicehashminer?method=version", worker); + string r1 = GetNiceHashAPIData(Links.NHM_API_version, worker); if (r1 == null) return null; nicehashminer_version nhjson; @@ -181,17 +188,17 @@ public static string GetNiceHashAPIData(string URL, string worker) string ResponseFromServer; try { - string ActiveMinersGroup = MinersManager.Instance.GetActiveMinersGroup(); + string ActiveMinersGroup = MinersManager.GetActiveMinersGroup(); HttpWebRequest WR = (HttpWebRequest)WebRequest.Create(URL); WR.UserAgent = "NiceHashMiner/" + Application.ProductVersion; if (worker.Length > 64) worker = worker.Substring(0, 64); WR.Headers.Add("NiceHash-Worker-ID", worker); WR.Headers.Add("NHM-Active-Miners-Group", ActiveMinersGroup); - WR.Timeout = 10000; + WR.Timeout = 30 * 1000; WebResponse Response = WR.GetResponse(); Stream SS = Response.GetResponseStream(); - SS.ReadTimeout = 10000; + SS.ReadTimeout = 20 * 1000; StreamReader Reader = new StreamReader(SS); ResponseFromServer = Reader.ReadToEnd(); if (ResponseFromServer.Length == 0 || ResponseFromServer[0] != '{') diff --git a/NiceHashMiner/PInvoke/CPUID.cs b/NiceHashMiner/PInvoke/CPUID.cs index ccb0567..c0e87e0 100644 --- a/NiceHashMiner/PInvoke/CPUID.cs +++ b/NiceHashMiner/PInvoke/CPUID.cs @@ -53,6 +53,20 @@ public static int GetVirtualCoresCount() return coreCount; } + public static int GetNumberOfCores() { + int coreCount = 0; + + foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get()) { + coreCount += int.Parse(item["NumberOfCores"].ToString()); + } + + return coreCount; + } + + public static bool IsHypeThreadingEnabled() { + return GetVirtualCoresCount() > GetNumberOfCores(); + } + public static ulong CreateAffinityMask(int index, int percpu) { ulong mask = 0; diff --git a/NiceHashMiner/PInvoke/NiceHashProcess.cs b/NiceHashMiner/PInvoke/NiceHashProcess.cs index c55d98b..4ca98d5 100644 --- a/NiceHashMiner/PInvoke/NiceHashProcess.cs +++ b/NiceHashMiner/PInvoke/NiceHashProcess.cs @@ -12,6 +12,8 @@ public class NiceHashProcess private const uint CREATE_NEW_CONSOLE = 0x00000010; private const uint NORMAL_PRIORITY_CLASS = 0x0020; private const uint CREATE_NO_WINDOW = 0x08000000; + private const int STARTF_USESHOWWINDOW = 0x00000001; + private const short SW_SHOWMINNOACTIVE = 7; private const uint INFINITE = 0xFFFFFFFF; private const uint STILL_ACTIVE = 259; @@ -116,10 +118,17 @@ public bool Start() tSec.nLength = Marshal.SizeOf(tSec); uint sflags = 0; - if (StartInfo.CreateNoWindow) + if (StartInfo.CreateNoWindow) { sflags = CREATE_NO_WINDOW; - else + } + else if (StartInfo.WindowStyle == ProcessWindowStyle.Minimized) { + sInfo.dwFlags = STARTF_USESHOWWINDOW; + sInfo.wShowWindow = SW_SHOWMINNOACTIVE; + sflags = CREATE_NEW_CONSOLE; + } + else { sflags = CREATE_NEW_CONSOLE; + } string workDir = null; if (StartInfo.WorkingDirectory != null && StartInfo.WorkingDirectory.Length > 0) diff --git a/NiceHashMiner/PInvoke/PInvokeHelpers.cs b/NiceHashMiner/PInvoke/PInvokeHelpers.cs index 1a71fb2..89f2364 100644 --- a/NiceHashMiner/PInvoke/PInvokeHelpers.cs +++ b/NiceHashMiner/PInvoke/PInvokeHelpers.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner.PInvoke { class PInvokeHelpers { @@ -19,6 +17,9 @@ [Out] out bool wow64Process [return: MarshalAsAttribute(UnmanagedType.Bool)] public static extern bool AllocConsole(); + [DllImport("wininet.dll")] + protected extern static bool InternetGetConnectedState(out int Description, int ReservedValue); + #region Check If Idle internal struct LASTINPUTINFO { public uint cbSize; diff --git a/NiceHashMiner/Program.cs b/NiceHashMiner/Program.cs index 6781a4c..b8de95d 100644 --- a/NiceHashMiner/Program.cs +++ b/NiceHashMiner/Program.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json; using System.Globalization; using System.Threading; +using System.Diagnostics; namespace NiceHashMiner { @@ -32,38 +33,64 @@ static void Main(string[] argv) }; // #1 first initialize config - ConfigManager.Instance.GeneralConfig.InitializeConfig(); - ConfigManager.Instance.LegacyConfigMigration(); + ConfigManager.InitializeConfig(); - if (ConfigManager.Instance.GeneralConfig.LogToFile) { - Logger.ConfigureWithFile(); + // #2 check if multiple instances are allowed + bool startProgram = true; + if (ConfigManager.GeneralConfig.AllowMultipleInstances == false) { + try { + Process current = Process.GetCurrentProcess(); + foreach (Process process in Process.GetProcessesByName(current.ProcessName)) { + if (process.Id != current.Id) { + startProgram = false; + } + } + } catch { } } - if (ConfigManager.Instance.GeneralConfig.DebugConsole) { - Helpers.AllocConsole(); - } + if (startProgram) { + if (ConfigManager.GeneralConfig.LogToFile) { + Logger.ConfigureWithFile(); + } - // #2 then parse args - var commandLineArgs = new CommandLineParser(argv); + if (ConfigManager.GeneralConfig.DebugConsole) { + Helpers.AllocConsole(); + } - Helpers.ConsolePrint("NICEHASH", "Starting up NiceHashMiner v" + Application.ProductVersion); + // init active display currency after config load + ExchangeRateAPI.ActiveDisplayCurrency = ConfigManager.GeneralConfig.DisplayCurrency; - if (!ConfigManager.Instance.GeneralConfig.IsFileExist() && !commandLineArgs.IsLang) - { - Helpers.ConsolePrint("NICEHASH", "No config file found. Running NiceHash Miner for the first time. Choosing a default language."); - Application.Run(new Form_ChooseLanguage()); - } + // #2 then parse args + var commandLineArgs = new CommandLineParser(argv); + + Helpers.ConsolePrint("NICEHASH", "Starting up NiceHashMiner v" + Application.ProductVersion); + bool tosChecked = ConfigManager.GeneralConfig.agreedWithTOS == Globals.CURRENT_TOS_VER; + if (!tosChecked || !ConfigManager.GeneralConfigIsFileExist() && !commandLineArgs.IsLang) { + Helpers.ConsolePrint("NICEHASH", "No config file found. Running NiceHash Miner for the first time. Choosing a default language."); + Application.Run(new Form_ChooseLanguage()); + } + + // Init languages + International.Initialize(ConfigManager.GeneralConfig.Language); - // Init languages - International.Initialize(ConfigManager.Instance.GeneralConfig.Language); + if (commandLineArgs.IsLang) { + Helpers.ConsolePrint("NICEHASH", "Language is overwritten by command line parameter (-lang)."); + International.Initialize(commandLineArgs.LangValue); + ConfigManager.GeneralConfig.Language = commandLineArgs.LangValue; + } - if (commandLineArgs.IsLang) { - Helpers.ConsolePrint("NICEHASH", "Language is overwritten by command line parameter (-lang)."); - International.Initialize(commandLineArgs.LangValue); - ConfigManager.Instance.GeneralConfig.Language = commandLineArgs.LangValue; + // check WMI + if (Helpers.IsWMIEnabled()) { + if (ConfigManager.GeneralConfig.agreedWithTOS == Globals.CURRENT_TOS_VER) { + Application.Run(new Form_Main()); + } + } + else { + MessageBox.Show(International.GetText("Program_WMI_Error_Text"), + International.GetText("Program_WMI_Error_Title"), + MessageBoxButtons.OK, MessageBoxIcon.Error); + } } - - Application.Run(new Form_Main()); } } diff --git a/NiceHashMiner/Properties/AssemblyInfo.cs b/NiceHashMiner/Properties/AssemblyInfo.cs index e9a2f45..f182e35 100644 --- a/NiceHashMiner/Properties/AssemblyInfo.cs +++ b/NiceHashMiner/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("NiceHash")] [assembly: AssemblyProduct("NiceHashMiner")] -[assembly: AssemblyCopyright("NiceHash © 2016")] +[assembly: AssemblyCopyright("NiceHash © 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.7.1.1")] -[assembly: AssemblyFileVersion("1.7.1.1")] +[assembly: AssemblyVersion("1.7.5.11")] +[assembly: AssemblyFileVersion("1.7.5.11")] diff --git a/NiceHashMiner/README_ExtraLaunchParameters .md b/NiceHashMiner/README_ExtraLaunchParameters .md new file mode 100644 index 0000000..4505aef --- /dev/null +++ b/NiceHashMiner/README_ExtraLaunchParameters .md @@ -0,0 +1,60 @@ +# Algorithm ExtraLaunchParameters +## How does it work: +If you are an advanced user that wants to tweak the performance of your GPUs or CPUs you can set **supported** options in the **ExtraLaunchParameters** for selected Device and Algorithm. + +If you have 3 AMD devices with the following **ExtraLaunchParameters** settings for algorithm A and B: + - **device1** --xintensity 1024 --worksize 64 --gputhreads 2 + - **device2** --xintensity 512 --worksize 128 --gputhreads 2 + - **device3** --xintensity 512 --worksize 64 --gputhreads 4 + +If **algorithm A** is most profitable for device1 and device2 and **algorithm B** for device3, NiceHashMiner will run two sgminers for A and B like so: + - sgminer .. --xintensity 1024,512 --worksize 64,128 --gputhreads 2,2 .. (device1 and device2) + - sgminer .. --xintensity 512 --worksize 64 --gputhreads 4 .. (device3) + +If **algorithm A** is most profitable for all three devices, NiceHashMiner will run two sgminers for A like so: + - sgminer .. --xintensity 1024,512,512 --worksize 64,128,64 --gputhreads 2,2,4 .. (device1, device2, device3) + +So when setting **ExtraLaunchParameters** set them **per device and algorithm** NiceHashMiner will group them accordingly. +If you leave **ExtraLaunchParameters** empty the defaults will be used or ignored if no parameters have been set. + +## Supported options +### NVIDIA ccminers + - **--intensity=** or **-i** (if not set default 0 or ignored if unused) + +### NVIDIA ccminer CryptoNight + - **--launch=** or **-l** (if not set default 8x40 or ignored if unused) + - **--bfactor=** (if not set default 0 or ignored if unused) + - **--bsleep=** (if not set default 0 or ignored if unused) + +### NVIDIA ethminer DaggerHashimoto + - **--cuda-block-size** (if not set default 128 or ignored if unused) + - **--cuda-grid-size** (if not set default 8192 or ignored if unused) + +### AMD sgminer + - **--keccak-unroll** (if not set default 0 or ignored if unused) + - **--hamsi-expand-big** (if not set default 4 or ignored if unused) + - **--nfactor** (if not set default 10 or ignored if unused) + - **--intensity** (if not set default d or ignored if unused) + - **--xintensity** (if not set default -1 or ignored if unused, overrides --intensity) + - **--rawintensity** (if not set default -1 or ignored if unused, overrides --xintensity) + - **--thread-concurrency** (if not set default -1 or ignored if unused) + - **--worksize** (if not set default -1 or ignored if unused) + - **--gpu-threads** (if not set default -1 or ignored if unused) + - **--lookup-gap** (if not set default -1 or ignored if unused) + +#### AMD sgminer Temperature Control (if Temperature Control disabled all options will be ignored) + - **--gpu-fan** (if not set default 30-60) + - **--temp-cutoff** (if not set default 95) + - **--temp-overheat** (if not set default 85) + - **--temp-target** (if not set default 75) + - **--auto-fan** (if not set default it means it will not be used) + - **--auto-gpu** (if not set default it means it will not be used) + +### AMD ethminer DaggerHashimoto + - **--cl-local-work** (if not set default 64 or ignored if unused) + - **--cl-global-work** (if not set default 4096 * 64 or ignored if unused) + +### CPU cpuminer + - **--threads=** (if not set default it will use all avaliable virtual threads) + - **--cpu-affinity** (if not set option will be ignored) + - **--cpu-priority** (if not set option will be ignored) \ No newline at end of file diff --git a/NiceHashMiner/Resources/logo.ico b/NiceHashMiner/Resources/logo.ico index 99c98a6..9d3aa70 100644 Binary files a/NiceHashMiner/Resources/logo.ico and b/NiceHashMiner/Resources/logo.ico differ diff --git a/NiceHashMiner/Utils/AlgorithmNiceHashNames.cs b/NiceHashMiner/Utils/AlgorithmNiceHashNames.cs new file mode 100644 index 0000000..76e227b --- /dev/null +++ b/NiceHashMiner/Utils/AlgorithmNiceHashNames.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NiceHashMiner.Enums; + +namespace NiceHashMiner +{ + /// + /// AlgorithmNiceHashNames class is just a data container for mapping NiceHash JSON API names to algo type + /// + public static class AlgorithmNiceHashNames + { + public static string GetName(AlgorithmType type) { + if (AlgorithmType.INVALID <= type && type <= AlgorithmType.X11Gost) { + return Enum.GetName(typeof(AlgorithmType), type); + } + return "NameNotFound type not supported"; + } + } +} diff --git a/NiceHashMiner/Utils/BINS_CODEGEN.cs b/NiceHashMiner/Utils/BINS_CODEGEN.cs index 050de00..a8ae0b7 100644 --- a/NiceHashMiner/Utils/BINS_CODEGEN.cs +++ b/NiceHashMiner/Utils/BINS_CODEGEN.cs @@ -1,411 +1,74 @@ namespace NiceHashMiner.Utils { - public partial class MinersDownloadManager : BaseLazySingleton { + public static class Bins_Data { #region CODE_GEN STUFF // listFiles.py -private static string[] ALL_FILES_BINS = { -@"\ccminer_cryptonight.exe", -@"\ccminer_decred.exe", -@"\ccminer_nanashi.exe", -@"\ccminer_neoscrypt.exe", -@"\ccminer_sp.exe", -@"\ccminer_tpruvot.exe", -@"\cpuminer_opt_AES.exe", -@"\cpuminer_opt_AVX.exe", -@"\cpuminer_opt_AVX2.exe", -@"\cpuminer_opt_SSE2.exe", -@"\cudart32_80.dll", -@"\cudart64_80.dll", -@"\ethminer.exe", -@"\libcrypto-1.0.0.dll", -@"\libcurl-4.dll", -@"\libcurl.dll", -@"\libgcc_s_seh-1.dll", -@"\libgmp-10.dll", -@"\libgmpxx-4.dll", -@"\libjansson-4.dll", -@"\libjson-c-2.dll", -@"\libmicrohttpd-dll.dll", -@"\libsigc-2.0-0.dll", -@"\libssl-1.0.0.dll", -@"\libstdc++-6.dll", -@"\libwinpthread-1.dll", -@"\libz-1.dll", -@"\msvcr120.dll", -@"\OpenCL.dll", -@"\zlib1.dll", -@"\sgminer-5-1-0-optimized\darkcoin-modHawaiigw64l4.bin", -@"\sgminer-5-1-0-optimized\darkcoin-modPitcairngw64l4.bin", -@"\sgminer-5-1-0-optimized\darkcoin-modPitcairngw64l4ku0.bin", -@"\sgminer-5-1-0-optimized\darkcoin-modTahitigw64l4.bin", -@"\sgminer-5-1-0-optimized\darkcoin-modTongagw64l4.bin", -@"\sgminer-5-1-0-optimized\libcurl-4.dll", -@"\sgminer-5-1-0-optimized\libcurl.dll", -@"\sgminer-5-1-0-optimized\libeay32.dll", -@"\sgminer-5-1-0-optimized\libgcc_s_dw2-1.dll", -@"\sgminer-5-1-0-optimized\libidn-11.dll", -@"\sgminer-5-1-0-optimized\libpdcurses.dll", -@"\sgminer-5-1-0-optimized\Lyra2REv2Hawaiigw64l4.bin", -@"\sgminer-5-1-0-optimized\Lyra2REv2Pitcairngw64l4.bin", -@"\sgminer-5-1-0-optimized\Lyra2REv2Tahitigw64l4.bin", -@"\sgminer-5-1-0-optimized\Lyra2REv2Tongagw64l4.bin", -@"\sgminer-5-1-0-optimized\pthreadGC2.dll", -@"\sgminer-5-1-0-optimized\quarkcoinHawaiigw256l4ku0.bin", -@"\sgminer-5-1-0-optimized\quarkcoinHawaiigw64l4ku0.bin", -@"\sgminer-5-1-0-optimized\quarkcoinPitcairngw256l4ku0.bin", -@"\sgminer-5-1-0-optimized\quarkcoinPitcairngw64l4ku0.bin", -@"\sgminer-5-1-0-optimized\quarkcoinTahitigw256l4ku0.bin", -@"\sgminer-5-1-0-optimized\quarkcoinTahitigw64l4ku0.bin", -@"\sgminer-5-1-0-optimized\quarkcoinTongagw256l4ku0.bin", -@"\sgminer-5-1-0-optimized\quarkcoinTongagw64l4ku0.bin", -@"\sgminer-5-1-0-optimized\runme.bat", -@"\sgminer-5-1-0-optimized\sgminer-fixed.conf", -@"\sgminer-5-1-0-optimized\sgminer.exe", -@"\sgminer-5-1-0-optimized\ssleay32.dll", -@"\sgminer-5-1-0-optimized\zlib1.dll", -@"\sgminer-5-1-0-optimized\kernel\aes_helper.cl", -@"\sgminer-5-1-0-optimized\kernel\alexkarnew.cl", -@"\sgminer-5-1-0-optimized\kernel\alexkarold.cl", -@"\sgminer-5-1-0-optimized\kernel\animecoin.cl", -@"\sgminer-5-1-0-optimized\kernel\arebyp.cl", -@"\sgminer-5-1-0-optimized\kernel\bitblock.cl", -@"\sgminer-5-1-0-optimized\kernel\bitblockold.cl", -@"\sgminer-5-1-0-optimized\kernel\blake.cl", -@"\sgminer-5-1-0-optimized\kernel\blake256.cl", -@"\sgminer-5-1-0-optimized\kernel\bmw.cl", -@"\sgminer-5-1-0-optimized\kernel\bmw256.cl", -@"\sgminer-5-1-0-optimized\kernel\bufius.cl", -@"\sgminer-5-1-0-optimized\kernel\ckolivas.cl", -@"\sgminer-5-1-0-optimized\kernel\credits.cl", -@"\sgminer-5-1-0-optimized\kernel\cubehash.cl", -@"\sgminer-5-1-0-optimized\kernel\cubehash256.cl", -@"\sgminer-5-1-0-optimized\kernel\darkcoin-mod.cl", -@"\sgminer-5-1-0-optimized\kernel\darkcoin.cl", -@"\sgminer-5-1-0-optimized\kernel\diamond.cl", -@"\sgminer-5-1-0-optimized\kernel\echo.cl", -@"\sgminer-5-1-0-optimized\kernel\fresh.cl", -@"\sgminer-5-1-0-optimized\kernel\fugue.cl", -@"\sgminer-5-1-0-optimized\kernel\fuguecoin.cl", -@"\sgminer-5-1-0-optimized\kernel\groestl.cl", -@"\sgminer-5-1-0-optimized\kernel\groestl256.cl", -@"\sgminer-5-1-0-optimized\kernel\groestlcoin-v1.cl", -@"\sgminer-5-1-0-optimized\kernel\groestlcoin.cl", -@"\sgminer-5-1-0-optimized\kernel\hamsi.cl", -@"\sgminer-5-1-0-optimized\kernel\hamsi_helper.cl", -@"\sgminer-5-1-0-optimized\kernel\hamsi_helper_big.cl", -@"\sgminer-5-1-0-optimized\kernel\inkcoin.cl", -@"\sgminer-5-1-0-optimized\kernel\jh.cl", -@"\sgminer-5-1-0-optimized\kernel\keccak.cl", -@"\sgminer-5-1-0-optimized\kernel\keccak1600.cl", -@"\sgminer-5-1-0-optimized\kernel\luffa.cl", -@"\sgminer-5-1-0-optimized\kernel\Lyra2.cl", -@"\sgminer-5-1-0-optimized\kernel\Lyra2RE.cl", -@"\sgminer-5-1-0-optimized\kernel\Lyra2REv2.cl", -@"\sgminer-5-1-0-optimized\kernel\Lyra2v2.cl", -@"\sgminer-5-1-0-optimized\kernel\marucoin-mod.cl", -@"\sgminer-5-1-0-optimized\kernel\marucoin-modold.cl", -@"\sgminer-5-1-0-optimized\kernel\marucoin.cl", -@"\sgminer-5-1-0-optimized\kernel\maxcoin.cl", -@"\sgminer-5-1-0-optimized\kernel\myriadcoin-groestl.cl", -@"\sgminer-5-1-0-optimized\kernel\neoscrypt.cl", -@"\sgminer-5-1-0-optimized\kernel\panama.cl", -@"\sgminer-5-1-0-optimized\kernel\pluck.cl", -@"\sgminer-5-1-0-optimized\kernel\psw.cl", -@"\sgminer-5-1-0-optimized\kernel\quarkcoin.cl", -@"\sgminer-5-1-0-optimized\kernel\qubitcoin.cl", -@"\sgminer-5-1-0-optimized\kernel\shabal.cl", -@"\sgminer-5-1-0-optimized\kernel\shavite.cl", -@"\sgminer-5-1-0-optimized\kernel\sifcoin.cl", -@"\sgminer-5-1-0-optimized\kernel\simd.cl", -@"\sgminer-5-1-0-optimized\kernel\skein.cl", -@"\sgminer-5-1-0-optimized\kernel\skein256.cl", -@"\sgminer-5-1-0-optimized\kernel\talkcoin-mod.cl", -@"\sgminer-5-1-0-optimized\kernel\twecoin.cl", -@"\sgminer-5-1-0-optimized\kernel\whirlcoin.cl", -@"\sgminer-5-1-0-optimized\kernel\whirlpool.cl", -@"\sgminer-5-1-0-optimized\kernel\x14.cl", -@"\sgminer-5-1-0-optimized\kernel\x14old.cl", -@"\sgminer-5-1-0-optimized\kernel\yescrypt-multi.cl", -@"\sgminer-5-1-0-optimized\kernel\yescrypt.cl", -@"\sgminer-5-1-0-optimized\kernel\yescrypt_essential.cl", -@"\sgminer-5-1-0-optimized\kernel\zuikkis.cl", -@"\sgminer-5-1-1-optimized\darkcoin-modHawaiigw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\darkcoin-modPitcairngw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\darkcoin-modTahitigw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\darkcoin-modTongagw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\libcurl.dll", -@"\sgminer-5-1-1-optimized\libeay32.dll", -@"\sgminer-5-1-1-optimized\libgcc_s_dw2-1.dll", -@"\sgminer-5-1-1-optimized\libidn-11.dll", -@"\sgminer-5-1-1-optimized\libpdcurses.dll", -@"\sgminer-5-1-1-optimized\pthreadGC2.dll", -@"\sgminer-5-1-1-optimized\quarkcoinHawaiigw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\quarkcoinPitcairngw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\quarkcoinTahitigw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\quarkcoinTongagw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\qubitcoinHawaiigw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\qubitcoinPitcairngw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\qubitcoinTahitigw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\qubitcoinTongagw64l4ku0.bin", -@"\sgminer-5-1-1-optimized\runme.bat", -@"\sgminer-5-1-1-optimized\sgminer-fixed.conf", -@"\sgminer-5-1-1-optimized\sgminer.exe", -@"\sgminer-5-1-1-optimized\ssleay32.dll", -@"\sgminer-5-1-1-optimized\zlib1.dll", -@"\sgminer-5-1-1-optimized\kernel\aes_helper.cl", -@"\sgminer-5-1-1-optimized\kernel\alexkarnew.cl", -@"\sgminer-5-1-1-optimized\kernel\alexkarold.cl", -@"\sgminer-5-1-1-optimized\kernel\animecoin.cl", -@"\sgminer-5-1-1-optimized\kernel\arebyp.cl", -@"\sgminer-5-1-1-optimized\kernel\bitblock.cl", -@"\sgminer-5-1-1-optimized\kernel\bitblockold.cl", -@"\sgminer-5-1-1-optimized\kernel\blake.cl", -@"\sgminer-5-1-1-optimized\kernel\blake256.cl", -@"\sgminer-5-1-1-optimized\kernel\bmw.cl", -@"\sgminer-5-1-1-optimized\kernel\bufius.cl", -@"\sgminer-5-1-1-optimized\kernel\ckolivas.cl", -@"\sgminer-5-1-1-optimized\kernel\cubehash.cl", -@"\sgminer-5-1-1-optimized\kernel\darkcoin-mod.cl", -@"\sgminer-5-1-1-optimized\kernel\darkcoin.cl", -@"\sgminer-5-1-1-optimized\kernel\diamond.cl", -@"\sgminer-5-1-1-optimized\kernel\echo.cl", -@"\sgminer-5-1-1-optimized\kernel\fresh.cl", -@"\sgminer-5-1-1-optimized\kernel\fugue.cl", -@"\sgminer-5-1-1-optimized\kernel\fuguecoin.cl", -@"\sgminer-5-1-1-optimized\kernel\groestl.cl", -@"\sgminer-5-1-1-optimized\kernel\groestl256.cl", -@"\sgminer-5-1-1-optimized\kernel\groestlcoin-v1.cl", -@"\sgminer-5-1-1-optimized\kernel\groestlcoin.cl", -@"\sgminer-5-1-1-optimized\kernel\hamsi.cl", -@"\sgminer-5-1-1-optimized\kernel\hamsi_helper.cl", -@"\sgminer-5-1-1-optimized\kernel\hamsi_helper_big.cl", -@"\sgminer-5-1-1-optimized\kernel\inkcoin.cl", -@"\sgminer-5-1-1-optimized\kernel\jh.cl", -@"\sgminer-5-1-1-optimized\kernel\keccak.cl", -@"\sgminer-5-1-1-optimized\kernel\keccak1600.cl", -@"\sgminer-5-1-1-optimized\kernel\luffa.cl", -@"\sgminer-5-1-1-optimized\kernel\lyra2.cl", -@"\sgminer-5-1-1-optimized\kernel\lyra2re.cl", -@"\sgminer-5-1-1-optimized\kernel\marucoin-mod.cl", -@"\sgminer-5-1-1-optimized\kernel\marucoin-modold.cl", -@"\sgminer-5-1-1-optimized\kernel\marucoin.cl", -@"\sgminer-5-1-1-optimized\kernel\maxcoin.cl", -@"\sgminer-5-1-1-optimized\kernel\myriadcoin-groestl.cl", -@"\sgminer-5-1-1-optimized\kernel\neoscrypt.cl", -@"\sgminer-5-1-1-optimized\kernel\panama.cl", -@"\sgminer-5-1-1-optimized\kernel\pluck.cl", -@"\sgminer-5-1-1-optimized\kernel\psw.cl", -@"\sgminer-5-1-1-optimized\kernel\quarkcoin.cl", -@"\sgminer-5-1-1-optimized\kernel\qubitcoin.cl", -@"\sgminer-5-1-1-optimized\kernel\shabal.cl", -@"\sgminer-5-1-1-optimized\kernel\shavite.cl", -@"\sgminer-5-1-1-optimized\kernel\sifcoin.cl", -@"\sgminer-5-1-1-optimized\kernel\simd.cl", -@"\sgminer-5-1-1-optimized\kernel\skein.cl", -@"\sgminer-5-1-1-optimized\kernel\skein256.cl", -@"\sgminer-5-1-1-optimized\kernel\talkcoin-mod.cl", -@"\sgminer-5-1-1-optimized\kernel\twecoin.cl", -@"\sgminer-5-1-1-optimized\kernel\whirlcoin.cl", -@"\sgminer-5-1-1-optimized\kernel\whirlpool.cl", -@"\sgminer-5-1-1-optimized\kernel\whirlpoolx.cl", -@"\sgminer-5-1-1-optimized\kernel\x14.cl", -@"\sgminer-5-1-1-optimized\kernel\x14old.cl", -@"\sgminer-5-1-1-optimized\kernel\zuikkis.cl", -@"\sgminer-5-4-0-general\bitblockFijigw64l4ku0big4.bin", -@"\sgminer-5-4-0-general\bitblockHawaiigw64l4ku0big4.bin", -@"\sgminer-5-4-0-general\bitblockTongagw64l4ku0big4.bin", -@"\sgminer-5-4-0-general\blake256r8Fijigw128l4.bin", -@"\sgminer-5-4-0-general\blake256r8Hawaiigw128l4.bin", -@"\sgminer-5-4-0-general\blake256r8Tongagw128l4.bin", -@"\sgminer-5-4-0-general\decredFijigw64l4tc24512.bin", -@"\sgminer-5-4-0-general\decredHawaiigw64l4tc24512.bin", -@"\sgminer-5-4-0-general\decredTongagw64l4tc24512.bin", -@"\sgminer-5-4-0-general\marucoin-modFijigw64l4ku0big4.bin", -@"\sgminer-5-4-0-general\marucoin-modHawaiigw64l4ku0big4.bin", -@"\sgminer-5-4-0-general\marucoin-modTongagw64l4ku0big4.bin", -@"\sgminer-5-4-0-general\maxcoinFijigw64l4.bin", -@"\sgminer-5-4-0-general\maxcoinHawaiigw64l4.bin", -@"\sgminer-5-4-0-general\maxcoinTongagw64l4.bin", -@"\sgminer-5-4-0-general\neoscryptFijigw64l4lgtc8192.bin", -@"\sgminer-5-4-0-general\neoscryptHawaiigw64l4lgtc8192.bin", -@"\sgminer-5-4-0-general\neoscryptTongagw64l4lgtc8192.bin", -@"\sgminer-5-4-0-general\runme.bat", -@"\sgminer-5-4-0-general\sgminer-fixed.conf", -@"\sgminer-5-4-0-general\sgminer.exe", -@"\sgminer-5-4-0-general\talkcoin-modFijigw64l4ku0.bin", -@"\sgminer-5-4-0-general\talkcoin-modHawaiigw64l4ku0.bin", -@"\sgminer-5-4-0-general\talkcoin-modTongagw64l4ku0.bin", -@"\sgminer-5-4-0-general\vanillaFijigw128l4.bin", -@"\sgminer-5-4-0-general\vanillaHawaiigw128l4.bin", -@"\sgminer-5-4-0-general\vanillaTongagw128l4.bin", -@"\sgminer-5-4-0-general\kernel\aes_helper.cl", -@"\sgminer-5-4-0-general\kernel\alexkarnew.cl", -@"\sgminer-5-4-0-general\kernel\alexkarold.cl", -@"\sgminer-5-4-0-general\kernel\animecoin.cl", -@"\sgminer-5-4-0-general\kernel\arebyp.cl", -@"\sgminer-5-4-0-general\kernel\bitblock.cl", -@"\sgminer-5-4-0-general\kernel\bitblockold.cl", -@"\sgminer-5-4-0-general\kernel\blake.cl", -@"\sgminer-5-4-0-general\kernel\blake256.cl", -@"\sgminer-5-4-0-general\kernel\blake256r14.cl", -@"\sgminer-5-4-0-general\kernel\blake256r8.cl", -@"\sgminer-5-4-0-general\kernel\bmw.cl", -@"\sgminer-5-4-0-general\kernel\bmw256.cl", -@"\sgminer-5-4-0-general\kernel\bufius.cl", -@"\sgminer-5-4-0-general\kernel\ckolivas.cl", -@"\sgminer-5-4-0-general\kernel\credits.cl", -@"\sgminer-5-4-0-general\kernel\cubehash.cl", -@"\sgminer-5-4-0-general\kernel\cubehash256.cl", -@"\sgminer-5-4-0-general\kernel\darkcoin-mod.cl", -@"\sgminer-5-4-0-general\kernel\darkcoin.cl", -@"\sgminer-5-4-0-general\kernel\decred.cl", -@"\sgminer-5-4-0-general\kernel\diamond.cl", -@"\sgminer-5-4-0-general\kernel\echo.cl", -@"\sgminer-5-4-0-general\kernel\fresh.cl", -@"\sgminer-5-4-0-general\kernel\fugue.cl", -@"\sgminer-5-4-0-general\kernel\fuguecoin.cl", -@"\sgminer-5-4-0-general\kernel\groestl.cl", -@"\sgminer-5-4-0-general\kernel\groestl256.cl", -@"\sgminer-5-4-0-general\kernel\groestlcoin-v1.cl", -@"\sgminer-5-4-0-general\kernel\groestlcoin.cl", -@"\sgminer-5-4-0-general\kernel\hamsi.cl", -@"\sgminer-5-4-0-general\kernel\hamsi_helper.cl", -@"\sgminer-5-4-0-general\kernel\hamsi_helper_big.cl", -@"\sgminer-5-4-0-general\kernel\inkcoin.cl", -@"\sgminer-5-4-0-general\kernel\jh.cl", -@"\sgminer-5-4-0-general\kernel\keccak.cl", -@"\sgminer-5-4-0-general\kernel\keccak1600.cl", -@"\sgminer-5-4-0-general\kernel\luffa.cl", -@"\sgminer-5-4-0-general\kernel\lyra2.cl", -@"\sgminer-5-4-0-general\kernel\lyra2re.cl", -@"\sgminer-5-4-0-general\kernel\lyra2rev2.cl", -@"\sgminer-5-4-0-general\kernel\lyra2v2.cl", -@"\sgminer-5-4-0-general\kernel\marucoin-mod.cl", -@"\sgminer-5-4-0-general\kernel\marucoin-modold.cl", -@"\sgminer-5-4-0-general\kernel\marucoin.cl", -@"\sgminer-5-4-0-general\kernel\maxcoin.cl", -@"\sgminer-5-4-0-general\kernel\myriadcoin-groestl.cl", -@"\sgminer-5-4-0-general\kernel\neoscrypt.cl", -@"\sgminer-5-4-0-general\kernel\panama.cl", -@"\sgminer-5-4-0-general\kernel\pluck.cl", -@"\sgminer-5-4-0-general\kernel\psw.cl", -@"\sgminer-5-4-0-general\kernel\quarkcoin.cl", -@"\sgminer-5-4-0-general\kernel\qubitcoin.cl", -@"\sgminer-5-4-0-general\kernel\shabal.cl", -@"\sgminer-5-4-0-general\kernel\shavite.cl", -@"\sgminer-5-4-0-general\kernel\sifcoin.cl", -@"\sgminer-5-4-0-general\kernel\simd.cl", -@"\sgminer-5-4-0-general\kernel\skein.cl", -@"\sgminer-5-4-0-general\kernel\skein256.cl", -@"\sgminer-5-4-0-general\kernel\talkcoin-mod.cl", -@"\sgminer-5-4-0-general\kernel\twecoin.cl", -@"\sgminer-5-4-0-general\kernel\vanilla.cl", -@"\sgminer-5-4-0-general\kernel\whirlcoin.cl", -@"\sgminer-5-4-0-general\kernel\whirlpool.cl", -@"\sgminer-5-4-0-general\kernel\whirlpoolx.cl", -@"\sgminer-5-4-0-general\kernel\x14.cl", -@"\sgminer-5-4-0-general\kernel\x14old.cl", -@"\sgminer-5-4-0-general\kernel\yescrypt-multi.cl", -@"\sgminer-5-4-0-general\kernel\yescrypt.cl", -@"\sgminer-5-4-0-general\kernel\yescrypt_essential.cl", -@"\sgminer-5-4-0-general\kernel\zuikkis.cl", -@"\sgminer-5-4-0-tweaked\darkcoin-modBonairegw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\darkcoin-modFijigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\darkcoin-modHawaiigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\darkcoin-modPitcairngw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\darkcoin-modTahitigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\darkcoin-modTongagw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\lyra2rev2Bonairegw64l4.bin", -@"\sgminer-5-4-0-tweaked\lyra2rev2Fijigw64l4.bin", -@"\sgminer-5-4-0-tweaked\lyra2rev2Hawaiigw64l4.bin", -@"\sgminer-5-4-0-tweaked\lyra2rev2Pitcairngw64l4.bin", -@"\sgminer-5-4-0-tweaked\lyra2rev2Tahitigw64l4.bin", -@"\sgminer-5-4-0-tweaked\lyra2rev2Tongagw64l4.bin", -@"\sgminer-5-4-0-tweaked\quarkcoinBonairegw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\quarkcoinFijigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\quarkcoinHawaiigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\quarkcoinPitcairngw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\quarkcoinTahitigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\quarkcoinTongagw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\qubitcoinBonairegw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\qubitcoinFijigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\qubitcoinHawaiigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\qubitcoinPitcairngw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\qubitcoinTahitigw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\qubitcoinTongagw64l4ku0.bin", -@"\sgminer-5-4-0-tweaked\sgminer.exe", -@"\sgminer-5-4-0-tweaked\kernel\aes_helper.cl", -@"\sgminer-5-4-0-tweaked\kernel\alexkarnew.cl", -@"\sgminer-5-4-0-tweaked\kernel\alexkarold.cl", -@"\sgminer-5-4-0-tweaked\kernel\animecoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\arebyp.cl", -@"\sgminer-5-4-0-tweaked\kernel\bitblock.cl", -@"\sgminer-5-4-0-tweaked\kernel\bitblockold.cl", -@"\sgminer-5-4-0-tweaked\kernel\blake.cl", -@"\sgminer-5-4-0-tweaked\kernel\blake256.cl", -@"\sgminer-5-4-0-tweaked\kernel\blake256r14.cl", -@"\sgminer-5-4-0-tweaked\kernel\blake256r8.cl", -@"\sgminer-5-4-0-tweaked\kernel\bmw.cl", -@"\sgminer-5-4-0-tweaked\kernel\bmw256.cl", -@"\sgminer-5-4-0-tweaked\kernel\bufius.cl", -@"\sgminer-5-4-0-tweaked\kernel\ckolivas.cl", -@"\sgminer-5-4-0-tweaked\kernel\credits.cl", -@"\sgminer-5-4-0-tweaked\kernel\cubehash.cl", -@"\sgminer-5-4-0-tweaked\kernel\cubehash256.cl", -@"\sgminer-5-4-0-tweaked\kernel\darkcoin-mod.cl", -@"\sgminer-5-4-0-tweaked\kernel\darkcoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\decred.cl", -@"\sgminer-5-4-0-tweaked\kernel\diamond.cl", -@"\sgminer-5-4-0-tweaked\kernel\echo.cl", -@"\sgminer-5-4-0-tweaked\kernel\fresh.cl", -@"\sgminer-5-4-0-tweaked\kernel\fugue.cl", -@"\sgminer-5-4-0-tweaked\kernel\fuguecoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\groestl.cl", -@"\sgminer-5-4-0-tweaked\kernel\groestl256.cl", -@"\sgminer-5-4-0-tweaked\kernel\groestlcoin-v1.cl", -@"\sgminer-5-4-0-tweaked\kernel\groestlcoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\hamsi.cl", -@"\sgminer-5-4-0-tweaked\kernel\hamsi_helper.cl", -@"\sgminer-5-4-0-tweaked\kernel\hamsi_helper_big.cl", -@"\sgminer-5-4-0-tweaked\kernel\inkcoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\jh.cl", -@"\sgminer-5-4-0-tweaked\kernel\keccak.cl", -@"\sgminer-5-4-0-tweaked\kernel\keccak1600.cl", -@"\sgminer-5-4-0-tweaked\kernel\luffa.cl", -@"\sgminer-5-4-0-tweaked\kernel\lyra2.cl", -@"\sgminer-5-4-0-tweaked\kernel\lyra2re.cl", -@"\sgminer-5-4-0-tweaked\kernel\lyra2rev2.cl", -@"\sgminer-5-4-0-tweaked\kernel\lyra2v2.cl", -@"\sgminer-5-4-0-tweaked\kernel\marucoin-mod.cl", -@"\sgminer-5-4-0-tweaked\kernel\marucoin-modold.cl", -@"\sgminer-5-4-0-tweaked\kernel\marucoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\maxcoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\myriadcoin-groestl.cl", -@"\sgminer-5-4-0-tweaked\kernel\neoscrypt.cl", -@"\sgminer-5-4-0-tweaked\kernel\panama.cl", -@"\sgminer-5-4-0-tweaked\kernel\pluck.cl", -@"\sgminer-5-4-0-tweaked\kernel\psw.cl", -@"\sgminer-5-4-0-tweaked\kernel\quarkcoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\qubitcoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\shabal.cl", -@"\sgminer-5-4-0-tweaked\kernel\shavite.cl", -@"\sgminer-5-4-0-tweaked\kernel\sifcoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\simd.cl", -@"\sgminer-5-4-0-tweaked\kernel\skein.cl", -@"\sgminer-5-4-0-tweaked\kernel\skein256.cl", -@"\sgminer-5-4-0-tweaked\kernel\talkcoin-mod.cl", -@"\sgminer-5-4-0-tweaked\kernel\twecoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\vanilla.cl", -@"\sgminer-5-4-0-tweaked\kernel\whirlcoin.cl", -@"\sgminer-5-4-0-tweaked\kernel\whirlpool.cl", -@"\sgminer-5-4-0-tweaked\kernel\whirlpoolx.cl", -@"\sgminer-5-4-0-tweaked\kernel\x14.cl", -@"\sgminer-5-4-0-tweaked\kernel\x14old.cl", -@"\sgminer-5-4-0-tweaked\kernel\yescrypt-multi.cl", -@"\sgminer-5-4-0-tweaked\kernel\yescrypt.cl", -@"\sgminer-5-4-0-tweaked\kernel\yescrypt_essential.cl", -@"\sgminer-5-4-0-tweaked\kernel\zuikkis.cl", + public static string[] ALL_FILES_BINS = { +@"\vc_redist.x64.exe", +@"\ccminer_cryptonight\ccminer.exe", +@"\ccminer_cryptonight\cudart32_80.dll", +@"\ccminer_cryptonight\cudart64_80.dll", +@"\ccminer_cryptonight\msvcp120.dll", +@"\ccminer_cryptonight\msvcr120.dll", +@"\ccminer_decred\ccminer.exe", +@"\ccminer_decred\cudart32_80.dll", +@"\ccminer_decred\cudart64_80.dll", +@"\ccminer_decred\msvcp120.dll", +@"\ccminer_decred\msvcr120.dll", +@"\ccminer_nanashi\ccminer.exe", +@"\ccminer_nanashi\cudart32_80.dll", +@"\ccminer_nanashi\cudart64_80.dll", +@"\ccminer_nanashi\msvcp120.dll", +@"\ccminer_nanashi\msvcr120.dll", +@"\ccminer_neoscrypt\ccminer.exe", +@"\ccminer_neoscrypt\cudart32_80.dll", +@"\ccminer_neoscrypt\cudart64_80.dll", +@"\ccminer_neoscrypt\msvcp120.dll", +@"\ccminer_neoscrypt\msvcr120.dll", +@"\ccminer_sp\ccminer.exe", +@"\ccminer_sp\cudart32_80.dll", +@"\ccminer_sp\cudart64_80.dll", +@"\ccminer_sp\msvcp120.dll", +@"\ccminer_sp\msvcr120.dll", +@"\ccminer_tpruvot\ccminer.exe", +@"\ccminer_tpruvot\cudart32_80.dll", +@"\ccminer_tpruvot\cudart64_80.dll", +@"\ccminer_tpruvot\msvcp120.dll", +@"\ccminer_tpruvot\msvcr120.dll", +@"\ccminer_x11gost\ccminer.exe", +@"\ccminer_x11gost\cudart32_80.dll", +@"\ccminer_x11gost\cudart64_80.dll", +@"\ccminer_x11gost\msvcp120.dll", +@"\ccminer_x11gost\msvcr120.dll", +@"\ethminer\cudart64_80.dll", +@"\ethminer\ethminer.exe", +@"\ethminer\libcurl.dll", +@"\ethminer\libmicrohttpd-dll.dll", +@"\ethminer\msvcp120.dll", +@"\ethminer\msvcr120.dll", +@"\ethminer\OpenCL.dll", +@"\excavator\cudart64_80.dll", +@"\excavator\excavator.exe", +@"\excavator\msvcp120.dll", +@"\excavator\msvcr120.dll", +@"\nheqminer_v0.4b\cpu_tromp_AVX.dll", +@"\nheqminer_v0.4b\cpu_tromp_SSE2.dll", +@"\nheqminer_v0.4b\cudart64_75.dll", +@"\nheqminer_v0.4b\cudart64_80.dll", +@"\nheqminer_v0.4b\cuda_tromp.dll", +@"\nheqminer_v0.4b\cuda_tromp_75.dll", +@"\nheqminer_v0.4b\equiw200k9.bin", +@"\nheqminer_v0.4b\msvcp120.dll", +@"\nheqminer_v0.4b\msvcr120.dll", +@"\nheqminer_v0.4b\nheqminer.exe", +@"\sgminer-5-6-0-general\sgminer.exe", +@"\sgminer-gm\sgminer.exe", +@"\xmr-stak-cpu\concrt140.dll", +@"\xmr-stak-cpu\msvcp140.dll", +@"\xmr-stak-cpu\vccorlib140.dll", +@"\xmr-stak-cpu\vcruntime140.dll", +@"\xmr-stak-cpu\xmr-stak-cpu.exe", }; -#endregion //CODE_GEN STUFF // listFiles.py -} + #endregion //CODE_GEN STUFF // listFiles.py + } } diff --git a/NiceHashMiner/Utils/BINS_CODEGEN_3rd.cs b/NiceHashMiner/Utils/BINS_CODEGEN_3rd.cs new file mode 100644 index 0000000..51ef112 --- /dev/null +++ b/NiceHashMiner/Utils/BINS_CODEGEN_3rd.cs @@ -0,0 +1,839 @@ + +namespace NiceHashMiner.Utils { + public static class Bins_Data_3rd { + #region CODE_GEN STUFF // listFiles.py + public static string[] ALL_FILES_BINS = { +@"\claymore_cryptonight\Data.bin", +@"\claymore_cryptonight\msvcr110.dll", +@"\claymore_cryptonight\NsGpuCNMiner.exe", +@"\claymore_cryptonight\Remote manager\EthMan.exe", +@"\claymore_zcash\Data.bin", +@"\claymore_zcash\Data1a1.bin", +@"\claymore_zcash\Data1b1.bin", +@"\claymore_zcash\Data1c1.bin", +@"\claymore_zcash\Data1d1.bin", +@"\claymore_zcash\Data1e1.bin", +@"\claymore_zcash\Data1g1.bin", +@"\claymore_zcash\Data2.bin", +@"\claymore_zcash\msvcr110.dll", +@"\claymore_zcash\ZecMiner64.exe", +@"\claymore_zcash\Remote manager\EthMan.exe", +@"\optiminer_zcash_win\Optiminer.exe", +@"\optiminer_zcash_win\bin\asm.bin", +@"\optiminer_zcash_win\bin\base.bin", +@"\optiminer_zcash_win\bin\round1.bin", +@"\optiminer_zcash_win\bin\round2.bin", +@"\optiminer_zcash_win\bin\round3.bin", +@"\optiminer_zcash_win\bin\round4.bin", +@"\optiminer_zcash_win\bin\round5.bin", +@"\optiminer_zcash_win\bin\round6.bin", +@"\optiminer_zcash_win\bin\round7.bin", +@"\optiminer_zcash_win\bin\round8.bin", +@"\optiminer_zcash_win\bin\round9.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round0.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round1.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round2.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round3.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round4.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round5.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round6.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round7.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round8.bin", +@"\optiminer_zcash_win\bin-191205\Bonaire_round9.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round0.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round1.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round2.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round3.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round4.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round5.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round6.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round7.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round8.bin", +@"\optiminer_zcash_win\bin-191205\CapeVerde_round9.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round0.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round1.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round2.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round3.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round4.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round5.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round6.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round7.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round8.bin", +@"\optiminer_zcash_win\bin-191205\Carrizo_round9.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round0.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round1.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round2.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round3.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round4.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round5.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round6.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round7.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round8.bin", +@"\optiminer_zcash_win\bin-191205\Fiji_round9.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round0.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round1.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round2.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round3.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round4.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round5.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round6.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round7.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round8.bin", +@"\optiminer_zcash_win\bin-191205\Hawaii_round9.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round0.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round1.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round2.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round3.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round4.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round5.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round6.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round7.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round8.bin", +@"\optiminer_zcash_win\bin-191205\Iceland_round9.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round0.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round1.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round2.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round3.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round4.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round5.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round6.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round7.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round8.bin", +@"\optiminer_zcash_win\bin-191205\Kalindi_round9.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round0.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round1.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round2.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round3.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round4.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round5.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round6.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round7.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round8.bin", +@"\optiminer_zcash_win\bin-191205\Mullins_round9.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round0.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round1.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round2.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round3.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round4.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round5.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round6.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round7.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round8.bin", +@"\optiminer_zcash_win\bin-191205\Oland_round9.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round0.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round1.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round2.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round3.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round4.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round5.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round6.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round7.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round8.bin", +@"\optiminer_zcash_win\bin-191205\Pitcairn_round9.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round0.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round1.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round2.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round3.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round4.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round5.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round6.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round7.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round8.bin", +@"\optiminer_zcash_win\bin-191205\Spectre_round9.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round0.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round1.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round2.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round3.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round4.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round5.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round6.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round7.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round8.bin", +@"\optiminer_zcash_win\bin-191205\Spooky_round9.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round0.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round1.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round2.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round3.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round4.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round5.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round6.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round7.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round8.bin", +@"\optiminer_zcash_win\bin-191205\Tahiti_round9.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round0.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round1.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round2.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round3.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round4.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round5.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round6.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round7.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round8.bin", +@"\optiminer_zcash_win\bin-191205\Tonga_round9.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round0.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round1.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round2.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round3.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round4.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round5.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round6.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round7.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round8.bin", +@"\optiminer_zcash_win\bin-200406\Bonaire_round9.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round0.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round1.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round2.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round3.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round4.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round5.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round6.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round7.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round8.bin", +@"\optiminer_zcash_win\bin-200406\CapeVerde_round9.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round0.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round1.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round2.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round3.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round4.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round5.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round6.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round7.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round8.bin", +@"\optiminer_zcash_win\bin-200406\Carrizo_round9.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round0.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round1.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round2.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round3.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round4.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round5.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round6.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round7.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round8.bin", +@"\optiminer_zcash_win\bin-200406\Fiji_round9.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round0.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round1.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round2.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round3.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round4.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round5.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round6.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round7.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round8.bin", +@"\optiminer_zcash_win\bin-200406\Hawaii_round9.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round0.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round1.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round2.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round3.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round4.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round5.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round6.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round7.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round8.bin", +@"\optiminer_zcash_win\bin-200406\Iceland_round9.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round0.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round1.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round2.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round3.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round4.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round5.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round6.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round7.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round8.bin", +@"\optiminer_zcash_win\bin-200406\Kalindi_round9.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round0.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round1.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round2.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round3.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round4.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round5.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round6.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round7.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round8.bin", +@"\optiminer_zcash_win\bin-200406\Mullins_round9.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round0.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round1.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round2.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round3.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round4.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round5.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round6.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round7.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round8.bin", +@"\optiminer_zcash_win\bin-200406\Oland_round9.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round0.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round1.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round2.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round3.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round4.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round5.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round6.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round7.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round8.bin", +@"\optiminer_zcash_win\bin-200406\Pitcairn_round9.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round0.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round1.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round2.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round3.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round4.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round5.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round6.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round7.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round8.bin", +@"\optiminer_zcash_win\bin-200406\Spectre_round9.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round0.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round1.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round2.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round3.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round4.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round5.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round6.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round7.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round8.bin", +@"\optiminer_zcash_win\bin-200406\Spooky_round9.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round0.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round1.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round2.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round3.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round4.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round5.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round6.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round7.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round8.bin", +@"\optiminer_zcash_win\bin-200406\Stoney_round9.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round0.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round1.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round2.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round3.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round4.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round5.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round6.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round7.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round8.bin", +@"\optiminer_zcash_win\bin-200406\Tahiti_round9.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round0.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round1.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round2.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round3.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round4.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round5.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round6.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round7.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round8.bin", +@"\optiminer_zcash_win\bin-200406\Tonga_round9.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round0.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round1.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round2.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round3.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round4.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round5.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round6.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round7.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round8.bin", +@"\optiminer_zcash_win\bin-203603\Baffin_round9.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round0.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round1.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round2.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round3.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round4.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round5.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round6.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round7.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round8.bin", +@"\optiminer_zcash_win\bin-203603\Bonaire_round9.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round0.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round1.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round2.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round3.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round4.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round5.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round6.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round7.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round8.bin", +@"\optiminer_zcash_win\bin-203603\CapeVerde_round9.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round0.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round1.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round2.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round3.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round4.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round5.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round6.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round7.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round8.bin", +@"\optiminer_zcash_win\bin-203603\Carrizo_round9.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round0.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round1.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round2.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round3.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round4.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round5.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round6.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round7.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round8.bin", +@"\optiminer_zcash_win\bin-203603\Ellesmere_round9.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round0.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round1.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round2.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round3.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round4.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round5.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round6.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round7.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round8.bin", +@"\optiminer_zcash_win\bin-203603\Fiji_round9.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round0.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round1.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round2.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round3.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round4.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round5.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round6.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round7.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round8.bin", +@"\optiminer_zcash_win\bin-203603\Hawaii_round9.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round0.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round1.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round2.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round3.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round4.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round5.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round6.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round7.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round8.bin", +@"\optiminer_zcash_win\bin-203603\Iceland_round9.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round0.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round1.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round2.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round3.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round4.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round5.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round6.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round7.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round8.bin", +@"\optiminer_zcash_win\bin-203603\Kalindi_round9.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round0.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round1.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round2.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round3.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round4.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round5.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round6.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round7.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round8.bin", +@"\optiminer_zcash_win\bin-203603\Mullins_round9.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round0.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round1.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round2.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round3.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round4.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round5.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round6.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round7.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round8.bin", +@"\optiminer_zcash_win\bin-203603\Oland_round9.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round0.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round1.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round2.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round3.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round4.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round5.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round6.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round7.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round8.bin", +@"\optiminer_zcash_win\bin-203603\Pitcairn_round9.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round0.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round1.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round2.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round3.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round4.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round5.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round6.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round7.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round8.bin", +@"\optiminer_zcash_win\bin-203603\Spectre_round9.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round0.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round1.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round2.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round3.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round4.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round5.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round6.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round7.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round8.bin", +@"\optiminer_zcash_win\bin-203603\Spooky_round9.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round0.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round1.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round2.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round3.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round4.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round5.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round6.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round7.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round8.bin", +@"\optiminer_zcash_win\bin-203603\Stoney_round9.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round0.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round1.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round2.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round3.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round4.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round5.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round6.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round7.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round8.bin", +@"\optiminer_zcash_win\bin-203603\Tahiti_round9.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round0.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round1.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round2.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round3.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round4.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round5.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round6.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round7.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round8.bin", +@"\optiminer_zcash_win\bin-203603\Tonga_round9.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round0.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round1.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round2.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round3.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round4.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round5.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round6.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round7.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round8.bin", +@"\optiminer_zcash_win\bin-207903\Baffin_round9.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round0.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round1.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round2.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round3.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round4.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round5.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round6.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round7.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round8.bin", +@"\optiminer_zcash_win\bin-207903\Bonaire_round9.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round0.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round1.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round2.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round3.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round4.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round5.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round6.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round7.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round8.bin", +@"\optiminer_zcash_win\bin-207903\CapeVerde_round9.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round0.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round1.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round2.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round3.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round4.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round5.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round6.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round7.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round8.bin", +@"\optiminer_zcash_win\bin-207903\Carrizo_round9.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round0.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round1.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round2.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round3.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round4.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round5.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round6.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round7.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round8.bin", +@"\optiminer_zcash_win\bin-207903\Ellesmere_round9.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round0.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round1.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round2.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round3.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round4.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round5.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round6.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round7.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round8.bin", +@"\optiminer_zcash_win\bin-207903\Fiji_round9.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round0.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round1.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round2.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round3.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round4.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round5.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round6.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round7.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round8.bin", +@"\optiminer_zcash_win\bin-207903\Hawaii_round9.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round0.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round1.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round2.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round3.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round4.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round5.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round6.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round7.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round8.bin", +@"\optiminer_zcash_win\bin-207903\Iceland_round9.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round0.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round1.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round2.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round3.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round4.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round5.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round6.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round7.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round8.bin", +@"\optiminer_zcash_win\bin-207903\Kalindi_round9.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round0.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round1.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round2.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round3.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round4.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round5.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round6.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round7.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round8.bin", +@"\optiminer_zcash_win\bin-207903\Mullins_round9.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round0.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round1.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round2.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round3.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round4.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round5.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round6.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round7.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round8.bin", +@"\optiminer_zcash_win\bin-207903\Oland_round9.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round0.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round1.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round2.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round3.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round4.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round5.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round6.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round7.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round8.bin", +@"\optiminer_zcash_win\bin-207903\Pitcairn_round9.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round0.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round1.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round2.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round3.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round4.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round5.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round6.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round7.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round8.bin", +@"\optiminer_zcash_win\bin-207903\Spectre_round9.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round0.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round1.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round2.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round3.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round4.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round5.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round6.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round7.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round8.bin", +@"\optiminer_zcash_win\bin-207903\Spooky_round9.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round0.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round1.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round2.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round3.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round4.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round5.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round6.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round7.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round8.bin", +@"\optiminer_zcash_win\bin-207903\Stoney_round9.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round0.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round1.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round2.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round3.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round4.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round5.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round6.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round7.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round8.bin", +@"\optiminer_zcash_win\bin-207903\Tahiti_round9.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round0.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round1.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round2.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round3.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round4.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round5.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round6.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round7.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round8.bin", +@"\optiminer_zcash_win\bin-207903\Tonga_round9.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round0.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round1.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round2.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round3.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round4.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round5.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round6.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round7.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round8.bin", +@"\optiminer_zcash_win\bin-223600\Baffin_round9.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round0.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round1.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round2.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round3.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round4.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round5.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round6.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round7.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round8.bin", +@"\optiminer_zcash_win\bin-223600\Bonaire_round9.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round0.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round1.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round2.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round3.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round4.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round5.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round6.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round7.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round8.bin", +@"\optiminer_zcash_win\bin-223600\CapeVerde_round9.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round0.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round1.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round2.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round3.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round4.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round5.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round6.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round7.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round8.bin", +@"\optiminer_zcash_win\bin-223600\Carrizo_round9.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round0.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round1.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round2.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round3.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round4.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round5.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round6.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round7.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round8.bin", +@"\optiminer_zcash_win\bin-223600\Ellesmere_round9.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round0.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round1.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round2.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round3.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round4.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round5.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round6.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round7.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round8.bin", +@"\optiminer_zcash_win\bin-223600\Fiji_round9.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round0.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round1.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round2.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round3.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round4.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round5.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round6.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round7.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round8.bin", +@"\optiminer_zcash_win\bin-223600\Hawaii_round9.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round0.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round1.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round2.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round3.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round4.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round5.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round6.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round7.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round8.bin", +@"\optiminer_zcash_win\bin-223600\Iceland_round9.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round0.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round1.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round2.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round3.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round4.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round5.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round6.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round7.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round8.bin", +@"\optiminer_zcash_win\bin-223600\Kalindi_round9.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round0.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round1.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round2.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round3.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round4.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round5.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round6.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round7.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round8.bin", +@"\optiminer_zcash_win\bin-223600\Mullins_round9.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round0.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round1.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round2.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round3.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round4.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round5.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round6.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round7.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round8.bin", +@"\optiminer_zcash_win\bin-223600\Oland_round9.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round0.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round1.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round2.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round3.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round4.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round5.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round6.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round7.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round8.bin", +@"\optiminer_zcash_win\bin-223600\Pitcairn_round9.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round0.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round1.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round2.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round3.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round4.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round5.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round6.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round7.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round8.bin", +@"\optiminer_zcash_win\bin-223600\Spectre_round9.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round0.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round1.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round2.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round3.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round4.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round5.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round6.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round7.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round8.bin", +@"\optiminer_zcash_win\bin-223600\Spooky_round9.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round0.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round1.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round2.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round3.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round4.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round5.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round6.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round7.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round8.bin", +@"\optiminer_zcash_win\bin-223600\Stoney_round9.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round0.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round1.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round2.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round3.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round4.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round5.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round6.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round7.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round8.bin", +@"\optiminer_zcash_win\bin-223600\Tahiti_round9.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round0.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round1.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round2.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round3.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round4.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round5.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round6.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round7.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round8.bin", +@"\optiminer_zcash_win\bin-223600\Tonga_round9.bin", + +@"\claymore_dual\EthDcrMiner64.exe", +}; + #endregion //CODE_GEN STUFF // listFiles.py + } +} + diff --git a/NiceHashMiner/Utils/BINS_CODEGEN_AMD.cs b/NiceHashMiner/Utils/BINS_CODEGEN_AMD.cs deleted file mode 100644 index e44722b..0000000 --- a/NiceHashMiner/Utils/BINS_CODEGEN_AMD.cs +++ /dev/null @@ -1,753 +0,0 @@ - -namespace NiceHashMiner.Utils { - public partial class MinersDownloadManager : BaseLazySingleton { - #region CODE_GEN STUFF // listFiles.py -private static string[] ALL_FILES_BINS_AMD = { - -@"\amd\sgminer-5-1-0-optimized\darkcoin-modHawaiigw64l4.bin", - -@"\amd\sgminer-5-1-0-optimized\darkcoin-modPitcairngw64l4.bin", - -@"\amd\sgminer-5-1-0-optimized\darkcoin-modPitcairngw64l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\darkcoin-modTahitigw64l4.bin", - -@"\amd\sgminer-5-1-0-optimized\darkcoin-modTongagw64l4.bin", - -@"\amd\sgminer-5-1-0-optimized\libcurl-4.dll", - -@"\amd\sgminer-5-1-0-optimized\libcurl.dll", - -@"\amd\sgminer-5-1-0-optimized\libeay32.dll", - -@"\amd\sgminer-5-1-0-optimized\libgcc_s_dw2-1.dll", - -@"\amd\sgminer-5-1-0-optimized\libidn-11.dll", - -@"\amd\sgminer-5-1-0-optimized\libpdcurses.dll", - -@"\amd\sgminer-5-1-0-optimized\Lyra2REv2Hawaiigw64l4.bin", - -@"\amd\sgminer-5-1-0-optimized\Lyra2REv2Pitcairngw64l4.bin", - -@"\amd\sgminer-5-1-0-optimized\Lyra2REv2Tahitigw64l4.bin", - -@"\amd\sgminer-5-1-0-optimized\Lyra2REv2Tongagw64l4.bin", - -@"\amd\sgminer-5-1-0-optimized\pthreadGC2.dll", - -@"\amd\sgminer-5-1-0-optimized\quarkcoinHawaiigw256l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\quarkcoinHawaiigw64l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\quarkcoinPitcairngw256l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\quarkcoinPitcairngw64l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\quarkcoinTahitigw256l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\quarkcoinTahitigw64l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\quarkcoinTongagw256l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\quarkcoinTongagw64l4ku0.bin", - -@"\amd\sgminer-5-1-0-optimized\runme.bat", - -@"\amd\sgminer-5-1-0-optimized\sgminer-fixed.conf", - -@"\amd\sgminer-5-1-0-optimized\sgminer.exe", - -@"\amd\sgminer-5-1-0-optimized\ssleay32.dll", - -@"\amd\sgminer-5-1-0-optimized\zlib1.dll", - -@"\amd\sgminer-5-1-0-optimized\kernel\aes_helper.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\alexkarnew.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\alexkarold.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\animecoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\arebyp.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\bitblock.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\bitblockold.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\blake.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\blake256.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\bmw.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\bmw256.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\bufius.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\ckolivas.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\credits.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\cubehash.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\cubehash256.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\darkcoin-mod.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\darkcoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\diamond.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\echo.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\fresh.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\fugue.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\fuguecoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\groestl.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\groestl256.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\groestlcoin-v1.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\groestlcoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\hamsi.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\hamsi_helper.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\hamsi_helper_big.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\inkcoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\jh.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\keccak.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\keccak1600.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\luffa.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\Lyra2.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\Lyra2RE.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\Lyra2REv2.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\Lyra2v2.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\marucoin-mod.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\marucoin-modold.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\marucoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\maxcoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\myriadcoin-groestl.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\neoscrypt.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\panama.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\pluck.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\psw.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\quarkcoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\qubitcoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\shabal.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\shavite.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\sifcoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\simd.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\skein.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\skein256.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\talkcoin-mod.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\twecoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\whirlcoin.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\whirlpool.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\x14.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\x14old.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\yescrypt-multi.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\yescrypt.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\yescrypt_essential.cl", - -@"\amd\sgminer-5-1-0-optimized\kernel\zuikkis.cl", - -@"\amd\sgminer-5-1-1-optimized\darkcoin-modHawaiigw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\darkcoin-modPitcairngw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\darkcoin-modTahitigw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\darkcoin-modTongagw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\libcurl.dll", - -@"\amd\sgminer-5-1-1-optimized\libeay32.dll", - -@"\amd\sgminer-5-1-1-optimized\libgcc_s_dw2-1.dll", - -@"\amd\sgminer-5-1-1-optimized\libidn-11.dll", - -@"\amd\sgminer-5-1-1-optimized\libpdcurses.dll", - -@"\amd\sgminer-5-1-1-optimized\pthreadGC2.dll", - -@"\amd\sgminer-5-1-1-optimized\quarkcoinHawaiigw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\quarkcoinPitcairngw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\quarkcoinTahitigw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\quarkcoinTongagw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\qubitcoinHawaiigw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\qubitcoinPitcairngw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\qubitcoinTahitigw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\qubitcoinTongagw64l4ku0.bin", - -@"\amd\sgminer-5-1-1-optimized\runme.bat", - -@"\amd\sgminer-5-1-1-optimized\sgminer-fixed.conf", - -@"\amd\sgminer-5-1-1-optimized\sgminer.exe", - -@"\amd\sgminer-5-1-1-optimized\ssleay32.dll", - -@"\amd\sgminer-5-1-1-optimized\zlib1.dll", - -@"\amd\sgminer-5-1-1-optimized\kernel\aes_helper.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\alexkarnew.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\alexkarold.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\animecoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\arebyp.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\bitblock.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\bitblockold.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\blake.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\blake256.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\bmw.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\bufius.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\ckolivas.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\cubehash.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\darkcoin-mod.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\darkcoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\diamond.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\echo.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\fresh.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\fugue.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\fuguecoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\groestl.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\groestl256.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\groestlcoin-v1.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\groestlcoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\hamsi.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\hamsi_helper.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\hamsi_helper_big.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\inkcoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\jh.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\keccak.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\keccak1600.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\luffa.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\lyra2.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\lyra2re.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\marucoin-mod.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\marucoin-modold.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\marucoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\maxcoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\myriadcoin-groestl.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\neoscrypt.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\panama.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\pluck.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\psw.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\quarkcoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\qubitcoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\shabal.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\shavite.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\sifcoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\simd.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\skein.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\skein256.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\talkcoin-mod.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\twecoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\whirlcoin.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\whirlpool.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\whirlpoolx.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\x14.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\x14old.cl", - -@"\amd\sgminer-5-1-1-optimized\kernel\zuikkis.cl", - -@"\amd\sgminer-5-4-0-general\bitblockFijigw64l4ku0big4.bin", - -@"\amd\sgminer-5-4-0-general\bitblockHawaiigw64l4ku0big4.bin", - -@"\amd\sgminer-5-4-0-general\bitblockTongagw64l4ku0big4.bin", - -@"\amd\sgminer-5-4-0-general\blake256r8Fijigw128l4.bin", - -@"\amd\sgminer-5-4-0-general\blake256r8Hawaiigw128l4.bin", - -@"\amd\sgminer-5-4-0-general\blake256r8Tongagw128l4.bin", - -@"\amd\sgminer-5-4-0-general\decredFijigw64l4tc24512.bin", - -@"\amd\sgminer-5-4-0-general\decredHawaiigw64l4tc24512.bin", - -@"\amd\sgminer-5-4-0-general\decredTongagw64l4tc24512.bin", - -@"\amd\sgminer-5-4-0-general\marucoin-modFijigw64l4ku0big4.bin", - -@"\amd\sgminer-5-4-0-general\marucoin-modHawaiigw64l4ku0big4.bin", - -@"\amd\sgminer-5-4-0-general\marucoin-modTongagw64l4ku0big4.bin", - -@"\amd\sgminer-5-4-0-general\maxcoinFijigw64l4.bin", - -@"\amd\sgminer-5-4-0-general\maxcoinHawaiigw64l4.bin", - -@"\amd\sgminer-5-4-0-general\maxcoinTongagw64l4.bin", - -@"\amd\sgminer-5-4-0-general\neoscryptFijigw64l4lgtc8192.bin", - -@"\amd\sgminer-5-4-0-general\neoscryptHawaiigw64l4lgtc8192.bin", - -@"\amd\sgminer-5-4-0-general\neoscryptTongagw64l4lgtc8192.bin", - -@"\amd\sgminer-5-4-0-general\runme.bat", - -@"\amd\sgminer-5-4-0-general\sgminer-fixed.conf", - -@"\amd\sgminer-5-4-0-general\sgminer.exe", - -@"\amd\sgminer-5-4-0-general\talkcoin-modFijigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-general\talkcoin-modHawaiigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-general\talkcoin-modTongagw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-general\vanillaFijigw128l4.bin", - -@"\amd\sgminer-5-4-0-general\vanillaHawaiigw128l4.bin", - -@"\amd\sgminer-5-4-0-general\vanillaTongagw128l4.bin", - -@"\amd\sgminer-5-4-0-general\kernel\aes_helper.cl", - -@"\amd\sgminer-5-4-0-general\kernel\alexkarnew.cl", - -@"\amd\sgminer-5-4-0-general\kernel\alexkarold.cl", - -@"\amd\sgminer-5-4-0-general\kernel\animecoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\arebyp.cl", - -@"\amd\sgminer-5-4-0-general\kernel\bitblock.cl", - -@"\amd\sgminer-5-4-0-general\kernel\bitblockold.cl", - -@"\amd\sgminer-5-4-0-general\kernel\blake.cl", - -@"\amd\sgminer-5-4-0-general\kernel\blake256.cl", - -@"\amd\sgminer-5-4-0-general\kernel\blake256r14.cl", - -@"\amd\sgminer-5-4-0-general\kernel\blake256r8.cl", - -@"\amd\sgminer-5-4-0-general\kernel\bmw.cl", - -@"\amd\sgminer-5-4-0-general\kernel\bmw256.cl", - -@"\amd\sgminer-5-4-0-general\kernel\bufius.cl", - -@"\amd\sgminer-5-4-0-general\kernel\ckolivas.cl", - -@"\amd\sgminer-5-4-0-general\kernel\credits.cl", - -@"\amd\sgminer-5-4-0-general\kernel\cubehash.cl", - -@"\amd\sgminer-5-4-0-general\kernel\cubehash256.cl", - -@"\amd\sgminer-5-4-0-general\kernel\darkcoin-mod.cl", - -@"\amd\sgminer-5-4-0-general\kernel\darkcoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\decred.cl", - -@"\amd\sgminer-5-4-0-general\kernel\diamond.cl", - -@"\amd\sgminer-5-4-0-general\kernel\echo.cl", - -@"\amd\sgminer-5-4-0-general\kernel\fresh.cl", - -@"\amd\sgminer-5-4-0-general\kernel\fugue.cl", - -@"\amd\sgminer-5-4-0-general\kernel\fuguecoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\groestl.cl", - -@"\amd\sgminer-5-4-0-general\kernel\groestl256.cl", - -@"\amd\sgminer-5-4-0-general\kernel\groestlcoin-v1.cl", - -@"\amd\sgminer-5-4-0-general\kernel\groestlcoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\hamsi.cl", - -@"\amd\sgminer-5-4-0-general\kernel\hamsi_helper.cl", - -@"\amd\sgminer-5-4-0-general\kernel\hamsi_helper_big.cl", - -@"\amd\sgminer-5-4-0-general\kernel\inkcoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\jh.cl", - -@"\amd\sgminer-5-4-0-general\kernel\keccak.cl", - -@"\amd\sgminer-5-4-0-general\kernel\keccak1600.cl", - -@"\amd\sgminer-5-4-0-general\kernel\luffa.cl", - -@"\amd\sgminer-5-4-0-general\kernel\lyra2.cl", - -@"\amd\sgminer-5-4-0-general\kernel\lyra2re.cl", - -@"\amd\sgminer-5-4-0-general\kernel\lyra2rev2.cl", - -@"\amd\sgminer-5-4-0-general\kernel\lyra2v2.cl", - -@"\amd\sgminer-5-4-0-general\kernel\marucoin-mod.cl", - -@"\amd\sgminer-5-4-0-general\kernel\marucoin-modold.cl", - -@"\amd\sgminer-5-4-0-general\kernel\marucoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\maxcoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\myriadcoin-groestl.cl", - -@"\amd\sgminer-5-4-0-general\kernel\neoscrypt.cl", - -@"\amd\sgminer-5-4-0-general\kernel\panama.cl", - -@"\amd\sgminer-5-4-0-general\kernel\pluck.cl", - -@"\amd\sgminer-5-4-0-general\kernel\psw.cl", - -@"\amd\sgminer-5-4-0-general\kernel\quarkcoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\qubitcoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\shabal.cl", - -@"\amd\sgminer-5-4-0-general\kernel\shavite.cl", - -@"\amd\sgminer-5-4-0-general\kernel\sifcoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\simd.cl", - -@"\amd\sgminer-5-4-0-general\kernel\skein.cl", - -@"\amd\sgminer-5-4-0-general\kernel\skein256.cl", - -@"\amd\sgminer-5-4-0-general\kernel\talkcoin-mod.cl", - -@"\amd\sgminer-5-4-0-general\kernel\twecoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\vanilla.cl", - -@"\amd\sgminer-5-4-0-general\kernel\whirlcoin.cl", - -@"\amd\sgminer-5-4-0-general\kernel\whirlpool.cl", - -@"\amd\sgminer-5-4-0-general\kernel\whirlpoolx.cl", - -@"\amd\sgminer-5-4-0-general\kernel\x14.cl", - -@"\amd\sgminer-5-4-0-general\kernel\x14old.cl", - -@"\amd\sgminer-5-4-0-general\kernel\yescrypt-multi.cl", - -@"\amd\sgminer-5-4-0-general\kernel\yescrypt.cl", - -@"\amd\sgminer-5-4-0-general\kernel\yescrypt_essential.cl", - -@"\amd\sgminer-5-4-0-general\kernel\zuikkis.cl", - -@"\amd\sgminer-5-4-0-tweaked\darkcoin-modBonairegw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\darkcoin-modFijigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\darkcoin-modHawaiigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\darkcoin-modPitcairngw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\darkcoin-modTahitigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\darkcoin-modTongagw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\lyra2rev2Bonairegw64l4.bin", - -@"\amd\sgminer-5-4-0-tweaked\lyra2rev2Fijigw64l4.bin", - -@"\amd\sgminer-5-4-0-tweaked\lyra2rev2Hawaiigw64l4.bin", - -@"\amd\sgminer-5-4-0-tweaked\lyra2rev2Pitcairngw64l4.bin", - -@"\amd\sgminer-5-4-0-tweaked\lyra2rev2Tahitigw64l4.bin", - -@"\amd\sgminer-5-4-0-tweaked\lyra2rev2Tongagw64l4.bin", - -@"\amd\sgminer-5-4-0-tweaked\quarkcoinBonairegw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\quarkcoinFijigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\quarkcoinHawaiigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\quarkcoinPitcairngw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\quarkcoinTahitigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\quarkcoinTongagw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\qubitcoinBonairegw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\qubitcoinFijigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\qubitcoinHawaiigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\qubitcoinPitcairngw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\qubitcoinTahitigw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\qubitcoinTongagw64l4ku0.bin", - -@"\amd\sgminer-5-4-0-tweaked\sgminer.exe", - -@"\amd\sgminer-5-4-0-tweaked\kernel\aes_helper.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\alexkarnew.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\alexkarold.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\animecoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\arebyp.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\bitblock.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\bitblockold.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\blake.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\blake256.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\blake256r14.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\blake256r8.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\bmw.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\bmw256.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\bufius.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\ckolivas.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\credits.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\cubehash.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\cubehash256.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\darkcoin-mod.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\darkcoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\decred.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\diamond.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\echo.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\fresh.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\fugue.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\fuguecoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\groestl.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\groestl256.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\groestlcoin-v1.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\groestlcoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\hamsi.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\hamsi_helper.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\hamsi_helper_big.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\inkcoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\jh.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\keccak.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\keccak1600.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\luffa.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\lyra2.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\lyra2re.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\lyra2rev2.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\lyra2v2.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\marucoin-mod.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\marucoin-modold.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\marucoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\maxcoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\myriadcoin-groestl.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\neoscrypt.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\panama.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\pluck.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\psw.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\quarkcoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\qubitcoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\shabal.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\shavite.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\sifcoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\simd.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\skein.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\skein256.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\talkcoin-mod.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\twecoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\vanilla.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\whirlcoin.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\whirlpool.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\whirlpoolx.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\x14.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\x14old.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\yescrypt-multi.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\yescrypt.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\yescrypt_essential.cl", - -@"\amd\sgminer-5-4-0-tweaked\kernel\zuikkis.cl", - -}; -#endregion //CODE_GEN STUFF // listFiles.py -} -} - diff --git a/NiceHashMiner/Utils/BINS_CODEGEN_NVIDIA.cs b/NiceHashMiner/Utils/BINS_CODEGEN_NVIDIA.cs deleted file mode 100644 index b1af0ba..0000000 --- a/NiceHashMiner/Utils/BINS_CODEGEN_NVIDIA.cs +++ /dev/null @@ -1,23 +0,0 @@ - -namespace NiceHashMiner.Utils { - public partial class MinersDownloadManager : BaseLazySingleton { - #region CODE_GEN STUFF // listFiles.py -private static string[] ALL_FILES_BINS_NVIDIA = { - -@"\nvidia\ccminer_cryptonight.exe", - -@"\nvidia\ccminer_decred.exe", - -@"\nvidia\ccminer_nanashi.exe", - -@"\nvidia\ccminer_neoscrypt.exe", - -@"\nvidia\ccminer_sp.exe", - -@"\nvidia\ccminer_tpruvot.exe", - -}; -#endregion //CODE_GEN STUFF // listFiles.py -} -} - diff --git a/NiceHashMiner/Utils/BINS_CODEGEN_SHARED.cs b/NiceHashMiner/Utils/BINS_CODEGEN_SHARED.cs deleted file mode 100644 index a801d67..0000000 --- a/NiceHashMiner/Utils/BINS_CODEGEN_SHARED.cs +++ /dev/null @@ -1,57 +0,0 @@ - -namespace NiceHashMiner.Utils { - public partial class MinersDownloadManager : BaseLazySingleton { - #region CODE_GEN STUFF // listFiles.py -private static string[] ALL_FILES_BINS_SHARED = { - -@"\cpu\cpuminer_opt_AVX.exe", - -@"\cpu\cpuminer_opt_AVX2.exe", - -@"\cpu\cpuminer_opt_SSE2.exe", - -@"\dlls\cudart32_80.dll", - -@"\dlls\cudart64_80.dll", - -@"\dlls\libcrypto-1.0.0.dll", - -@"\dlls\libcurl-4.dll", - -@"\dlls\libcurl.dll", - -@"\dlls\libgcc_s_seh-1.dll", - -@"\dlls\libgmp-10.dll", - -@"\dlls\libgmpxx-4.dll", - -@"\dlls\libjansson-4.dll", - -@"\dlls\libjson-c-2.dll", - -@"\dlls\libmicrohttpd-dll.dll", - -@"\dlls\libsigc-2.0-0.dll", - -@"\dlls\libssl-1.0.0.dll", - -@"\dlls\libstdc++-6.dll", - -@"\dlls\libwinpthread-1.dll", - -@"\dlls\libz-1.dll", - -@"\dlls\msvcr120.dll", - -@"\dlls\OpenCL.dll", - -@"\dlls\zlib1.dll", - -@"\shared\ethminer.exe", - -}; -#endregion //CODE_GEN STUFF // listFiles.py -} -} - diff --git a/NiceHashMiner/BitcoinAddress.cs b/NiceHashMiner/Utils/BitcoinAddress.cs similarity index 100% rename from NiceHashMiner/BitcoinAddress.cs rename to NiceHashMiner/Utils/BitcoinAddress.cs diff --git a/NiceHashMiner/Utils/DownloadSetup.cs b/NiceHashMiner/Utils/DownloadSetup.cs new file mode 100644 index 0000000..8e737a3 --- /dev/null +++ b/NiceHashMiner/Utils/DownloadSetup.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner.Utils { + public class DownloadSetup { + public DownloadSetup(string url, string dlName, string inFolderName) { + BinsDownloadURL = url; + BinsZipLocation = dlName; + ZipedFolderName = inFolderName; + } + public readonly string BinsDownloadURL; + public readonly string BinsZipLocation; + public readonly string ZipedFolderName; + } +} diff --git a/NiceHashMiner/Helpers.cs b/NiceHashMiner/Utils/Helpers.cs similarity index 59% rename from NiceHashMiner/Helpers.cs rename to NiceHashMiner/Utils/Helpers.cs index 889ffda..7bfdcd9 100644 --- a/NiceHashMiner/Helpers.cs +++ b/NiceHashMiner/Utils/Helpers.cs @@ -43,7 +43,7 @@ public static void ConsolePrint(string grp, string text) { Console.WriteLine("[" +DateTime.Now.ToLongTimeString() + "] [" + grp + "] " + text); - if (ConfigManager.Instance.GeneralConfig.LogToFile) + if (ConfigManager.GeneralConfig.LogToFile && Logger.IsInit) Logger.log.Info("[" + grp + "] " + text); } @@ -152,13 +152,15 @@ public static string GetMotherboardID() { // TODO could have multiple cpus public static string GetCpuID() { - ManagementObjectCollection mbsList = null; - ManagementObjectSearcher mbs = new ManagementObjectSearcher("Select * From Win32_processor"); - mbsList = mbs.Get(); - string id = ""; - foreach (ManagementObject mo in mbsList) { - id = mo["ProcessorID"].ToString(); - } + string id = "N/A"; + try { + ManagementObjectCollection mbsList = null; + ManagementObjectSearcher mbs = new ManagementObjectSearcher("Select * From Win32_processor"); + mbsList = mbs.Get(); + foreach (ManagementObject mo in mbsList) { + id = mo["ProcessorID"].ToString(); + } + } catch { } return id; } @@ -174,5 +176,98 @@ public static bool WebRequestTestGoogle() { return true; } + public static bool IsConnectedToInternet() { + bool returnValue = false; + try { + int Desc; + returnValue = InternetGetConnectedState(out Desc, 0); + } catch { + returnValue = false; + } + return returnValue; + } + + // parsing helpers + public static int ParseInt(string text) { + int tmpVal = 0; + if (Int32.TryParse(text, out tmpVal)) { + return tmpVal; + } + return 0; + } + public static long ParseLong(string text) { + long tmpVal = 0; + if (Int64.TryParse(text, out tmpVal)) { + return tmpVal; + } + return 0; + } + public static double ParseDouble(string text) { + try { + string parseText = text.Replace(',', '.'); + return Double.Parse(parseText, CultureInfo.InvariantCulture); + } catch { + return 0; + } + } + + // IsWMI enabled + public static bool IsWMIEnabled() { + try { + ManagementObjectCollection moc = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_OperatingSystem").Get(); + ConsolePrint("NICEHASH", "WMI service seems to be running, ManagementObjectSearcher returned success."); + return true; + } + catch { + ConsolePrint("NICEHASH", "ManagementObjectSearcher not working need WMI service to be running"); + } + return false; + } + + public static void InstallVcRedist() { + Process CudaDevicesDetection = new Process(); + CudaDevicesDetection.StartInfo.FileName = @"bin\vc_redist.x64.exe"; + CudaDevicesDetection.StartInfo.Arguments = "/q /norestart"; + CudaDevicesDetection.StartInfo.UseShellExecute = false; + CudaDevicesDetection.StartInfo.RedirectStandardError = false; + CudaDevicesDetection.StartInfo.RedirectStandardOutput = false; + CudaDevicesDetection.StartInfo.CreateNoWindow = false; + + //const int waitTime = 45 * 1000; // 45seconds + //CudaDevicesDetection.WaitForExit(waitTime); + CudaDevicesDetection.Start(); + } + + public static void SetDefaultEnvironmentVariables() + { + Helpers.ConsolePrint("NICEHASH", "Setting environment variables"); + + Dictionary envNameValues = new Dictionary() { + { "GPU_MAX_ALLOC_PERCENT", "100" }, + { "GPU_USE_SYNC_OBJECTS", "1" }, + { "GPU_SINGLE_ALLOC_PERCENT", "100" }, + { "GPU_MAX_HEAP_SIZE", "100" }, + { "GPU_FORCE_64BIT_PTR", "1" } + }; + + foreach (var kvp in envNameValues) { + string envName = kvp.Key; + string envValue = kvp.Value; + // Check if all the variables is set + if (Environment.GetEnvironmentVariable(envName) == null) + { + try { Environment.SetEnvironmentVariable(envName, envValue); } + catch (Exception e) { Helpers.ConsolePrint("NICEHASH", e.ToString()); } + } + + // Check to make sure all the values are set correctly + if (!Environment.GetEnvironmentVariable(envName).Equals(envValue)) + { + try { Environment.SetEnvironmentVariable(envName, envValue); } + catch (Exception e) { Helpers.ConsolePrint("NICEHASH", e.ToString()); } + } + } + } + } } diff --git a/NiceHashMiner/Utils/Links.cs b/NiceHashMiner/Utils/Links.cs new file mode 100644 index 0000000..9e07a51 --- /dev/null +++ b/NiceHashMiner/Utils/Links.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner { + public static class Links { + public static string VisitURL = "https://www.nicehash.com?utm_source=NHM"; + // add version + public static string VisitURLNew = "https://github.com/nicehash/NiceHashMiner/releases/tag/"; + // add btc adress as parameter + public static string CheckStats = "https://www.nicehash.com/index.jsp?utm_source=NHM&p=miners&addr="; + // help and faq + public static string NHM_Help = "https://github.com/nicehash/NiceHashMiner"; + // faq + public static string NHM_BTC_Wallet_Faq = "https://www.nicehash.com/index.jsp?utm_source=NHM&p=faq#faqs15"; + public static string NHM_Paying_Faq = "https://www.nicehash.com/index.jsp?utm_source=NHM&p=faq#faqs6"; + // API + // btc adress as parameter + public static string NHM_API_stats = "https://www.nicehash.com/api?method=stats.provider&addr="; + public static string NHM_API_info = "https://www.nicehash.com/api?method=simplemultialgo.info"; + public static string NHM_API_version = "https://www.nicehash.com/nicehashminer?method=version"; + //public static string NHM_API_stats_provider_workers = "https://www.nicehash.com/api?method=stats.provider.workers&addr="; + + // device profits + public static string NHM_Profit_Check = "https://www.nicehash.com/?utm_source=NHM&p=calc&name="; + } +} diff --git a/NiceHashMiner/Logger.cs b/NiceHashMiner/Utils/Logger.cs similarity index 63% rename from NiceHashMiner/Logger.cs rename to NiceHashMiner/Utils/Logger.cs index e18c42e..723b992 100644 --- a/NiceHashMiner/Logger.cs +++ b/NiceHashMiner/Utils/Logger.cs @@ -13,9 +13,10 @@ namespace NiceHashMiner { public class Logger { + public static bool IsInit = false; public static readonly ILog log = LogManager.GetLogger(typeof(Logger)); - const string _logPath = @"logs\"; + public const string _logPath = @"logs\"; public static void ConfigureWithFile() { @@ -25,17 +26,22 @@ public static void ConfigureWithFile() } } catch { } - Hierarchy h = (Hierarchy)LogManager.GetRepository(); + IsInit = true; + try { + Hierarchy h = (Hierarchy)LogManager.GetRepository(); - if (ConfigManager.Instance.GeneralConfig.LogToFile) - h.Root.Level = Level.Info; - //else if (ConfigManager.Instance.GeneralConfig.LogLevel == 2) - // h.Root.Level = Level.Warn; - //else if (ConfigManager.Instance.GeneralConfig.LogLevel == 3) - // h.Root.Level = Level.Error; + if (ConfigManager.GeneralConfig.LogToFile) + h.Root.Level = Level.Info; + //else if (ConfigManager.Instance.GeneralConfig.LogLevel == 2) + // h.Root.Level = Level.Warn; + //else if (ConfigManager.Instance.GeneralConfig.LogLevel == 3) + // h.Root.Level = Level.Error; - h.Root.AddAppender(CreateFileAppender()); - h.Configured = true; + h.Root.AddAppender(CreateFileAppender()); + h.Configured = true; + } catch (Exception e) { + IsInit = false; + } } public static IAppender CreateFileAppender() @@ -46,7 +52,7 @@ public static IAppender CreateFileAppender() appender.AppendToFile = true; appender.RollingStyle = RollingFileAppender.RollingMode.Size; appender.MaxSizeRollBackups = 1; - appender.MaxFileSize = ConfigManager.Instance.GeneralConfig.LogMaxFileSize; + appender.MaxFileSize = ConfigManager.GeneralConfig.LogMaxFileSize; appender.PreserveLogFileNameExtension = true; appender.Encoding = System.Text.Encoding.Unicode; diff --git a/NiceHashMiner/MemoryHelper.cs b/NiceHashMiner/Utils/MemoryHelper.cs similarity index 91% rename from NiceHashMiner/MemoryHelper.cs rename to NiceHashMiner/Utils/MemoryHelper.cs index 1994843..34911bb 100644 --- a/NiceHashMiner/MemoryHelper.cs +++ b/NiceHashMiner/Utils/MemoryHelper.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using System.Text; -using System.Threading.Tasks; namespace NiceHashMiner { static class MemoryHelper { diff --git a/NiceHashMiner/Utils/MinersDownloadManager.cs b/NiceHashMiner/Utils/MinersDownloadManager.cs index c12a394..ad60ef1 100644 --- a/NiceHashMiner/Utils/MinersDownloadManager.cs +++ b/NiceHashMiner/Utils/MinersDownloadManager.cs @@ -3,10 +3,8 @@ using System.ComponentModel; using System.Diagnostics; using System.IO; -using System.Linq; using System.Net; using System.Text; -using System.Threading.Tasks; using System.IO.Compression; using System.Windows.Forms; using NiceHashMiner.Interfaces; @@ -15,246 +13,15 @@ using NiceHashMiner.Devices; namespace NiceHashMiner.Utils { - public partial class MinersDownloadManager : BaseLazySingleton { - - private readonly string TAG; - - private WebClient _webClient; - private Stopwatch _stopwatch; - - const string d_01 = "https://github.com/nicehash/NiceHashMiner/releases/download/1.7.0.0-dev/bin.zip"; - const string d_v1_7_0_4 = "https://github.com/nicehash/NiceHashMiner/releases/download/1.7.0.0-dev/bin_1_7_0_4.zip"; - public string BinsDownloadURL = d_v1_7_0_4; - public string BinsZipLocation = "bins.zip"; - - private class DownloadData { - public string url { get; set; } - public string zipLocation { get; set; } - public bool shouldDownload { get; set; } - } - // shared - DownloadData dl_shared = new DownloadData() { - url = "https://github.com/nicehash/NiceHashMiner/releases/download/1.7.0.0-dev/bin_cpu_shared.zip", - zipLocation = "bins_shared.zip" - }; - // nvidia - DownloadData dl_nvidia = new DownloadData() { - url = "https://github.com/nicehash/NiceHashMiner/releases/download/1.7.0.0-dev/bin_nvidia.zip", - zipLocation = "bins_nvidia.zip" - }; - // amd - DownloadData dl_amd = new DownloadData() { - url = "https://github.com/nicehash/NiceHashMiner/releases/download/1.7.0.0-dev/bin_amd.zip", - zipLocation = "bins_amd.zip" - }; - // all - DownloadData dl_all = new DownloadData() { - url = "https://github.com/nicehash/NiceHashMiner/releases/download/1.7.0.0-dev/bin_all.zip", - zipLocation = "bins_all.zip" - }; - - List _downloadsData; - - bool isDownloadSizeInit = false; - - IMinerUpdateIndicator _minerUpdateIndicator; - - protected MinersDownloadManager() { - TAG = this.GetType().Name; - } - - public void InitDownloadPaths() { - _downloadsData = new List(); - dl_shared.shouldDownload = !IsMinersBins_SHARED_Init(); - dl_nvidia.shouldDownload = !IsMinersBins_NVIDIA_Init() && ComputeDeviceQueryManager.Instance.HasNVIDIA; - dl_amd.shouldDownload = !IsMinersBins_AMD_Init() && ComputeDeviceQueryManager.Instance.HasAMD; - _downloadsData.Add(dl_shared); - _downloadsData.Add(dl_nvidia); - _downloadsData.Add(dl_amd); - } - - public void Start(IMinerUpdateIndicator minerUpdateIndicator) { - _minerUpdateIndicator = minerUpdateIndicator; - - // if something not right delete previous and download new - try { - if (File.Exists(BinsZipLocation)) { - File.Delete(BinsZipLocation); - } - if (Directory.Exists("bin")) { - Directory.Delete("bin", true); - } - } catch { } - Downlaod(); - } - - // #1 check if miners exits - public bool IsMinerBinFolder() { - return Directory.Exists("bin"); - } - - bool IsMinerBinZip() { - return File.Exists(BinsZipLocation); - } - - // #2 download the file - private void Downlaod() { - _minerUpdateIndicator.SetTitle(International.GetText("MinersDownloadManager_Title_Downloading")); - _stopwatch = new Stopwatch(); - using (_webClient = new WebClient()) { - _webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); - _webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted); - - Uri downloadURL = new Uri(BinsDownloadURL); - - _stopwatch.Start(); - try { - _webClient.DownloadFileAsync(downloadURL, BinsZipLocation); - } catch (Exception ex) { - Helpers.ConsolePrint("MinersDownloadManager", ex.Message); - } - } - } - - #region Download delegates - - private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) { - if (!isDownloadSizeInit) { - isDownloadSizeInit = true; - _minerUpdateIndicator.SetMaxProgressValue((int)(e.TotalBytesToReceive / 1024)); - } - - // Calculate download speed and output it to labelSpeed. - var speedString = string.Format("{0} kb/s", (e.BytesReceived / 1024d / _stopwatch.Elapsed.TotalSeconds).ToString("0.00")); - - // Show the percentage on our label. - var percString = e.ProgressPercentage.ToString() + "%"; - - // Update the label with how much data have been downloaded so far and the total size of the file we are currently downloading - var labelDownloaded = string.Format("{0} MB / {1} MB", - (e.BytesReceived / 1024d / 1024d).ToString("0.00"), - (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00")); - - _minerUpdateIndicator.SetProgressValueAndMsg( - (int)(e.BytesReceived / 1024d), - String.Format("{0} {1} {2}", speedString, percString,labelDownloaded)); - - } - - // The event that will trigger when the WebClient is completed - private void DownloadCompleted(object sender, AsyncCompletedEventArgs e) { - _stopwatch.Stop(); - _stopwatch = null; - - if (e.Cancelled == true) { - // TODO handle Cancelled - Helpers.ConsolePrint(TAG, "DownloadCompleted Cancelled"); - } else { - // TODO handle Success - Helpers.ConsolePrint(TAG, "DownloadCompleted Success"); - UnzipStart(); - } - } - - #endregion Download delegates - - - private void UnzipStart() { - _minerUpdateIndicator.SetTitle(International.GetText("MinersDownloadManager_Title_Settup")); - Thread BenchmarkThread = new Thread(UnzipThreadRoutine); - BenchmarkThread.Start(); - } - - private void UnzipThreadRoutine() { - if (File.Exists(BinsZipLocation)) { - Helpers.ConsolePrint(TAG, BinsZipLocation + " already downloaded"); - Helpers.ConsolePrint(TAG, "unzipping"); - using (ZipArchive archive = ZipFile.Open(BinsZipLocation, ZipArchiveMode.Read)) { - //archive.ExtractToDirectory("bin"); - _minerUpdateIndicator.SetMaxProgressValue(archive.Entries.Count); - int prog = 0; - // first create dirs - foreach (ZipArchiveEntry entry in archive.Entries) { - if (entry.Length == 0) { - Helpers.ConsolePrint("ZipArchiveEntry", entry.FullName); - Helpers.ConsolePrint("ZipArchiveEntry", entry.Length.ToString()); - Directory.CreateDirectory(entry.FullName); - _minerUpdateIndicator.SetProgressValueAndMsg(prog++, String.Format(International.GetText("MinersDownloadManager_Title_Settup_Unzipping"), ((double)(prog) / (double)(archive.Entries.Count) * 100).ToString("F2"))); - } - } - // unzip files - foreach (ZipArchiveEntry entry in archive.Entries) { - if (entry.Length > 0) { - Helpers.ConsolePrint("ZipArchiveEntry", entry.FullName); - Helpers.ConsolePrint("ZipArchiveEntry", entry.Length.ToString()); - entry.ExtractToFile(entry.FullName); - _minerUpdateIndicator.SetProgressValueAndMsg(prog++, String.Format(International.GetText("MinersDownloadManager_Title_Settup_Unzipping"), ((double)(prog) / (double)(archive.Entries.Count) * 100).ToString("F2"))); - } - } - } - } - ConfigManager.Instance.GeneralConfig.DownloadInit = true; - ConfigManager.Instance.GeneralConfig.Commit(); - _minerUpdateIndicator.FinishMsg(IsMinersBinsInit()); - // remove bins zip - try { - if (File.Exists(BinsZipLocation)) { - File.Delete(BinsZipLocation); - } - } catch { } - } - - - public bool IsMinersBins_ALL_Init() { - foreach (var filePath in ALL_FILES_BINS) { - if (!File.Exists(String.Format("bin{0}", filePath))) { - return false; - } - } - return true; - } - - // this one is mandatory download it regardles of CPU avaliability - private bool IsMinersBins_SHARED_Init() { - foreach (var filePath in ALL_FILES_BINS_SHARED) { - if (!File.Exists(String.Format("bin{0}", filePath))) { - return false; - } - } - return true; - } - - private bool IsMinersBins_NVIDIA_Init() { - foreach (var filePath in ALL_FILES_BINS_NVIDIA) { - if (!File.Exists(String.Format("bin{0}", filePath))) { - return false; - } - } - return true; - } - - private bool IsMinersBins_AMD_Init() { - foreach (var filePath in ALL_FILES_BINS_AMD) { - if (!File.Exists(String.Format("bin{0}", filePath))) { - return false; - } - } - return true; - } - - public bool IsMinersBinsInit() { - // in the future or 2.0 - //bool isOk = IsMinersBins_SHARED_Init(); - //if (isOk && ComputeDeviceQueryManager.Instance.HasNVIDIA) { - // isOk = IsMinersBins_NVIDIA_Init(); - //} - //if (isOk && ComputeDeviceQueryManager.Instance.HasAMD) { - // isOk = IsMinersBins_AMD_Init(); - //} - - //return isOk; - return IsMinersBins_ALL_Init(); - } - + public static class MinersDownloadManager { + public static DownloadSetup StandardDlSetup = new DownloadSetup( + "https://github.com/nicehash/NiceHashMiner/releases/download/1.7.0.0-dev/bin_1_7_5_8.zip", + "bins.zip", + "bin"); + + public static DownloadSetup ThirdPartyDlSetup = new DownloadSetup( + "https://github.com/nicehash/NiceHashMiner/releases/download/1.7.0.0-dev/bin_3rdparty_1_7_5_8.zip", + "bins_3rdparty.zip", + "bin_3rdparty"); } } diff --git a/NiceHashMiner/Utils/MinersDownloader.cs b/NiceHashMiner/Utils/MinersDownloader.cs new file mode 100644 index 0000000..e0d9859 --- /dev/null +++ b/NiceHashMiner/Utils/MinersDownloader.cs @@ -0,0 +1,165 @@ +using NiceHashMiner.Interfaces; +using SharpCompress.Archive; +using SharpCompress.Archive.SevenZip; +using SharpCompress.Common; +using SharpCompress.Reader; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Net; +using System.Text; +using System.Threading; + +namespace NiceHashMiner.Utils { + public class MinersDownloader { + private const string TAG = "MinersDownloader"; + + DownloadSetup _downloadSetup; + + private WebClient _webClient; + private Stopwatch _stopwatch; + Thread _UnzipThread = null; + + bool isDownloadSizeInit = false; + + IMinerUpdateIndicator _minerUpdateIndicator; + + public MinersDownloader(DownloadSetup downloadSetup) { + _downloadSetup = downloadSetup; + } + + public void Start(IMinerUpdateIndicator minerUpdateIndicator) { + _minerUpdateIndicator = minerUpdateIndicator; + + // if something not right delete previous and download new + try { + if (File.Exists(_downloadSetup.BinsZipLocation)) { + File.Delete(_downloadSetup.BinsZipLocation); + } + if (Directory.Exists(_downloadSetup.ZipedFolderName)) { + Directory.Delete(_downloadSetup.ZipedFolderName, true); + } + } catch { } + Downlaod(); + } + + // #2 download the file + private void Downlaod() { + _minerUpdateIndicator.SetTitle(International.GetText("MinersDownloadManager_Title_Downloading")); + _stopwatch = new Stopwatch(); + using (_webClient = new WebClient()) { + _webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); + _webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted); + + Uri downloadURL = new Uri(_downloadSetup.BinsDownloadURL); + + _stopwatch.Start(); + try { + _webClient.DownloadFileAsync(downloadURL, _downloadSetup.BinsZipLocation); + } catch (Exception ex) { + Helpers.ConsolePrint("MinersDownloadManager", ex.Message); + } + } + } + + #region Download delegates + + private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) { + if (!isDownloadSizeInit) { + isDownloadSizeInit = true; + _minerUpdateIndicator.SetMaxProgressValue((int)(e.TotalBytesToReceive / 1024)); + } + + // Calculate download speed and output it to labelSpeed. + var speedString = string.Format("{0} kb/s", (e.BytesReceived / 1024d / _stopwatch.Elapsed.TotalSeconds).ToString("0.00")); + + // Show the percentage on our label. + var percString = e.ProgressPercentage.ToString() + "%"; + + // Update the label with how much data have been downloaded so far and the total size of the file we are currently downloading + var labelDownloaded = string.Format("{0} MB / {1} MB", + (e.BytesReceived / 1024d / 1024d).ToString("0.00"), + (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00")); + + _minerUpdateIndicator.SetProgressValueAndMsg( + (int)(e.BytesReceived / 1024d), + String.Format("{0} {1} {2}", speedString, percString,labelDownloaded)); + + } + + // The event that will trigger when the WebClient is completed + private void DownloadCompleted(object sender, AsyncCompletedEventArgs e) { + _stopwatch.Stop(); + _stopwatch = null; + + if (e.Cancelled == true) { + // TODO handle Cancelled + Helpers.ConsolePrint(TAG, "DownloadCompleted Cancelled"); + } else { + // TODO handle Success + Helpers.ConsolePrint(TAG, "DownloadCompleted Success"); + // wait one second for binary to exist + System.Threading.Thread.Sleep(1000); + // extra check dirty + int try_count = 50; + while (!File.Exists(_downloadSetup.BinsZipLocation) && try_count > 0) { --try_count; } + + UnzipStart(); + } + } + + #endregion Download delegates + + + private void UnzipStart() { + _minerUpdateIndicator.SetTitle(International.GetText("MinersDownloadManager_Title_Settup")); + _UnzipThread = new Thread(UnzipThreadRoutine); + _UnzipThread.Start(); + } + + private void UnzipThreadRoutine() { + try { + if (File.Exists(_downloadSetup.BinsZipLocation)) { + + Helpers.ConsolePrint(TAG, _downloadSetup.BinsZipLocation + " already downloaded"); + Helpers.ConsolePrint(TAG, "unzipping"); + + // if using other formats as zip are returning 0 + FileInfo fileArchive = new FileInfo(_downloadSetup.BinsZipLocation); + var archive = ArchiveFactory.Open(_downloadSetup.BinsZipLocation); + _minerUpdateIndicator.SetMaxProgressValue(100); + long SizeCount = 0; + foreach (var entry in archive.Entries) { + if (!entry.IsDirectory) { + SizeCount += entry.CompressedSize; + Helpers.ConsolePrint(TAG, entry.Key); + entry.WriteToDirectory("", ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite); + + double prog = ((double)(SizeCount) / (double)(fileArchive.Length) * 100); + _minerUpdateIndicator.SetProgressValueAndMsg((int)prog, String.Format(International.GetText("MinersDownloadManager_Title_Settup_Unzipping"), prog.ToString("F2"))); + } + } + archive.Dispose(); + archive = null; + // after unzip stuff + _minerUpdateIndicator.FinishMsg(true); + // remove bins zip + try { + if (File.Exists(_downloadSetup.BinsZipLocation)) { + File.Delete(_downloadSetup.BinsZipLocation); + } + } catch (Exception e) { + Helpers.ConsolePrint("MinersDownloader.UnzipThreadRoutine", "Cannot delete exception: " + e.Message); + } + } else { + Helpers.ConsolePrint(TAG, String.Format("UnzipThreadRoutine {0} file not found", _downloadSetup.BinsZipLocation)); + } + } catch (Exception e) { + Helpers.ConsolePrint(TAG, "UnzipThreadRoutine has encountered an error: " + e.Message); + } + } + } +} diff --git a/NiceHashMiner/Utils/MinersExistanceChecker.cs b/NiceHashMiner/Utils/MinersExistanceChecker.cs new file mode 100644 index 0000000..a56e731 --- /dev/null +++ b/NiceHashMiner/Utils/MinersExistanceChecker.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace NiceHashMiner.Utils { + public static class MinersExistanceChecker { + public static bool IsMinersBins_ALL_Init() { + foreach (var filePath in Bins_Data.ALL_FILES_BINS) { + if (!File.Exists(String.Format("bin{0}", filePath))) { + return false; + } + } + return true; + } + + public static bool IsMiners3rdPartyBinsInit() { + foreach (var filePath in Bins_Data_3rd.ALL_FILES_BINS) { + if (!File.Exists(String.Format("bin_3rdparty{0}", filePath))) { + return false; + } + } + return true; + } + + public static bool IsMinersBinsInit() { + //return isOk; + return IsMinersBins_ALL_Init(); + } + } +} diff --git a/NiceHashMiner/Utils/ProfitabilityCalculator.cs b/NiceHashMiner/Utils/ProfitabilityCalculator.cs new file mode 100644 index 0000000..90fc5f8 --- /dev/null +++ b/NiceHashMiner/Utils/ProfitabilityCalculator.cs @@ -0,0 +1,55 @@ +using NiceHashMiner.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NiceHashMiner { + // this class mirrors the web profitability, chech what https://www.nicehash.com/?p=calc is using for each algo + static class ProfitabilityCalculator { + private const double kHs = 1000; + private const double MHs = 1000000; + private const double GHs = 1000000000; + private const double THs = 1000000000000; + + // divide factor to mirror web values + readonly static private Dictionary _div = new Dictionary() + { + { AlgorithmType.INVALID , 1 }, + { AlgorithmType.NONE , 1 }, + { AlgorithmType.Scrypt_UNUSED, MHs }, // NOT used + { AlgorithmType.SHA256_UNUSED , THs }, // NOT used + { AlgorithmType.ScryptNf_UNUSED , MHs }, // NOT used + { AlgorithmType.X11_UNUSED , MHs }, // NOT used + { AlgorithmType.X13_UNUSED , MHs }, + { AlgorithmType.Keccak_UNUSED , MHs }, + { AlgorithmType.X15_UNUSED , MHs }, + { AlgorithmType.Nist5_UNUSED , MHs }, + { AlgorithmType.NeoScrypt , MHs }, + { AlgorithmType.Lyra2RE , MHs }, + { AlgorithmType.WhirlpoolX_UNUSED , MHs }, + { AlgorithmType.Qubit_UNUSED , MHs }, + { AlgorithmType.Quark_UNUSED , MHs }, + { AlgorithmType.Axiom_UNUSED , kHs }, // NOT used + { AlgorithmType.Lyra2REv2 , MHs }, + { AlgorithmType.ScryptJaneNf16_UNUSED , kHs }, // NOT used + { AlgorithmType.Blake256r8_UNUSED , GHs }, + { AlgorithmType.Blake256r14_UNUSED , GHs }, + { AlgorithmType.Blake256r8vnl_UNUSED , GHs }, + { AlgorithmType.Hodl , kHs }, + { AlgorithmType.DaggerHashimoto , MHs }, + { AlgorithmType.Decred , GHs }, + { AlgorithmType.CryptoNight , kHs }, + { AlgorithmType.Lbry , GHs }, + { AlgorithmType.Equihash , 1 }, // Sols /s + { AlgorithmType.Pascal , GHs }, + { AlgorithmType.X11Gost , MHs }, + }; + + public static double GetFormatedSpeed(double speed, AlgorithmType type) { + if (_div.ContainsKey(type)) { + return speed / _div[type]; + } + return speed; // should never happen + } + } +} diff --git a/NiceHashMiner/app.config b/NiceHashMiner/app.config index 51278a4..2fa6e95 100644 --- a/NiceHashMiner/app.config +++ b/NiceHashMiner/app.config @@ -1,3 +1,3 @@ - + diff --git a/NiceHashMiner/langs/en.lang b/NiceHashMiner/langs/en.lang index 20d28fa..7c422c1 100644 --- a/NiceHashMiner/langs/en.lang +++ b/NiceHashMiner/langs/en.lang @@ -233,6 +233,8 @@ "Form_Settings_ToolTip_AlgoBenchmarkSpeed": "Fine tune algorithm ratios by manually setting benchmark speeds for each algorithm.", "Form_Settings_ToolTip_AlgoDisabledDevices": "Any devices that are checked will be skipped by NiceHashMiner (only for this algorithm).", "Form_Settings_ToolTip_AlgoExtraLaunchParameters": "Additional launch parameters when launching miner and this algorithm.", + "Form_Settings_Text_ContinueMiningIfNoInternetAccess" : "Idle When No Internet Access", + "Form_Settings_ToolTip_ContinueMiningIfNoInternetAccess" : "If enabled NiceHashMiner will stop mining without internet connectivity", "Form_Settings_DisplayCurrency": "Display Currency", "Form_Settings_ToolTip_DisplayCurrency": "Choose what Currency to Display mining protif.", "Form_Settings_APIBindPortStart": "API Bind port pool start", @@ -254,9 +256,10 @@ "Form_Main_MiningDevices": "Mining Devices {0}:", "Form_Main_bins_folder_files_missing": "There are missing files from last Miners Initialization. Please make sure that your anti-virus is not blocking the application. NiceHash Miner might not work properly without missing files. Click Yes to reinitialize NiceHash Miner to try to fix this issue.", "Form_Main_MINING_NOT_PROFITABLE": "CURRENTLY MINING NOT PROFITABLE.", + "Form_Main_MINING_NO_INTERNET_CONNECTION": "CURRENTLY NOT MINING. NO INTERNET CONNECTION.", "Form_Main_Group_Device_Rates": "Group/Device Rates:", "FormBenchmark_Benchmark_Step": "Benchmark step ( {0} / {1} )", - "FormBenchmark_Benchmark_Finish_Succes_MsgBox_Msg": "All benchmakrs have been successful", + "FormBenchmark_Benchmark_Finish_Succes_MsgBox_Msg": "All benchmarks have been successful", "FormBenchmark_Benchmark_Finish_Fail_MsgBox_Msg": "Not all benchmarks finished successfully. Retry to rebenchmark unbenchmarked algos or Cancel to disable unbenchmarked.", "FormBenchmark_Benchmark_Finish_MsgBox_Title": "Benchmark finished report", "FormBenchmark_Benchmark_GroupBoxStatus": "Benchmark progress status:", @@ -312,8 +315,35 @@ "Compute_Device_Query_Manager_AMD_Query": "Checking AMD OpenCL GPUs", "Compute_Device_Query_Manager_AMD_Query_Skip": "Skip check for AMD OpenCL GPUs", "Compute_Device_Query_Manager_NVIDIA_RecomendedDriver_Title": "Nvidia Recomended driver", - "Compute_Device_Query_Manager_NVIDIA_Driver_Detection": "We have detected that your system has Nvidia GPUs, but your driver is older than {0}. In order for NiceHash Miner to work correctly you should upgrade your drivers to recomended {1} or newer.", + "Compute_Device_Query_Manager_NVIDIA_Driver_Detection": "We have detected that your system has Nvidia GPUs, but your driver is older than {0}. In order for NiceHash Miner to work correctly you should upgrade your drivers to recomended {1} or newer. If you still see this warning after updating the driver please uninstall all your Nvidia drivers and make a clean install of latest official driver from http://www.nvidia.com.", "Compute_Device_Query_Manager_NVIDIA_Driver_Recomended_PART" : " (current {0})", "Compute_Device_Query_Manager_NVIDIA_Driver_Recomended": "We have detected that your Nvidia Driver is older than {0}{1}. We recommend you to update to {2} or newer.", + "NET45_Not_Intsalled_msg": "NiceHash Miner requires .NET Framework 4.5 or higher to work properly. Please install Microsoft .NET Framework 4.5", + "Form_Settings_ToolTip_DisableDefaultOptimizations": "When checked it disables all default optimization settings, making mining potentially more stable but significantly slower (especially for AMD cards).", + "Form_Settings_Text_DisableDefaultOptimizations": "Disable Default Optimizations", + "AlgorithmsListView_ContextMenu_DisableAll": "Disable All Algorithms", + "AlgorithmsListView_ContextMenu_EnableAll": "Enable All Algorithms", + "AlgorithmsListView_ContextMenu_ClearItem": "Clear Algorithm Speed", + "Form_Main_No_Device_Enabled_For_Mining": "Warning no device has been enabled for mining, please enable at least 1 device to proceed mining.", + "Form_Main_3rdParty_Title": "Disclaimer on usage of 3rd party software", + "Form_Main_3rdParty_Text": "We have integrated 3rd party mining software (developed by Claymore) that should speed up your mining and give you more stable mining experience - this could potentially result in more earnings over a shorter period of time even after developer's fee is deducted. However, since this is 3rd party software that is fully closed-source, we have no chance to inspect it in any way. NiceHash can not vouch for using that software and is refusing to take any responsibility for any damage caused - security breaches, loss of data or funds, system or hardware error, and other issues. By agreeing to this disclaimer you take full responsibility for using these Claymore closed-source miners as they are.", + "Form_Main_3rdParty_Button_Agree_Text": "I agree", + "Form_Main_3rdParty_Button_Refuse_Text": "I refuse", + "Form_Settings_General_3rdparty_Text": "Enable3rdPartyMiners", + "Form_Settings_General_3rdparty_ToolTip": "Use 3rd party closed-source mining software for higher profitability. Usage is on your own responsibility.", + "Form_Settings_General_AllowMultipleInstances_Text": "Allow Multiple Instances", + "Form_Settings_General_AllowMultipleInstances_ToolTip": "When unchecked NiceHash Miner will allow only one instance running (it will close a new started instance if there is an opened instance running).", + "Form_Main_No_Device_Enabled_Algorithms_For_Mining": "There are no enabled algorithms for selected devices. Go to Settings or Benchmarks and enable at least 1 Algorithm.", + "Form_Benchmark_checkbox_StartMiningAfterBenchmark": "Start mining after benchmark", + "Form_Main_StartMiningReturnedFalse": "NiceHash Miner cannot start mining. Make sure you have at least one enabled device that has at least one enabled and benchmarked algorithm.", + "Program_WMI_Error_Text": "NiceHash Miner cannot run needed components. It seems that your system has Windows Management Instrumentation service Disabled. In order for NiceHash Miner to work properly Windows Management Instrumentation service needs to be Enabled. This service is needed to detect RAM usage and Avaliable Video controler information. Enable Windows Management Instrumentation service manually and start NiceHash Miner.", + "Program_WMI_Error_Title": "Windows Management Instrumentation Error", + "Form_Main_Accepted_Speed_Zero": "Warning! Algorithm {0} is reporting 0 shares accepted. Please disable this algorithm in Benchmark/Settings and report this issue to support@nicehash.com!", + "NHM_TOS": "NiceHash Miners Term Of Use NiceHash operates as in intermediate service by providing hashing power from hashing power owners to hashing power buyers. NiceHash does not directly provide it's own hashing power. We will do our best to provide stable, secure and feature full service. We do not take responsibility for any kind of hashing power loss or funds loss and do not take any kind of financial, material, legal or other responsibilities for any issues that my arise from using NiceHash Miner. NiceHash service and it's products (NiceHash Miner, etc.) is still in development, therefore some bugs or other issues may arise. We will work hard to fix any issues as soon as possible, add new features and overall improve our service. NiceHash reserves the rights to seize any funds of suspicious illegal activity such as mining with botnets, money laundering, hacking attempts, etc.\r\n\r\nAs a user of NiceHash Miner, you are providing your hashing power (your are a seller) to the hashing power buyers though NiceHash's hashing power marketplace. You earn Bitcoins from selling your hashing power for every valid share your miner generates and is accepted by NiceHash service. In some cases no shares are sent to or are accepted by NiceHash service. This cases are rare and includes usage of slower hardware, software or network errors or simmilar. In these cases (no shares generated and accepted by NiceHash service) no reward in form of Bitcoins can be accounted to you. Payouts are automatic and are paid to BTC address, used in NiceHash Miner. Payment schedule can be found in FAQ on our website and is subject to change. You can always monitor your statistics on this site: https://www.nicehash.com/?p=myminer\r\n\r\nIf you have any questions relating to these Terms of Use, your rights and obligations arising from these Terms and/or your use of the NiceHash service, or any other matter, please contact us at support@nicehash.com.", + + "Form_Settings_General_SwitchProfitabilityThreshold": "SwitchProfitabilityThreshold", + "Form_Settings_ToolTip_SwitchProfitabilityThreshold": "Miner will not switch if the profitability is below SwitchProfitabilityThreshold. Value is in percentage [0 - 1]", + "VirtualMemorySize_BAD": "NiceHash Miner recommends increasing virtual memory size so that all algorithms would work fine.", + "sgminer_precise_try": "Failed - try Precise" } -} \ No newline at end of file +} diff --git a/NiceHashMiner/langs/es.lang b/NiceHashMiner/langs/es.lang index 9acaaa0..11ed258 100644 --- a/NiceHashMiner/langs/es.lang +++ b/NiceHashMiner/langs/es.lang @@ -1,236 +1,346 @@ { - "Name": "Español", - "ID": 2, - "Entries": { - "Global_Yes": "&Sí", - "Global_No": "&No", - "Global_OK": "&OK", - - "Service_Location": "Servidor", - "Warning_with_Exclamation": "¡Cuidado!", - "Error_with_Exclamation": "¡Error!", - "BitcoinAddress": "Dirección Bitcoin", - "WorkerName": "Nombre del equipo", - "Rate": "Ratio", - "Day": "Día", - "Quick": "Rápido", - "Standard": "Estandar", - "Precise": "Preciso", - "ListView_Enabled": "Habilitado", - "ListView_Group": "Grupo", - "ListView_Device": "Dispositivo", - "ListView_Algorithm": "Algoritmo", - "ListView_Speed": "Velocidad", - - "Form_Main_visit_us": "Visítanos en @ www.nicehash.com", - "Form_Main_check_stats": "¡Ver mis estadísticas!", - "Form_Main_choose_bitcoin_wallet": "Ayúdame a escoger una cartera Bitcoin", - "Form_Main_global_rate": "Ratio global", - "Form_Main_balance": "Fondos", - "Form_Main_benchmark": "&Benchmark", - "Form_Main_settings": "&Configuración", - "Form_Main_start": "&Empezar", - "Form_Main_stop": "&Parar", - "Form_Main_new_version_released": "¡Importante! La nueva versión v{0} ha\r\nsido liberada. Pincha aquí para descargarla.", - "Form_Main_DemoModeLabel": "NiceHash Miner está en modo DEMO", - "Form_Main_DemoModeTitle": "¿Abrir NiceHash Miner en modo DEMO?", - "Form_Main_DemoModeMsg": "No has introducido una dirección Bitcoin. NiceHash Miner empezará a minar en modo DEMO. En el modo DEMO, puedes probar tu ordenador para ver cuántos Bitcoin podrías ganar. ¿Quieres continuar en modo DEMO? \n\n AVISO: ¡NO GANARÁS NADA EN MODO DEMO!", - - "Form_Main_loadtext_CPU": "Buscando CPU...", - "Form_Main_loadtext_NVIDIA5X": "Buscando dispositivos NVIDIA5.x y NVIDIA6.x ...", - "Form_Main_loadtext_NVIDIA3X": "Buscando dispositivos NVIDIA3.x ...", - "Form_Main_loadtext_NVIDIA2X": "Buscando dispositivos NVIDIA2.1 ...", - "Form_Main_loadtext_AMD": "Buscando dispositivos AMD OpenCL...", - "Form_Main_loadtext_SaveConfig": "Guardando configuración...", - "Form_Main_loadtext_CheckLatestVersion": "Comprobando que está usando la última versión...", - "Form_Main_loadtext_GetNiceHashSMA": "Obteniendo la información de NiceHash SMA...", - "Form_Main_loadtext_GetBTCRate": "Obteniendo los valores de intercambio de NiceHash...", - "Form_Main_loadtext_GetNiceHashBalance": "Obteniendo fondos de NiceHash...", - "Form_Main_loadtext_SetEnvironmentVariable": "Configurando variables...", - "Form_Main_loadtext_SetWindowsErrorReporting": "Configurando el reporte de errores de Windows...", - "Form_Main_loadtext_NVIDIAP0State": "Poniendo todas las GPU de NVIDIA en estado P0...", - - "Form_Main_msgbox_CPUMining64bitMsg": "El minado CPU de NiceHash Miner solo funciona en la version de 64 bit del sistema operativo.", - "Form_Main_msgbox_CPUMining64CoresMsg": "NiceHash Miner solo soporta hasta 64 núcleos virtuales. El minado de CPU se desactivará.", - "Form_Main_msgbox_CPUMiningLessThreadMsg": "LessThreads es mayor a el número de hilos por CPU. El minado de CPU será desactivado.", - "Form_Main_msgbox_NoInternetTitle": "Comprueba la conexión a Internet", - "Form_Main_msgbox_NoInternetMsg": "NiceHash Miner requiere una conexión a Internet. Asegúrate de que estás conectado a internet antes de ejecutar NiceHash Miner. ¿Quieres continuar?", - "Form_Main_msgbox_InvalidBTCAddressMsg": "¡Dirección Bitcoin inválida!\n\nPor favor introduce una dirección Bitcoin valida o pulsa Sí para crear una", - "Form_Main_msgbox_InvalidWorkerNameMsg": "¡Nombre inválido!\n\nIntroduce un nombre válido, por favor. (Aa-Zz, 0-9, de hasta 7 carácteres).", - "Form_Main_msgbox_NullNiceHashDataMsg": "Imposible obtener los datos de rentabilidad de NiceHash. Si estás conectado a Internet, por favor inténtalo de nuevo.", - "Form_Main_msgbox_HaveNotBenchmarkedMsg": "No has realizado el benchmark para este dispositivo {0}. Sin hacer un benchmark antes, NiceHashMiner no sera capaz de elegir el algoritmo mas rentable. Para continuar minando, pulsa Sí. Si quieres hacer un benchmark antes, elige No y pincha en el botón de Benchmark.", - "Form_Main_msgbox_buttonBenchmarkWarningMsg": "Editar las siguientes opciones no es recomendado para usuarios principiantes.\r\n\r\nSi {0} se cierra por una mala configuración, puedes restaurarlo eliminando 'config.json'.\r\n\r\n¿Continuar con la edición de la configuración?", - "Form_Main_msgbox_buttonBenchmarkRestartWarningTitle": "Reiniciando {0}", - "Form_Main_msgbox_buttonBenchmarkRestartWarningMsg": "{0} se cerrará. Estas nuevas configuraciones aún estan en beta y {0} necesitan un reinicio del programa para que se apliquen.", - - - "Form_Benchmark_title": "Benchmark", - "Form_Benchmark_buttonStartBenchmark": "Empezar &benchmark", - "Form_Benchmark_buttonStopBenchmark": "&Parar benchmark", - "Form_Benchmark_buttonReset": "Resete&ar", - "Form_Benchmark_buttonClose": "&Cerrar", - "Form_Benchmark_buttonCheckProfitability": "Ren&tabilidad", - "Form_Benchmark_buttonSubmitHardware": "Publicar &hardware", - "Form_Benchmark_radioButton_QuickBenchmark": "Benchmark &rápido (podría ser impreciso)", - "Form_Benchmark_radioButton_StandardBenchmark": "Benchmark &estandar", - "Form_Benchmark_radioButton_PreciseBenchmark": "Benchmark &detallado (tardará mas)", - "Form_Benchmark_listView_WaitSeconds": "Por favor espera {0} segundos...", - "Form_Benchmark_listView_WaitMinutes": "Por favor espera {0} minutos...", - "Form_Benchmark_listView_WaitForEth": "Benchmarking (2-4 minutos)...", - - - "Form_Loading_label_LoadingText": "Cargando, por favor espera...", - - - "DriverVersionConfirmationDialog_title": "Actualización del driver de AMD recomendada", - "DriverVersionConfirmationDialog_labelWarning": "No estás usando el driver de AMD recomendado. el driver mas estable para minar es la version 15.7.1.\nRecomendamos que uses dicha versión.", - "DriverVersionConfirmationDialog_linkToDriverDownloadPage": "&Enlace de descarga del driver", - "DriverVersionConfirmationDialog_chkBoxDontShowAgain": "&No mostrar esta advertencia nunca mas", - - - "MinerFileNotFoundDialog_title": "¡Archivo no encontrado!", - "MinerFileNotFoundDialog_linkLabelError": "{0}: ¡El archivo {1} no se encuentra!\n\nPor favor asegúrate que el archivo es accesible y que tu antivirus no está bloqueando el programa.\nPor favor ve a la sección Mi antivirus está bloqueando la aplicación \"My anti-virus is blocking the application \" en la sección de Solución de problemas (Troubleshooting) ({2}).\n\nVolver a descargar NiceHash Miner podría ser necesaria.", - "MinerFileNotFoundDialog_link": "Enlace", - "MinerFileNotFoundDialog_chkBoxDisableDetection": "&Desactivar detección de este dispositivo.", - - - "SubmitResultDialog_title": "Enviar los resultados del benchmark.", - "SubmitResultDialog_labelInstruction": "Por favor selecciona un dispositivo, y una vez que finalize el benchmark, automáticamente se abrirá \r\nuna página para mostrar la calculadora de rentabilidad en la web de NiceHash.", - "SubmitResultDialog_StartBtn": "&Enviar", - "SubmitResultDialog_StopBtn": "&Parar", - "SubmitResultDialog_CloseBtn": "&Cerrar", - "SubmitResultDialog_LabelProgressPercentageCompleted": "¡Completado!", - "SubmitResultDialog_LabelProgressPercentageStopped": "¡Detenido!", - "SubmitResultDialog_LabelProgressPercentageInProgress": "{0}% : Benchmarking {1}.. por favor espera..", - - "SubmitResultDialog_NoDeviceCheckedTitle": "No hay ningún dispositivo seleccionado.", - "SubmitResultDialog_NoDeviceCheckedMsg": "Por favor selecciona al menos un dispositivo para subir los resultados.", - "SubmitResultDialog_UsePreviousBenchmarkedValueTitle": "¿Usar los resultados de un benchmark anterior?", - "SubmitResultDialog_UsePreviousBenchmarkedValueMsg": "Podrías usar los resultados de un benchmark anterior. Elige Sí para usar dichos resultados o No para volver a ejecutar en benchmark.", - - - "Form_Settings_General_DebugConsole": "Consola de depuración", - "Form_Settings_General_AutoStartMining": "Autoempezar a minar", - "Form_Settings_General_HideMiningWindows": "Ocultar ventanas de minado", - "Form_Settings_General_MinimizeToTray": "Minimizar a la bandeja", - "Form_Settings_General_DisableDetection": "Desactivar detección de {0}", - "Form_Settings_General_AutoScaleBTCValues": "Autoescalar valores de BTC", - "Form_Settings_General_StartMiningWhenIdle": "Minar si no se usa el ordenador", - "Form_Settings_General_ShowDriverVersionWarning": "Mostrar alerta de versión del driver", - "Form_Settings_General_DisableWindowsErrorReporting": "Desactivar reporte de Windows", - "Form_Settings_General_UseNewSettingsPage": "Usar nueva página de configuración", - "Form_Settings_General_NVIDIAP0State": "Estado de NVIDIA P0", - "Form_Settings_General_LogToFile": "Registrar (log) en archivo", - - "Form_Settings_General_Language": "Lenguaje", - "Form_Settings_General_MinIdleSeconds": "Tiempo de espera mínimo [s]", - "Form_Settings_General_MinerRestartDelayMS": "Retraso de reinicio [ms]", - "Form_Settings_General_MinerAPIGraceSeconds": "Tolerancia fallo API del minero [s]", - "Form_Settings_General_MinerAPIGraceSecondsAMD": "Tolerancia fallo API del minero AMD [s]", - "Form_Settings_General_MinerAPIQueryInterval": "Intervalo de llamada API [s]", - "Form_Settings_General_LogMaxFileSize": "Tamaño del registro", - - "Form_Settings_General_SwitchMinSecondsFixed": "Cambiar mínimo fijo [s]", - "Form_Settings_General_SwitchMinSecondsDynamic": "Cambiar mínimo variable [s]", - "Form_Settings_General_SwitchMinSecondsAMD": "Cambiar mínimo AMD [s]", - - "Form_Settings_General_ethminerDefaultBlockHeight": "Bloque predeterminado de ethminer", - "Form_Settings_General_ethminerAPIPortNVIDIA": "Puerto API de ethminer NVIDIA", - "Form_Settings_General_ethminerAPIPortAMD": "Puerto API de ethminer AMD", - - "Form_Settings_General_BenchmarkTimeLimitsCPU_Group": "Duración de benchmark (CPU) [s]", - "Form_Settings_General_BenchmarkTimeLimitsNVIDIA_Group": "Duración de benchmark (NVIDIA) [s]", - "Form_Settings_General_BenchmarkTimeLimitsAMD_Group": "Duración de benchmark (AMD) [s]", - - "Form_Settings_General_CPU_ForceCPUExtension": "Forzar extensión CPU", - "Form_Settings_General_CPU_LessThreads": "Hilos", - - "Form_Settings_General_APIBindPort": "Puerto de API", - "Form_Settings_General_UsePassword": "Contraseña", - "Form_Settings_General_MinimumProfit": "Ganancias mínimas ($/día)", - "Form_Settings_General_DisabledDevices": "Dispositivos sin uso", - "Form_Settings_General_ExtraLaunchParameters": "Parámetros de inicio", - "Form_Settings_General_DaggerHashimotoGenerateDevice": "Dispositivo que generará el DAG", - "Form_Settings_General_DisableAMDTempControl": "Desactivar control de temperatura de AMD", - - "Form_Settings_Algo_Skip": "Saltar", - "Form_Settings_Algo_BenchmarkSpeed": "Rapidez de benchmark", - - "Form_Settings_LessThreadWarningTitle": "Número inválido para LessThreads!", - "Form_Settings_LessThreadWarningMsg": "¡Error! Por favor introduce un número valido para LessThreads.", - "Form_Settings_MinimumProfitWarningTitle": "¡Ganancias mínimas inválidas!", - "Form_Settings_MinimumProfitWarningMsg": "¡Error! Por favor introduce una ganancia mínima que sea un número y sea mayor o igual a 0.", - "Form_Settings_APIBindPortWarningTitle": "¡Número de puerto de la API inválido!", - "Form_Settings_APIBindPortWarningMsg": "¡Error! Por favor introduce un número de puerto para la API válido.", - "Form_Settings_BenchmarkSpeedWarningTitle": "¡Velocidad de benchmark inválida!", - "Form_Settings_BenchmarkSpeedWarningMsg": "¡Error! Por favor introduce una velocidad de benchmark que sea un número y sea mayor o igual a 0.", - "Form_Settings_DaggerHashimotoGenerateDeviceWarningTitle": "¡Número de dispositivo inválido!", - "Form_Settings_DaggerHashimotoGenerateDeviceWarningMsg": "¡Error! Por favor introduce un número de dispositivo que sea mayor o igual a 0.", - "Form_Settings_labelCPUDevice": "Usar Saltar para CPUs...", - "Form_Settings_labelNoDevice": "No se ha encontrado dispositivo...", - "Form_Settings_ParseIntTitle": "Error de entrada", - "Form_Settings_ParseIntMsg": "Solo se aceptan números (0-9).", - "Form_Settings_buttonDefaultsText": "&Predeterminados", - "Form_Settings_buttonDefaultsTitle": "¿Poner configuración predeterminada?", - "Form_Settings_buttonDefaultsMsg": "¿Estás seguro de que quieres establecer la configuración predeterminada? NiceHash Miner se reiniciará automáticamente.", - "Form_Settings_buttonSaveText": "&Guardar y cerrar", - "Form_Settings_buttonSaveTitle": "¡Configuración guardada!", - "Form_Settings_buttonSaveMsg": "¡Configuración guardada!", - "Form_Settings_buttonCloseNoSaveText": "&Cerrar sin guardar", - "Form_Settings_buttonCloseNoSaveTitle": "¡Alerta!", - "Form_Settings_buttonCloseNoSaveMsg": "¡Alerta! Has elegido cerrar sin guardar. ¿Seguro que quieres continuar?", - - "Form_Settings_ToolTip_Explaination": "Explicación", - "Form_Settings_ToolTip_Language": "Cambia el lenguaje predeterminado de NiceHash Miner.", - "Form_Settings_ToolTip_checkBox_DebugConsole": "Si está marcada, abre la consola de depuración.", - "Form_Settings_ToolTip_BitcoinAddress": "Dirección Bitcoin del usuario para minar.", - "Form_Settings_ToolTip_WorkerName": "Para identificar el ordenador del usuario.", - "Form_Settings_ToolTip_ServiceLocation": "Establece la ubicación de minado. Elegir Hong Kong o Japón añadirá latencia extra.", - "Form_Settings_ToolTip_checkBox_AutoStartMining": "Si está marcada, NiceHashMiner empezará a minar al abrirse.", - "Form_Settings_ToolTip_checkBox_HideMiningWindows": "Si está marcada, las consolas de sgminer, ccminer, cpuminer y ethminer se ocultarán.", - "Form_Settings_ToolTip_checkBox_MinimizeToTray": "Si está marcada, NiceHashMiner se minimizará a la bandeja (Tray).", - "Form_Settings_ToolTip_CPU_LessThreads": "Reducir número de hilos usados por cada CPU por LessThreads.", - "Form_Settings_ToolTip_CPU_ForceCPUExtension": "Forzar minero de una extensión en particular.", - - "Form_Settings_ToolTip_SwitchMinSecondsFixed": "Parte fija de tiempo mínimo (en segundos) antes de que el minero cambie de algoritmo.\nEl tiempo total es SwitchMinSecondsFixed + SwitchMinSecondsDynamic.", - "Form_Settings_ToolTip_SwitchMinSecondsDynamic": "Parte aleatoria del tiempo mínimo (en segundos) antes de que el minero cambie de algoritmo.\nEl tiempo total es SwitchMinSecondsFixed + SwitchMinSecondsDynamic.\nEsta parte aleatoria es usada para que no todos los usuarios de NiceHash Miner tengan los mismos patrones de cambio de algoritmo.", - "Form_Settings_ToolTip_SwitchMinSecondsAMD": "Parte fija del tiempo mínimo (en segundos) antes de que el minero cambie de algoritmo (tiempo adicional para targetas gráficas AMD).\nEl tiempo total es SwitchMinSecondsFixed + SwitchMinSecondsAMD + SwitchMinSecondsDynamic.", - - "Form_Settings_ToolTip_MinerAPIQueryInterval": "Intervalo de consulta de API para ccminer, sgminer cpuminer and ethminer.", - "Form_Settings_ToolTip_MinerRestartDelayMS": "Cantidad de tiempo (en milisegundos) que NiceHashMiner esperará antes de reiniciar el minero.", - "Form_Settings_ToolTip_MinerAPIGraceSeconds": "Periodo de tiempo en el que el minero no es forzado a reiniciarse cuando falla una consulta de API.", - "Form_Settings_ToolTip_MinerAPIGraceSecondsAMD": "Periodo de tiempo en el que el minero AMD no es forzado a reiniciarse cuando falla una consulta de API.", - - "Form_Settings_ToolTip_BenchmarkTimeLimits": "Cantidad de tiempo (en segundos) para {0} ejecutar el benchmark de {1}", - - "Form_Settings_ToolTip_checkBox_DisableDetection": "Marcalo si quieres saltar la detección de GPUs de {0}", - "Form_Settings_ToolTip_checkBox_AutoScaleBTCValues": "Marcalo si quieres ver los valores de BTC autoescalar a la escala apropiada.", - "Form_Settings_ToolTip_checkBox_StartMiningWhenIdle": "Empezar a minar cuando el ordenador está inactivo y parar de minar cuando está en uso.", - - "Form_Settings_ToolTip_MinIdleSeconds": "Cuando StartMiningWhenIdle (minar el ordenador está inactivo) está activado, MinIdleSeconds dice \ncuántos segundos tiene el ordenador que estar inactivo antes de minar.", - "Form_Settings_ToolTip_checkBox_LogToFile": "Márcalo para registrar la salida de la consola en un archivo.", - "Form_Settings_ToolTip_LogMaxFileSize": "Establece el tamaño máximo para el archivo de registro (log).", - - "Form_Settings_ToolTip_checkBox_ShowDriverVersionWarning": "Si está marcado, NiceHash Miner dará un aviso si\nla versión óptima del driver está instalada.", - "Form_Settings_ToolTip_checkBox_DisableWindowsErrorReporting": "Si está marcado, si un minero crasheara,NiceHash Miner sería capaz de reabrirlo si no está bloqueado por algún mensaje de error de Windows.\nEs recomendable dejarlo activado para que se pueda minar ininterrunpidamente con unos mineros que no sean completamente estables.", - "Form_Settings_ToolTip_checkBox_UseNewSettingsPage": "Si está marcado, NiceHashMiner usará la nueva página de configuración.", - "Form_Settings_ToolTip_checkBox_NVIDIAP0State": "Si está marcado, NiceHashMiner pondrá todas las GPUs de NVIDIA al estado P0.\nEsto incrementará ligeramente el rendimiento en algunos algoritmos.\nSe necesitan privilegios de administrador.", - "Form_Settings_ToolTip_ethminerAPIPort": "Puerto de la API que será usado por ethminer para {0} GPUs.", - "Form_Settings_ToolTip_ethminerDefaultBlockHeight": "Establece la altura de bloque usado para hacer el benchmark si la llamada a la API falla.", - - "Form_Settings_ToolTip_APIBindPort": "Puerto de la API que será usado por este grupo.", - "Form_Settings_ToolTip_UsePassword": "Usa esta contraseña al iniciar el minero (el usuario es tu dirección Bitcoin y la contraseña es la que pongas aquí). Si está vacío, la contraseña 'x' será usada. ", - "Form_Settings_ToolTip_MinimumProfit": "Si se establece cualquier valor diferente a 0 (USD), NiceHash Miner parará de minar\nsi la rentabilidad cae por debajo del mínimo indicado.", - "Form_Settings_ToolTip_DisabledDevices": "NiceHash Miner ignorará los dispositivos marcados.", - "Form_Settings_ToolTip_ExtraLaunchParameters": "Parámetros de inicio adicionales.", - "Form_Settings_ToolTip_DaggerHashimotoGenerateDevice": "Elige que GPU creará el archivo DAG.\nElije la GPU más rápida posible.", - "Form_Settings_ToolTip_DisableAMDTempControl": "Márcalo si quieres desactivar el control de temperatura predeterminado\npara las GPUs de AMD (excepto para el algoritmo daggerhashimoto).", - - "Form_Settings_ToolTip_AlgoSkip": "Márcalo si quieres saltar y desactivar un algoritmo en particular.\nEl minado y el benchmark serán desactivados para este algoritmo en particular.\nEl cambio automático de algoritmo también ignorará este algoritmo.", - "Form_Settings_ToolTip_AlgoUsePassword": "Usa esta contraseña al iniciar este minero y este algoritmo. Si no se establece, UsePassword del grupo se usará.", - "Form_Settings_ToolTip_AlgoBenchmarkSpeed": "Personalización de los ratios de los algoritmos al cambiar manualmente las velocidades de los benchmark.", - "Form_Settings_ToolTip_AlgoDisabledDevices": "Todos los dispositivos marcados serán ignorados por NiceHash Miner (solo para este algoritmo).", - "Form_Settings_ToolTip_AlgoExtraLaunchParameters": "Parámetros de inicio adicionales al lanzar el minero y este algoritmo.", - "Form_Settings_DisplayCurrency": "Presentación de moneda" - } + "Name": "Español", + "ID": 2, + "Entries": { + "Global_Yes": "&Sí", + "Global_No": "&No", + "Global_OK": "&OK", + + "Service_Location": "Servidor", + "Warning_with_Exclamation": "¡Alerta!", + "Error_with_Exclamation": "¡Error!", + "BitcoinAddress": "Dirección Bitcoin", + "WorkerName": "Nombre del minero", + "Rate": "Ratio", + "Day": "Día", + "Quick": "Rápido", + "Standard": "Normal", + "Precise": "Preciso", + "ListView_Enabled": "Habilitado", + "ListView_Group": "Grupo", + "ListView_Device": "Dispositivo", + "ListView_Algorithm": "Algoritmo", + "ListView_Speed": "Velocidad", + + + "Form_Main_visit_us": "Visítanos @ www.nicehash.com", + "Form_Main_check_stats": "¡&Ver mis estadísticas!", + "Form_Main_choose_bitcoin_wallet": "&Ayúdame a escojer una cartera Bitcoin", + "Form_Main_global_rate": "Ratio global", + "Form_Main_balance": "Fondos", + "Form_Main_benchmark": "&Benchmark", + "Form_Main_settings": "&Configuración", + "Form_Main_start": "&Empezar", + "Form_Main_stop": "&Parar", + "Form_Main_new_version_released": "¡IMPORTANTE! La nueva versión v{0} ha\r\nsido liberada. Haga click aquí para descargarla.", + "Form_Main_DemoModeLabel": "¡NiceHash Miner está ejecutandose en modo DEMO!", + "Form_Main_DemoModeTitle": "¿Empezar a minar en modo DEMO?", + "Form_Main_DemoModeMsg": "No has introducido una dirección Bitcoin. NiceHash Miner empezará a minar en modo DEMO. En el modo DEMO, pueder probar al minero y ver cuanto puedes ganar usando tu ordenador. ¿Quieres continuar en modo DEMO?\n\nAVISO: ¡No ganarás nada en modo DEMO!", + + "Form_Main_loadtext_CPU": "Buscando GPU...", + "Form_Main_loadtext_NVIDIA5X": "Buscando dispositivos NVIDIA5.x y NVIDIA6.x...", + "Form_Main_loadtext_NVIDIA3X": "Buscando dispositivos NVIDIA3.x...", + "Form_Main_loadtext_NVIDIA2X": "Buscando dispositivos NVIDIA2.1...", + "Form_Main_loadtext_AMD": "Buscando dispositivos AMD OpenCL...", + "Form_Main_loadtext_SaveConfig": "Guardando configuración...", + "Form_Main_loadtext_CheckLatestVersion": "Buscando la última versión...", + "Form_Main_loadtext_GetNiceHashSMA": "Obteniedo la información NiceHash SMA...", + "Form_Main_loadtext_GetBTCRate": "Obteniendo el ratio de cámbio de Bitcoin...", + "Form_Main_loadtext_GetNiceHashBalance": "Obteniendo fondos en NiceHash...", + "Form_Main_loadtext_SetEnvironmentVariable": "Configurando variables...", + "Form_Main_loadtext_SetWindowsErrorReporting": "Configurando reportes de errores de Windows...", + "Form_Main_loadtext_NVIDIAP0State": "Poniendo tadas las GPUs de NVIDIA al estado P0...", + + "Form_Main_msgbox_CPUMining64bitMsg": "NiceHash Miner solo funciona en sistemas de 64bit (para el minado con CPU). El minado CPU será desactivado.", + "Form_Main_msgbox_CPUMining64CoresMsg": "NiceHash Miner no soporta más de 64 núcleos virtuales. El minado CPU será desactivado.", + "Form_Main_msgbox_CPUMiningLessThreadMsg": "LessThreads es mayor al número de nucleos por CPU. Opción ignorada", + "Form_Main_msgbox_NoInternetTitle": "Comprueba la conexión a Internet", + "Form_Main_msgbox_NoInternetMsg": "NiceHash Miner requiere una conexión a Internet. Asegúrese de que tiene una conexión a internet antes de continuar. ¿Le gustaría continuar?", + "Form_Main_msgbox_InvalidBTCAddressMsg": "¡Dirección Bitcoin inválida!\n\nIntruduzca una dirección válida o pulse Sí para crear una.", + "Form_Main_msgbox_InvalidWorkerNameMsg": "¡Nombre inválido!\n\nPor favor introduzca un nombre válido (Aa-Zz, 0-9, de hasta 7 carácteres).", + "Form_Main_msgbox_NullNiceHashDataMsg": "No se puede obtener los datos de rentabilidad de NiceHash. Si está conectado a Internet, inténtelo más tarde.", + "Form_Main_msgbox_HaveNotBenchmarkedMsg": "No ha hecho ningún benchmark para el dispositivo {0}. Sin hacer un benchmark primero, NiceHashMiner no podrá cambiar al algoritmo más rentable. Para continuar, pulsa Sí. Si le gustaría hacer un benchmark primero, pulse No y haga click en Benchmark.", + "Form_Main_msgbox_buttonBenchmarkWarningMsg": "Solo usuarios avanzados deberían cambiar las configuraciones avanzadas. \r\n\r\nSi {0} se cierra por una mala configuración, puede arreglarlo eliminando el archivo 'config.json' .\r\n\r\n¿Seguro que quiere editar la configuración avanzada?", + "Form_Main_msgbox_buttonBenchmarkRestartWarningTitle": "Reiniciando {0}", + "Form_Main_msgbox_buttonBenchmarkRestartWarningMsg": "{0} se cierrará. Esta nueva ventana de configuración está aún en beta y {0} necesita un reinicio para que haga efecto.", + "Form_Main_msgbox_anti_botnet_msgbox": "NiceHash Miner ha detectado un cambio en la identificación del hardware. Si no has descargado e instalado NiceHash Miner, tu ordenador puede estar en peligro. En tal caso, se recomienda instalar un software antivirus o reinstalar Windows.\r\n\r\n¿Continuar con NiceHash Miner?", + + + "Form_Benchmark_title": "Benchmark", + "Form_Benchmark_buttonStartBenchmark": "Empezar &benchmark", + "Form_Benchmark_buttonStopBenchmark": "&Detener benchmark", + "Form_Benchmark_buttonReset": "&Resetear", + "Form_Benchmark_buttonClose": "&Cerrar", + "Form_Benchmark_buttonCheckProfitability": "Comprobar re&ntabilidad", + "Form_Benchmark_buttonSubmitHardware": "&Enviar info de hardware", + "Form_Benchmark_radioButton_QuickBenchmark": "Rá&pido (puede ser impreciso)", + "Form_Benchmark_radioButton_StandardBenchmark": "Es&tandar", + "Form_Benchmark_radioButton_PreciseBenchmark": "&Preciso (tardará más)", + "Form_Benchmark_listView_WaitSeconds": "Por favor espere unos {0} segundos...", + "Form_Benchmark_listView_WaitMinutes": "Por favor espere unos {0} minutos...", + "Form_Benchmark_listView_WaitForEth": "Corriendo benchmark (2-4 minutos)...", + + + "Form_Loading_label_LoadingText": "Cargando, espere por favor...", + + + "DriverVersionConfirmationDialog_title": "Actualización del driver de AMD recomendada", + "DriverVersionConfirmationDialog_labelWarning": "No esta usando una versión óptima del driver de AMD. La versión más estable para minar es la 15.7.1 .\nLe recomendamos encarecidamente usar esta versión.", + "DriverVersionConfirmationDialog_linkToDriverDownloadPage": "&Enlace a la página de descargas del driver", + "DriverVersionConfirmationDialog_chkBoxDontShowAgain": "&No volver a mostrar esta ventana", + + + "MinerFileNotFoundDialog_title": "¡Archivo no encontrado!", + "MinerFileNotFoundDialog_linkLabelError": "{0}: No se ha encontrado el archivo {1}!\n\nPor favor asegúrate de que el archivo as accesible y que tu antivirus no está bloqueando la aplicación.\nPor favor vea la sección \"My anti-virus is blocking the application\" en la sección de corrección de errores {2}.\n\nSe podría necesitar reinstalar NiceHash Miner", + "MinerFileNotFoundDialog_link": "Enlace", + "MinerFileNotFoundDialog_chkBoxDisableDetection": "&Desactivar la detección para este dispositivo", + + + "SubmitResultDialog_title": "Enviar los resultados del benchmark", + "SubmitResultDialog_labelInstruction": "Por favor seleccione un dispositivo para que se le haga un benchmark y una vez hecho, abrirá automáticamente una \r\nnueva ventana con la calculadora de rentabilidad de NiceHash.", + "SubmitResultDialog_StartBtn": "&Empezar", + "SubmitResultDialog_StopBtn": "&Detener", + "SubmitResultDialog_CloseBtn": "&Cerrar", + "SubmitResultDialog_LabelProgressPercentageCompleted": "¡Completado!", + "SubmitResultDialog_LabelProgressPercentageStopped": "¡Detenido!", + "SubmitResultDialog_LabelProgressPercentageInProgress": "{0}% : Corriendo benchmark {1}.. Espera, por favor..", + + "SubmitResultDialog_NoDeviceCheckedTitle": "Ningún dispositivo seleccionado", + "SubmitResultDialog_NoDeviceCheckedMsg": "Elija al menos un dispositivo para enviar los resultados.", + "SubmitResultDialog_UsePreviousBenchmarkedValueTitle": "¿Usar resultados de un benchmark previo?", + "SubmitResultDialog_UsePreviousBenchmarkedValueMsg": "Podría usar los resultados de un benckmark anterior. Elige Sí para usar los resultados anteriores o No para volver a correr un benchmark.", + + + "Form_Settings_General_DebugConsole": "Consola de depuración", + "Form_Settings_General_AutoStartMining": "Empezar a minar", + "Form_Settings_General_HideMiningWindows": "Ocultar ventanas de minado", + "Form_Settings_General_MinimizeToTray": "Minimizar a la bandeja", + "Form_Settings_General_DisableDetection": "Desactivar detección de {0}", + "Form_Settings_General_AutoScaleBTCValues": "Escalar valores de BTC automáticamente", + "Form_Settings_General_StartMiningWhenIdle": "Empezar a minar si no se usa el PC", + "Form_Settings_General_ShowDriverVersionWarning": "Mostrar la ventana de alerta del driver", + "Form_Settings_General_DisableWindowsErrorReporting": "Desactivar reportes de errores de Windows", + "Form_Settings_General_UseNewSettingsPage": "Usar la nueva página de configuración", + "Form_Settings_General_NVIDIAP0State": "Estado NVIDIA P0", + "Form_Settings_General_LogToFile": "Guardar el registro de eventos", + + "Form_Settings_General_Language": "Lenguaje", + "Form_Settings_General_MinIdleSeconds": "Tiempo mínimo detenido [s]", + "Form_Settings_General_MinerRestartDelayMS": "Retraso reinicio de minero[ms]", + "Form_Settings_General_MinerAPIGraceSeconds": "Periodo de gracia de la API del minero[s]", + "Form_Settings_General_MinerAPIGraceSecondsAMD": "Periodo de gracia de la API del minero(AMD)[s]", + "Form_Settings_General_MinerAPIQueryInterval": "Intervalo API del minero [s]", + "Form_Settings_General_LogMaxFileSize": "Tamaño máximo del registro [bytes]", + + "Form_Settings_General_SwitchMinSecondsFixed": "Cambiar mínimo fijo [s]", + "Form_Settings_General_SwitchMinSecondsDynamic": "Cambiar mínimo variable [s]", + "Form_Settings_General_SwitchMinSecondsAMD": "Cambiar mínimo AMD [s]", + + "Form_Settings_General_ethminerDefaultBlockHeight": "Bloque de Ethminer", + "Form_Settings_General_ethminerAPIPortNVIDIA": "Puerto API de ethminer NVIDIA", + "Form_Settings_General_ethminerAPIPortAMD": "Puerto API de ethminer AMD", + + "Form_Settings_General_BenchmarkTimeLimitsCPU_Group": "(CPU) [s]", + "Form_Settings_General_BenchmarkTimeLimitsNVIDIA_Group": "(NVIDIA) [s]", + "Form_Settings_General_BenchmarkTimeLimitsAMD_Group": "(AMD) [s]", + + "Form_Settings_General_CPU_ForceCPUExtension": "Forzar extensión CPU", + "Form_Settings_General_CPU_LessThreads": "Núcleos", + + "Form_Settings_General_APIBindPort": "Puerto de API", + "Form_Settings_General_UsePassword": "Usar contraseña", + "Form_Settings_General_MinimumProfit": "Benefícios mínimas ($/día)", + "Form_Settings_General_DisabledDevices": "Dispositivos sin usar", + "Form_Settings_General_ExtraLaunchParameters": "Parámetros de inicio", + "Form_Settings_General_DaggerHashimotoGenerateDevice": "Dispositivo que generará el DAG", + "Form_Settings_General_DisableAMDTempControl": "Desactivar control de temperatura de AMD", + + "Form_Settings_Algo_Skip": "Saltar", + "Form_Settings_Algo_BenchmarkSpeed": "Velocidad del benchmark (H/s)", + + "Form_Settings_LessThreadWarningTitle": "¡Número inválido para LessThreads!", + "Form_Settings_LessThreadWarningMsg": "¡Error! Por favor introduce un número valido para LessThreads.", + "Form_Settings_MinimumProfitWarningTitle": "¡Ganancias mínimas inválidas!", + "Form_Settings_MinimumProfitWarningMsg": "¡Error! Por favor introduzca una ganancia mínima que sea un número y sea mayor o igual a 0.", + "Form_Settings_APIBindPortWarningTitle": "¡Número de puerto de la API inválido!", + "Form_Settings_APIBindPortWarningMsg": "¡Error! Por favor introduzca un número de puerto para la API válido.", + "Form_Settings_BenchmarkSpeedWarningTitle": "¡Velocidad de benchmark inválida!", + "Form_Settings_BenchmarkSpeedWarningMsg": "¡Error! Por favor introduce una velocidad de benchmark que sea un número y sea mayor o igual a 0.", + "Form_Settings_DaggerHashimotoGenerateDeviceWarningTitle": "¡Número de dispositivo inválido!", + "Form_Settings_DaggerHashimotoGenerateDeviceWarningMsg": "¡Error! Por favor introduzca un número de dispositivo que sea mayor o igual a 0.", + "Form_Settings_labelCPUDevice": "Usar Saltar para CPUs...", + "Form_Settings_labelNoDevice": "No se ha encontrado dispositivo...", + "Form_Settings_ParseIntTitle": "Error de entrada", + "Form_Settings_ParseIntMsg": "Solo se aceptan números (0-9).", + "Form_Settings_buttonDefaultsText": "&Predeterminados", + "Form_Settings_buttonDefaultsTitle": "¿Poner configuración predeterminada?", + "Form_Settings_buttonDefaultsMsg": "¿Está seguro de que quiere establecer la configuración predeterminada? NiceHash Miner se reiniciará automáticamente.", + "Form_Settings_buttonSaveText": "&Guardar y cerrar", + "Form_Settings_buttonSaveTitle": "¡Configuración guardada!", + "Form_Settings_buttonSaveMsg": "¡Configuración guardada!", + "Form_Settings_buttonCloseNoSaveText": "&Cerrar sin guardar", + "Form_Settings_buttonCloseNoSaveTitle": "¡Alerta!", + "Form_Settings_buttonCloseNoSaveMsg": "¡Alerta! Ha elegido cerrar sin guardar. ¿Seguro que quiere continuar?", + + + "Form_Settings_ToolTip_Explaination": "Explicación", + "Form_Settings_ToolTip_Language": "Cambia el lenguaje predeterminado de NiceHash Miner.", + "Form_Settings_ToolTip_checkBox_DebugConsole": "Si está marcada, abre la consola de depuración.", + "Form_Settings_ToolTip_BitcoinAddress": "Dirección Bitcoin del usuario para minar.", + "Form_Settings_ToolTip_WorkerName": "Para identificar el ordenador del usuario.", + "Form_Settings_ToolTip_ServiceLocation": "Establece la ubicación de minado. Elegir Hong Kong o Japón añadirá latencia extra.", + "Form_Settings_ToolTip_checkBox_AutoStartMining": "Si está marcada, NiceHashMiner empezará a minar al abrirse.", + "Form_Settings_ToolTip_checkBox_HideMiningWindows": "Si está marcada, las consolas de sgminer, ccminer, cpuminer y ethminer se ocultarán.", + "Form_Settings_ToolTip_checkBox_MinimizeToTray": "Si está marcada, NiceHashMiner se minimizará a la bandeja (Tray).", + "Form_Settings_ToolTip_CPU_LessThreads": "Reducir número de hilos usados por cada CPU por LessThreads.", + "Form_Settings_ToolTip_CPU_ForceCPUExtension": "Forzar minero de una extensión en particular.", + + "Form_Settings_ToolTip_SwitchMinSecondsFixed": "Parte fija de tiempo mínimo (en segundos) antes de que el minero cambie de algoritmo.\nEl tiempo total es SwitchMinSecondsFixed + SwitchMinSecondsDynamic.", + "Form_Settings_ToolTip_SwitchMinSecondsDynamic": "Parte aleatoria del tiempo mínimo (en segundos) antes de que el minero cambie de algoritmo.\nEl tiempo total es SwitchMinSecondsFixed + SwitchMinSecondsDynamic.\nEsta parte aleatoria es usada para que no todos los usuarios de NiceHash Miner tengan los mismos patrones de cambio de algoritmo.", + "Form_Settings_ToolTip_SwitchMinSecondsAMD": "Parte fija del tiempo mínimo (en segundos) antes de que el minero cambie de algoritmo (tiempo adicional para targetas gráficas AMD).\nEl tiempo total es SwitchMinSecondsFixed + SwitchMinSecondsAMD + SwitchMinSecondsDynamic.", + + "Form_Settings_ToolTip_MinerAPIQueryInterval": "Intervalo de consulta de API para ccminer, sgminer cpuminer and ethminer.", + "Form_Settings_ToolTip_MinerRestartDelayMS": "Cantidad de tiempo (en milisegundos) que NiceHashMiner esperará antes de reiniciar el minero.", + "Form_Settings_ToolTip_MinerAPIGraceSeconds": "Periodo de tiempo en el que el minero no es forzado a reiniciarse cuando falla una consulta de API.", + "Form_Settings_ToolTip_MinerAPIGraceSecondsAMD": "Periodo de tiempo en el que el minero AMD no es forzado a reiniciarse cuando falla una consulta de API.", + + "Form_Settings_ToolTip_BenchmarkTimeLimits": "Cantidad de tiempo (en segundos) para {0} ejecutar el benchmark de {1}", + + "Form_Settings_ToolTip_checkBox_DisableDetection": "Marcalo si quieres saltar la detección de GPUs de {0}", + "Form_Settings_ToolTip_checkBox_AutoScaleBTCValues": "Marcalo si quieres ver los valores de BTC autoescalar a la escala apropiada.", + "Form_Settings_ToolTip_checkBox_StartMiningWhenIdle": "Empezar a minar cuando el ordenador está inactivo y parar de minar cuando está en uso.", + + "Form_Settings_ToolTip_MinIdleSeconds": "Cuando StartMiningWhenIdle (minar el ordenador está inactivo) está activado, MinIdleSeconds dice \ncuántos segundos tiene el ordenador que estar inactivo antes de minar.", + "Form_Settings_ToolTip_checkBox_LogToFile": "Márcalo para registrar la salida de la consola en un archivo.", + "Form_Settings_ToolTip_LogMaxFileSize": "Establece el tamaño máximo para el archivo de registro (log).", + + "Form_Settings_ToolTip_checkBox_ShowDriverVersionWarning": "Si está marcado, NiceHash Miner dará un aviso si\nla versión óptima del driver está instalada.", + "Form_Settings_ToolTip_checkBox_DisableWindowsErrorReporting": "Si está marcado, si un minero crasheara,NiceHash Miner sería capaz de reabrirlo si no está bloqueado por algún mensaje de error de Windows.\nEs recomendable dejarlo activado para que se pueda minar ininterrunpidamente con unos mineros que no sean completamente estables.", + "Form_Settings_ToolTip_checkBox_UseNewSettingsPage": "Si está marcado, NiceHashMiner usará la nueva página de configuración.", + "Form_Settings_ToolTip_checkBox_NVIDIAP0State": "Si está marcado, NiceHashMiner pondrá todas las GPUs de NVIDIA al estado P0.\nEsto incrementará ligeramente el rendimiento en algunos algoritmos.\nSe necesitan privilegios de administrador.", + "Form_Settings_ToolTip_ethminerAPIPort": "Puerto de la API que será usado por ethminer para {0} GPUs.", + "Form_Settings_ToolTip_ethminerDefaultBlockHeight": "Establece la altura de bloque usado para hacer el benchmark si la llamada a la API falla.", + + "Form_Settings_ToolTip_APIBindPort": "Puerto de la API que será usado por este grupo.", + "Form_Settings_ToolTip_UsePassword": "Usa esta contraseña al iniciar el minero (el usuario es tu dirección Bitcoin y la contraseña es la que pongas aquí). Si está vacío, la contraseña 'x' será usada. ", + "Form_Settings_ToolTip_MinimumProfit": "Si se establece cualquier valor diferente a 0 (USD), NiceHash Miner parará de minar\nsi la rentabilidad cae por debajo del mínimo indicado.", + "Form_Settings_ToolTip_DisabledDevices": "NiceHash Miner ignorará los dispositivos marcados.", + "Form_Settings_ToolTip_ExtraLaunchParameters": "Parámetros de inicio adicionales.", + "Form_Settings_ToolTip_DaggerHashimotoGenerateDevice": "Elige que GPU creará el archivo DAG.\nElije la GPU más rápida posible.", + "Form_Settings_ToolTip_DisableAMDTempControl": "Márcalo si quieres desactivar el control de temperatura predeterminado\npara las GPUs de AMD (excepto para el algoritmo daggerhashimoto).", + + "Form_Settings_ToolTip_AlgoSkip": "Márcalo si quieres saltar y desactivar un algoritmo en particular.\nEl minado y el benchmark serán desactivados para este algoritmo en particular.\nEl cambio automático de algoritmo también ignorará este algoritmo.", + "Form_Settings_ToolTip_AlgoUsePassword": "Usa esta contraseña al iniciar este minero y este algoritmo. Si no se establece, UsePassword del grupo se usará.", + "Form_Settings_ToolTip_AlgoBenchmarkSpeed": "Personalización de los ratios de los algoritmos al cambiar manualmente las velocidades de los benchmark.", + "Form_Settings_ToolTip_AlgoDisabledDevices": "Todos los dispositivos marcados serán ignorados por NiceHash Miner (solo para este algoritmo).", + "Form_Settings_ToolTip_AlgoExtraLaunchParameters": "Parámetros de inicio adicionales al lanzar el minero y este algoritmo.", + "Form_Settings_DisplayCurrency": "Mostrar divisa", + "Form_Settings_ToolTip_DisplayCurrency": "Elija qué divisa mostrar", + "Form_Settings_APIBindPortStart": "Puertos disponibles para la API", + "Form_Settings_ToolTip_APIBindPortStart": "Seleccione el puerto mínimo por el cual la API del minero utilizará para la comunicación", + "Form_Settings_DagGeneration": "Modo de carga del DAG", + "Form_Settings_ToolTip_DagGeneration": "Establece el modo de carga del DAG para ethminers.", + "AlgorithmsListView_Enabled": "Habilitado", + "AlgorithmsListView_Algorithm": "Algoritmo", + "AlgorithmsListView_Speed": "Velocidad", + "AlgorithmsListView_Ratio": "Ratio BTC/GH/Día", + "AlgorithmsListView_Rate": "BTC/Día", + "AlgorithmSettingsControl_IntensityWaringn": "Los valores de intensidad para el algoritmo seleccionado deben estar entre {0} y {1}", + "EnabledUnbenchmarkedAlgorithmsWarning": "No hay benchamark para alguno de los dispositivos seleccionados. Haga click en Sí para realizar un benchmark y empezar a minar, o a No para saltar el benchmark y empezar a minar, o a Cancelar para detenerse.", + "AlgorithmSettingsControl_Label_Intensity": "Intensidad", + "AlgorithmSettingsControl_ToolTip_Intensity": "Establece la intensidad para el algoritmo seleccionado (valores entre 8.0 - 25.0 o 31.0 dependiendo del algoritmo). La intensidad 0 usa la valor predeterminado. OPCIÓN DE USUARIO AVANZADO.", + "AlgorithmsListView_GroupBox": "Algoritmo seleccionado: {0}", + "AlgorithmsListView_GroupBox_NONE": "NADA", + "BenchmarkOptions_Benchmark_Type": "Tipo de benchmark:", + "Form_Main_MiningDevices": "Dispositivos minando {0}:", + "Form_Main_bins_folder_files_missing": "Faltan algunos archivos desde el último inicio. Asegúrese de que su antivirus no bloquea la aplicación. NiceHash Miner podría no funcionar correctamente al faltar algunos archivos. Elige Sí para reinicializar NiceHash Miner e intentar repararlo.", + "Form_Main_MINING_NOT_PROFITABLE": "EL MINADO NO ES RENTABLE ACTUALMENTE.", + "Form_Main_MINING_NO_INTERNET_CONNECTION": "NO MINANDO. NO HAY CONEXIÓN A INTERNET", + "Form_Main_Group_Device_Rates": "Grupo/ratios del dispositivo:", + "FormBenchmark_Benchmark_Step": "Progreso del benchmark ( {0} / {1} )", + "FormBenchmark_Benchmark_Finish_Succes_MsgBox_Msg": "Todos los benchmark se han realizado correctamente", + "FormBenchmark_Benchmark_Finish_Fail_MsgBox_Msg": "Algunos benchmark han fallado. Intente reiniciar los benchamark de tales algoritmos o pulsee No para cancelar y desactivar los algoritmos que han fallado.", + "FormBenchmark_Benchmark_Finish_MsgBox_Title": "Información", + "FormBenchmark_Benchmark_GroupBoxStatus": "Progreso del benchmark:", + "FormBenchmark_Benchmark_All_Selected_Unbenchmarked": "Correr benchmark para los algoritmos seleccionados que no tengan un benchmark hecho", + "FormBenchmark_Benchmark_All_Selected_ReUnbenchmarked": "Correr benchamark a todos los algoritmos seleccionados", + "FormSettings_Tab_General": "General", + "FormSettings_Tab_Advanced": "Avanzado", + "FormSettings_Tab_Devices_Algorithms": "Dispositivos/Algoritmos", + "FormSettings_Tab_General_Group_Main": "Principal:", + "FormSettings_Tab_General_Group_Localization": "Localización:", + "FormSettings_Tab_General_Group_Logging": "Registro:", + "FormSettings_Tab_General_Group_Misc": "Misceláneo:", + "FormSettings_Tab_Advanced_Group_Miners": "Mineros:", + "FormSettings_Tab_Advanced_Group_BenchmarkTimeLimits": "Límites de tiempo de los benchamark:", + "FormSettings_Tab_Devices_Algorithms_Check_SingleProfitability": "Comprobar rentabilidad de uno", + "FormSettings_Tab_Devices_Algorithms_Check_ALLProfitability": "Comprobar rentabilidad de todos", + "MinersDownloadManager_Title_Downloading": "Descargando mineros", + "MinersDownloadManager_Title_Settup": "Configurando mineros", + "MinersDownloadManager_Title_Settup_Unzipping": "Descomprimiendo {0} %", + "DeviceListView_ContextMenu_DisableDevice": "Desactivar dispisitivo", + "DeviceListView_ContextMenu_EnableDevice": "Activar dispositivo", + "DeviceListView_ContextMenu_CopySettings": "Copiar configuración desde (Benchmarks, parámetros de algoritmos, ...)", + "DeviceListView_ContextMenu_CopySettings_Confirm_Dialog_Msg": "¿Está seguro que quiere copiar la configuración de {0} a {1}?", + "DeviceListView_ContextMenu_CopySettings_Confirm_Dialog_Title": "Comfirmar copia de configuración", + "FormSettings_AlgorithmsSettings": "Configuración de los algoritmos para {0} :", + "FormSettings_ButtonProfitSingle": "Selecciona un dispositivo primero", + "Form_Settings_General_BenchmarkTimeLimits_Title": "Límites de tiempo de benchmark", + "Form_Settings_Title": "Configuración", + "FormBenchmark_No_Devices_Selected_Msg": "No hay ningún dispositivo seleccionado, no hay nada a lo que hacer un benchamark", + "FormBenchmark_No_Devices_Selected_Title": "Ningún dispositivo seleccionado", + "FormBenchmark_Nothing_to_Benchmark_Msg": "Opciones acctuales del benchmark ya configuradas. No hay que hacer nada.", + "FormBenchmark_Nothing_to_Benchmark_Title": "No es necesario un benchamark", + "Algorithm_Waiting_Benchmark": "Esperando benchmark", + "BenchmarkSpeedStringNone": "nada", + "BenchmarkRatioRateN_A": "N/A", + "Benchmark_Timedout": "Tiempo de espera agotado", + "Benchmark_Terminated": "Finalizado", + "QueryVideoControllers_NOT_ALL_OK_Msg": "Hemos detectado que un controlador de vídeo no está funcionando correctamente. NiceHash Miner no será capaz de usar este controlador de vídeo para minar. Le recomendamos reiniciar el ordenador o reinstalar los drivers o controladores de vídeo.", + "QueryVideoControllers_NOT_ALL_OK_Msg_Append": "Nombre: {0}, Estado {1}, PNPDeviceID {2}", + "QueryVideoControllers_NOT_ALL_OK_Title": "¡Alerta! El driver de vídeo no está bien", + "Form_Main_Restart_Required_Msg": "Algunas opciones exigen que NiceHash Miner se reinicie.", + "Form_Main_Restart_Required_Title": "Aviso de reinicio", + "ComputeDevice_Short_Name": "CDev#{0}", + "ComputeDevice_Short_Name_CPU": "CPU#{0}", + "ComputeDevice_Short_Name_NVIDIA_GPU": "GPU#{0}", + "ComputeDevice_Short_Name_AMD_GPU": "GPU#{0}", + "ComputeDevice_Full_Device_Name": "{0} {1}", + "ComputeDevice_UNKNOWN_VENDOR_REPLACE": "V_ID_{0}", + "ComputeDevice_Get_With_UUID_NONE": "NADA", + "Form_Main_x64_Support_Only": "NiceHash Miner solo soporta sistemas de 64 bit. No se podrá usar NiceHash MIner con un equipo de 32 bit.", + "Compute_Device_Query_Manager_CUDA_Query": "Buscando dispositivos CUDA", + "Compute_Device_Query_Manager_OpenCL_Query": "Buscando dispositivos OpenCL", + "Compute_Device_Query_Manager_AMD_Query": "Comprobando los dispositivos AMD OpenCL", + "Compute_Device_Query_Manager_AMD_Query_Skip": "Saltar comprobación de AMD OpenCL GPUs", + "Compute_Device_Query_Manager_NVIDIA_RecomendedDriver_Title": "Driver recomendado de NVIDIA", + "Compute_Device_Query_Manager_NVIDIA_Driver_Detection": "Hemos detectado que el sistema tiene GPUs de NVIDIA, pero tu driver es más antiguo que {0}. Para que NiceHash Miner funcione correctamente debería actualizar su driver a la versión recomendada {1} o mayor.", + "Compute_Device_Query_Manager_NVIDIA_Driver_Recomended_PART": " (actual {0})", + "Compute_Device_Query_Manager_NVIDIA_Driver_Recomended": "Hemos detectado que tu driver es más antiguo que {0}{1}. Le recomendamos actualizar a la versión {2} o mayor.", + "NET45_Not_Intsalled_msg": "NiceHash Miner requiere .NET Framework 4.5 o mayor para funcionar correctamente. Por favor reinstala Microsoft .NET Framework 4.5", + "Form_Settings_ToolTip_DisableDefaultOptimizations": "Al marcarse desactiva todas las optimizaciones predeterminadas, hciendo que el minado sea notablemente mas estable pero especialmente lento (especialmente en GPUs de AMD).", + "Form_Settings_Text_DisableDefaultOptimizations": "Desactivar optimizaciones predeterminadas", + "AlgorithmsListView_ContextMenu_DisableAll": "Deshabilitar todos los algoritmos", + "AlgorithmsListView_ContextMenu_EnableAll": "Habilitar todos los algoritmos", + "AlgorithmsListView_ContextMenu_ClearItem": "Velocidad del Algoritmo Limpio", + "Form_Main_No_Device_Enabled_For_Mining": "¡Alerta! Ningún dispisitivo se ha establecido para minar, por favor habilite al menos 1 dispositivo para poder minar.", + "Form_Main_3rdParty_Title": "Aviso en el uso de software de terceros", + "Form_Main_3rdParty_Text": "Hemos integrado software de minado de terceros (desarrollado por Claymore) que debería aumentar su verlocidad y estabilidad minando - esto podría resultar en mas beneficios en un menor periodo de tiempo después de la regalía del desarrollador. Aun así, dado que no es de código abierto, no podemos inspeccionarlo de ninguna forma. NiceHash no puede garantizar el uso de ese software y se niega a asumir ninguna responsabilidad por cualquier daño causado - incumplimientos de seguridad, pérdida de datos o fondos, errores de sistema o hardware y otros problemas. Al aceptar esta exención de responsabilidad usted asume toda la responsabilidad de usar estos mineros cerrados de Claymore como son.", + "Form_Main_3rdParty_Button_Agree_Text": "Acepto", + "Form_Main_3rdParty_Button_Refuse_Text": "Rechazo", + "Form_Settings_General_3rdparty_Text": "Usar mineros de terceros", + "Form_Settings_General_3rdparty_ToolTip": "Usa mineros de terceros para una mayor rentabilidad. Úselo bajo su responsabilidad.", + "Form_Settings_General_AllowMultipleInstances_Text": "Habilitar múltiples instancias", + "Form_Settings_General_AllowMultipleInstances_ToolTip": "Cuando está desactivado, NiceHash Miner solo podrá estar ejecutandose una ver al mismo tiempo (cerraá cuaquier instancia adicional).", + "Form_Main_No_Device_Enabled_Algorithms_For_Mining": "No hay ningún algoritmo habilitado para el dispositivo seleccionado. Vaya a Configuración o a Benchmark y habilite al menos un algoritmo.", + "Form_Benchmark_checkbox_StartMiningAfterBenchmark": "Empezar a minar al acabar el Benchmark", + "Form_Main_StartMiningReturnedFalse": "NiceHash Miner no puede empezar a minar. Asegúrese de que ha habilitado al menos un dispisitivo y un algoritmo.", + "Program_WMI_Error_Text": "NiceHash Miner no puede inicializar sus componentes requeridos. Parece que su sistema tiene el servicio de Windows Management Instrumentation deshabilitado. Para que NiceHash Miner funcione correctamente, el servicio de Administración de Instrumentos de Windows debe estar habilitado. Este servicio es necesario para detectar el uso de RAM y la información del driver disponible. Habilite el servicio de Administración de Instrumentos de Windows manualmente e inicie NiceHash Miner.", + "Program_WMI_Error_Title": "Error de Administración de Instrumentos de Windows", + "Form_Main_Accepted_Speed_Zero": "¡Advertencia! El algoritmo {0} indica 0 acciones aceptadas. Deshabilite este algoritmo en Benchmark / Configuración e informe este problema a support@nicehash.com.", + "NHM_TOS": "Términos de uso de NiceHash Miner \r\n\r\nNiceHash opera como en servicio intermedio, proporcionando poder de hashing de los propietarios de poder de hashing a los compradores de poder hashing. NiceHash no proporciona directamente su propio poder de hashing. Haremos nuestro mejor para proporcionar el servicio completo estable, seguro y de la característica. No asumimos la responsabilidad de ningún tipo de pérdida de energía de hashing o pérdida de fondos y no tomamos ningún tipo de responsabilidad financiera, material, legal u otras responsabilidades por cualquier problema que surja de usar NiceHash Miner. El servicio NiceHash y sus productos (NiceHash Miner, etc.) aún están en desarrollo, por lo que pueden surgir algunos errores u otros problemas. Trabajaremos duro para solucionar cualquier problema tan pronto como sea posible, agregar nuevas características y mejorar en general nuestro servicio. NiceHash se reserva el derecho de aprovechar los fondos de actividades ilegales sospechosas como la minería con botnets, el lavado de dinero, los intentos de hacking, etc. \r\n\r\nComo usuario de NiceHash Miner, está proporcionando su poder (como hing Vendedor) a los compradores de la energía del hashing en el mercado de la energía del hashing de NiceHash. Usted gana Bitcoins al vender su poder de hashing por cada acción válida que su minero genera y es aceptada por el servicio de NiceHash. En algunos casos, no se envían acciones o no son aceptadas por el servicio NiceHash. Estos casos son raros e incluyen el uso de hardware más lento, software o errores de red o similar. En estos casos (sin acciones generadas y sin aceptadas por el servicio de NiceHash) ninguna recompensa en forma de Bitcoins pule será contabilizada. Los pagos son automáticos y se pagan a la dirección de BTC, utilizada en NiceHash Miner. El horario de pago se puede encontrar en FAQ en nuestro sitio web y está sujeto a cambios. Siempre puede supervisar sus estadísticas en este sitio: https://www.nicehash.com/?p=myminer \r\n\r\nSi tiene alguna pregunta relacionada con estos Términos de uso, sus derechos y obligaciones derivados de estos Términos y/o su uso del servicio NiceHash, o cualquier otro asunto, póngase en contacto con nosotros en support@nicehash.com", + + "Form_Settings_General_SwitchProfitabilityThreshold": "Umbral de rentabilidad", + "Form_Settings_ToolTip_SwitchProfitabilityThreshold": "El minero no se cambiará si la rentabilidad es menor a el umbral de rentabilidad establecido. El valor es un porcentaje [0 - 1]" + } } diff --git a/NiceHashMiner/langs/ru.lang b/NiceHashMiner/langs/ru.lang index 744a098..7f5de62 100644 --- a/NiceHashMiner/langs/ru.lang +++ b/NiceHashMiner/langs/ru.lang @@ -64,6 +64,8 @@ "Form_Main_msgbox_buttonBenchmarkRestartWarningTitle":"Перезагрузка {0}", "Form_Main_msgbox_buttonBenchmarkRestartWarningMsg":"Работа {0} завершится. Этот новое диалоговое окно еще тестируется и {0} нужен перезапуск для результата.", "Form_Main_msgbox_anti_botnet_msgbox": "NiceHash Miner обнаружил изменение ID оборудования. Если вы не загружали и не устанавливали NiceHash Miner, ваш компьютер может быть взломан. В этом случае, мы советуем вам установить антивирус или переустановить ваш Windows.\r\n\r\nПродолжить работу с NiceHash Miner?", + "Form_Main_No_Device_Enabled_For_Mining": "Предупреждение: устройства для майнинга не были включены. Включите, пожалуйста, хотя-бы одно устройство для запуска майнинга.", + "Form_Main_MINING_NO_INTERNET_CONNECTION": "НА ДАННЫЙ МОМЕНТ НЕ МАЙНИТ. НЕТ ПОДКЛЮЧЕНИЯ К ИНТЕРНЕТУ.", "Form_Benchmark_title":"Бенчмарк", @@ -250,6 +252,9 @@ "AlgorithmSettingsControl_ToolTip_Intensity": "Устанавливает интенсивность для выбранного алгоритма (значения между 8.0 - 25.0 или 31.0, в зависимости от алгоритма). Интенсивность 0 использует интенсивность по умолчанию. ФУНКЦИЯ ДЛЯ ПРОДВИНУТЫХ ПОЛЬЗОВАТЕЛЕЙ.", "AlgorithmsListView_GroupBox": "Выбранный алгоритм: {0}", "AlgorithmsListView_GroupBox_NONE": "NONE", + "AlgorithmsListView_ContextMenu_DisableAll": "Отключить все алгоритмы", + "AlgorithmsListView_ContextMenu_EnableAll" : "Включить все алгоритмы", + "AlgorithmsListView_ContextMenu_ClearItem": "Сбросить скорость алгоритма", "BenchmarkOptions_Benchmark_Type": "Тип бенчмарка:", "Form_Main_MiningDevices": "Устройства {0}:", "Form_Main_bins_folder_files_missing": "Отсутствуют файлы с последней инициализации майнеров. Убедитесь, что ваш антивирус не блокирует приложение. NiceHash Miner может не работать правильно без недостающих файлов. Нажмите Да для переустановки NiceHash Miner, чтобы попробовать исправить ошибку.", @@ -312,8 +317,33 @@ "Compute_Device_Query_Manager_AMD_Query": "Проверка GPU AMD OpenCL", "Compute_Device_Query_Manager_AMD_Query_Skip": "Пропустить проверку GPU AMD OpenCL", "Compute_Device_Query_Manager_NVIDIA_RecomendedDriver_Title": "Рекомендуемый драйвер Nvidia", - "Compute_Device_Query_Manager_NVIDIA_Driver_Detection": "Мы обнаружили, что в вашей системе есть Nvidia GPU, но ваш драйвер старее {0}. Для корректной работы NiceHash Miner, вам необходимо обновить драйверы до рекомендуемого {1} или новее.", + "Compute_Device_Query_Manager_NVIDIA_Driver_Detection": "Мы обнаружили, что в вашей системе есть устройства Nvidia GPU, но ваш драйвер старее, чем {0}. Для правильной работы NiceHash Miner вам следует обновить ваши драйверы до рекомендуемых {1} или новее. Если вы все еще видите это предупреждение после обновления драйверов, удалите, пожалуйста, все ваши драйверы для Nvidia и выполните чистую установку последних официальных драйверов с http://www.nvidia.com.", "Compute_Device_Query_Manager_NVIDIA_Driver_Recomended_PART" : " (текущий {0})", "Compute_Device_Query_Manager_NVIDIA_Driver_Recomended": "Мы обнаружили, что ваш драйвер старее {0}{1}. Мы рекомендуем вам обновиться до {2} или новее.", + "NET45_Not_Intsalled_msg" : "Для корректной работы NiceHash Miner требуется .NET Framework 4.5 или выше. Установите, пожалуйста, Microsoft .NET Framework 4.5", + "Form_Settings_ToolTip_DisableDefaultOptimizations": "Если отмечено, отключает все настройки оптимизации по умолчанию, делая майнинг потенциально более стабильным, но значительно медленнее (особенно для карт AMD).", + "Form_Settings_Text_DisableDefaultOptimizations": "Отключить оптимизацию", + "Form_Settings_Text_ContinueMiningIfNoInternetAccess" : "Простаивать, когда нет интернета", + "Form_Settings_ToolTip_ContinueMiningIfNoInternetAccess": "Если включено, NiceHashMiner будет останавливать майнинг, при отсутствии доступа к интернету", + "Form_Main_3rdParty_Title": "Дисклеймер от использования стороннего ПО", + "Form_Main_3rdParty_Text": "Мы интегрировали стороннее программное обеспечение (разработанное Claymore), которое должно поднять скорость вашего майнинга и дать вам более стабильный опыт майнинга — это потенциально может привести к большему заработку за короткий период времени, даже после вычета комиссии разработчика. Однако, поскольку это стороннее программное обеспечение является полностью закрытым, у нас нет никакой возможности исследовать его. NiceHash не может ручаться за использование этого ПО и отказывается брать на себя ответственность за любой причиненный ущерб - нарушение безопасности, потерю данных или средств и другие проблемы. Соглашением с этим дисклеймером, вы берете полную ответственность за использование этих майнеров с закрытым исходным кодом от Claymore.", + "Form_Main_3rdParty_Button_Agree_Text": "Я соглашаюсь", + "Form_Main_3rdParty_Button_Refuse_Text": "Я отказываюсь", + "Form_Settings_General_3rdparty_Text": "Включить сторонние майнеры", + "Form_Settings_General_3rdparty_ToolTip": "Используйте закрытое стороннее программное обеспечение для майнинга для высшей прибыльности. Использование на вашей собственной ответственности.", + "Form_Settings_General_AllowMultipleInstances_Text": "Разрешить несколько экземпляров", + "Form_Settings_General_AllowMultipleInstances_ToolTip": "Когда не отмечено, NiceHash Miner разрешит работу только одного экземпляра (он закроет новый запущенный экземпляр, если один экземпляр уже работает).", + "Form_Main_No_Device_Enabled_Algorithms_For_Mining": "Для выбранных устройств нет включенных алгоритмов. Перейдите в Настройки или Бенчмарк и включите хотя-бы 1 алгоритм.", + "Form_Benchmark_checkbox_StartMiningAfterBenchmark": "Запустить майнинг после бенчмарка", + "Form_Main_StartMiningReturnedFalse": "NiceHashMiner не может начать майнинг. Убедитесь, что хотя-бы одно устройство включено с хотя-бы одним включенным и прошедшим бенчмарк алгоритмом", + "Program_WMI_Error_Text": "NiceHash Miner не может запустить необходимые компоненты. Похоже, что в вашей системе отключен сервис Инструментарий управления Windows. Для корректной работы NiceHash Miner, сервис Инструментарий управления Windows должен быть включен. Этот сервис нужен для определения использования RAM и доступной информации видеоконтроллера. Включите сервис Инструментарий управления Windows вручную и запустите NiceHash Miner.", + "Program_WMI_Error_Title": "Ошибка Инструментария управления Windows", + "Form_Main_Accepted_Speed_Zero": "Предупреждение! Алгоритм {0} сообщает 0 принятых шар. Отключите, пожалуйста, этот алгоритм в Бенчмарке/Настройках и сообщите о данной проблеме на support-ru@nicehash.com!", + + "Form_Settings_General_SwitchProfitabilityThreshold": "Порог переключения прибыльности", + "Form_Settings_ToolTip_SwitchProfitabilityThreshold": "Майнер не будет переключаться, если разница между прибыльностью алгоритмов ниже Порога переключения прибыльности. Значение в процентах [0 — 1]", + "VirtualMemorySize_BAD": "NiceHash Miner рекомендует увеличить размер виртуальной памяти для нормальной работы всех алгоритмов.", + "sgminer_precise_try": "Неудача — попробуйте Точный" + } } \ No newline at end of file diff --git a/README.md b/README.md index 3e1f290..3ef1b25 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ NiceHash Miner is essentially the only tool a miner needs. No need to go through All you have to do is download, extract and run the miner (no installation needed), choose the server location that is the **closest to your location**, run built-in benchmark and enter your Bitcoin wallet address where you want to get your coins sent at - and you are ready to start mining and maximizing your profit. -**Note**: .NET Framework 4.5 or higher and Microsoft Visual C++ Redistributable 2013 is required. No additional installations should be needed if you use Windows 7 or later. However, if you encounter any issues when starting application (application would fail to start or errors/warnings about missing DLL files are displayed) you should download and install Microsoft **.NET Framework 4.5** and Microsoft **Visual C++ Redistributable 2013 (vcredist_x64.exe)** (after installation a reboot might be required). +**Note**: .NET Framework 2.0 or higher and Microsoft Visual C++ Redistributable 2013 is required. No additional installations should be needed if you use Windows 7 or later. However, if you encounter any issues when starting application (application would fail to start or errors/warnings about missing DLL files are displayed) you should download and install Microsoft **.NET Framework 2.0** and Microsoft **Visual C++ Redistributable 2013 (vcredist_x64.exe)** (after installation a reboot might be required). Detailed instructions: - Download binaries from here: https://github.com/nicehash/NiceHashMiner/releases diff --git a/codegen/genBins.py b/codegen/genBins.py index 02dea6b..9cc2201 100644 --- a/codegen/genBins.py +++ b/codegen/genBins.py @@ -3,24 +3,22 @@ c_sharp_Class_START = """ namespace NiceHashMiner.Utils { - public partial class MinersDownloadManager : BaseLazySingleton { + public static class Bins_Data { #region CODE_GEN STUFF // listFiles.py """ -containsFilesC_SHARP_Code = "private static string[] ALL_FILES_BINS = {" +containsFilesC_SHARP_Code = "public static string[] ALL_FILES_BINS = {" root = "." outFile = "BINS_CODEGEN.cs" -outFile_shared = "BINS_CODEGEN_SHARED.cs" -outFile_amd = "BINS_CODEGEN_AMD.cs" -outFile_nvidia = "BINS_CODEGEN_NVIDIA.cs" inFile = "genBins.py" for path, subdirs, files in os.walk(root): for name in files: #print os.path.join(path, name) - if (".py" not in name) and (".cs" not in name): + #if (".py" not in name) and (".cs" not in name): + if (".exe" in name) or (".dll" in name) or (".bin" in name): file = '@"%s",' % os.path.join(path, name)[1:] containsFilesC_SHARP_Code = "%s%s%s" % (containsFilesC_SHARP_Code, os.linesep, file) diff --git a/nvidiasetp0state/nvidiasetp0state.csproj b/nvidiasetp0state/nvidiasetp0state.csproj index 82ed879..1945ac0 100644 --- a/nvidiasetp0state/nvidiasetp0state.csproj +++ b/nvidiasetp0state/nvidiasetp0state.csproj @@ -22,6 +22,7 @@ DEBUG;TRACE prompt 4 + false AnyCPU @@ -31,6 +32,7 @@ TRACE prompt 4 + false app.manifest