diff --git a/CMakeLists.txt b/CMakeLists.txt index fb4a822..41d5cb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,13 +215,21 @@ endif() if (LINUX) find_package(X11 REQUIRED) + + # Generate icon_bytes.c from the app icon PNG. + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.h + COMMAND file_to_c ${CMAKE_SOURCE_DIR}/icons/512.png icon_bytes ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.h + DEPENDS ${CMAKE_SOURCE_DIR}/icons/512.png + ) + target_include_directories(Zelda64Recompiled PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + target_sources(Zelda64Recompiled PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/icon_bytes.c) message(STATUS "X11_FOUND = ${X11_FOUND}") message(STATUS "X11_Xrandr_FOUND = ${X11_Xrandr_FOUND}") message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}") message(STATUS "X11_LIBRARIES = ${X11_LIBRARIES}") - include_directories(${X11_INCLUDE_DIR} ${X11_Xrandr_INCLUDE_PATH}) + target_include_directories(Zelda64Recompiled PRIVATE ${X11_INCLUDE_DIR} ${X11_Xrandr_INCLUDE_PATH}) target_link_libraries(Zelda64Recompiled PRIVATE ${X11_LIBRARIES} ${X11_Xrandr_LIB}) find_package(Freetype REQUIRED) diff --git a/src/game/config.cpp b/src/game/config.cpp index 698a3c2..8194da3 100644 --- a/src/game/config.cpp +++ b/src/game/config.cpp @@ -19,7 +19,6 @@ constexpr std::u8string_view controls_filename = u8"controls.json"; constexpr std::u8string_view sound_filename = u8"sound.json"; constexpr auto res_default = ultramodern::Resolution::Auto; -constexpr auto wm_default = ultramodern::WindowMode::Windowed; constexpr auto hr_default = ultramodern::HUDRatioMode::Clamp16x9; constexpr auto api_default = ultramodern::GraphicsApi::Auto; constexpr auto ar_default = RT64::UserConfiguration::AspectRatio::Expand; @@ -29,6 +28,36 @@ constexpr int ds_default = 1; constexpr int rr_manual_default = 60; constexpr bool developer_mode_default = false; +static bool is_steam_deck = false; + +ultramodern::WindowMode wm_default() { + return is_steam_deck ? ultramodern::WindowMode::Fullscreen : ultramodern::WindowMode::Windowed; +} + +#ifdef __gnu_linux__ +void detect_steam_deck() { + // Check if the board vendor is Valve. + std::ifstream board_vendor_file("/sys/devices/virtual/dmi/id/board_vendor"); + std::string line; + if (std::getline(board_vendor_file, line).good() && line == "Valve") { + is_steam_deck = true; + return; + } + + // Check if the SteamDeck variable is set to 1. + const char* steam_deck_env = getenv("SteamDeck"); + if (steam_deck_env != nullptr && std::string{steam_deck_env} == "1") { + is_steam_deck = true; + return; + } + + is_steam_deck = false; + return; +} +#else +void detect_steam_deck() { is_steam_deck = false; } +#endif + template T from_or_default(const json& j, const std::string& key, T default_value) { T ret; @@ -71,7 +100,7 @@ namespace ultramodern { void from_json(const json& j, GraphicsConfig& config) { config.res_option = from_or_default(j, "res_option", res_default); - config.wm_option = from_or_default(j, "wm_option", wm_default); + config.wm_option = from_or_default(j, "wm_option", wm_default()); config.hr_option = from_or_default(j, "hr_option", hr_default); config.api_option = from_or_default(j, "api_option", api_default); config.ds_option = from_or_default(j, "ds_option", ds_default); @@ -145,7 +174,7 @@ void load_general_config(const std::filesystem::path& path) { recomp::set_background_input_mode(from_or_default(config_json, "background_input_mode", recomp::BackgroundInputMode::On)); recomp::set_rumble_strength(from_or_default(config_json, "rumble_strength", 25)); recomp::set_gyro_sensitivity(from_or_default(config_json, "gyro_sensitivity", 50)); - recomp::set_mouse_sensitivity(from_or_default(config_json, "mouse_sensitivity", 0)); + recomp::set_mouse_sensitivity(from_or_default(config_json, "mouse_sensitivity", is_steam_deck ? 50 : 0)); recomp::set_debug_mode_enabled(from_or_default(config_json, "debug_mode", false)); } @@ -204,7 +233,7 @@ void recomp::reset_kb_input_bindings() { void reset_graphics_options() { ultramodern::GraphicsConfig new_config{}; new_config.res_option = res_default; - new_config.wm_option = wm_default; + new_config.wm_option = wm_default(); new_config.hr_option = hr_default; new_config.ds_option = ds_default; new_config.ar_option = ar_default; @@ -329,6 +358,8 @@ void load_sound_config(const std::filesystem::path& path) { } void recomp::load_config() { + detect_steam_deck(); + std::filesystem::path recomp_dir = recomp::get_app_folder_path(); std::filesystem::path general_path = recomp_dir / general_filename; std::filesystem::path graphics_path = recomp_dir / graphics_filename; diff --git a/src/main/main.cpp b/src/main/main.cpp index 15dd750..215b7b0 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -58,12 +58,14 @@ ultramodern::gfx_callbacks_t::gfx_data_t create_gfx() { return {}; } -#if defined(__linux__) +#if defined(__gnu_linux__) +#include "icon_bytes.h" + bool SetImageAsIcon(const char* filename, SDL_Window* window) { // Read data int width, height, bytesPerPixel; - void* data = stbi_load(filename, &width, &height, &bytesPerPixel, 4); + void* data = stbi_load_from_memory(reinterpret_cast(icon_bytes), sizeof(icon_bytes), &width, &height, &bytesPerPixel, 4); // Calculate pitch int pitch; @@ -85,14 +87,14 @@ bool SetImageAsIcon(const char* filename, SDL_Window* window) Amask = 0x000000FF; #endif - SDL_Surface* surface; - if (data != NULL) { + SDL_Surface* surface = nullptr; + if (data != nullptr) { surface = SDL_CreateRGBSurfaceFrom(data, width, height, 32, pitch, Rmask, Gmask, Bmask, Amask); } - if (surface == NULL) { - if (data != NULL) { + if (surface == nullptr) { + if (data != nullptr) { stbi_image_free(data); } return false;