diff --git a/BUILD.md b/BUILD.md index 31c26531..0bedb8f0 100644 --- a/BUILD.md +++ b/BUILD.md @@ -20,6 +20,9 @@ - [Installing Tool Dependencies](#installing-tool-dependencies) - [Installing Library Dependencies](#installing-library-dependencies) - [Build Cemu using CMake](#build-cemu-using-cmake) +- [FreeBSD](#freebsd) + - [Installing Dependencies](#installing-dependencies) + - [Build Cemu on BSD with CMake](#build-cemu-on-bsd-with-cmake) - [Updating Cemu and source code](#updating-cemu-and-source-code) ## Windows @@ -185,6 +188,33 @@ Then install the dependencies: #### Troubleshooting steps - If step 3 gives you an error about not being able to find ninja, try appending `-DCMAKE_MAKE_PROGRAM=/usr/local/bin/ninja` to the command and running it again. +## FreeBSD + +The following instructions to build Cemu on FreeBSD are experimental. Some features available on other platforms are not available on FreeBSD (discord rich presence, bluetooth/support for actual Wii U controllers, auto-updates, etc.) + +To compile Cemu, a recent enough compiler and STL with C++20 support is required! Clang-15 or higher is what we recommend. Any version of FreeBSD 13.3-RELEASE or higher comes bundled with LLVM > version 15 as part of the base system. However, if for whatever reason your system lacks a recent version of LLVM you can install one by executing: + +`sudo pkg install llvm15` + +Or a higher version as desired. + +### Installing Dependencies + +`sudo pkg install boost-libs cmake-core curl glslang gtk3 libzip ninja png pkgconf pugixml rapidjson sdl2 wayland wayland-protocols wx32-gtk3 xorg zstd` + +### Build Cemu on BSD with CMake + +``` +git clone --recursive https://github.com/cemu-project/Cemu +cd Cemu +cmake -B build -DCMAKE_BUILD_TYPE=release -DENABLE_BLUEZ=OFF -DENABLE_DISCORD_RPC=OFF -DENABLE_FERAL_GAMEMODE=OFF -DENABLE_HIDAPI=OFF -DENABLE_VCPKG=OFF -G Ninja +cmake --build build + +cd build && ninja install +``` + +You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`. + ## Updating Cemu and source code 1. To update your Cemu local repository, use the command `git pull --recurse-submodules` (run this command on the Cemu root). - This should update your local copy of Cemu and all of its dependencies. diff --git a/CMakeLists.txt b/CMakeLists.txt index 697086c4..8710641d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,7 +159,7 @@ if (UNIX AND NOT APPLE) BASENAME viewporter) add_library(CemuWaylandProtocols STATIC ${WAYLAND_PROTOCOL_SRCS}) target_include_directories(CemuWaylandProtocols PUBLIC "${CMAKE_CURRENT_BINARY_DIR}") - + target_include_directories(CemuWaylandProtocols PRIVATE ${Wayland_INCLUDE_DIRS}) add_compile_definitions(HAS_WAYLAND) endif() find_package(GTK3 REQUIRED) @@ -234,4 +234,4 @@ if (NOT ZArchive_FOUND) add_subdirectory("dependencies/ZArchive" EXCLUDE_FROM_ALL) endif() -add_subdirectory(src) \ No newline at end of file +add_subdirectory(src) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5ab2154..04b6e56c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -150,3 +150,7 @@ if(UNIX AND NOT APPLE) # most likely not helpful in debugging problems with cemu code target_link_options(CemuBin PRIVATE "$<$:-Xlinker;--strip-debug>") endif() + +if (BSD) + target_link_libraries(CemuBin PRIVATE execinfo SPIRV-Tools SPIRV-Tools-opt) +endif() diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index 0a145a94..abfda232 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -69,7 +69,7 @@ #if BOOST_OS_LINUX #include -#elif BOOST_OS_MACOS +#elif BOOST_OS_MACOS || BOOST_OS_BSD #include #include #endif @@ -473,6 +473,12 @@ namespace CafeSystem int64_t totalRam; size_t size = sizeof(totalRam); int result = sysctlbyname("hw.memsize", &totalRam, &size, NULL, 0); + if (result == 0) + cemuLog_log(LogType::Force, "RAM: {}MB", (totalRam / 1024LL / 1024LL)); + #elif BOOST_OS_BSD + int64_t totalRam; + size_t size = sizeof(totalRam); + int result = sysctlbyname("hw.physmem", &totalRam, &size, NULL, 0); if (result == 0) cemuLog_log(LogType::Force, "RAM: {}MB", (totalRam / 1024LL / 1024LL)); #endif @@ -523,6 +529,16 @@ namespace CafeSystem platform = "Linux"; #elif BOOST_OS_MACOS platform = "MacOS"; + #elif BOOST_OS_BSD + #if defined(__FreeBSD__) + platform = "FreeBSD"; + #elif defined(__OpenBSD__) + platform = "OpenBSD"; + #elif defined(__NetBSD__) + platform = "NetBSD"; + #else + platform = "Unknown BSD"; + #endif #endif cemuLog_log(LogType::Force, "Platform: {}", platform); } diff --git a/src/Cafe/HW/Latte/LatteAddrLib/LatteAddrLib_Coord.cpp b/src/Cafe/HW/Latte/LatteAddrLib/LatteAddrLib_Coord.cpp index bc43202a..26da5ec1 100644 --- a/src/Cafe/HW/Latte/LatteAddrLib/LatteAddrLib_Coord.cpp +++ b/src/Cafe/HW/Latte/LatteAddrLib/LatteAddrLib_Coord.cpp @@ -7,7 +7,7 @@ using namespace Latte; namespace LatteAddrLib { -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD unsigned char _BitScanReverse(uint32* _Index, uint32 _Mask) { if (!_Mask) @@ -402,4 +402,4 @@ namespace LatteAddrLib return finalMacroTileOffset | pipeOffset | bankOffset; } -}; \ No newline at end of file +}; diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp index ed09a12f..63c344ca 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp @@ -241,7 +241,7 @@ void LoadOpenGLImports() #include "Common/GLInclude/glFunctions.h" #undef GLFUNC } -#elif BOOST_OS_LINUX +#elif BOOST_OS_LINUX || BOOST_OS_BSD GL_IMPORT _GetOpenGLFunction(void* hLib, PFNGLXGETPROCADDRESSPROC func, const char* name) { GL_IMPORT r = (GL_IMPORT)func((const GLubyte*)name); @@ -276,7 +276,7 @@ void LoadOpenGLImports() #undef EGLFUNC } -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD // dummy function for all code that is statically linked with cemu and attempts to use eglSwapInterval // used to suppress wxWidgets calls to eglSwapInterval extern "C" diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp index 8a66c81b..665a5da3 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include "util/helpers/helpers.h" bool s_isLoadingShadersVk{ false }; class FileCache* s_spirvCache{nullptr}; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.cpp index ad32b541..e09ebcd1 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.cpp @@ -3,7 +3,7 @@ #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" #include // for std::iota -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD #include #endif @@ -138,7 +138,7 @@ bool InitializeDeviceVulkan(VkDevice device) void* dlopen_vulkan_loader() { -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD void* vulkan_so = dlopen("libvulkan.so", RTLD_NOW); if(!vulkan_so) vulkan_so = dlopen("libvulkan.so.1", RTLD_NOW); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h index ae2a62f2..e670cbd1 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h @@ -130,7 +130,7 @@ VKFUNC_DEVICE(vkDestroyPipeline); VKFUNC_DEVICE(vkCmdBindPipeline); // swapchain -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD VKFUNC_INSTANCE(vkCreateXlibSurfaceKHR); VKFUNC_INSTANCE(vkCreateXcbSurfaceKHR); #ifdef HAS_WAYLAND diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 867c7ead..60db6ff7 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -110,7 +110,7 @@ std::vector VulkanRenderer::GetDevices() requiredExtensions.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); #if BOOST_OS_WINDOWS requiredExtensions.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); - #elif BOOST_OS_LINUX + #elif BOOST_OS_LINUX || BOOST_OS_BSD auto backend = WindowSystem::GetWindowInfo().window_main.backend; if(backend == WindowSystem::WindowHandleInfo::Backend::X11) requiredExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); @@ -1307,7 +1307,7 @@ std::vector VulkanRenderer::CheckInstanceExtensionSupport(FeatureCo requiredInstanceExtensions.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); #if BOOST_OS_WINDOWS requiredInstanceExtensions.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); - #elif BOOST_OS_LINUX + #elif BOOST_OS_LINUX || BOOST_OS_BSD auto backend = WindowSystem::GetWindowInfo().window_main.backend; if(backend == WindowSystem::WindowHandleInfo::Backend::X11) requiredInstanceExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); @@ -1394,7 +1394,7 @@ VkSurfaceKHR VulkanRenderer::CreateWinSurface(VkInstance instance, HWND hwindow) } #endif -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD VkSurfaceKHR VulkanRenderer::CreateXlibSurface(VkInstance instance, Display* dpy, Window window) { VkXlibSurfaceCreateInfoKHR sci{}; @@ -1458,8 +1458,7 @@ VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, Windo { #if BOOST_OS_WINDOWS return CreateWinSurface(instance, static_cast(windowInfo.surface)); -#elif BOOST_OS_LINUX - +#elif BOOST_OS_LINUX || BOOST_OS_BSD if(windowInfo.backend == WindowSystem::WindowHandleInfo::Backend::X11) return CreateXlibSurface(instance, static_cast(windowInfo.display), reinterpret_cast(windowInfo.surface)); #ifdef HAS_WAYLAND diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h index 7aa31b0c..7290fdd7 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h @@ -201,7 +201,7 @@ public: #if BOOST_OS_WINDOWS static VkSurfaceKHR CreateWinSurface(VkInstance instance, HWND hwindow); #endif -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD static VkSurfaceKHR CreateXlibSurface(VkInstance instance, Display* dpy, Window window); static VkSurfaceKHR CreateXcbSurface(VkInstance instance, xcb_connection_t* connection, xcb_window_t window); #ifdef HAS_WAYLAND diff --git a/src/Cafe/HW/MMU/MMU.h b/src/Cafe/HW/MMU/MMU.h index a8367f88..6e3bee70 100644 --- a/src/Cafe/HW/MMU/MMU.h +++ b/src/Cafe/HW/MMU/MMU.h @@ -184,6 +184,16 @@ bool memory_isAddressRangeAccessible(MPTR virtualAddress, uint32 size); #define CPU_swapEndianU64(_v) OSSwapInt64((uint64)(_v)) #define CPU_swapEndianU32(_v) OSSwapInt32((uint32)(_v)) #define CPU_swapEndianU16(_v) OSSwapInt16((uint16)(_v)) +#elif BOOST_OS_BSD +#ifdef __OpenBSD__ +#define CPU_swapEndianU64(_v) swap64((uint64)(_v)) +#define CPU_swapEndianU32(_v) swap32((uint32)(_v)) +#define CPU_swapEndianU16(_v) swap16((uint16)(_v)) +#else // FreeBSD and NetBSD +#define CPU_swapEndianU64(_v) bswap64((uint64)(_v)) +#define CPU_swapEndianU32(_v) bswap32((uint32)(_v)) +#define CPU_swapEndianU16(_v) bswap16((uint16)(_v)) +#endif #endif // C-style memory access, deprecated. Use memory_read<> and memory_write<> templates instead @@ -266,4 +276,4 @@ namespace MMU } -#define MMU_IsInPPCMemorySpace(__ptr) ((const uint8*)(__ptr) >= memory_base && (const uint8*)(__ptr) < (memory_base + 0x100000000)) \ No newline at end of file +#define MMU_IsInPPCMemorySpace(__ptr) ((const uint8*)(__ptr) >= memory_base && (const uint8*)(__ptr) < (memory_base + 0x100000000)) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp index 330663ac..95f3c6db 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp @@ -466,7 +466,7 @@ typedef struct static_assert(sizeof(UCParamStruct_t) == 0x54); // unsure -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD #define _strcmpi strcasecmp #endif diff --git a/src/Cafe/OS/libs/nsyshid/BackendLibusb.h b/src/Cafe/OS/libs/nsyshid/BackendLibusb.h index 6b2d8e1a..955b3071 100644 --- a/src/Cafe/OS/libs/nsyshid/BackendLibusb.h +++ b/src/Cafe/OS/libs/nsyshid/BackendLibusb.h @@ -1,6 +1,10 @@ #include "nsyshid.h" +#if BOOST_OS_BSD +#include +#else #include +#endif #include "Backend.h" namespace nsyshid::backend::libusb diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt index 9a764593..dec0bc42 100644 --- a/src/Common/CMakeLists.txt +++ b/src/Common/CMakeLists.txt @@ -46,7 +46,7 @@ PRIVATE ) endif() -if(UNIX AND NOT APPLE) +if(LINUX) target_sources(CemuCommon PRIVATE ExceptionHandler/ELFSymbolTable.cpp ExceptionHandler/ELFSymbolTable.h diff --git a/src/Common/GLInclude/GLInclude.h b/src/Common/GLInclude/GLInclude.h index 86df0232..e6a4e8cf 100644 --- a/src/Common/GLInclude/GLInclude.h +++ b/src/Common/GLInclude/GLInclude.h @@ -6,7 +6,7 @@ #include "wglext.h" #endif -#if BOOST_OS_LINUX > 0 +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) > 0 // from Xlib #define Bool int diff --git a/src/Common/GLInclude/glFunctions.h b/src/Common/GLInclude/glFunctions.h index 76308fdb..412816af 100644 --- a/src/Common/GLInclude/glFunctions.h +++ b/src/Common/GLInclude/glFunctions.h @@ -297,7 +297,7 @@ GLFUNC(PFNWGLSWAPINTERVALEXTPROC, wglSwapIntervalEXT) // x -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD EGLFUNC(PFNEGLSWAPINTERVALPROC, eglSwapInterval) EGLFUNC(PFNEGLGETCURRENTDISPLAYPROC, eglGetCurrentDisplay) #endif diff --git a/src/Common/platform.h b/src/Common/platform.h index 3f480f43..08462a97 100644 --- a/src/Common/platform.h +++ b/src/Common/platform.h @@ -5,8 +5,12 @@ #if BOOST_OS_WINDOWS #include "Common/windows/platform.h" -#elif BOOST_OS_LINUX +#elif BOOST_OS_LINUX || BOOST_OS_BSD +#if BOOST_OS_LINUX #include +#elif BOOST_OS_BSD +#include +#endif #include #include #include diff --git a/src/Common/precompiled.h b/src/Common/precompiled.h index 2d3f7e2a..0c080f29 100644 --- a/src/Common/precompiled.h +++ b/src/Common/precompiled.h @@ -184,6 +184,12 @@ inline uint64 _swapEndianU64(uint64 v) { #if BOOST_OS_MACOS return OSSwapInt64(v); +#elif BOOST_OS_BSD +#ifdef __OpenBSD__ + return swap64(v); +#else // FreeBSD and NetBSD + return bswap64(v); +#endif #else return bswap_64(v); #endif @@ -193,6 +199,12 @@ inline uint32 _swapEndianU32(uint32 v) { #if BOOST_OS_MACOS return OSSwapInt32(v); +#elif BOOST_OS_BSD +#ifdef __OpenBSD__ + return swap32(v); +#else // FreeBSD and NetBSD + return bswap32(v); +#endif #else return bswap_32(v); #endif @@ -202,6 +214,12 @@ inline sint32 _swapEndianS32(sint32 v) { #if BOOST_OS_MACOS return (sint32)OSSwapInt32((uint32)v); +#elif BOOST_OS_BSD +#ifdef __OpenBSD__ + return (sint32)swap32((uint32)v); +#else // FreeBSD and NetBSD + return (sint32)bswap32((uint32)v); +#endif #else return (sint32)bswap_32((uint32)v); #endif @@ -493,6 +511,11 @@ bool match_any_of(T1&& value, Types&&... others) #elif BOOST_OS_MACOS return std::chrono::steady_clock::time_point( std::chrono::nanoseconds(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW))); +#elif BOOST_OS_BSD + struct timespec tp; + clock_gettime(CLOCK_MONOTONIC, &tp); + return std::chrono::steady_clock::time_point( + std::chrono::seconds(tp.tv_sec) + std::chrono::nanoseconds(tp.tv_nsec)); #endif } diff --git a/src/Common/unix/platform.cpp b/src/Common/unix/platform.cpp index 144d4f02..879ae4dc 100644 --- a/src/Common/unix/platform.cpp +++ b/src/Common/unix/platform.cpp @@ -9,6 +9,10 @@ uint32_t GetTickCount() return (1000 * ts.tv_sec + ts.tv_nsec / 1000000); #elif BOOST_OS_MACOS return clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) / 1000000; +#elif BOOST_OS_BSD + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (1000 * ts.tv_sec + ts.tv_nsec / 1000000); #endif -} \ No newline at end of file +} diff --git a/src/gui/wxgui/CemuApp.cpp b/src/gui/wxgui/CemuApp.cpp index 78f4b83f..7279c827 100644 --- a/src/gui/wxgui/CemuApp.cpp +++ b/src/gui/wxgui/CemuApp.cpp @@ -14,7 +14,7 @@ #include "wxgui/input/HotkeySettings.h" #include -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND #include "wxgui/helpers/wxWayland.h" #endif #if __WXGTK__ @@ -117,7 +117,7 @@ void CemuApp::DeterminePaths(std::set& failedWriteAccess) // for Windo } #endif -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD void CemuApp::DeterminePaths(std::set& failedWriteAccess) // for Linux { std::error_code ec; @@ -347,7 +347,7 @@ bool CemuApp::OnInit() SetTopWindow(m_mainFrame); m_mainFrame->Show(); -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND if (wxWlIsWaylandWindow(m_mainFrame)) wxWlSetAppId(m_mainFrame, "info.cemu.Cemu"); #endif diff --git a/src/gui/wxgui/CemuUpdateWindow.cpp b/src/gui/wxgui/CemuUpdateWindow.cpp index 16b9d2d4..542ae588 100644 --- a/src/gui/wxgui/CemuUpdateWindow.cpp +++ b/src/gui/wxgui/CemuUpdateWindow.cpp @@ -110,13 +110,13 @@ bool CemuUpdateWindow::QueryUpdateInfo(std::string& downloadUrlOut, std::string& std::string urlStr("https://cemu.info/api2/version.php?v="); auto* curl = curl_easy_init(); urlStr.append(_curlUrlEscape(curl, BUILD_VERSION_STRING)); -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD // dummy placeholder on BSD for now urlStr.append("&platform=linux_appimage"); #elif BOOST_OS_WINDOWS urlStr.append("&platform=windows"); #elif BOOST_OS_MACOS urlStr.append("&platform=macos_bundle"); -#elif +#else #error Name for current platform is missing #endif #if defined(__aarch64__) @@ -126,6 +126,9 @@ bool CemuUpdateWindow::QueryUpdateInfo(std::string& downloadUrlOut, std::string& #else urlStr.append("_unknown"); #endif +#if BOOST_OS_BSD + return false; // BSD users must update from source; no binary available +#endif const auto& config = GetWxGUIConfig(); if(config.receive_untested_updates) @@ -425,7 +428,7 @@ void CemuUpdateWindow::WorkerThread() #if BOOST_OS_WINDOWS const auto update_file = tmppath / L"update.zip"; -#elif BOOST_OS_LINUX +#elif BOOST_OS_LINUX || BOOST_OS_BSD // dummy placeholder on BSD for now const auto update_file = tmppath / L"Cemu.AppImage"; #elif BOOST_OS_MACOS const auto update_file = tmppath / L"cemu.dmg"; diff --git a/src/gui/wxgui/GameProfileWindow.cpp b/src/gui/wxgui/GameProfileWindow.cpp index 7948b1f9..0092bb84 100644 --- a/src/gui/wxgui/GameProfileWindow.cpp +++ b/src/gui/wxgui/GameProfileWindow.cpp @@ -11,7 +11,7 @@ #include "wxgui/helpers/wxHelpers.h" #include "input/InputManager.h" -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD #include "resource/embedded/resources.h" #endif @@ -365,4 +365,4 @@ void GameProfileWindow::SetSliderValue(wxSlider* slider, sint32 new_value) const slider_event.SetEventObject(slider); slider_event.SetClientData((void*)IsFrozen()); wxPostEvent(slider->GetEventHandler(), slider_event); -} \ No newline at end of file +} diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index ac993700..89a0bd85 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -225,6 +225,8 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook) if (!std::getenv("APPIMAGE")) { m_auto_update->Disable(); } +#elif BOOST_OS_BSD // BSD users must update from source so disable auto updates + m_auto_update->Disable(); #endif box_sizer->Add(second_row, 0, wxEXPAND, 5); diff --git a/src/gui/wxgui/GettingStartedDialog.cpp b/src/gui/wxgui/GettingStartedDialog.cpp index dc9bc811..c2a0eb2e 100644 --- a/src/gui/wxgui/GettingStartedDialog.cpp +++ b/src/gui/wxgui/GettingStartedDialog.cpp @@ -17,7 +17,7 @@ #include "Cafe/TitleList/TitleList.h" -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD #include "resource/embedded/resources.h" #endif diff --git a/src/gui/wxgui/GraphicPacksWindow2.cpp b/src/gui/wxgui/GraphicPacksWindow2.cpp index 1298f72f..96b939bb 100644 --- a/src/gui/wxgui/GraphicPacksWindow2.cpp +++ b/src/gui/wxgui/GraphicPacksWindow2.cpp @@ -12,7 +12,7 @@ #include "wxHelper.h" -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD #include "resource/embedded/resources.h" #endif diff --git a/src/gui/wxgui/MainWindow.cpp b/src/gui/wxgui/MainWindow.cpp index bdc0db20..477edb7b 100644 --- a/src/gui/wxgui/MainWindow.cpp +++ b/src/gui/wxgui/MainWindow.cpp @@ -51,11 +51,11 @@ #define exit(__c) _Exit(__c) #endif -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD #include "resource/embedded/resources.h" #endif -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND #include "wxgui/helpers/wxWayland.h" #endif @@ -710,7 +710,7 @@ void MainWindow::OnInstallUpdate(wxCommandEvent& event) break; if (modalChoice == wxID_OK) { - #if BOOST_OS_LINUX || BOOST_OS_MACOS + #if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD fs::path dirPath((const char*)(openDirDialog.GetPath().fn_str())); #else fs::path dirPath(openDirDialog.GetPath().fn_str()); @@ -812,7 +812,7 @@ void MainWindow::TogglePadView() m_padView->Show(true); -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND if (wxWlIsWaylandWindow(m_padView)) wxWlSetAppId(m_padView, "info.cemu.Cemu"); #endif @@ -2320,6 +2320,8 @@ void MainWindow::RecreateMenu() if (!std::getenv("APPIMAGE")) { m_check_update_menu->Enable(false); } +#elif BOOST_OS_BSD // BSD users must update from source so disable update checks + m_check_update_menu->Enable(false); #endif helpMenu->AppendSeparator(); helpMenu->Append(MAINFRAME_MENU_ID_HELP_ABOUT, _("&About Cemu")); diff --git a/src/gui/wxgui/PadViewFrame.cpp b/src/gui/wxgui/PadViewFrame.cpp index 565f42c6..556db579 100644 --- a/src/gui/wxgui/PadViewFrame.cpp +++ b/src/gui/wxgui/PadViewFrame.cpp @@ -13,7 +13,7 @@ #include "wxgui/helpers/wxHelpers.h" #include "input/InputManager.h" -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD #include "resource/embedded/resources.h" #endif #include "wxHelper.h" diff --git a/src/gui/wxgui/canvas/OpenGLCanvas.cpp b/src/gui/wxgui/canvas/OpenGLCanvas.cpp index 4e48e26c..0eb76a3d 100644 --- a/src/gui/wxgui/canvas/OpenGLCanvas.cpp +++ b/src/gui/wxgui/canvas/OpenGLCanvas.cpp @@ -124,7 +124,7 @@ public: #if BOOST_OS_WINDOWS if(wglSwapIntervalEXT) wglSwapIntervalEXT(configValue); // 1 = enabled, 0 = disabled -#elif BOOST_OS_LINUX +#elif BOOST_OS_LINUX || BOOST_OS_BSD if (eglSwapInterval) { if (eglSwapInterval(eglGetCurrentDisplay(), configValue) == EGL_FALSE) diff --git a/src/gui/wxgui/canvas/VulkanCanvas.cpp b/src/gui/wxgui/canvas/VulkanCanvas.cpp index 79d4de3b..914e85c8 100644 --- a/src/gui/wxgui/canvas/VulkanCanvas.cpp +++ b/src/gui/wxgui/canvas/VulkanCanvas.cpp @@ -1,7 +1,7 @@ #include "wxgui/canvas/VulkanCanvas.h" #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h" -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND #include "wxgui/helpers/wxWayland.h" #endif @@ -16,7 +16,7 @@ VulkanCanvas::VulkanCanvas(wxWindow* parent, const wxSize& size, bool is_main_wi auto& canvas = is_main_window ? WindowSystem::GetWindowInfo().canvas_main : WindowSystem::GetWindowInfo().canvas_pad; canvas = initHandleContextFromWxWidgetsWindow(this); - #if BOOST_OS_LINUX && HAS_WAYLAND + #if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND if (canvas.backend == WindowSystem::WindowHandleInfo::Backend::Wayland) { m_subsurface = std::make_unique(this); @@ -69,7 +69,7 @@ void VulkanCanvas::OnResize(wxSizeEvent& event) if (size.GetWidth() == 0 || size.GetHeight() == 0) return; -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND if(m_subsurface) { auto sRect = GetScreenRect(); diff --git a/src/gui/wxgui/canvas/VulkanCanvas.h b/src/gui/wxgui/canvas/VulkanCanvas.h index 3db31520..731638f3 100644 --- a/src/gui/wxgui/canvas/VulkanCanvas.h +++ b/src/gui/wxgui/canvas/VulkanCanvas.h @@ -9,7 +9,7 @@ class VulkanCanvas : public IRenderCanvas, public wxWindow { -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND std::unique_ptr m_subsurface; #endif public: diff --git a/src/gui/wxgui/components/wxGameList.cpp b/src/gui/wxgui/components/wxGameList.cpp index bb6e9653..4212a6b2 100644 --- a/src/gui/wxgui/components/wxGameList.cpp +++ b/src/gui/wxgui/components/wxGameList.cpp @@ -1373,7 +1373,7 @@ void wxGameList::DeleteCachedStrings() m_name_cache.clear(); } -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD void wxGameList::CreateShortcut(GameInfo2& gameInfo) { const auto titleId = gameInfo.GetBaseTitleId(); diff --git a/src/gui/wxgui/helpers/wxHelpers.cpp b/src/gui/wxgui/helpers/wxHelpers.cpp index 7904a3bf..0d734372 100644 --- a/src/gui/wxgui/helpers/wxHelpers.cpp +++ b/src/gui/wxgui/helpers/wxHelpers.cpp @@ -5,7 +5,7 @@ #include #include -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD #include #include #include @@ -81,7 +81,7 @@ WindowSystem::WindowHandleInfo initHandleContextFromWxWidgetsWindow(wxWindow* wx #if BOOST_OS_WINDOWS handleInfo.backend = WindowSystem::WindowHandleInfo::Backend::Windows; handleInfo.surface = reinterpret_cast(wxw->GetHWND()); -#elif BOOST_OS_LINUX +#elif BOOST_OS_LINUX || BOOST_OS_BSD GtkWidget* gtkWidget = (GtkWidget*)wxw->GetHandle(); // returns GtkWidget gtk_widget_realize(gtkWidget); GdkWindow* gdkWindow = gtk_widget_get_window(gtkWidget); diff --git a/src/gui/wxgui/helpers/wxWayland.cpp b/src/gui/wxgui/helpers/wxWayland.cpp index 6ec932bd..6e7ff789 100644 --- a/src/gui/wxgui/helpers/wxWayland.cpp +++ b/src/gui/wxgui/helpers/wxWayland.cpp @@ -1,6 +1,6 @@ #include "wxgui/helpers/wxWayland.h" -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND #include diff --git a/src/gui/wxgui/helpers/wxWayland.h b/src/gui/wxgui/helpers/wxWayland.h index a3b82119..0f162787 100644 --- a/src/gui/wxgui/helpers/wxWayland.h +++ b/src/gui/wxgui/helpers/wxWayland.h @@ -1,6 +1,6 @@ #pragma once -#if BOOST_OS_LINUX && HAS_WAYLAND +#if ( BOOST_OS_LINUX || BOOST_OS_BSD ) && HAS_WAYLAND #include #include diff --git a/src/gui/wxgui/input/HotkeySettings.cpp b/src/gui/wxgui/input/HotkeySettings.cpp index 15b05fc6..5334820c 100644 --- a/src/gui/wxgui/input/HotkeySettings.cpp +++ b/src/gui/wxgui/input/HotkeySettings.cpp @@ -11,7 +11,7 @@ #include #endif -#if BOOST_OS_LINUX || BOOST_OS_MACOS +#if BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_BSD #include "resource/embedded/resources.h" #endif diff --git a/src/gui/wxgui/input/InputAPIAddWindow.cpp b/src/gui/wxgui/input/InputAPIAddWindow.cpp index 6a9d74bd..1e5b1d66 100644 --- a/src/gui/wxgui/input/InputAPIAddWindow.cpp +++ b/src/gui/wxgui/input/InputAPIAddWindow.cpp @@ -190,7 +190,7 @@ void InputAPIAddWindow::on_api_selected(wxCommandEvent& event) } else { -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD // We rely on the wxEVT_COMBOBOX_DROPDOWN event to trigger filling the controller list, // but on wxGTK the dropdown button cannot be clicked if the list is empty // so as a quick and dirty workaround we fill the list here diff --git a/src/gui/wxgui/input/InputSettings2.cpp b/src/gui/wxgui/input/InputSettings2.cpp index b36b2993..3fc0a409 100644 --- a/src/gui/wxgui/input/InputSettings2.cpp +++ b/src/gui/wxgui/input/InputSettings2.cpp @@ -149,7 +149,7 @@ wxWindow* InputSettings2::initialize_page(size_t index) auto* profiles = new wxComboBox(page, wxID_ANY, kDefaultProfileName); sizer->Add(profiles, wxGBPosition(0, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5); -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD // We rely on the wxEVT_COMBOBOX_DROPDOWN event to trigger filling the profile list, // but on wxGTK the dropdown button cannot be clicked if the list is empty // so as a quick and dirty workaround we fill the list here diff --git a/src/gui/wxgui/wxWindowSystem.cpp b/src/gui/wxgui/wxWindowSystem.cpp index a444eb19..fe33829f 100644 --- a/src/gui/wxgui/wxWindowSystem.cpp +++ b/src/gui/wxgui/wxWindowSystem.cpp @@ -3,7 +3,7 @@ #include "helpers/wxHelpers.h" -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD #include #include #include @@ -231,7 +231,7 @@ bool WindowSystem::IsKeyDown(PlatformKeyCodes platformKey) case PlatformKeyCodes::ESCAPE: key = VK_ESCAPE; break; -#elif BOOST_OS_LINUX +#elif BOOST_OS_LINUX || BOOST_OS_BSD case PlatformKeyCodes::LCONTROL: key = GDK_KEY_Control_L; break; @@ -300,7 +300,7 @@ std::string WindowSystem::GetKeyCodeName(uint32 button) return key_name; else return fmt::format("key_{}", button); -#elif BOOST_OS_LINUX +#elif BOOST_OS_LINUX || BOOST_OS_BSD return gdk_keyval_name(button); #else return fmt::format("key_{}", button); diff --git a/src/main.cpp b/src/main.cpp index 0336fd64..ed48252c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,7 +36,7 @@ #if BOOST_OS_LINUX #define _putenv(__s) putenv((char*)(__s)) #include -#elif BOOST_OS_MACOS +#elif BOOST_OS_MACOS || BOOST_OS_BSD #define _putenv(__s) putenv((char*)(__s)) #include #include @@ -247,7 +247,7 @@ int main(int argc, char* argv[]) int main(int argc, char *argv[]) { -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX || BOOST_OS_BSD XInitThreads(); #endif if (!LaunchSettings::HandleCommandline(argc, argv)) diff --git a/src/util/highresolutiontimer/HighResolutionTimer.cpp b/src/util/highresolutiontimer/HighResolutionTimer.cpp index bb4a40ab..48a7ad1f 100644 --- a/src/util/highresolutiontimer/HighResolutionTimer.cpp +++ b/src/util/highresolutiontimer/HighResolutionTimer.cpp @@ -14,6 +14,11 @@ HighResolutionTimer HighResolutionTimer::now() return HighResolutionTimer(nsec); #elif BOOST_OS_MACOS return HighResolutionTimer(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW)); +#elif BOOST_OS_BSD + timespec pc; + clock_gettime(CLOCK_MONOTONIC, &pc); + uint64 nsec = (uint64)pc.tv_sec * (uint64)1000000000 + (uint64)pc.tv_nsec; + return HighResolutionTimer(nsec); #endif } @@ -29,6 +34,10 @@ uint64 HighResolutionTimer::m_freq = []() -> uint64 { return (uint64)(freq.QuadPart); #elif BOOST_OS_MACOS return 1000000000; +#elif BOOST_OS_BSD + timespec pc; + clock_getres(CLOCK_MONOTONIC, &pc); + return (uint64)1000000000 / (uint64)pc.tv_nsec; #else timespec pc; clock_getres(CLOCK_MONOTONIC_RAW, &pc);