mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Add Windows build support via MSYS2 and fix platform-specific code
Guard X11 display crash handler with __linux__, add Windows GlobalMemoryStatusEx path in memory_monitor, guard warden cache paths with APPDATA on Windows, and make pkg-config optional in CMakeLists with a find_library fallback. Add Windows x86-64 CI job using MSYS2 MINGW64 to the build workflow.
This commit is contained in:
parent
02fd0166e9
commit
cb01821d89
6 changed files with 125 additions and 16 deletions
44
.github/workflows/build.yml
vendored
44
.github/workflows/build.yml
vendored
|
|
@ -64,3 +64,47 @@ jobs:
|
||||||
name: wowee-${{ matrix.arch }}
|
name: wowee-${{ matrix.arch }}
|
||||||
path: build/bin/
|
path: build/bin/
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
name: Build (windows-x86-64)
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up MSYS2
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: MINGW64
|
||||||
|
update: false
|
||||||
|
install: >-
|
||||||
|
mingw-w64-x86_64-cmake
|
||||||
|
mingw-w64-x86_64-gcc
|
||||||
|
mingw-w64-x86_64-pkgconf
|
||||||
|
mingw-w64-x86_64-SDL2
|
||||||
|
mingw-w64-x86_64-glew
|
||||||
|
mingw-w64-x86_64-glm
|
||||||
|
mingw-w64-x86_64-openssl
|
||||||
|
mingw-w64-x86_64-zlib
|
||||||
|
mingw-w64-x86_64-ffmpeg
|
||||||
|
mingw-w64-x86_64-unicorn
|
||||||
|
git
|
||||||
|
|
||||||
|
- name: Clone ImGui
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: git clone --depth 1 https://github.com/ocornut/imgui.git extern/imgui
|
||||||
|
|
||||||
|
- name: Configure
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: cmake -S . -B build -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: cmake --build build --parallel $(nproc)
|
||||||
|
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: wowee-windows-x86-64
|
||||||
|
path: build/bin/
|
||||||
|
if-no-files-found: error
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,25 @@ find_package(GLEW REQUIRED)
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
find_package(PkgConfig REQUIRED)
|
if(WIN32)
|
||||||
pkg_check_modules(FFMPEG REQUIRED libavformat libavcodec libswscale libavutil)
|
find_package(PkgConfig QUIET)
|
||||||
|
else()
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
endif()
|
||||||
|
if(PkgConfig_FOUND)
|
||||||
|
pkg_check_modules(FFMPEG REQUIRED libavformat libavcodec libswscale libavutil)
|
||||||
|
else()
|
||||||
|
# Fallback for MSVC/vcpkg — find FFmpeg libraries manually
|
||||||
|
find_path(FFMPEG_INCLUDE_DIRS libavformat/avformat.h)
|
||||||
|
find_library(AVFORMAT_LIB NAMES avformat)
|
||||||
|
find_library(AVCODEC_LIB NAMES avcodec)
|
||||||
|
find_library(AVUTIL_LIB NAMES avutil)
|
||||||
|
find_library(SWSCALE_LIB NAMES swscale)
|
||||||
|
set(FFMPEG_LIBRARIES ${AVFORMAT_LIB} ${AVCODEC_LIB} ${AVUTIL_LIB} ${SWSCALE_LIB})
|
||||||
|
if(NOT AVFORMAT_LIB)
|
||||||
|
message(FATAL_ERROR "FFmpeg not found. On Windows install via MSYS2: mingw-w64-x86_64-ffmpeg")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Unicorn Engine (x86 emulator for cross-platform Warden module execution)
|
# Unicorn Engine (x86 emulator for cross-platform Warden module execution)
|
||||||
find_library(UNICORN_LIBRARY NAMES unicorn)
|
find_library(UNICORN_LIBRARY NAMES unicorn)
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,16 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace wowee {
|
namespace wowee {
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
namespace {
|
namespace {
|
||||||
size_t readMemAvailableBytesFromProc() {
|
size_t readMemAvailableBytesFromProc() {
|
||||||
std::ifstream meminfo("/proc/meminfo");
|
std::ifstream meminfo("/proc/meminfo");
|
||||||
|
|
@ -26,6 +31,7 @@ size_t readMemAvailableBytesFromProc() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
#endif
|
||||||
|
|
||||||
MemoryMonitor& MemoryMonitor::getInstance() {
|
MemoryMonitor& MemoryMonitor::getInstance() {
|
||||||
static MemoryMonitor instance;
|
static MemoryMonitor instance;
|
||||||
|
|
@ -33,6 +39,16 @@ MemoryMonitor& MemoryMonitor::getInstance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryMonitor::initialize() {
|
void MemoryMonitor::initialize() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
ULONGLONG totalKB = 0;
|
||||||
|
if (GetPhysicallyInstalledSystemMemory(&totalKB)) {
|
||||||
|
totalRAM_ = static_cast<size_t>(totalKB) * 1024ull;
|
||||||
|
LOG_INFO("System RAM detected: ", totalRAM_ / (1024 * 1024 * 1024), " GB");
|
||||||
|
} else {
|
||||||
|
totalRAM_ = 16ull * 1024 * 1024 * 1024;
|
||||||
|
LOG_WARNING("Could not detect system RAM, assuming 16GB");
|
||||||
|
}
|
||||||
|
#else
|
||||||
struct sysinfo info;
|
struct sysinfo info;
|
||||||
if (sysinfo(&info) == 0) {
|
if (sysinfo(&info) == 0) {
|
||||||
totalRAM_ = static_cast<size_t>(info.totalram) * info.mem_unit;
|
totalRAM_ = static_cast<size_t>(info.totalram) * info.mem_unit;
|
||||||
|
|
@ -42,9 +58,18 @@ void MemoryMonitor::initialize() {
|
||||||
totalRAM_ = 16ull * 1024 * 1024 * 1024;
|
totalRAM_ = 16ull * 1024 * 1024 * 1024;
|
||||||
LOG_WARNING("Could not detect system RAM, assuming 16GB");
|
LOG_WARNING("Could not detect system RAM, assuming 16GB");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MemoryMonitor::getAvailableRAM() const {
|
size_t MemoryMonitor::getAvailableRAM() const {
|
||||||
|
#ifdef _WIN32
|
||||||
|
MEMORYSTATUSEX status;
|
||||||
|
status.dwLength = sizeof(status);
|
||||||
|
if (GlobalMemoryStatusEx(&status)) {
|
||||||
|
return static_cast<size_t>(status.ullAvailPhys);
|
||||||
|
}
|
||||||
|
return totalRAM_ / 2;
|
||||||
|
#else
|
||||||
// Best source on Linux for reclaimable memory headroom.
|
// Best source on Linux for reclaimable memory headroom.
|
||||||
if (size_t memAvailable = readMemAvailableBytesFromProc(); memAvailable > 0) {
|
if (size_t memAvailable = readMemAvailableBytesFromProc(); memAvailable > 0) {
|
||||||
return memAvailable;
|
return memAvailable;
|
||||||
|
|
@ -59,6 +84,7 @@ size_t MemoryMonitor::getAvailableRAM() const {
|
||||||
return (totalRAM_ > 0 && available > totalRAM_) ? totalRAM_ : available;
|
return (totalRAM_ > 0 && available > totalRAM_) ? totalRAM_ : available;
|
||||||
}
|
}
|
||||||
return totalRAM_ / 2; // Fallback: assume 50% available
|
return totalRAM_ / 2; // Fallback: assume 50% available
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MemoryMonitor::getRecommendedCacheBudget() const {
|
size_t MemoryMonitor::getRecommendedCacheBudget() const {
|
||||||
|
|
|
||||||
|
|
@ -2397,11 +2397,15 @@ bool GameHandler::loadWardenCRFile(const std::string& moduleHashHex) {
|
||||||
wardenCREntries_.clear();
|
wardenCREntries_.clear();
|
||||||
|
|
||||||
// Look for .cr file in warden cache
|
// Look for .cr file in warden cache
|
||||||
std::string homeDir;
|
std::string cacheBase;
|
||||||
if (const char* h = std::getenv("HOME")) homeDir = h;
|
#ifdef _WIN32
|
||||||
else homeDir = ".";
|
if (const char* h = std::getenv("APPDATA")) cacheBase = std::string(h) + "\\wowee\\warden_cache";
|
||||||
|
else cacheBase = ".\\warden_cache";
|
||||||
std::string crPath = homeDir + "/.local/share/wowee/warden_cache/" + moduleHashHex + ".cr";
|
#else
|
||||||
|
if (const char* h = std::getenv("HOME")) cacheBase = std::string(h) + "/.local/share/wowee/warden_cache";
|
||||||
|
else cacheBase = "./warden_cache";
|
||||||
|
#endif
|
||||||
|
std::string crPath = cacheBase + "/" + moduleHashHex + ".cr";
|
||||||
|
|
||||||
std::ifstream crFile(crPath, std::ios::binary);
|
std::ifstream crFile(crPath, std::ios::binary);
|
||||||
if (!crFile) {
|
if (!crFile) {
|
||||||
|
|
@ -2581,10 +2585,15 @@ void GameHandler::handleWardenData(network::Packet& packet) {
|
||||||
|
|
||||||
// Cache raw module to disk
|
// Cache raw module to disk
|
||||||
{
|
{
|
||||||
std::string homeDir;
|
#ifdef _WIN32
|
||||||
if (const char* h = std::getenv("HOME")) homeDir = h;
|
std::string cacheDir;
|
||||||
else homeDir = ".";
|
if (const char* h = std::getenv("APPDATA")) cacheDir = std::string(h) + "\\wowee\\warden_cache";
|
||||||
std::string cacheDir = homeDir + "/.local/share/wowee/warden_cache";
|
else cacheDir = ".\\warden_cache";
|
||||||
|
#else
|
||||||
|
std::string cacheDir;
|
||||||
|
if (const char* h = std::getenv("HOME")) cacheDir = std::string(h) + "/.local/share/wowee/warden_cache";
|
||||||
|
else cacheDir = "./warden_cache";
|
||||||
|
#endif
|
||||||
std::filesystem::create_directories(cacheDir);
|
std::filesystem::create_directories(cacheDir);
|
||||||
|
|
||||||
std::string hashHex;
|
std::string hashHex;
|
||||||
|
|
|
||||||
|
|
@ -906,13 +906,18 @@ bool WardenModule::initializeModule() {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
WardenModuleManager::WardenModuleManager() {
|
WardenModuleManager::WardenModuleManager() {
|
||||||
// Set cache directory: ~/.local/share/wowee/warden_cache/
|
// Set cache directory
|
||||||
const char* home = std::getenv("HOME");
|
#ifdef _WIN32
|
||||||
if (home) {
|
if (const char* appdata = std::getenv("APPDATA"))
|
||||||
|
cacheDirectory_ = std::string(appdata) + "\\wowee\\warden_cache";
|
||||||
|
else
|
||||||
|
cacheDirectory_ = ".\\warden_cache";
|
||||||
|
#else
|
||||||
|
if (const char* home = std::getenv("HOME"))
|
||||||
cacheDirectory_ = std::string(home) + "/.local/share/wowee/warden_cache";
|
cacheDirectory_ = std::string(home) + "/.local/share/wowee/warden_cache";
|
||||||
} else {
|
else
|
||||||
cacheDirectory_ = "./warden_cache";
|
cacheDirectory_ = "./warden_cache";
|
||||||
}
|
#endif
|
||||||
|
|
||||||
// Create cache directory if it doesn't exist
|
// Create cache directory if it doesn't exist
|
||||||
std::filesystem::create_directories(cacheDirectory_);
|
std::filesystem::create_directories(cacheDirectory_);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#ifdef __linux__
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
// Keep a persistent X11 connection for emergency mouse release in signal handlers.
|
// Keep a persistent X11 connection for emergency mouse release in signal handlers.
|
||||||
|
|
@ -16,6 +17,9 @@ static void releaseMouseGrab() {
|
||||||
XFlush(g_emergencyDisplay);
|
XFlush(g_emergencyDisplay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static void releaseMouseGrab() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void crashHandler(int sig) {
|
static void crashHandler(int sig) {
|
||||||
releaseMouseGrab();
|
releaseMouseGrab();
|
||||||
|
|
@ -24,7 +28,9 @@ static void crashHandler(int sig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
|
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
|
||||||
|
#ifdef __linux__
|
||||||
g_emergencyDisplay = XOpenDisplay(nullptr);
|
g_emergencyDisplay = XOpenDisplay(nullptr);
|
||||||
|
#endif
|
||||||
std::signal(SIGSEGV, crashHandler);
|
std::signal(SIGSEGV, crashHandler);
|
||||||
std::signal(SIGABRT, crashHandler);
|
std::signal(SIGABRT, crashHandler);
|
||||||
std::signal(SIGFPE, crashHandler);
|
std::signal(SIGFPE, crashHandler);
|
||||||
|
|
@ -46,7 +52,9 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
|
||||||
app.shutdown();
|
app.shutdown();
|
||||||
|
|
||||||
LOG_INFO("Application exited successfully");
|
LOG_INFO("Application exited successfully");
|
||||||
|
#ifdef __linux__
|
||||||
if (g_emergencyDisplay) { XCloseDisplay(g_emergencyDisplay); g_emergencyDisplay = nullptr; }
|
if (g_emergencyDisplay) { XCloseDisplay(g_emergencyDisplay); g_emergencyDisplay = nullptr; }
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e) {
|
catch (const std::exception& e) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue