#include "console/Detect.hpp" #include "db/Db.hpp" #include "db/Startup_Strings.hpp" #include "gx/CGxFormat.hpp" #include "gx/Device.hpp" #include "os/Debug.hpp" #include "os/Gui.hpp" #include #include #if defined(WHOA_SYSTEM_MAC) #include #include #endif WowClientDB g_videoHardwareDB; CGxFormat s_formats[7] = { { 0, { 640, 480 }, CGxFormat::Fmt_Rgb565, CGxFormat::Fmt_Ds160, 60, 1, true, false, true, true, false }, { 0, { 800, 600 }, CGxFormat::Fmt_Rgb565, CGxFormat::Fmt_Ds160, 60, 1, true, false, true, true, false }, { 0, { 640, 480 }, CGxFormat::Fmt_ArgbX888, CGxFormat::Fmt_Ds24X, 60, 1, true, false, true, true, false }, { 0, { 800, 600 }, CGxFormat::Fmt_ArgbX888, CGxFormat::Fmt_Ds24X, 60, 1, true, false, true, true, false }, { 0, { 1024, 768 }, CGxFormat::Fmt_ArgbX888, CGxFormat::Fmt_Ds24X, 60, 1, true, false, true, true, false }, { 0, { 1280, 1024 }, CGxFormat::Fmt_ArgbX888, CGxFormat::Fmt_Ds24X, 60, 1, true, false, true, true, false }, { 0, { 1600, 1200 }, CGxFormat::Fmt_ArgbX888, CGxFormat::Fmt_Ds24X, 60, 1, true, false, true, true, false } }; CpuHardware s_cpuHwSettings[2] = { { 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 1 } }; SoundHardware s_soundHwSettings[1] = { { 1, false } }; uint32_t s_detailDoodadDensity[4] = { 8, 12, 16, 24 }; bool s_animatingDoodads[2][2] = { { false, false }, { false, true } }; uint32_t s_waterLOD[2][2] = { { 0, 0 }, { 0, 1 } }; float s_particleDensity[4][2] = { { 0.3f, 0.4f }, { 0.5f, 0.6f }, { 0.9f, 1.0f }, { 1.0f, 1.0f } }; float s_unitDrawDist[4][2] = { { 35.0f, 50.0f }, { 50.0f, 75.0f }, { 75.0f, 300.0f }, { 300.0f, 300.0f } }; float s_smallCull[4][2] = { { 0.08f, 0.08f }, { 0.07f, 0.07f }, { 0.07f, 0.07f }, { 0.04f, 0.04f } }; float s_distCull[4][2] = { { 350.0f, 350.0f }, { 400.0f, 400.0f }, { 450.0f, 450.0f }, { 500.0f, 500.0f }, }; float s_farClip[5][2] = { { 200.0f, 277.0f }, { 300.0f, 350.0f }, { 350.0f, 400.0f }, { 450.0f, 550.0f }, { 450.0f, 777.0f } }; void AddResolution(TSGrowableArray& resolutions, const C2iVector& resolution) { resolutions.Add(1, &resolution); } void ConsoleDetectGetResolutions(TSGrowableArray& resolutions, int32_t widescreen) { if (widescreen) { TSGrowableArray modes; GxAdapterMonitorModes(modes); C2iVector prev = { 0, 0 }; for (uint32_t i = 0; i < modes.Count(); i++) { auto& mode = modes[i]; if ((static_cast(mode.size.x) / static_cast(mode.size.y)) > 1.248f && mode.size.x >= 640 && mode.size.y >= 480 && mode.size.x != prev.x && mode.size.y != prev.y) { AddResolution(resolutions, mode.size); prev = mode.size; } } } if (!resolutions.Count() || !widescreen) { // Add generic 4:3 fallback resolutions AddResolution(resolutions, { 640, 480 }); AddResolution(resolutions, { 800, 600 }); AddResolution(resolutions, { 1024, 768 }); AddResolution(resolutions, { 1152, 864 }); AddResolution(resolutions, { 1280, 960 }); AddResolution(resolutions, { 1280, 1024 }); AddResolution(resolutions, { 1600, 1200 }); } } void ConsoleDetectSaveHardware(Hardware& hardware, bool& hwChanged) { uint32_t cpuIdx; uint32_t memIdx; uint32_t videoID; uint32_t soundIdx; if (!SRegLoadValue("World of Warcraft\\Client", "HWCpuIdx", 0, &cpuIdx)) { cpuIdx = hardware.cpuIdx; } if (!SRegLoadValue("World of Warcraft\\Client", "HWMemIdx", 0, &memIdx)) { memIdx = hardware.memIdx; } if (!SRegLoadValue("World of Warcraft\\Client", "HWVideoID", 0, &videoID)) { videoID = hardware.videoID; } if (!SRegLoadValue("World of Warcraft\\Client", "HWSoundIdx", 0, &soundIdx)) { soundIdx = hardware.soundIdx; } bool v2 = (((videoID == 1 || videoID == 168) || (videoID == 169)) || videoID == 170); if (hardware.cpuIdx == cpuIdx && hardware.memIdx == memIdx && (v2 || hardware.videoID == videoID) && hardware.soundIdx == soundIdx) { hwChanged = false; } else { #if defined(WHOA_SYSTEM_WIN) || defined(WHOA_SYSTEM_LINUX) auto titleRecord = g_Startup_StringsDB.GetRecord(MSG_TITLE_WOW); auto title = titleRecord ? titleRecord->m_message : "World of Warcraft"; auto hwChangedMessageRecord = g_Startup_StringsDB.GetRecord(MSG_HW_CHANGED); auto message = hwChangedMessageRecord ? hwChangedMessageRecord->m_message : "Hardware changed. Reload default settings?"; hwChanged = !OsGuiMessageBox(OsGuiGetWindow(2), 2, message, title); #endif #if defined(WHOA_SYSTEM_MAC) hwChanged = true; #endif } SRegSaveValue("World of Warcraft\\Client", "HWCpuIdx", 0, hardware.cpuIdx); SRegSaveValue("World of Warcraft\\Client", "HWMemIdx", 0, hardware.memIdx); SRegSaveValue("World of Warcraft\\Client", "HWVideoID", 0, hardware.videoID); SRegSaveValue("World of Warcraft\\Client", "HWSoundIdx", 0, hardware.soundIdx); } [[noreturn]] void PrintStartupError(int32_t messageID, const char* fallbackMessage) { auto titleRecord = g_Startup_StringsDB.GetRecord(MSG_TITLE_WOW); auto title = titleRecord ? titleRecord->m_message : "World of Warcraft"; auto messageRecord = g_Startup_StringsDB.GetRecord(messageID); auto message = messageRecord ? messageRecord->m_message : fallbackMessage; OsGuiMessageBox(OsGuiGetWindow(2), 0, message, title); exit(0); } void SetVideoIdx(Hardware& hardware) { int32_t index = 1; while (index < g_videoHardwareDB.m_numRecords) { auto videoHw = g_videoHardwareDB.GetRecordByIndex(index); if (hardware.videoDevice.vendorID == videoHw->m_vendorID && hardware.videoDevice.deviceID == videoHw->m_deviceID) { hardware.videoID = videoHw->m_ID; } index++; } } #if defined(WHOA_SYSTEM_WIN) || defined(WHOA_SYSTEM_LINUX) void ConsoleDetectDetectHardware(Hardware& hardware, bool& hwChanged) { // anti-feature // if (OsIsRemoteSession()) { // PrintStartupError(12, "Running World of Warcraft through a Remote Desktop connection is not supported. Exiting program."); // } // g_videoHardwareDB.Load(__FILE__, __LINE__); hardware.cpuIdx = (static_cast(OsGetProcessorTicksPerSecond()) * 0.000001f) > 1500.0f; hardware.memIdx = 0; hardware.videoID = 0; if (GxAdapterID(hardware.videoDevice.vendorID, hardware.videoDevice.deviceID, hardware.videoDevice.driverVersionHi, hardware.videoDevice.driverVersionLo)) { SetVideoIdx(hardware); } if (!hardware.videoID) { hardware.videoDevice.vendorID = 0xFFFF; if (GxAdapterInfer(hardware.videoDevice.deviceID)) { SetVideoIdx(hardware); } if (!hardware.videoID) { PrintStartupError(MSG_GX_NO_DEVICE, "Failed to find a suitable display device. Exiting program."); } } hardware.cpuHw = &s_cpuHwSettings[hardware.cpuIdx]; hardware.videoHw = g_videoHardwareDB.GetRecord(hardware.videoID); hardware.soundHw = &s_soundHwSettings[hardware.soundIdx]; ConsoleDetectSaveHardware(hardware, hwChanged); char str[1024]; GxLog("ConsoleDetectDetectHardware():"); SStrPrintf(str, 1024, "\tcpuIdx: %d", hardware.cpuIdx); GxLog(str); SStrPrintf(str, 1024, "\tvideoID: %d", hardware.videoID); GxLog(str); SStrPrintf(str, 1024, "\tsoundIdx: %d", hardware.soundIdx); GxLog(str); SStrPrintf(str, 1024, "\tmemIdx: %d", hardware.memIdx); GxLog(str); } #endif #if defined(WHOA_SYSTEM_MAC) uint32_t FindVRAMSize() { CGDirectDisplayID activeDisplays[32]; uint32_t displayCount; if (CGGetActiveDisplayList(32, activeDisplays, &displayCount)) { return 0; } CGLRendererInfoObj rend; GLint nrend; GLint accelerated; GLint vram_size; auto display_mask = CGDisplayIDToOpenGLDisplayMask(activeDisplays[0]); if (!CGLQueryRendererInfo(display_mask, &rend, &nrend)) { CGLDescribeRenderer(rend, 0, kCGLRPRendererCount, &nrend); for (int32_t i = 0; i < nrend; i++) { CGLDescribeRenderer(rend, i, kCGLRPAccelerated, &accelerated); if (accelerated) { CGLDescribeRenderer(rend, i, kCGLRPVideoMemory, &vram_size); CGLDestroyRendererInfo(rend); return static_cast(vram_size); } } } CGLDestroyRendererInfo(rend); return 0; } void ConsoleDetectDetectHardware(Hardware& hardware, bool& hwChanged) { g_videoHardwareDB.Load(__FILE__, __LINE__); if (GxAdapterID(hardware.videoDevice.vendorID, hardware.videoDevice.deviceID, hardware.videoDevice.driverVersionHi, hardware.videoDevice.driverVersionLo)) { SetVideoIdx(hardware); } if (!hardware.videoIdx) { hardware.videoDevice.vendorID = 0xFFFF; if (GxAdapterInfer(hardware.videoDevice.deviceID)) { SetVideoIdx(hardware); } } uint32_t hw_cputype = 0; uint32_t hw_cpusubtype = 0; uint32_t hw_ncpu = 0; uint64_t hw_cpufrequency_max = 0; uint64_t hw_busfrequency_max = 0; uint64_t hw_l2cachesize = 0; uint64_t hw_l3cachesize = 0; size_t size32 = sizeof(uint32_t); size_t size64 = sizeof(uint64_t); uint32_t hw_cputype; auto hw_cputype_error = sysctlbyname("hw.cputype", &hw_cputype, &size32, nullptr, 0); if (hw_cputype_error) { OsOutputDebugString("[Mac sys detect] ! error %d reading hw.cputype\n", hw_cputype_error); } auto hw_cpusubtype_error = sysctlbyname("hw.cpusubtype", &hw_cpusubtype, &size32, nullptr, 0); if (hw_cpusubtype_error) { OsOutputDebugString("[Mac sys detect] ! error %d reading hw.cpusubtype\n", hw_cpusubtype_error); } auto hw_ncpu_error = sysctlbyname("hw.ncpu", &hw_ncpu, &size32, nullptr, 0); if (hw_ncpu_error) { OsOutputDebugString("[Mac sys detect] ! error %d reading hw.ncpu\n", hw_ncpu_error); } auto hw_cpufrequency_max_error = sysctlbyname("hw.cpufrequency_max", &hw_cpufrequency_max, &size64, nullptr, 0); if (hw_cpufrequency_max_error) { OsOutputDebugString("[Mac sys detect] ! error %d reading hw.cpufrequency_max\n", hw_cpufrequency_max_error); } auto hw_busfrequency_max_error = sysctlbyname("hw.busfrequency_max", hw_busfrequency_max, &size64, nullptr, 0); if (hw_busfrequency_max_error) { OsOutputDebugString("[Mac sys detect] ! error %d reading hw.busfrequency_max\n", iVar6); } auto hw_l2cachesize_error = sysctlbyname("hw.l2cachesize", &hw_l2cachesize, &size64, nullptr, 0); if (hw_l2cachesize_error) { hw_l2cachesize_error = 0; OsOutputDebugString("[Mac sys detect] ! error %d reading hw.l2cachesize\n", hw_l2cachesize_error); } auto hw_l3cachesize_error = sysctlbyname("hw.l3cachesize", &hw_l3cachesize, &size64, nullptr, 0); if (hw_l3cachesize_error) { hw_l3cachesize_error = 0; OsOutputDebugString("[Mac sys detect] ! error %d reading hw.l3cachesize\n", iVar8); } auto hw_memsize_error = sysctlbyname("hw.memsize", &hw_memsize, &size64, nullptr, 0); if (hw_memsize_error) { OsOutputDebugString("[Mac sys detect] ! error %d reading hw.memsize\n", hw_memsize_error); } auto vram_size = FindVRAMSize(); bool ddr_ram; if (hw_busfrequency_max > 110000000 && (hw_busfrequency_max > 140000000 || h2_l3cachesize > 0xFFFFF && hw_l2cachesize > 0x7FFFF)) { OsOutputDebugString("[Mac sys detect] - DDR RAM\n"); ddr_ram = true; } else { OsOutputDebugString("[Mac sys detect] - non DDR RAM\n"); ddr_ram = false; } uint32_t cpuIdx; uint32_t macTier; if (hw_cpusubtype_error || hw_cputype_error || hw_ncpu_error || hw_cpufrequency_max_error || hw_busfrequency_max_error || hw_l2cachesize_error || hw_l3cachesize_error || hw_memsize_error) { OsOutputDebugString("[Mac sys detect] ! error reading specs, down to tier 0\n", v27); cpuIdx = 0; macTier = 0; } else { macTier = 3; if (hw_ncpu < 2) { OsOutputDebugString("[Mac sys detect] - non dual proc, down to tier 2\n"); macTier = 2; } if (hw_busfrequency_max < 500000000) { OsOutputDebugString("[Mac sys detect] - sub 500MHz FSB, down to tier 2\n"); macTier = 2; } if (hw_memsize < 0x30000000) { OsOutputDebugString("[Mac sys detect] - under 768MB RAM, down to tier 2\n"); macTier = 2; } if (hw_cpufrequency_max < 1100000000) { OsOutputDebugString("[Mac sys detect] - under 1.1GHz CPU, down to tier 1\n"); macTier = 1; } if (vram_size < 0x4000000) { OsOutputDebugString("[Mac sys detect] - < 64MB VRAM, down to tier 1\n"); macTier = 1; } if (hw_cputype == 18 && hw_cpusubtype < 11) { OsOutputDebugString("[Mac sys detect] - G3 or G4, down to tier 0\n"); macTier = 0; } if (vram_size <= 0x2000000) { OsOutputDebugString("[Mac sys detect] - <= 32 MB VRAM, down to tier 0\n"); macTier = 0; } if (!ddr_ram) { OsOutputDebugString("[Mac sys detect] - no DDR RAM, down to tier 0\n"); macTier = 0; } if (hw_l2cachesize <= 0x40000 && hw_l3cachesize <= 0xFFFFF) { OsOutputDebugString("[Mac sys detect] - L2 <= 256K and L3 <= 1MB, down to tier 0\n"); macTier = 0; } if (hw_memsize < 0x20000000) { OsOutputDebugString("[Mac sys detect] - < 512MB RAM, down to tier 0\n"); cpuIdx = 0; macTier = 0; } else { cpuIdx = macTier / 2; } } hardware.cpuIdx = cpuIdx; hardware.memIdx = 0; hardware.soundIdx = 0; hardware.macTierIdx = macTier; hardware.macVramMB = vram_size / 0x100000; hardware.cpuHw = s_cpuHwSettings[cpuIdx]; hardware.videoHw = g_videoHardwareDB.GetRecord(hardware.videoID); hardware.soundHw = s_soundHwSettings[hardware.soundIdx]; ConsoleDetectSaveHardware(hardware, hwChanged); char str[1024]; GxLog("ConsoleDetectDetectHardware [Mac] ():"); SStrPrintf(str, 1024, "\tcpuIdx: %d", hardware.cpuIdx); GxLog(str); SStrPrintf(str, 1024, "\tvideoID: %d", hardware.videoIdx); GxLog(str); SStrPrintf(str, 1024, "\tsoundIdx: %d", hardware.soundIdx); GxLog(str); SStrPrintf(str, 1024, "\tmemIdx: %d", hardware.memIdx); GxLog(str); SStrPrintf(str, 1024, "\tmacTierIdx: %d", hardware.macTierIdx); GxLog(str); SStrPrintf(str, 1024, "\tmacVramMB: %d", hardware.macVramMB); GxLog(str); } #endif void ConsoleDetectSetDefaultsFormat(DefaultSettings& defaults, const Hardware& hardware) { defaults.format = &s_formats[hardware.videoHw->m_resolutionIdx]; } void ConsoleDetectSetDefaults(DefaultSettings& defaults, const Hardware& hw) { defaults.farClip = s_farClip[hw.videoHw->m_farclipIdx][hw.cpuHw->farclipIdx]; defaults.terrainShadowLOD = hw.videoHw->m_terrainShadowLod; defaults.detailDoodadDensity = s_detailDoodadDensity[hw.videoHw->m_detailDoodadDensityIdx]; defaults.detailDoodadAlpha = hw.videoHw->m_detailDoodadAlpha; defaults.animatingDoodads = s_animatingDoodads[hw.videoHw->m_animatingDoodadIdx][hw.cpuHw->animatingDoodadIdx]; defaults.trilinear = hw.videoHw->m_trilinear != 0; defaults.numLights = hw.videoHw->m_numLights; auto specularity = hw.videoHw->m_specularity != 0; defaults.unk1A = specularity; defaults.specularity = specularity; defaults.waterLOD = s_waterLOD[hw.videoHw->m_waterLodidx][hw.cpuHw->waterLODIdx]; defaults.particleDensity = s_particleDensity[hw.videoHw->m_particleDensityIdx][hw.cpuHw->particleDensityIdx]; defaults.unitDrawDist = s_unitDrawDist[hw.videoHw->m_unitDrawDistIdx][hw.cpuHw->unitDrawDistIdx]; defaults.smallCull = s_smallCull[hw.videoHw->m_smallCullDistIdx][hw.cpuHw->smallCullDistIdx]; defaults.distCull = s_distCull[hw.videoHw->m_smallCullDistIdx][hw.cpuHw->smallCullDistIdx]; defaults.format = s_formats + hw.videoHw->m_resolutionIdx; defaults.baseMipLevel = hw.videoHw->m_baseMipLevel; defaults.unk19 = true; defaults.numChannels = 0; defaults.fivePointOne = false; }