deps: update to SDL3 (#3852)

This PR updates to SDL3, and with it, adds a handful of new features.
Everything seems to work but I'm going to look over the code once last
time before merging, some of the API changes are hard to spot.

Fixes #2773

### Pressure sensitivity support for DS3 Controllers

SDL3 adds pressure sensitivity support for DS3 controllers on windows. I
have not tested on linux. The option is disabled by default.

On windows you will need https://docs.nefarius.at/projects/DsHidMini/
and to be using SXS mode.

### DualSense and Xbox One Trigger Effects

If enabled, Jak 2 will have certain trigger effects.  They are:
   - xbox1:
     - small vibrate when collecting dark eco
     - big vibrate when changing to dark jak
     - vibrate when shooting gun, proportional to gun type
   - ps5:
     - resistance when changing to dark jak
     - different gun shooting effects
       - red (resistance)
       - yellow (weapon trigger)
       - blue (vibrates)
       - purple (less resistance)
> **Gun Shooting effects are only enabled if the new "Swap R1 and R2"
option is enabled**

There are more effects that could be used in `dualsense_effects.cpp`,
but I only exposed the ones I needed to OpenGOAL. If a modder wants to
use some of the others and wires them up end-to-end, please consider
contributing that upstream.

### New ImGUI Menu

Added new imgui options for selecting the active controller, for those
people that struggle to select the initial controller.


![image](https://github.com/user-attachments/assets/48ff2985-d9ef-417a-b1f2-a25c74595935)

### Testing

The highlights of what I tested successfully:
   - display
     - [x] all mode switch permutations
     - [x] launch with all modes saved
- [x] switch monitors / unplug monitor that was active, how does it
handle it
     - [x] load with alternate monitor saved and all modes
     - [x] allowing hidpi doesnt break macos
   - controls
     - [x] keyboard and mouse still work
     - [x] pressure sensitivity on linux
This commit is contained in:
Tyler Wilding 2025-03-02 16:36:22 -05:00 committed by GitHub
parent 651b5b2a93
commit 1f6438e517
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2506 changed files with 637047 additions and 337848 deletions

View File

@ -32,6 +32,12 @@ if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json" )
"${PROJECT_SOURCE_DIR}/build/compile_commands.json")
endif()
# NOTE - for SDL, i think SDL3 regressed this - https://github.com/libsdl-org/SDL/pull/6455
# a more recent issue - https://github.com/libsdl-org/SDL/issues/12078
if (APPLE)
enable_language(OBJC)
endif()
# Setup compiler flags
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(STATUS "Clang Detected - Setting Defaults")
@ -254,9 +260,9 @@ build_third_party_lib(zstd libzstd_static)
# build SDL
include(SDLOptions)
if(STATICALLY_LINK)
build_third_party_lib(SDL SDL2-static)
build_third_party_lib(SDL SDL3-static)
else()
build_third_party_lib(SDL SDL2)
build_third_party_lib(SDL SDL3-shared)
endif()
# build imgui

View File

@ -1697,6 +1697,7 @@
(input-opts-binds-unknown #x1615)
(progress-no-other-resolution-options #x1616)
(input-opts-controller-led-reflect-heat #x1617)
(input-opts-controller-pressure-sensitivity #x1618)
;; GAME-TEXT-ID ENUM ENDS
)

View File

@ -8835,6 +8835,9 @@ Unlike [[engine]], users can use [[engine-pers]] as a parent class."
(language-name-czech #x1347)
(language-name-croatian #x1348)
(language-name-galician #x1349)
(progress-controller-options-enable-pressure-sensitivity #x134a)
(progress-controller-options-swap-r1-r2 #x134b)
(progress-controller-options-enable-trigger-effects #x134c)
)
;; ---text-id-h:text-id

View File

@ -9247,9 +9247,7 @@
"(event idle fac-gun-tower-base)": [[[18, 86], "s4", "projectile"]],
"(code idle fac-gun-tower-base)": [[10, "v1", "art-joint-anim"]],
"(method 36 fac-gun-tower)": [[46, "s2", "process-focusable"]],
"(method 35 fac-gun-tower)": [
[[72,76], "a0", "vehicle"]
],
"(method 35 fac-gun-tower)": [[[72, 76], "a0", "vehicle"]],
"fac-robotank-init-by-other": [
[182, "gp", "factory-manager"],
[208, "gp", "factory-manager"],

View File

@ -292,6 +292,7 @@ set(RUNTIME_SOURCE
settings/settings.cpp
system/background_worker.cpp
system/Deci2Server.cpp
system/hid/devices/dualsense_effects.cpp
system/hid/devices/game_controller.cpp
system/hid/devices/keyboard.cpp
system/hid/devices/mouse.cpp
@ -313,7 +314,7 @@ add_subdirectory(sound)
# we build the runtime as a static library.
add_library(runtime STATIC ${RUNTIME_SOURCE} "../third-party/glad/src/glad.c")
target_link_libraries(runtime common fmt SDL2::SDL2 imgui discord-rpc sound stb_image libco libcurl)
target_link_libraries(runtime common fmt SDL3::SDL3 imgui discord-rpc sound stb_image libco libcurl)
if(WIN32)
target_link_libraries(runtime mman)
else()

View File

@ -226,5 +226,6 @@
"1614": "UNSET",
"1615": "UNKNOWN",
"1616": "NO OTHER OPTIONS FOR ASPECT RATIO",
"1617": "CONTROLLER LED FOR HEAT"
"1617": "CONTROLLER LED FOR HEAT",
"1618": "PRESSURE SENSITIVITY"
}

View File

@ -248,5 +248,8 @@
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego"
"1349": "Galego",
"134a": "Pressure Sensitivity",
"134b": "Swap R1 and R2",
"134c": "Trigger Effects"
}

View File

@ -17,7 +17,7 @@ GPUTestOutput run_gpu_test(const std::string& test_type) {
lg::info("Running GPU Test - {}", test_type);
GPUTestOutput output = {false, "", ""};
if (test_type == "opengl") {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
if (!SDL_Init(SDL_INIT_VIDEO)) {
output = {false, "SDL initialization failed",
sdl_util::log_and_return_error("SDL initialization failed")};
return output;
@ -29,8 +29,7 @@ GPUTestOutput run_gpu_test(const std::string& test_type) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
#endif
SDL_Window* window =
SDL_CreateWindow("OpenGL Version", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800,
600, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
SDL_CreateWindow("OpenGL Version", 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
if (!window) {
output = {false, "SDL window creation failed",
sdl_util::log_and_return_error("SDL initialization failed")};
@ -56,7 +55,7 @@ GPUTestOutput run_gpu_test(const std::string& test_type) {
output.gpuVendorString = (const char*)vendorString;
}
}
SDL_GL_DeleteContext(glContext);
SDL_GL_DestroyContext(glContext);
}
SDL_DestroyWindow(window);
SDL_Quit();

View File

@ -104,5 +104,5 @@ void BlitDisplays::draw_debug_window() {
int w, h;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
ImGui::Image((void*)(u64)m_copier->texture(), ImVec2(w, h));
ImGui::Image((ImTextureID)(intptr_t)m_copier->texture(), ImVec2(w, h));
}

View File

@ -11,6 +11,9 @@
#include "third-party/imgui/imgui.h"
#define _USE_MATH_DEFINES
#include <math.h>
// #define dprintf(...) printf(__VA_ARGS__)
// #define dfmt(...) fmt::print(__VA_ARGS__)
#define dprintf(...)
@ -675,7 +678,7 @@ void imgui_show_tex(GLuint tex) {
int w, h;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
ImGui::Image((void*)(u64)tex, ImVec2(w, h));
ImGui::Image((ImTextureID)(intptr_t)tex, ImVec2(w, h));
}
void TextureAnimator::draw_debug_window() {

View File

@ -129,6 +129,7 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
}
if (ImGui::BeginMenu("Settings")) {
// ImGUI stuff
if (ImGui::TreeNode("ImGui Styling (restart required for these)")) {
ImGui::InputInt("Font Size", &Gfx::g_debug_settings.imgui_font_size);
ImGui::Checkbox("Monospaced Font", &Gfx::g_debug_settings.monospaced_font);
@ -142,6 +143,36 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
ImGui::TreePop();
}
ImGui::Checkbox("Ignore Hide ImGui Bind", &Gfx::g_debug_settings.ignore_hide_imgui);
// Controller Stuff
ImGui::Separator();
ImGui::Checkbox("Treat Controller Port 0 as Port 1",
&Gfx::g_debug_settings.treat_pad0_as_pad1);
auto is_keyboard_enabled =
Display::GetMainDisplay()->get_input_manager()->is_keyboard_enabled();
if (ImGui::Checkbox("Enable Keyboard (forced on if no controllers detected)",
&is_keyboard_enabled)) {
Display::GetMainDisplay()->get_input_manager()->enable_keyboard(is_keyboard_enabled);
}
for (int port = 0; port < 1; port++) {
const auto label = fmt::format("Selected Controller (Port {})", port);
if (ImGui::TreeNode(label.c_str())) {
const auto num_controllers =
Display::GetMainDisplay()->get_input_manager()->get_num_controllers();
for (int i = 0; i < num_controllers; i++) {
const auto controller_name =
Display::GetMainDisplay()->get_input_manager()->get_controller_name(i);
auto is_controller_active =
Display::GetMainDisplay()->get_input_manager()->get_controller_index(port) == i;
if (ImGui::RadioButton(controller_name.c_str(), is_controller_active)) {
Display::GetMainDisplay()->get_input_manager()->set_controller_for_port(i, port);
}
}
ImGui::TreePop();
}
}
// FPS Stuff
ImGui::Separator();
if (ImGui::TreeNode("Frame Rate")) {
ImGui::Checkbox("Framelimiter", &Gfx::g_global_settings.framelimiter);
ImGui::InputFloat("Target FPS", &target_fps_input);
@ -153,13 +184,6 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
ImGui::Checkbox("Sleep in Frame Limiter", &Gfx::g_global_settings.sleep_in_frame_limiter);
ImGui::TreePop();
}
ImGui::Checkbox("Treat Pad0 as Pad1", &Gfx::g_debug_settings.treat_pad0_as_pad1);
auto is_keyboard_enabled =
Display::GetMainDisplay()->get_input_manager()->is_keyboard_enabled();
if (ImGui::Checkbox("Enable Keyboard (forced on if no controllers detected)",
&is_keyboard_enabled)) {
Display::GetMainDisplay()->get_input_manager()->enable_keyboard(is_keyboard_enabled);
}
ImGui::EndMenu();
}

View File

@ -76,7 +76,7 @@ void OceanTexture::init_textures(TexturePool& pool, GameVersion version) {
void OceanTexture::draw_debug_window() {
if (m_tex0_gpu) {
ImGui::Image((void*)(u64)m_tex0_gpu->gpu_textures.at(0).gl,
ImGui::Image((ImTextureID)(intptr_t)m_tex0_gpu->gpu_textures.at(0).gl,
ImVec2(m_tex0_gpu->w, m_tex0_gpu->h));
}
}

View File

@ -31,10 +31,12 @@
#include "game/system/hid/sdl_util.h"
#include "fmt/core.h"
#include "third-party/SDL/include/SDL.h"
#include "third-party/SDL/include/SDL3/SDL.h"
#include "third-party/SDL/include/SDL3/SDL_hints.h"
#include "third-party/SDL/include/SDL3/SDL_version.h"
#include "third-party/imgui/imgui.h"
#include "third-party/imgui/imgui_impl_opengl3.h"
#include "third-party/imgui/imgui_impl_sdl.h"
#include "third-party/imgui/imgui_impl_sdl3.h"
#include "third-party/imgui/imgui_style.h"
#define STBI_WINDOWS_UTF8
#include "common/util/dialogs.h"
@ -101,7 +103,7 @@ static int gl_init(GfxGlobalSettings& settings) {
auto p = scoped_prof("startup::sdl::init_sdl");
// remove SDL garbage from hooking signal handler.
SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
if (!SDL_Init(SDL_INIT_VIDEO)) {
sdl_util::log_error("Could not initialize SDL, exiting");
dialogs::create_error_message_dialog("Critical Error Encountered",
"Could not initialize SDL, exiting");
@ -111,13 +113,11 @@ static int gl_init(GfxGlobalSettings& settings) {
{
auto p = scoped_prof("startup::sdl::get_version_info");
SDL_version compiled;
SDL_VERSION(&compiled);
SDL_version linked;
SDL_GetVersion(&linked);
lg::info("SDL Initialized, compiled with version - {}.{}.{} | linked with version - {}.{}.{}",
compiled.major, compiled.minor, compiled.patch, linked.major, linked.minor,
linked.patch);
auto compiled_sdl_version = SDL_VERSION;
auto linked_sdl_version = SDL_GetVersion();
lg::info("SDL Initialized, compiled with version - {} | linked with version - {}",
compiled_sdl_version, linked_sdl_version);
}
{
@ -197,7 +197,7 @@ static void init_imgui(SDL_Window* window,
}
// set up to get inputs for this window
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplSDL3_InitForOpenGL(window, gl_context);
// NOTE: imgui's setup calls functions that may fail intentionally, and attempts to disable error
// reporting so these errors are invisible. But it does not work, and some weird X11 default
@ -217,13 +217,9 @@ static std::shared_ptr<GfxDisplay> gl_make_display(int width,
// Setup the window
prof().instant_event("ROOT");
prof().begin_event("startup::sdl::create_window");
// TODO - SDL2 doesn't seem to support HDR (and neither does windows)
// Related -
// https://answers.microsoft.com/en-us/windows/forum/all/hdr-monitor-low-brightness-after-exiting-full/999f7ee9-7ba3-4f9c-b812-bbeb9ff8dcc1
SDL_Window* window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
// TODO - rendering code on hiDPI/Retina displays is not adequate, solve it properly so that
// `SDL_WINDOW_ALLOW_HIGHDPI` can be added back to the window flags.
SDL_Window* window =
SDL_CreateWindow(title, width, height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY);
prof().end_event();
if (!window) {
sdl_util::log_error("gl_make_display failed - Could not create display window");
@ -249,7 +245,7 @@ static std::shared_ptr<GfxDisplay> gl_make_display(int width,
{
auto p = scoped_prof("startup::sdl::assign_context");
if (SDL_GL_MakeCurrent(window, gl_context) != 0) {
if (!SDL_GL_MakeCurrent(window, gl_context)) {
sdl_util::log_error("gl_make_display failed - Could not associated context with window");
dialogs::create_error_message_dialog("Critical Error Encountered",
"Unable to create OpenGL window with context.\nOpenGOAL "
@ -285,14 +281,9 @@ static std::shared_ptr<GfxDisplay> gl_make_display(int width,
{
auto p = scoped_prof("startup::sdl::window_extras");
float dpi = 1.0f;
int window_display_idx = SDL_GetWindowDisplayIndex(window);
if (window_display_idx >= 0) {
SDL_GetDisplayDPI(window_display_idx, &dpi, NULL, NULL);
dpi /= 96.0f;
if (dpi <= 0.0f) {
dpi = 1.0f;
}
float display_scale = SDL_GetWindowDisplayScale(window);
if (display_scale > 0.0) {
dpi = display_scale * 96.0f;
}
// Setup Window Icon
@ -306,10 +297,14 @@ static std::shared_ptr<GfxDisplay> gl_make_display(int width,
auto icon_data = stbi_load(image_path.string().c_str(), &icon_width, &icon_height, nullptr,
STBI_rgb_alpha);
if (icon_data) {
SDL_Surface* icon_surf = SDL_CreateRGBSurfaceWithFormatFrom(
(void*)icon_data, icon_width, icon_height, 32, 4 * icon_width, SDL_PIXELFORMAT_RGBA32);
SDL_SetWindowIcon(window, icon_surf);
SDL_FreeSurface(icon_surf);
SDL_Surface* icon_surf = SDL_CreateSurfaceFrom(
icon_width, icon_height, SDL_PIXELFORMAT_RGBA32, (void*)icon_data, 4 * icon_width);
if (!icon_surf) {
sdl_util::log_error("unable to generate surface from app icon data");
} else {
SDL_SetWindowIcon(window, icon_surf);
SDL_DestroySurface(icon_surf);
}
stbi_image_free(icon_data);
} else {
lg::error("Could not load icon for OpenGL window, couldn't load image data");
@ -341,7 +336,7 @@ GLDisplay::GLDisplay(SDL_Window* window, SDL_GLContext gl_context, bool is_main)
: m_window(window),
m_gl_context(gl_context),
m_display_manager(std::make_shared<DisplayManager>(window)),
m_input_manager(std::make_shared<InputManager>()) {
m_input_manager(std::make_shared<InputManager>(window)) {
m_main = is_main;
m_display_manager->set_input_manager(m_input_manager);
// Register commands
@ -362,10 +357,10 @@ GLDisplay::~GLDisplay() {
io.IniFilename = nullptr;
io.LogFilename = nullptr;
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
// Cleanup SDL
SDL_GL_DeleteContext(m_gl_context);
SDL_GL_DestroyContext(m_gl_context);
SDL_DestroyWindow(m_window);
SDL_Quit();
if (m_main) {
@ -467,7 +462,7 @@ void render_game_frame(int game_width,
void GLDisplay::process_sdl_events() {
SDL_Event evt;
while (SDL_PollEvent(&evt) != 0) {
if (evt.type == SDL_QUIT) {
if (evt.type == SDL_EVENT_QUIT) {
m_should_quit = true;
}
{
@ -477,7 +472,7 @@ void GLDisplay::process_sdl_events() {
if (!m_should_quit) {
{
auto p = scoped_prof("imgui-sdl-process");
ImGui_ImplSDL2_ProcessEvent(&evt);
ImGui_ImplSDL3_ProcessEvent(&evt);
}
}
{
@ -528,13 +523,13 @@ void GLDisplay::render() {
{
auto p = scoped_prof("imgui-new-frame");
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
}
// framebuffer size
int fbuf_w, fbuf_h;
SDL_GL_GetDrawableSize(m_window, &fbuf_w, &fbuf_h);
SDL_GetWindowSizeInPixels(m_window, &fbuf_w, &fbuf_h);
// render game!
g_gfx_data->debug_gui.master_enable = is_imgui_visible();
@ -595,7 +590,7 @@ void GLDisplay::render() {
if (Gfx::g_global_settings.vsync != Gfx::g_global_settings.old_vsync) {
Gfx::g_global_settings.old_vsync = Gfx::g_global_settings.vsync;
// NOTE - -1 can be used for adaptive vsync, maybe useful for Jak 2+?
// https://wiki.libsdl.org/SDL2/SDL_GL_SetSwapInterval
// https://wiki.libsdl.org/SDL3/SDL_GL_SetSwapInterval
SDL_GL_SetSwapInterval(Gfx::g_global_settings.vsync);
}

View File

@ -11,7 +11,7 @@
#include "game/graphics/display.h"
#include "game/graphics/gfx.h"
#include "third-party/SDL/include/SDL.h"
#include "third-party/SDL/include/SDL3/SDL.h"
#include "third-party/glad/include/glad/glad.h"
class GLDisplay : public GfxDisplay {

View File

@ -382,7 +382,7 @@ void TexturePool::draw_debug_for_tex(const std::string& name, GpuTexture* tex, u
if (ImGui::TreeNode(fmt::format("{}) {}", slot, name).c_str())) {
ImGui::Text("P: %s sz: %d x %d", get_debug_texture_name(tex->tex_id).c_str(), tex->w, tex->h);
if (!tex->is_placeholder) {
ImGui::Image((void*)(u64)tex->gpu_textures.at(0).gl, ImVec2(tex->w, tex->h));
ImGui::Image((ImTextureID)(intptr_t)tex->gpu_textures.at(0).gl, ImVec2(tex->w, tex->h));
} else {
ImGui::Text("PLACEHOLDER");
}

View File

@ -450,7 +450,7 @@ u64 pc_get_mips2c(u32 name) {
u64 pc_get_display_id() {
if (Display::GetMainDisplay()) {
return Display::GetMainDisplay()->get_display_manager()->get_active_display_id();
return Display::GetMainDisplay()->get_display_manager()->get_active_display_index();
}
return 0;
}
@ -788,6 +788,96 @@ void pc_set_auto_hide_cursor(u32 val) {
}
}
u64 pc_get_pressure_sensitivity_enabled() {
if (Display::GetMainDisplay()) {
return bool_to_symbol(
Display::GetMainDisplay()->get_input_manager()->is_pressure_sensitivity_enabled());
}
return bool_to_symbol(false);
}
void pc_set_pressure_sensitivity_enabled(u32 val) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_input_manager()->set_pressure_sensitivity_enabled(
symbol_to_bool(val));
}
}
u64 pc_current_controller_has_pressure_sensitivity() {
if (Display::GetMainDisplay()) {
return bool_to_symbol(
Display::GetMainDisplay()->get_input_manager()->controller_has_pressure_sensitivity_support(
0));
}
return bool_to_symbol(false);
}
u64 pc_current_controller_has_trigger_effect_support() {
if (Display::GetMainDisplay()) {
return bool_to_symbol(
Display::GetMainDisplay()->get_input_manager()->controller_has_trigger_effect_support(0));
}
return bool_to_symbol(false);
}
u64 pc_get_trigger_effects_enabled() {
if (Display::GetMainDisplay()) {
return bool_to_symbol(
Display::GetMainDisplay()->get_input_manager()->are_trigger_effects_enabled());
}
return bool_to_symbol(false);
}
void pc_set_trigger_effects_enabled(u32 val) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_input_manager()->enqueue_set_trigger_effects_enabled(
symbol_to_bool(val));
}
}
void pc_clear_trigger_effect(dualsense_effects::TriggerEffectOption option) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_input_manager()->enqueue_controller_clear_trigger_effect(0,
option);
}
}
void pc_send_trigger_effect_feedback(dualsense_effects::TriggerEffectOption option,
u8 position,
u8 strength) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_input_manager()->enqueue_controller_send_trigger_effect_feedback(
0, option, position, strength);
}
}
void pc_send_trigger_effect_vibrate(dualsense_effects::TriggerEffectOption option,
u8 position,
u8 amplitude,
u8 frequency) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_input_manager()->enqueue_controller_send_trigger_effect_vibrate(
0, option, position, amplitude, frequency);
}
}
void pc_send_trigger_effect_weapon(dualsense_effects::TriggerEffectOption option,
u8 start_position,
u8 end_position,
u8 strength) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_input_manager()->enqueue_controller_send_trigger_effect_weapon(
0, option, start_position, end_position, strength);
}
}
void pc_send_trigger_rumble(u16 left_rumble, u16 right_rumble, u32 duration_ms) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_input_manager()->enqueue_controller_send_trigger_rumble(
0, left_rumble, right_rumble, duration_ms);
}
}
void pc_set_vsync(u32 sym_val) {
Gfx::g_global_settings.vsync = symbol_to_bool(sym_val);
}
@ -979,6 +1069,21 @@ void init_common_pc_port_functions(
make_func_symbol_func("pc-stop-waiting-for-bind!", (void*)pc_stop_waiting_for_bind);
make_func_symbol_func("pc-reset-bindings-to-defaults!", (void*)pc_reset_bindings_to_defaults);
make_func_symbol_func("pc-set-auto-hide-cursor!", (void*)pc_set_auto_hide_cursor);
make_func_symbol_func("pc-get-pressure-sensitivity-enabled?",
(void*)pc_get_pressure_sensitivity_enabled);
make_func_symbol_func("pc-set-pressure-sensitivity-enabled!",
(void*)pc_set_pressure_sensitivity_enabled);
make_func_symbol_func("pc-current-controller-has-pressure-sensitivity?",
(void*)pc_current_controller_has_pressure_sensitivity);
make_func_symbol_func("pc-current-controller-has-trigger-effect-support?",
(void*)pc_current_controller_has_trigger_effect_support);
make_func_symbol_func("pc-get-trigger-effects-enabled?", (void*)pc_get_trigger_effects_enabled);
make_func_symbol_func("pc-set-trigger-effects-enabled!", (void*)pc_set_trigger_effects_enabled);
make_func_symbol_func("pc-clear-trigger-effect!", (void*)pc_clear_trigger_effect);
make_func_symbol_func("pc-send-trigger-effect-feedback!", (void*)pc_send_trigger_effect_feedback);
make_func_symbol_func("pc-send-trigger-effect-vibrate!", (void*)pc_send_trigger_effect_vibrate);
make_func_symbol_func("pc-send-trigger-effect-weapon!", (void*)pc_send_trigger_effect_weapon);
make_func_symbol_func("pc-send-trigger-rumble!", (void*)pc_send_trigger_rumble);
// graphics things
make_func_symbol_func("pc-set-vsync", (void*)pc_set_vsync);

View File

@ -83,10 +83,9 @@ int scePadRead(int port, int /*slot*/, u8* rdata) {
std::tie(cpad->rightx, cpad->righty) = pad_data.value()->analog_right();
std::tie(cpad->leftx, cpad->lefty) = pad_data.value()->analog_left();
// pressure sensitivity. ignore for now.
for (size_t i = 0; i < PAD_DATA_PRESSURE_INDEX_ORDER.size(); i++) {
cpad->abutton[i] =
pad_data.value()->button_data.at(PAD_DATA_PRESSURE_INDEX_ORDER.at(i)) * 255;
// pressure sensitivity, ignored for almost all controllers
for (size_t i = 0; i < pad_data.value()->pressure_data.size(); i++) {
cpad->abutton[i] = pad_data.value()->pressure_data.at(i);
}
cpad->button0 = 0;

View File

@ -115,6 +115,8 @@ void to_json(json& j, const InputSettings& obj) {
json_serialize(keyboard_binds);
json_serialize(mouse_binds);
json_serialize(keyboard_enabled);
json_serialize(enable_pressure_sensitivity);
json_serialize(enable_trigger_effects);
}
void from_json(const json& j, InputSettings& obj) {
@ -125,6 +127,8 @@ void from_json(const json& j, InputSettings& obj) {
json_deserialize_if_exists(keyboard_binds);
json_deserialize_if_exists(mouse_binds);
json_deserialize_if_exists(keyboard_enabled);
json_deserialize_if_exists(enable_pressure_sensitivity);
json_deserialize_if_exists(enable_trigger_effects);
}
InputSettings::InputSettings() {}

View File

@ -65,8 +65,10 @@ struct InputSettings {
InputBindingGroups keyboard_binds;
InputBindingGroups mouse_binds;
bool keyboard_enabled = false;
bool keyboard_temp_enabled =
false; // not saved or restored, flips on if no controllers are detected
bool enable_trigger_effects = false;
bool enable_pressure_sensitivity = false;
// not saved or restored, flips on if no controllers are detected
bool _keyboard_temp_enabled = false;
void load_settings();
void save_settings();

View File

@ -0,0 +1,309 @@
/*
* MIT License
*
* Copyright (c) 2021-2022 John "Nielk1" Klein
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* https://gist.github.com/Nielk1/6d54cc2c00d2201ccb8c2720ad7538db
*/
#include "dualsense_effects.h"
#include <vector>
#include "array"
#include "common/common_types.h"
#include "common/log/log.h"
namespace dualsense_effects {
std::array<u8, 11> trigger_effect_off() {
std::array<u8, 11> effect_data;
effect_data[0] = (u8)TriggerEffectType::Off;
effect_data[1] = 0x00;
effect_data[2] = 0x00;
effect_data[3] = 0x00;
effect_data[4] = 0x00;
effect_data[5] = 0x00;
effect_data[6] = 0x00;
effect_data[7] = 0x00;
effect_data[8] = 0x00;
effect_data[9] = 0x00;
effect_data[10] = 0x00;
return effect_data;
}
std::array<u8, 11> trigger_effect_feedback(u8 position, u8 strength) {
if (position > 9) {
lg::error("Invalid argument for feedback trigger effect, position must be <= 9");
return trigger_effect_off();
}
if (strength > 8) {
lg::error("Invalid argument for feedback trigger effect, strength must be <= 8");
return trigger_effect_off();
}
if (strength > 0) {
std::array<u8, 11> effect_data;
u8 forceValue = (u8)((strength - 1) & 0x07);
u32 forceZones = 0;
u16 activeZones = 0;
for (int i = position; i < 10; i++) {
forceZones |= (u32)(forceValue << (3 * i));
activeZones |= (u16)(1 << i);
}
effect_data[0] = (u8)TriggerEffectType::Feedback;
effect_data[1] = (u8)((activeZones >> 0) & 0xff);
effect_data[2] = (u8)((activeZones >> 8) & 0xff);
effect_data[3] = (u8)((forceZones >> 0) & 0xff);
effect_data[4] = (u8)((forceZones >> 8) & 0xff);
effect_data[5] = (u8)((forceZones >> 16) & 0xff);
effect_data[6] = (u8)((forceZones >> 24) & 0xff);
effect_data[7] = 0x00; // (byte)((forceZones >> 32) & 0xff); // need 64bit for this, but we
// already have enough space
effect_data[8] = 0x00; // (byte)((forceZones >> 40) & 0xff); // need 64bit for this, but we
// already have enough space
effect_data[9] = 0x00;
effect_data[10] = 0x00;
return effect_data;
}
return trigger_effect_off();
}
std::array<u8, 11> trigger_effect_weapon(u8 start_position, u8 end_position, u8 strength) {
if (start_position > 7 || start_position < 2) {
lg::error("Invalid argument for weapon trigger effect, start_position must be <= 7 and >= 2");
return trigger_effect_off();
}
if (end_position > 8) {
lg::error("Invalid argument for weapon trigger effect, end_position must be <= 8");
return trigger_effect_off();
}
if (end_position <= start_position) {
lg::error("Invalid argument for weapon trigger effect, end_position must be > start_position");
return trigger_effect_off();
}
if (strength > 8) {
lg::error("Invalid argument for weapon trigger effect, strength must be <= 8");
return trigger_effect_off();
}
if (strength > 0) {
std::array<u8, 11> effect_data;
u16 startAndStopZones = (u16)((1 << start_position) | (1 << end_position));
effect_data[0] = (u8)TriggerEffectType::Weapon;
effect_data[1] = (u8)((startAndStopZones >> 0) & 0xff);
effect_data[2] = (u8)((startAndStopZones >> 8) & 0xff);
effect_data[3] = (u8)(strength - 1); // this is actually packed into 3 bits, but since it's
// only one why bother with the fancy code?
effect_data[4] = 0x00;
effect_data[5] = 0x00;
effect_data[6] = 0x00;
effect_data[7] = 0x00;
effect_data[8] = 0x00;
effect_data[9] = 0x00;
effect_data[10] = 0x00;
return effect_data;
}
return trigger_effect_off();
}
std::array<u8, 11> trigger_effect_vibration(u8 position, u8 amplitude, u8 frequency) {
if (position > 9) {
lg::error("Invalid argument for vibration trigger effect, position must be <= 9");
return trigger_effect_off();
}
if (amplitude > 8) {
lg::error("Invalid argument for vibration trigger effect, amplitude must be <= 8");
return trigger_effect_off();
}
if (amplitude > 0 && frequency > 0) {
u8 strengthValue = (u8)((amplitude - 1) & 0x07);
u32 amplitudeZones = 0;
u16 activeZones = 0;
for (int i = position; i < 10; i++) {
amplitudeZones |= (u32)(strengthValue << (3 * i));
activeZones |= (u16)(1 << i);
}
std::array<u8, 11> effect_data;
effect_data[0] = (u8)TriggerEffectType::Vibration;
effect_data[1] = (u8)((activeZones >> 0) & 0xff);
effect_data[2] = (u8)((activeZones >> 8) & 0xff);
effect_data[3] = (u8)((amplitudeZones >> 0) & 0xff);
effect_data[4] = (u8)((amplitudeZones >> 8) & 0xff);
effect_data[5] = (u8)((amplitudeZones >> 16) & 0xff);
effect_data[6] = (u8)((amplitudeZones >> 24) & 0xff);
effect_data[7] = 0x00; // (u8)((strengthZones >> 32) & 0xff); // need 64bit for this, but we
// already have enough space
effect_data[8] = 0x00; // (u8)((strengthZones >> 40) & 0xff); // need 64bit for this, but we
// already have enough space
effect_data[9] = frequency;
effect_data[10] = 0x00;
return effect_data;
}
return trigger_effect_off();
}
std::array<u8, 11> trigger_effect_multiple_position_feedback(const std::vector<u8>& strength) {
if (strength.size() != 10) {
lg::error(
"Invalid argument for multiple_position_feedback trigger effect, strength array must be "
"length 10");
return trigger_effect_off();
}
// Check to see if any of the strength values are actually above 0
bool return_off = true;
for (const auto& strength : strength) {
if (strength > 0) {
return_off = false;
break;
}
}
if (return_off) {
return trigger_effect_off();
}
u32 forceZones = 0;
u16 activeZones = 0;
for (int i = 0; i < 10; i++) {
if (strength[i] > 0) {
u8 forceValue = (u8)((strength[i] - 1) & 0x07);
forceZones |= (u32)(forceValue << (3 * i));
activeZones |= (u16)(1 << i);
}
}
std::array<u8, 11> effect_data;
effect_data[0] = (u8)TriggerEffectType::Feedback;
effect_data[1] = (u8)((activeZones >> 0) & 0xff);
effect_data[2] = (u8)((activeZones >> 8) & 0xff);
effect_data[3] = (u8)((forceZones >> 0) & 0xff);
effect_data[4] = (u8)((forceZones >> 8) & 0xff);
effect_data[5] = (u8)((forceZones >> 16) & 0xff);
effect_data[6] = (u8)((forceZones >> 24) & 0xff);
effect_data[7] = 0x00; // (byte)((forceZones >> 32) & 0xff); // need 64bit for this, but we
// already have enough space
effect_data[8] = 0x00; // (byte)((forceZones >> 40) & 0xff); // need 64bit for this, but we
// already have enough space
effect_data[9] = 0x00;
effect_data[10] = 0x00;
return effect_data;
}
std::array<u8, 11> trigger_effect_slope_feedback(u8 start_position,
u8 end_position,
u8 start_strength,
u8 end_strength) {
if (start_position > 8 || start_position < 0) {
lg::error(
"Invalid argument for slope_feedback trigger effect, start_position must be <= 8 and > 0");
return trigger_effect_off();
}
if (end_position > 9) {
lg::error("Invalid argument for slope_feedback trigger effect, end_position must be <= 9");
return trigger_effect_off();
}
if (end_position <= start_position) {
lg::error(
"Invalid argument for slope_feedback trigger effect, end_position must be > "
"start_position");
return trigger_effect_off();
}
if (start_strength > 8) {
lg::error("Invalid argument for slope_feedback trigger effect, start_strength must be >= 8");
return trigger_effect_off();
}
if (start_strength < 1) {
lg::error("Invalid argument for slope_feedback trigger effect, start_strength must be >= 1");
return trigger_effect_off();
}
if (end_strength > 8) {
lg::error("Invalid argument for slope_feedback trigger effect, end_strength must be <= 8");
return trigger_effect_off();
}
if (end_strength < 1) {
lg::error("Invalid argument for slope_feedback trigger effect, end_strength must be >= 1");
return trigger_effect_off();
}
std::vector<u8> strength;
float slope = 1.0f * (end_strength - start_strength) / (end_position - start_position);
for (int i = (int)start_position; i < 10; i++)
if (i <= end_position)
strength[i] = (u8)round(start_strength + slope * (i - start_position));
else
strength[i] = end_strength;
return trigger_effect_multiple_position_feedback(strength);
}
std::array<u8, 11> trigger_effect_multiple_position_vibrate(u8 frequency,
const std::vector<u8>& amplitude) {
if (amplitude.size() != 10) {
lg::error("Invalid argument for slope_feedback trigger effect, amplitude must be length 10");
return trigger_effect_off();
}
// Check to see if any of the amplitude values are actually above 0
bool return_off = true;
for (const auto& amplitude : amplitude) {
if (amplitude > 0) {
return_off = false;
break;
}
}
if (return_off) {
return trigger_effect_off();
}
if (frequency > 0) {
u32 strengthZones = 0;
u16 activeZones = 0;
for (int i = 0; i < 10; i++) {
if (amplitude[i] > 0) {
u8 strengthValue = (u8)((amplitude[i] - 1) & 0x07);
strengthZones |= (u32)(strengthValue << (3 * i));
activeZones |= (u16)(1 << i);
}
}
std::array<u8, 11> effect_data;
effect_data[0] = (u8)TriggerEffectType::Vibration;
effect_data[1] = (u8)((activeZones >> 0) & 0xff);
effect_data[2] = (u8)((activeZones >> 8) & 0xff);
effect_data[3] = (u8)((strengthZones >> 0) & 0xff);
effect_data[4] = (u8)((strengthZones >> 8) & 0xff);
effect_data[5] = (u8)((strengthZones >> 16) & 0xff);
effect_data[6] = (u8)((strengthZones >> 24) & 0xff);
effect_data[7] = 0x00; // (byte)((forceZones >> 32) & 0xff); // need 64bit for this, but we
// already have enough space
effect_data[8] = 0x00; // (byte)((forceZones >> 40) & 0xff); // need 64bit for this, but we
// already have enough space
effect_data[9] = frequency;
effect_data[10] = 0x00;
return effect_data;
}
return trigger_effect_off();
}
}; // namespace dualsense_effects

View File

@ -0,0 +1,176 @@
/*
* MIT License
*
* Copyright (c) 2021-2022 John "Nielk1" Klein
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* https://gist.github.com/Nielk1/6d54cc2c00d2201ccb8c2720ad7538db
*/
#pragma once
#include <array>
#include <vector>
#include "common/common_types.h"
namespace dualsense_effects {
enum class TriggerEffectOption { LEFT = 0, RIGHT = 1, BOTH = 2 };
struct DS5EffectsState_t {
u8 ucEnableBits1; /* 0 */
u8 ucEnableBits2; /* 1 */
u8 ucRumbleRight; /* 2 */
u8 ucRumbleLeft; /* 3 */
u8 ucHeadphoneVolume; /* 4 */
u8 ucSpeakerVolume; /* 5 */
u8 ucMicrophoneVolume; /* 6 */
u8 ucAudioEnableBits; /* 7 */
u8 ucMicLightMode; /* 8 */
u8 ucAudioMuteBits; /* 9 */
u8 rgucRightTriggerEffect[11]; /* 10 */
u8 rgucLeftTriggerEffect[11]; /* 21 */
u8 rgucUnknown1[6]; /* 32 */
u8 ucLedFlags; /* 38 */
u8 rgucUnknown2[2]; /* 39 */
u8 ucLedAnim; /* 41 */
u8 ucLedBrightness; /* 42 */
u8 ucPadLights; /* 43 */
u8 ucLedRed; /* 44 */
u8 ucLedGreen; /* 45 */
u8 ucLedBlue; /* 46 */
};
enum TriggerEffectType {
// Offically recognized modes
// These are 100% safe and are the only effects that modify the trigger status nybble
Off = 0x05, // 00 00 0 101
Feedback = 0x21, // 00 10 0 001
Weapon = 0x25, // 00 10 0 101
Vibration = 0x26, // 00 10 0 110
};
/// <summary>
/// Turn the trigger effect off and return the trigger stop to the neutral position.
/// This is an offical effect and is expected to be present in future DualSense firmware.
/// </summary>
/// <returns>The success of the effect
/// write.</returns>
std::array<u8, 11> trigger_effect_off();
/// <summary>
/// Trigger will resist movement beyond the start position.
/// The trigger status nybble will report 0 before the effect and 1 when in the effect.
/// This is an offical effect and is expected to be present in future DualSense firmware.
/// </summary>
/// <param name="position">The starting zone of the trigger effect. Must be between 0 and 9
/// inclusive.</param>
///
/// <param name="strength">The force of the resistance. Must be between 0 and 8 inclusive.</param>
///
/// <returns>The success of the effect write.</returns>
std::array<u8, 11> trigger_effect_feedback(u8 position, u8 strength);
/// <summary>
/// Trigger will resist movement beyond the start position until the end position.
/// The trigger status nybble will report 0 before the effect and 1 when in the effect,
/// and 2 after until again before the start position.
/// This is an offical effect and is expected to be present in future DualSense firmware.
/// </summary>
/// <param name="start_position">The starting zone of the trigger effect. Must be between 2 and 7
/// inclusive.</param>
///
/// <param name="end_position">The ending zone of the trigger effect. Must be between <paramref
/// name="start_position"/>+1 and 8 inclusive.</param>
///
/// <param name="strength">The force of the resistance. Must be between 0 and 8 inclusive.</param>
///
/// <returns>The success of the effect write.</returns>
std::array<u8, 11> trigger_effect_weapon(u8 start_position, u8 end_position, u8 strength);
/// <summary>
/// Trigger will vibrate with the input amplitude and frequency beyond the start position.
/// The trigger status nybble will report 0 before the effect and 1 when in the effect.
/// This is an offical effect and is expected to be present in future DualSense firmware.
/// </summary>
/// <param name="position">The starting zone of the trigger effect. Must be between 0 and 9
/// inclusive.</param>
///
/// <param name="amplitude">Strength of the automatic cycling action. Must be between 0 and 8
/// inclusive.</param>
///
/// <param name="frequency">Frequency of the automatic cycling action in hertz.</param>
///
/// <returns>The success of the effect write.</returns>
std::array<u8, 11> trigger_effect_vibration(u8 position, u8 amplitude, u8 frequency);
/// <summary>
/// Trigger will resist movement at varrying strengths in 10 regions.
/// This is an offical effect and is expected to be present in future DualSense firmware.
/// </summary>
/// <seealso cref="Feedback(byte[], int, byte, byte)"/>
/// <param name="strength">Array of 10 resistance values for zones 0 through 9. Must be between 0
/// and 8 inclusive.</param>
///
/// <returns>The success of the effect write.</returns>
std::array<u8, 11> trigger_effect_multiple_position_feedback(const std::vector<u8>& strength);
/// <summary>
/// Trigger will resist movement at a linear range of strengths.
/// This is an offical effect and is expected to be present in future DualSense firmware.
/// </summary>
/// <seealso cref="Feedback(byte[], int, byte, byte)"/>
/// <param name="startPosition">The starting zone of the trigger effect. Must be between 0 and 8
/// inclusive.</param>
///
/// <param name="endPosition">The ending zone of the trigger effect. Must be between <paramref
/// name="startPosition"/>+1 and 9 inclusive.</param>
///
/// <param name="startStrength">The force of the resistance at the start. Must be between 1 and 8
/// inclusive.</param>
///
/// <param name="endStrength">The force of the resistance at the end. Must be between 1 and 8
/// inclusive.</param>
///
/// <returns>The success of the effect write.</returns>
std::array<u8, 11> trigger_effect_slope_feedback(u8 start_position,
u8 end_position,
u8 start_strength,
u8 end_strength);
/// <summary>
/// Trigger will vibrate movement at varrying amplitudes and one frequency in 10 regions.
/// This is an offical effect and is expected to be present in future DualSense firmware.
/// </summary>
/// <remarks>
/// Note this factory's results may not perform as expected.
/// </remarks>
/// <seealso cref="Vibration(byte[], int, byte, byte, byte)"/>
/// <param name="amplitude">Array of 10 strength values for zones 0 through 9. Must be between 0 and
/// 8 inclusive.</param>
///
/// <param name="frequency">Frequency of the automatic cycling action in hertz.</param>
///
/// <returns>The success of the effect write.</returns>
std::array<u8, 11> trigger_effect_multiple_position_vibrate(u8 frequency,
const std::vector<u8>& amplitude);
}; // namespace dualsense_effects

View File

@ -1,5 +1,10 @@
#include "game_controller.h"
#include <optional>
#include "dualsense_effects.h"
#include "game_controller.h"
#include "game/system/hid/sdl_util.h"
#include "fmt/core.h"
@ -9,32 +14,33 @@ GameController::GameController(int sdl_device_id,
: m_sdl_instance_id(sdl_device_id) {
m_settings = settings;
m_loaded = false;
m_device_handle = SDL_GameControllerOpen(sdl_device_id);
m_device_handle = SDL_OpenGamepad(sdl_device_id);
if (!m_device_handle) {
sdl_util::log_error(
fmt::format("Could not open game controller with device id: {}", sdl_device_id));
return;
}
auto joystick = SDL_GameControllerGetJoystick(m_device_handle);
if (!joystick) {
m_low_device_handle = SDL_GetGamepadJoystick(m_device_handle);
if (!m_low_device_handle) {
sdl_util::log_error(
fmt::format("Could not get underlying joystick for gamecontroller: id {}", sdl_device_id));
return;
}
m_sdl_instance_id = SDL_JoystickInstanceID(joystick);
if (m_sdl_instance_id < 0) {
auto test = SDL_GetNumJoystickAxes(m_low_device_handle);
m_sdl_instance_id = SDL_GetJoystickID(m_low_device_handle);
if (!m_sdl_instance_id) {
sdl_util::log_error(
fmt::format("Could not determine instance id for gamecontroller: id {}", sdl_device_id));
return;
}
const auto controller_guid = SDL_JoystickGetGUID(joystick);
const auto controller_guid = SDL_GetJoystickGUID(m_low_device_handle);
if (sdl_util::is_SDL_GUID_zero(controller_guid)) {
sdl_util::log_error(fmt::format("Could not determine controller guid: id {}", sdl_device_id));
return;
}
char guidStr[33];
SDL_JoystickGetGUIDString(controller_guid, guidStr, sizeof(guidStr));
SDL_GUIDToString(controller_guid, guidStr, sizeof(guidStr));
m_guid = guidStr;
// NOTE - it has been observed that this function will return `NULL` which indicates a bad
@ -46,49 +52,87 @@ GameController::GameController(int sdl_device_id,
//
// So I'm letting this one go through, in most cases it had an invalid guid as well (so caught
// above).
auto name = SDL_GameControllerName(m_device_handle);
auto name = SDL_GetGamepadName(m_device_handle);
if (!name) {
sdl_util::log_error(fmt::format("Could not get device name with id: {}", sdl_device_id));
m_device_name = "";
} else {
m_device_name = name;
}
m_has_led = sdl_util::from_sdl_bool(SDL_GameControllerHasLED(m_device_handle));
m_has_rumble = sdl_util::from_sdl_bool(SDL_GameControllerHasRumble(m_device_handle));
auto properties = SDL_GetGamepadProperties(m_device_handle);
if (!properties) {
sdl_util::log_error(
fmt::format("Unable to retrieve properties for gamepad: id {}", sdl_device_id));
m_has_led = false;
m_has_rumble = false;
m_has_trigger_rumble = false;
m_is_dualsense = false;
} else {
m_has_led = SDL_GetBooleanProperty(properties, SDL_PROP_GAMEPAD_CAP_RGB_LED_BOOLEAN, false);
m_has_rumble = SDL_GetBooleanProperty(properties, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false);
m_has_trigger_rumble =
SDL_GetBooleanProperty(properties, SDL_PROP_GAMEPAD_CAP_TRIGGER_RUMBLE_BOOLEAN, false);
m_is_dualsense = SDL_GetGamepadType(m_device_handle) == SDL_GAMEPAD_TYPE_PS5;
clear_trigger_effect(dualsense_effects::TriggerEffectOption::BOTH);
}
if (m_settings->controller_binds.find(m_guid) == m_settings->controller_binds.end()) {
m_settings->controller_binds[m_guid] = DEFAULT_CONTROLLER_BINDS;
}
const auto num_axes = SDL_GetNumJoystickAxes(m_low_device_handle);
m_has_pressure_sensitive_buttons =
SDL_GetGamepadType(m_device_handle) == SDL_GAMEPAD_TYPE_PS3 && num_axes == 16;
if (m_has_pressure_sensitive_buttons) {
lg::info("Detected a PS3 controller with support for pressure sensitive buttons");
}
m_loaded = true;
}
static std::unordered_map<int, int> button_to_pressure_axes = {
{SDL_GAMEPAD_BUTTON_SOUTH, 6}, {SDL_GAMEPAD_BUTTON_EAST, 7},
{SDL_GAMEPAD_BUTTON_WEST, 8}, {SDL_GAMEPAD_BUTTON_NORTH, 9},
{SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, 10}, {SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, 11},
{SDL_GAMEPAD_BUTTON_DPAD_UP, 12}, {SDL_GAMEPAD_BUTTON_DPAD_DOWN, 13},
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, 14}, {SDL_GAMEPAD_BUTTON_DPAD_RIGHT, 15}};
static std::unordered_map<int, int> pressure_axes_to_button = {
{6, SDL_GAMEPAD_BUTTON_SOUTH}, {7, SDL_GAMEPAD_BUTTON_EAST},
{8, SDL_GAMEPAD_BUTTON_WEST}, {9, SDL_GAMEPAD_BUTTON_NORTH},
{10, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, {11, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER},
{12, SDL_GAMEPAD_BUTTON_DPAD_UP}, {13, SDL_GAMEPAD_BUTTON_DPAD_DOWN},
{14, SDL_GAMEPAD_BUTTON_DPAD_LEFT}, {15, SDL_GAMEPAD_BUTTON_DPAD_RIGHT}};
// Adjust the value range to 0-255 (127 being neutral)
// Values come out of SDL as -32,768 to 32,767
int normalize_axes_value(int sdl_val) {
return ((sdl_val + 32768) * 256) / 65536;
}
void GameController::process_event(const SDL_Event& event,
const CommandBindingGroups& commands,
std::shared_ptr<PadData> data,
std::optional<InputBindAssignmentMeta>& bind_assignment) {
if (event.type == SDL_CONTROLLERAXISMOTION && event.caxis.which == m_sdl_instance_id) {
// https://wiki.libsdl.org/SDL2/SDL_GameControllerAxis
if ((int)event.caxis.axis <= SDL_CONTROLLER_AXIS_INVALID ||
event.caxis.axis >= SDL_CONTROLLER_AXIS_MAX) {
if (event.type == SDL_EVENT_GAMEPAD_AXIS_MOTION && event.gaxis.which == m_sdl_instance_id) {
// https://wiki.libsdl.org/SDL3/SDL_GamepadAxis
if ((int)event.gaxis.axis <= SDL_GAMEPAD_AXIS_INVALID ||
event.gaxis.axis >= SDL_GAMEPAD_AXIS_COUNT) {
return;
}
auto& binds = m_settings->controller_binds.at(m_guid);
// Handle analog stick binds
if (event.caxis.axis >= SDL_CONTROLLER_AXIS_LEFTX &&
event.caxis.axis <= SDL_CONTROLLER_AXIS_RIGHTY && !data->analogs_being_simulated() &&
binds.analog_axii.find(event.caxis.axis) != binds.analog_axii.end()) {
for (const auto& bind : binds.analog_axii.at(event.caxis.axis)) {
// Adjust the value range to 0-255 (127 being neutral)
// Values come out of SDL as -32,768 + 32,767
int axis_val = ((event.caxis.value + 32768) * 256) / 65536;
data->analog_data.at(bind.pad_data_index) = axis_val;
if (event.gaxis.axis >= SDL_GAMEPAD_AXIS_LEFTX && event.gaxis.axis <= SDL_GAMEPAD_AXIS_RIGHTY &&
!data->analogs_being_simulated() &&
binds.analog_axii.find(event.gaxis.axis) != binds.analog_axii.end()) {
for (const auto& bind : binds.analog_axii.at(event.gaxis.axis)) {
data->analog_data.at(bind.pad_data_index) = normalize_axes_value(event.gaxis.value);
}
} else if (event.caxis.axis >= SDL_CONTROLLER_AXIS_TRIGGERLEFT &&
event.caxis.axis <= SDL_CONTROLLER_AXIS_TRIGGERRIGHT &&
binds.button_axii.find(event.caxis.axis) != binds.button_axii.end()) {
} else if (event.gaxis.axis >= SDL_GAMEPAD_AXIS_LEFT_TRIGGER &&
event.gaxis.axis <= SDL_GAMEPAD_AXIS_RIGHT_TRIGGER &&
binds.button_axii.find(event.gaxis.axis) != binds.button_axii.end()) {
// Binding re-assignment
if (bind_assignment) {
// In the event that the user binds an analog input to the confirm binds
@ -99,8 +143,8 @@ void GameController::process_event(const SDL_Event& event,
// assignment has been set but atleast it's in a mostly working state right now
if (!bind_assignment->seen_controller_confirm_neutral) {
for (const auto& confirm_bind : bind_assignment->controller_confirmation_binds) {
if (confirm_bind.sdl_idx == event.caxis.axis) {
if (event.caxis.value <= 0) {
if (confirm_bind.sdl_idx == event.gaxis.axis) {
if (event.gaxis.value <= 0) {
bind_assignment->seen_controller_confirm_neutral = true;
}
return;
@ -110,80 +154,203 @@ void GameController::process_event(const SDL_Event& event,
if (bind_assignment->device_type == InputDeviceType::CONTROLLER &&
!bind_assignment->for_analog) {
binds.assign_button_bind(event.caxis.axis, bind_assignment.value(), true);
binds.assign_button_bind(event.gaxis.axis, bind_assignment.value(), true);
}
return;
}
// and analog triggers
for (const auto& bind : binds.button_axii.at(event.caxis.axis)) {
data->button_data.at(bind.pad_data_index) = event.caxis.value > 0;
for (const auto& bind : binds.button_axii.at(event.gaxis.axis)) {
data->button_data.at(bind.pad_data_index) = event.gaxis.value > 0;
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
if (m_settings->enable_pressure_sensitivity && m_has_pressure_sensitive_buttons) {
data->pressure_data.at(pressure_index) = normalize_axes_value(event.gaxis.value);
} else {
data->pressure_data.at(pressure_index) = event.gaxis.value > 0 ? 255 : 0;
}
}
}
}
} else if ((event.type == SDL_CONTROLLERBUTTONDOWN || event.type == SDL_CONTROLLERBUTTONUP) &&
event.cbutton.which == m_sdl_instance_id) {
} else if ((event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN ||
event.type == SDL_EVENT_GAMEPAD_BUTTON_UP) &&
event.gbutton.which == m_sdl_instance_id) {
auto& binds = m_settings->controller_binds.at(m_guid);
// https://wiki.libsdl.org/SDL2/SDL_GameControllerButton
if ((int)event.cbutton.button <= SDL_CONTROLLER_BUTTON_INVALID ||
event.cbutton.button >= SDL_CONTROLLER_BUTTON_MAX) {
// https://wiki.libsdl.org/SDL3/SDL_GamepadButton
if ((int)event.gbutton.button <= SDL_GAMEPAD_BUTTON_INVALID ||
event.gbutton.button >= SDL_GAMEPAD_BUTTON_COUNT) {
return;
}
// Binding re-assignment
if (bind_assignment && event.type == SDL_CONTROLLERBUTTONDOWN) {
if (bind_assignment && event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
if (bind_assignment->device_type == InputDeviceType::CONTROLLER &&
!bind_assignment->for_analog) {
binds.assign_button_bind(event.cbutton.button, bind_assignment.value());
binds.assign_button_bind(event.gbutton.button, bind_assignment.value());
}
return;
}
if (binds.buttons.find(event.cbutton.button) == binds.buttons.end()) {
if (binds.buttons.find(event.gbutton.button) == binds.buttons.end()) {
return;
}
// Iterate the binds, and apply all of them
for (const auto& bind : binds.buttons.at(event.cbutton.button)) {
data->button_data.at(bind.pad_data_index) = event.type == SDL_CONTROLLERBUTTONDOWN;
for (const auto& bind : binds.buttons.at(event.gbutton.button)) {
// 1. pressed flag
data->button_data.at(bind.pad_data_index) = event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN;
// 2. potentially get the pressure value as well
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
if (m_settings->enable_pressure_sensitivity && m_has_pressure_sensitive_buttons &&
button_to_pressure_axes.contains(event.gbutton.button)) {
// TODO - handle error
const auto pressure_val = SDL_GetJoystickAxis(
m_low_device_handle, button_to_pressure_axes.at(event.gbutton.button));
data->pressure_data.at(pressure_index) = normalize_axes_value(pressure_val);
} else {
data->pressure_data.at(pressure_index) =
event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN ? 255 : 0;
}
}
}
// Check for commands
if (event.type == SDL_CONTROLLERBUTTONDOWN &&
commands.controller_binds.find(event.cbutton.button) != commands.controller_binds.end()) {
for (const auto& command : commands.controller_binds.at(event.cbutton.button)) {
if (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN &&
commands.controller_binds.find(event.gbutton.button) != commands.controller_binds.end()) {
for (const auto& command : commands.controller_binds.at(event.gbutton.button)) {
command.command();
}
}
} else if (SDL_EVENT_JOYSTICK_AXIS_MOTION && m_has_pressure_sensitive_buttons) {
// handle changes in pressure on axii not mapped to the gamepad (ie. PS3 analog buttons)
if (m_settings->enable_pressure_sensitivity &&
pressure_axes_to_button.contains(event.jaxis.axis)) {
auto& binds = m_settings->controller_binds.at(m_guid);
// Work backwords, get the button so we can iterate the binds
const auto sdl_button_index = pressure_axes_to_button.at(event.jaxis.axis);
for (const auto& bind : binds.buttons.at(sdl_button_index)) {
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = normalize_axes_value(event.jaxis.value);
}
}
}
}
}
void GameController::close_device() {
if (m_device_handle) {
SDL_GameControllerClose(m_device_handle);
clear_trigger_effect(dualsense_effects::TriggerEffectOption::BOTH);
SDL_CloseGamepad(m_device_handle);
}
}
int GameController::update_rumble(const u8 low_rumble, const u8 high_rumble) {
int GameController::send_rumble(const u8 low_rumble, const u8 high_rumble) {
if (m_has_rumble && m_device_handle) {
// https://wiki.libsdl.org/SDL2/SDL_GameControllerRumble
// https://wiki.libsdl.org/SDL3/SDL_RumbleGamepad
// Arbitrary duration, since it's called every frame anyway, just so the vibration doesn't last
// forever. SDL expects a value in the range of 0-0xFFFF, so the `257` is just normalizing the
// 0-255 we get to that range
if (SDL_GameControllerRumble(m_device_handle, low_rumble * 257, high_rumble * 257, 100) == 0) {
//
// NOTE - the 100ms is arbitrary, not sure how long the vibration lasted on the original ps2?
if (!SDL_RumbleGamepad(m_device_handle, low_rumble * 257, high_rumble * 257, 100)) {
return 1;
}
}
return 0;
}
void GameController::send_trigger_rumble(const u16 left_rumble,
const u16 right_rumble,
const u32 duration_ms) {
if (m_has_trigger_rumble && m_device_handle) {
// https://wiki.libsdl.org/SDL3/SDL_RumbleGamepadTriggers
if (!SDL_RumbleGamepadTriggers(m_device_handle, left_rumble, right_rumble, duration_ms)) {
sdl_util::log_error("Unable to rumble gamepad's triggers!");
}
}
}
dualsense_effects::DS5EffectsState_t prepare_effects_struct(
const dualsense_effects::TriggerEffectOption option,
const std::array<u8, 11>& effect) {
dualsense_effects::DS5EffectsState_t effects;
SDL_zero(effects);
// Modify right (0x04) and left (0x08) trigger effect
if (option == dualsense_effects::TriggerEffectOption::LEFT ||
option == dualsense_effects::TriggerEffectOption::BOTH) {
effects.ucEnableBits1 |= 0x08;
SDL_memcpy(effects.rgucLeftTriggerEffect, effect.data(), sizeof(effect));
}
if (option == dualsense_effects::TriggerEffectOption::RIGHT ||
option == dualsense_effects::TriggerEffectOption::BOTH) {
effects.ucEnableBits1 |= 0x04;
SDL_memcpy(effects.rgucRightTriggerEffect, effect.data(), sizeof(effect));
}
return effects;
}
void GameController::clear_trigger_effect(dualsense_effects::TriggerEffectOption option) {
if (m_is_dualsense && m_device_handle) {
const auto trigger_effect = dualsense_effects::trigger_effect_off();
const auto effects = prepare_effects_struct(option, trigger_effect);
if (!SDL_SendGamepadEffect(m_device_handle, &effects, sizeof(effects))) {
sdl_util::log_error("Unable to clear dualsense trigger effect!");
}
}
}
void GameController::send_trigger_effect_feedback(dualsense_effects::TriggerEffectOption option,
u8 position,
u8 strength) {
if (m_is_dualsense && m_device_handle) {
const auto trigger_effect = dualsense_effects::trigger_effect_feedback(position, strength);
const auto effects = prepare_effects_struct(option, trigger_effect);
if (!SDL_SendGamepadEffect(m_device_handle, &effects, sizeof(effects))) {
sdl_util::log_error("Unable to send dualsense feedback trigger effect!");
}
}
}
void GameController::send_trigger_effect_vibrate(dualsense_effects::TriggerEffectOption option,
u8 position,
u8 amplitude,
u8 frequency) {
if (m_is_dualsense && m_device_handle) {
const auto trigger_effect =
dualsense_effects::trigger_effect_vibration(position, amplitude, frequency);
const auto effects = prepare_effects_struct(option, trigger_effect);
if (!SDL_SendGamepadEffect(m_device_handle, &effects, sizeof(effects))) {
sdl_util::log_error("Unable to send dualsense vibrate trigger effect!");
}
}
}
void GameController::send_trigger_effect_weapon(dualsense_effects::TriggerEffectOption option,
u8 start_position,
u8 end_position,
u8 strength) {
if (m_is_dualsense && m_device_handle) {
const auto trigger_effect =
dualsense_effects::trigger_effect_weapon(start_position, end_position, strength);
const auto effects = prepare_effects_struct(option, trigger_effect);
if (!SDL_SendGamepadEffect(m_device_handle, &effects, sizeof(effects))) {
sdl_util::log_error("Unable to send dualsense weapon trigger effect!");
}
}
}
void GameController::set_led(const u8 red, const u8 green, const u8 blue) {
if (!m_has_led) {
return;
}
if (m_device_handle) {
auto ok = SDL_GameControllerSetLED(m_device_handle, red, green, blue);
if (ok != 0) {
if (!SDL_SetGamepadLED(m_device_handle, red, green, blue)) {
m_has_led = false;
}
}

View File

@ -1,8 +1,9 @@
#pragma once
#include "dualsense_effects.h"
#include "input_device.h"
// https://wiki.libsdl.org/SDL2/CategoryGameController
// https://wiki.libsdl.org/SDL3/CategoryGamepad
class GameController : public InputDevice {
public:
GameController(int sdl_device_id, std::shared_ptr<game_settings::InputSettings> settings);
@ -13,18 +14,41 @@ class GameController : public InputDevice {
std::shared_ptr<PadData> data,
std::optional<InputBindAssignmentMeta>& bind_assignment) override;
void close_device() override;
int update_rumble(const u8 low_rumble, const u8 high_rumble);
int send_rumble(const u8 low_rumble, const u8 high_rumble);
void send_trigger_rumble(const u16 left_rumble,
const u16 right_rumble,
const u32 duration_ms = 100);
void clear_trigger_effect(dualsense_effects::TriggerEffectOption option);
void send_trigger_effect_feedback(dualsense_effects::TriggerEffectOption option,
u8 position,
u8 strength);
void send_trigger_effect_vibrate(dualsense_effects::TriggerEffectOption option,
u8 position,
u8 amplitude,
u8 frequency);
void send_trigger_effect_weapon(dualsense_effects::TriggerEffectOption option,
u8 start_position,
u8 end_position,
u8 strength);
std::string get_name() const { return m_device_name; }
bool has_led() { return m_has_led; }
bool has_rumble() { return m_has_rumble; }
void set_led(const u8 red, const u8 green, const u8 blue);
std::string get_guid() { return m_guid; }
bool is_dualsense() { return m_is_dualsense; }
bool has_trigger_rumble() { return m_has_trigger_rumble; }
bool has_trigger_effect_support() { return has_trigger_rumble() || is_dualsense(); }
bool has_pressure_sensitivity_support() { return m_has_pressure_sensitive_buttons; }
private:
int m_sdl_instance_id = -1;
SDL_GameController* m_device_handle;
SDL_Gamepad* m_device_handle;
SDL_Joystick* m_low_device_handle;
std::string m_device_name = "";
bool m_has_led;
bool m_has_rumble;
std::string m_guid = "";
bool m_has_pressure_sensitive_buttons = false;
bool m_is_dualsense;
bool m_has_trigger_rumble;
};

View File

@ -4,8 +4,7 @@
#include "game/settings/settings.h"
#include "game/system/hid/input_bindings.h"
#include "third-party/SDL/include/SDL.h"
#include "game/system/hid/sdl_util.h"
// A distinct input device. Only those devices that are "active" should be read
class InputDevice {

View File

@ -19,19 +19,30 @@ bool KeyboardDevice::is_action_already_active(const u32 sdl_keycode) {
void KeyboardDevice::poll_state(std::shared_ptr<PadData> data) {
auto& binds = m_settings->keyboard_binds;
const auto keyboard_state = SDL_GetKeyboardState(NULL);
const auto keyboard_modifier_state = SDL_GetModState();
auto keyboard_modifier_state = SDL_GetModState();
// Iterate binds, see if there are any new actions we need to track
// - Normal Buttons
for (const auto& [sdl_keycode, bind_list] : binds.buttons) {
for (const auto& bind : bind_list) {
if (keyboard_state[SDL_GetScancodeFromKey(sdl_keycode)] &&
if (keyboard_state[SDL_GetScancodeFromKey(sdl_keycode, &keyboard_modifier_state)] &&
bind.modifiers.has_necessary_modifiers(keyboard_modifier_state) &&
!is_action_already_active(sdl_keycode)) {
data->button_data.at(bind.pad_data_index) = true; // press the button
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = 255;
}
m_active_actions.push_back(
{sdl_keycode, bind, [](std::shared_ptr<PadData> data, InputBinding bind) {
data->button_data.at(bind.pad_data_index) = false; // let go of the button
// let go of the button
data->button_data.at(bind.pad_data_index) = false;
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = 0;
}
}});
}
}
@ -39,13 +50,24 @@ void KeyboardDevice::poll_state(std::shared_ptr<PadData> data) {
// - Analog Buttons
for (const auto& [sdl_keycode, bind_list] : binds.button_axii) {
for (const auto& bind : bind_list) {
if (keyboard_state[SDL_GetScancodeFromKey(sdl_keycode)] &&
if (keyboard_state[SDL_GetScancodeFromKey(sdl_keycode, &keyboard_modifier_state)] &&
bind.modifiers.has_necessary_modifiers(keyboard_modifier_state) &&
!is_action_already_active(sdl_keycode)) {
data->button_data.at(bind.pad_data_index) = true; // press the button
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = 255;
}
m_active_actions.push_back(
{sdl_keycode, bind, [](std::shared_ptr<PadData> data, InputBinding bind) {
data->button_data.at(bind.pad_data_index) = false; // let go of the button
// let go of the button
data->button_data.at(bind.pad_data_index) = false;
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = 0;
}
}});
}
}
@ -53,7 +75,7 @@ void KeyboardDevice::poll_state(std::shared_ptr<PadData> data) {
// - Analog Sticks
for (const auto& [sdl_keycode, bind_list] : binds.analog_axii) {
for (const auto& bind : bind_list) {
if (keyboard_state[SDL_GetScancodeFromKey(sdl_keycode)] &&
if (keyboard_state[SDL_GetScancodeFromKey(sdl_keycode, &keyboard_modifier_state)] &&
bind.modifiers.has_necessary_modifiers(keyboard_modifier_state) &&
!is_action_already_active(sdl_keycode)) {
data->analog_data.at(bind.pad_data_index) += bind.minimum_in_range ? -127 : 127;
@ -72,7 +94,7 @@ void KeyboardDevice::poll_state(std::shared_ptr<PadData> data) {
for (auto it = m_active_actions.begin(); it != m_active_actions.end();) {
// Modifiers are easy, if the action required one and it's not pressed anymore, evict it
// Alternatively, was the primary key released
if (!keyboard_state[SDL_GetScancodeFromKey(it->sdl_keycode)] ||
if (!keyboard_state[SDL_GetScancodeFromKey(it->sdl_keycode, &keyboard_modifier_state)] ||
!it->binding.modifiers.has_necessary_modifiers(keyboard_modifier_state)) {
it->revert_action(data, it->binding);
it = m_active_actions.erase(it);
@ -93,10 +115,10 @@ void KeyboardDevice::process_event(const SDL_Event& event,
const CommandBindingGroups& commands,
std::shared_ptr<PadData> /*data*/,
std::optional<InputBindAssignmentMeta>& bind_assignment) {
if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
if (event.type == SDL_EVENT_KEY_DOWN || event.type == SDL_EVENT_KEY_UP) {
const auto key_event = event.key;
if (m_ignore_key_on_keyup && m_ignore_key_on_keyup.value() == (u32)key_event.keysym.sym &&
event.type == SDL_KEYUP) {
if (m_ignore_key_on_keyup && m_ignore_key_on_keyup.value() == (u32)key_event.key &&
event.type == SDL_EVENT_KEY_UP) {
m_ignore_key_on_keyup = std::nullopt;
return;
}
@ -109,22 +131,22 @@ void KeyboardDevice::process_event(const SDL_Event& event,
return;
}
// A normal key down event (a new key was pressed) and it's not a modifier
if (event.type == SDL_KEYDOWN && !sdl_util::is_modifier_key(key_event.keysym.sym)) {
if (event.type == SDL_EVENT_KEY_DOWN && !sdl_util::is_modifier_key(key_event.key)) {
if (bind_assignment->for_analog) {
m_ignore_key_on_keyup = key_event.keysym.sym;
binds.assign_analog_bind(key_event.keysym.sym, bind_assignment.value(),
InputModifiers(key_event.keysym.mod));
m_ignore_key_on_keyup = key_event.key;
binds.assign_analog_bind(key_event.key, bind_assignment.value(),
InputModifiers(key_event.mod));
} else {
binds.assign_button_bind(key_event.keysym.sym, bind_assignment.value(), false,
InputModifiers(key_event.keysym.mod));
binds.assign_button_bind(key_event.key, bind_assignment.value(), false,
InputModifiers(key_event.mod));
}
} else if (event.type == SDL_KEYUP) {
} else if (event.type == SDL_EVENT_KEY_UP) {
// modifiers are instead inspected on a KEYUP, however if it's one of the keys
// for triggering the binding assignment, and it's the first time we've seen it -- we ignore
// it
if (!bind_assignment->seen_keyboard_confirm_up) {
for (const auto& confirm_bind : bind_assignment->keyboard_confirmation_binds) {
if (confirm_bind.sdl_idx == key_event.keysym.sym) {
if (confirm_bind.sdl_idx == key_event.key) {
bind_assignment->seen_keyboard_confirm_up = true;
return;
}
@ -132,21 +154,21 @@ void KeyboardDevice::process_event(const SDL_Event& event,
}
// otherwise, set the bind
if (bind_assignment->for_analog) {
binds.assign_analog_bind(key_event.keysym.sym, bind_assignment.value(),
InputModifiers(key_event.keysym.mod));
binds.assign_analog_bind(key_event.key, bind_assignment.value(),
InputModifiers(key_event.mod));
} else {
binds.assign_button_bind(key_event.keysym.sym, bind_assignment.value(), false,
InputModifiers(key_event.keysym.mod));
binds.assign_button_bind(key_event.key, bind_assignment.value(), false,
InputModifiers(key_event.mod));
}
}
return;
}
// Check for commands
if (event.type == SDL_KEYDOWN &&
commands.keyboard_binds.find(key_event.keysym.sym) != commands.keyboard_binds.end()) {
for (const auto& command : commands.keyboard_binds.at(key_event.keysym.sym)) {
if (command.modifiers.has_necessary_modifiers(key_event.keysym.mod)) {
if (event.type == SDL_EVENT_KEY_DOWN &&
commands.keyboard_binds.find(key_event.key) != commands.keyboard_binds.end()) {
for (const auto& command : commands.keyboard_binds.at(key_event.key)) {
if (command.modifiers.has_necessary_modifiers(key_event.mod)) {
command.command();
}
}

View File

@ -1,8 +1,7 @@
#include "mouse.h"
#include "game/system/hid/sdl_util.h"
MouseDevice::MouseDevice(std::shared_ptr<game_settings::InputSettings> settings) {
MouseDevice::MouseDevice(SDL_Window* window, std::shared_ptr<game_settings::InputSettings> settings)
: m_window(window) {
m_settings = settings;
enable_relative_mode(m_control_camera);
}
@ -21,8 +20,8 @@ bool MouseDevice::is_action_already_active(const u32 sdl_code, const bool player
void MouseDevice::poll_state(std::shared_ptr<PadData> data) {
auto& binds = m_settings->mouse_binds;
int curr_mouse_x;
int curr_mouse_y;
float curr_mouse_x;
float curr_mouse_y;
const auto mouse_state = SDL_GetMouseState(&curr_mouse_x, &curr_mouse_y);
const auto keyboard_modifier_state = SDL_GetModState();
@ -36,8 +35,8 @@ void MouseDevice::poll_state(std::shared_ptr<PadData> data) {
if (m_frame_counter > 3) {
m_frame_counter = 0;
if (m_control_camera) {
int curr_mouse_relx;
int curr_mouse_rely;
float curr_mouse_relx;
float curr_mouse_rely;
const auto mouse_state_rel = SDL_GetRelativeMouseState(&curr_mouse_relx, &curr_mouse_rely);
(void)mouse_state_rel;
if (m_mouse_moved_x && m_last_xcoord == curr_mouse_x && curr_mouse_relx == 0) {
@ -57,13 +56,24 @@ void MouseDevice::poll_state(std::shared_ptr<PadData> data) {
// - Normal Buttons
for (const auto& [sdl_code, bind_list] : binds.buttons) {
for (const auto& bind : bind_list) {
if (mouse_state & SDL_BUTTON(sdl_code) &&
if (mouse_state & SDL_BUTTON_MASK(sdl_code) &&
bind.modifiers.has_necessary_modifiers(keyboard_modifier_state) &&
!is_action_already_active(sdl_code, false)) {
data->button_data.at(bind.pad_data_index) = true; // press the button
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = 255;
}
m_active_actions.push_back(
{sdl_code, bind, false, [](std::shared_ptr<PadData> data, InputBinding bind) {
data->button_data.at(bind.pad_data_index) = false; // let go of the button
// let go of the button
data->button_data.at(bind.pad_data_index) = false;
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = 0;
}
}});
}
}
@ -71,13 +81,24 @@ void MouseDevice::poll_state(std::shared_ptr<PadData> data) {
// - Analog Buttons (useless for keyboards, but here for completeness)
for (const auto& [sdl_code, bind_list] : binds.button_axii) {
for (const auto& bind : bind_list) {
if (mouse_state & SDL_BUTTON(sdl_code) &&
if (mouse_state & SDL_BUTTON_MASK(sdl_code) &&
bind.modifiers.has_necessary_modifiers(keyboard_modifier_state) &&
!is_action_already_active(sdl_code, false)) {
data->button_data.at(bind.pad_data_index) = true; // press the button
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = 255;
}
m_active_actions.push_back(
{sdl_code, bind, false, [](std::shared_ptr<PadData> data, InputBinding bind) {
data->button_data.at(bind.pad_data_index) = false; // let go of the button
// let go of the button
data->button_data.at(bind.pad_data_index) = false;
const auto pressure_index = data->button_index_to_pressure_index(
static_cast<PadData::ButtonIndex>(bind.pad_data_index));
if (pressure_index != PadData::PressureIndex::INVALID_PRESSURE) {
data->pressure_data.at(pressure_index) = 0;
}
}});
}
}
@ -111,7 +132,7 @@ void MouseDevice::poll_state(std::shared_ptr<PadData> data) {
it++;
}
} else {
if (!(mouse_state & SDL_BUTTON(it->sdl_mouse_button)) ||
if (!(mouse_state & SDL_BUTTON_MASK(it->sdl_mouse_button)) ||
!it->binding.modifiers.has_necessary_modifiers(keyboard_modifier_state)) {
it->revert_action(data, it->binding);
it = m_active_actions.erase(it);
@ -135,8 +156,8 @@ void MouseDevice::process_event(const SDL_Event& event,
std::optional<InputBindAssignmentMeta>& bind_assignment) {
// We still want to keep track of the cursor location even if we aren't using it for inputs
// return early
if (event.type == SDL_MOUSEMOTION) {
// https://wiki.libsdl.org/SDL2/SDL_MouseMotionEvent
if (event.type == SDL_EVENT_MOUSE_MOTION) {
// https://wiki.libsdl.org/SDL3/SDL_MouseMotionEvent
m_xcoord = event.motion.x;
m_ycoord = event.motion.y;
if (m_control_camera) {
@ -153,33 +174,33 @@ void MouseDevice::process_event(const SDL_Event& event,
}
data->analog_data.at(3) = yadjust;
}
} else if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
} else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN || event.type == SDL_EVENT_MOUSE_BUTTON_UP) {
// Mouse Button Events
// https://wiki.libsdl.org/SDL2/SDL_MouseButtonEvent
// https://wiki.libsdl.org/SDL3/SDL_MouseButtonEvent
const auto button_event = event.button;
// Update the internal mouse tracking, this is for GOAL reasons.
switch (button_event.button) {
case SDL_BUTTON_LEFT:
m_button_status.left = event.type == SDL_MOUSEBUTTONDOWN;
m_button_status.left = event.type == SDL_EVENT_MOUSE_BUTTON_DOWN;
break;
case SDL_BUTTON_RIGHT:
m_button_status.right = event.type == SDL_MOUSEBUTTONDOWN;
m_button_status.right = event.type == SDL_EVENT_MOUSE_BUTTON_DOWN;
break;
case SDL_BUTTON_MIDDLE:
m_button_status.middle = event.type == SDL_MOUSEBUTTONDOWN;
m_button_status.middle = event.type == SDL_EVENT_MOUSE_BUTTON_DOWN;
break;
case SDL_BUTTON_X1:
m_button_status.mouse4 = event.type == SDL_MOUSEBUTTONDOWN;
m_button_status.mouse4 = event.type == SDL_EVENT_MOUSE_BUTTON_DOWN;
break;
case SDL_BUTTON_X2:
m_button_status.mouse5 = event.type == SDL_MOUSEBUTTONDOWN;
m_button_status.mouse5 = event.type == SDL_EVENT_MOUSE_BUTTON_DOWN;
break;
}
auto& binds = m_settings->mouse_binds;
// Binding re-assignment
if (bind_assignment && event.type == SDL_MOUSEBUTTONDOWN) {
if (bind_assignment && event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (bind_assignment->device_type == InputDeviceType::MOUSE && !bind_assignment->for_analog) {
binds.assign_button_bind(button_event.button, bind_assignment.value(), false,
InputModifiers(SDL_GetModState()));
@ -188,7 +209,7 @@ void MouseDevice::process_event(const SDL_Event& event,
}
// Check for commands
if (event.type == SDL_MOUSEBUTTONDOWN &&
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN &&
commands.mouse_binds.find(button_event.button) != commands.mouse_binds.end()) {
for (const auto& command : commands.mouse_binds.at(button_event.button)) {
if (command.modifiers.has_necessary_modifiers(SDL_GetModState())) {
@ -200,8 +221,8 @@ void MouseDevice::process_event(const SDL_Event& event,
}
void MouseDevice::enable_relative_mode(const bool enable) {
// https://wiki.libsdl.org/SDL2/SDL_SetRelativeMouseMode
SDL_SetRelativeMouseMode(sdl_util::sdl_bool(enable));
// https://wiki.libsdl.org/SDL3/SDL_SetWindowRelativeMouseMode
SDL_SetWindowRelativeMouseMode(m_window, enable);
}
void MouseDevice::enable_camera_control(const bool enable) {

View File

@ -22,7 +22,7 @@ class MouseDevice : public InputDevice {
};
MouseDevice() {};
MouseDevice(std::shared_ptr<game_settings::InputSettings> settings);
MouseDevice(SDL_Window* window, std::shared_ptr<game_settings::InputSettings> settings);
~MouseDevice() {}
void poll_state(std::shared_ptr<PadData> data);
@ -46,6 +46,7 @@ class MouseDevice : public InputDevice {
bool is_camera_being_controlled() { return m_control_camera; }
private:
SDL_Window* m_window;
std::vector<ActiveMouseAction> m_active_actions = {};
// Track the state of mouse for Game reasons

View File

@ -20,6 +20,7 @@ DisplayManager::DisplayManager(SDL_Window* window) : m_window(window) {
#endif
update_curr_display_info();
update_video_modes();
// TODO - might be a good idea to end if no monitor is connected but...?
// Load from file now (after initializing current window settings)
m_display_settings.load_settings();
// Adjust window / monitor position
@ -42,8 +43,8 @@ DisplayManager::~DisplayManager() {
void DisplayManager::initialize_window_position_from_settings() {
// Check that the display id is still valid
if (m_current_display_modes.find(m_display_settings.display_id) ==
m_current_display_modes.end()) {
// Not to be confused with the new SDL_DisplayId, this is more like the display_index
if (m_display_settings.display_id >= m_current_display_modes.size()) {
lg::warn("[DISPLAY] Saved display ID is no longer valid, resetting to display 0");
m_display_settings.display_id = 0;
m_display_settings.window_xpos = 50;
@ -52,10 +53,12 @@ void DisplayManager::initialize_window_position_from_settings() {
}
SDL_Rect rect;
const auto ok = SDL_GetDisplayBounds(m_display_settings.display_id, &rect);
if (ok < 0) {
sdl_util::log_error(fmt::format("unable to get display bounds for display id {}",
m_display_settings.display_id));
const auto sdl_display_id =
m_current_display_modes.at(m_display_settings.display_id).sdl_display_id;
if (!SDL_GetDisplayBounds(sdl_display_id, &rect)) {
sdl_util::log_error(
fmt::format("unable to get display bounds for display index: {}, display id {}",
m_display_settings.display_id, sdl_display_id));
} else {
// Adjust the settings if they are out of bounds
if (m_display_settings.window_xpos <= rect.x ||
@ -77,51 +80,50 @@ void DisplayManager::initialize_window_position_from_settings() {
void DisplayManager::process_sdl_event(const SDL_Event& event) {
const auto event_type = event.type;
if (event_type == SDL_WINDOWEVENT) {
// https://wiki.libsdl.org/SDL2/SDL_WindowEvent
// https://wiki.libsdl.org/SDL2/SDL_WindowEventID
switch (event.window.event) {
case SDL_WINDOWEVENT_MINIMIZED:
if (event_type >= SDL_EVENT_WINDOW_FIRST && event_type <= SDL_EVENT_WINDOW_LAST) {
// https://wiki.libsdl.org/SDL3/SDL_WindowEvent
switch (event.window.type) {
case SDL_EVENT_WINDOW_MINIMIZED:
m_window_state = WindowState::Minimized;
break;
case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_EVENT_WINDOW_MAXIMIZED:
m_window_state = WindowState::Maximized;
break;
case SDL_WINDOWEVENT_RESTORED:
case SDL_EVENT_WINDOW_RESTORED:
m_window_state = WindowState::Restored;
break;
case SDL_WINDOWEVENT_MOVED:
case SDL_EVENT_WINDOW_MOVED:
m_window_xpos = event.window.data1;
m_window_ypos = event.window.data2;
break;
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
case SDL_EVENT_WINDOW_RESIZED:
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
m_window_width = event.window.data1;
m_window_height = event.window.data2;
break;
case SDL_WINDOWEVENT_DISPLAY_CHANGED:
case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
// NOTE - if the user changes the window to a display that doesn't support the same
// framerate we don't handle that
update_curr_display_info();
break;
case SDL_WINDOWEVENT_ENTER:
case SDL_EVENT_WINDOW_MOUSE_ENTER:
if (m_input_manager && m_input_manager.value()->auto_hiding_cursor()) {
m_input_manager.value()->hide_cursor(true);
}
break;
case SDL_WINDOWEVENT_LEAVE:
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
m_input_manager.value()->hide_cursor(false);
break;
}
} else if (event_type == SDL_DISPLAYEVENT) {
// https://wiki.libsdl.org/SDL2/SDL_DisplayEventID
switch (event.display.event) {
case SDL_DISPLAYEVENT_CONNECTED:
case SDL_DISPLAYEVENT_DISCONNECTED:
} else if (event_type >= SDL_EVENT_DISPLAY_FIRST && event_type <= SDL_EVENT_DISPLAY_LAST) {
// https://wiki.libsdl.org/SDL3/SDL_DisplayEvent
switch (event.display.type) {
case SDL_EVENT_DISPLAY_ADDED:
case SDL_EVENT_DISPLAY_REMOVED:
update_curr_display_info();
update_video_modes();
break;
case SDL_DISPLAYEVENT_ORIENTATION:
case SDL_EVENT_DISPLAY_ORIENTATION:
update_video_modes();
break;
}
@ -149,32 +151,32 @@ void DisplayManager::process_ee_events() {
}
std::string DisplayManager::get_connected_display_name(int id) {
if (m_current_display_modes.find(id) != m_current_display_modes.end()) {
if (m_current_display_modes.size() > id) {
return m_current_display_modes.at(id).display_name;
}
return "";
}
int DisplayManager::get_active_display_refresh_rate() {
if (get_active_display_id() >= 0 &&
m_current_display_modes.find(get_active_display_id()) != m_current_display_modes.end()) {
return m_current_display_modes.at(get_active_display_id()).refresh_rate;
const auto display_index = get_active_display_index();
if (m_current_display_modes.size() > display_index) {
return m_current_display_modes.at(display_index).refresh_rate;
}
return 0;
}
int DisplayManager::get_screen_width() {
if (get_active_display_id() >= 0 &&
m_current_display_modes.find(get_active_display_id()) != m_current_display_modes.end()) {
return m_current_display_modes.at(get_active_display_id()).screen_width;
const auto display_index = get_active_display_index();
if (m_current_display_modes.size() > display_index) {
return m_current_display_modes.at(display_index).screen_width;
}
return 640;
}
int DisplayManager::get_screen_height() {
if (get_active_display_id() >= 0 &&
m_current_display_modes.find(get_active_display_id()) != m_current_display_modes.end()) {
return m_current_display_modes.at(get_active_display_id()).screen_height;
const auto display_index = get_active_display_index();
if (m_current_display_modes.size() > display_index) {
return m_current_display_modes.at(display_index).screen_height;
}
return 480;
}
@ -222,59 +224,72 @@ void DisplayManager::enqueue_set_window_display_mode(
void DisplayManager::set_display_mode(game_settings::DisplaySettings::DisplayMode mode) {
lg::info("[DISPLAY] Setting to display mode: {}", static_cast<int>(mode));
// https://wiki.libsdl.org/SDL2/SDL_SetWindowFullscreen
// https://wiki.libsdl.org/SDL3/SDL_SetWindowFullscreen
int result = 0;
switch (mode) {
case game_settings::DisplaySettings::DisplayMode::Windowed:
result = SDL_SetWindowFullscreen(m_window, 0);
if (result == 0) {
if (SDL_SetWindowFullscreen(m_window, false)) {
lg::info("[DISPLAY] windowed mode - resizing window to {}x{}", m_window_width,
m_window_height);
SDL_SetWindowSize(m_window, m_window_width, m_window_height);
if (!SDL_SetWindowSize(m_window, m_window_width, m_window_height)) {
sdl_util::log_error("unable to change window size");
}
} else {
sdl_util::log_error("unable to change window to windowed mode");
}
break;
case game_settings::DisplaySettings::DisplayMode::Fullscreen:
case game_settings::DisplaySettings::DisplayMode::Borderless:
// 1. exit fullscreen
result = SDL_SetWindowFullscreen(m_window, 0);
if (result == 0) {
SDL_Rect display_bounds;
result = SDL_GetDisplayBounds(get_active_display_id(), &display_bounds);
if (result < 0) {
sdl_util::log_error(fmt::format("unable to get display bounds for display id {}",
get_active_display_id()));
} else {
// 2. move it to the right monitor
lg::info("[DISPLAY] preparing fullscreen - moving window to {},{} on display id {}",
display_bounds.x + 50, display_bounds.y + 50, get_active_display_id());
SDL_SetWindowPosition(m_window, display_bounds.x + 50, display_bounds.y + 50);
if (mode == game_settings::DisplaySettings::DisplayMode::Fullscreen) {
update_video_modes();
// If fullscreen, we have to resize the window to take up the full resolution
//
// Some people are weird and don't use the monitor's maximum supported resolution
// in which case, we use what the user actually has selected.
const auto& display_res = m_current_display_modes.at(get_active_display_id());
lg::info("[DISPLAY] preparing fullscreen - setting window resolution to {}x{}",
display_res.screen_width, display_res.screen_height);
set_window_size(display_res.screen_width, display_res.screen_height);
}
// 3. fullscreen it!
result = SDL_SetWindowFullscreen(
m_window, mode == game_settings::DisplaySettings::DisplayMode::Fullscreen
? SDL_WINDOW_FULLSCREEN
: SDL_WINDOW_FULLSCREEN_DESKTOP);
if (result < 0) {
sdl_util::log_error("unable to switch window fullscreen or borderless fullscreen");
}
}
} else {
sdl_util::log_error(
"unable to switch window to windowed mode in order to change fullscreen modes");
case game_settings::DisplaySettings::DisplayMode::Fullscreen: {
if (m_current_display_modes.size() <= get_active_display_index()) {
lg::error("Display index out of range, cannot switch to fullscreen");
break;
}
const auto current_display_mode = SDL_GetDesktopDisplayMode(
m_current_display_modes.at(get_active_display_index()).sdl_display_id);
if (!current_display_mode) {
sdl_util::log_error(fmt::format("unable to get current display mode for display index {}",
get_active_display_index()));
break;
}
if (!SDL_SetWindowFullscreenMode(m_window, current_display_mode)) {
sdl_util::log_error(fmt::format("unable to set fullscreen display mode"));
break;
}
if (!SDL_SetWindowFullscreen(m_window, true)) {
sdl_util::log_error(fmt::format("unable to enable fullscreen mode on window"));
break;
}
break;
}
case game_settings::DisplaySettings::DisplayMode::Borderless: {
// Move the window to the correct display first
SDL_Rect rect;
const auto sdl_display_id =
m_current_display_modes.at(m_display_settings.display_id).sdl_display_id;
if (!SDL_GetDisplayBounds(sdl_display_id, &rect)) {
sdl_util::log_error(
fmt::format("unable to get display bounds for display index: {}, display id {}",
m_display_settings.display_id, sdl_display_id));
break;
} else if (!SDL_SetWindowPosition(m_window, rect.x, rect.y)) {
sdl_util::log_error(
fmt::format("unable to move window before enabling borderless windowed mode"));
break;
}
if (!SDL_SyncWindow(m_window)) {
sdl_util::log_error(
fmt::format("failed waiting to move window before enabling borderless windowed mode"));
break;
}
if (!SDL_SetWindowFullscreenMode(m_window, NULL)) {
sdl_util::log_error(fmt::format("unable to set borderless fullscreen display mode"));
break;
}
if (!SDL_SetWindowFullscreen(m_window, true)) {
sdl_util::log_error(fmt::format("unable to enable borderless fullscreen mode on window"));
break;
}
break;
}
}
if (result != 0) {
sdl_util::log_error(
@ -305,12 +320,31 @@ void DisplayManager::set_display_id(int display_id) {
void DisplayManager::update_curr_display_info() {
lg::info("[DISPLAY] Updating current display info");
m_display_settings.display_id = SDL_GetWindowDisplayIndex(m_window);
if (get_active_display_id() < 0) {
sdl_util::log_error("could not retrieve current window's display index");
const auto current_sdl_display_id = SDL_GetDisplayForWindow(m_window);
if (current_sdl_display_id == 0) {
sdl_util::log_error("could not retrieve current window's sdl display id");
return;
}
lg::info("[DISPLAY] current display id is {}", m_display_settings.display_id);
SDL_GL_GetDrawableSize(m_window, &m_window_width, &m_window_height);
int num_displays = 0;
const auto display_ids = SDL_GetDisplays(&num_displays);
if (num_displays < 0 || !display_ids) {
sdl_util::log_error("could not retrieve sdl display ids");
return;
}
int display_index = -1;
for (int i = 0; i < num_displays; i++) {
if (current_sdl_display_id == display_ids[i]) {
display_index = i;
break;
}
}
if (display_index == -1) {
sdl_util::log_error("could not retrieve current window's display index");
return;
}
m_display_settings.display_id = display_index;
lg::info("[DISPLAY] current display idndex is {}", m_display_settings.display_id);
SDL_GetWindowSizeInPixels(m_window, &m_window_width, &m_window_height);
SDL_GetWindowPosition(m_window, &m_window_xpos, &m_window_ypos);
// Update the scale of the display as well
// TODO - figure out how to do this on SDL
@ -321,23 +355,23 @@ void DisplayManager::update_curr_display_info() {
void DisplayManager::update_video_modes() {
lg::info("[DISPLAY] Enumerating video modes");
const auto num_displays = SDL_GetNumVideoDisplays();
if (num_displays < 0) {
sdl_util::log_error("could not retrieve number of displays");
int num_displays = 0;
const auto display_ids = SDL_GetDisplays(&num_displays);
if (num_displays < 0 || !display_ids) {
sdl_util::log_error("could not retrieve display ids");
return;
}
m_current_display_modes.clear();
SDL_DisplayMode curr_mode;
for (int display_id = 0; display_id < num_displays; display_id++) {
const auto success = SDL_GetCurrentDisplayMode(display_id, &curr_mode);
if (success != 0) {
for (int i = 0; i < num_displays; i++) {
SDL_DisplayID display_id = display_ids[i];
const auto curr_mode = SDL_GetCurrentDisplayMode(display_id);
if (!curr_mode) {
sdl_util::log_error(
fmt::format("couldn't retrieve current display mode for display id {}", display_id));
continue;
}
auto display_orient = SDL_GetDisplayOrientation(display_id);
auto display_orient = SDL_GetCurrentDisplayOrientation(display_id);
Orientation orient = Orientation::Unknown;
switch (display_orient) {
case SDL_ORIENTATION_LANDSCAPE:
@ -364,9 +398,10 @@ void DisplayManager::update_video_modes() {
display_name_str = display_name;
}
DisplayMode new_mode = {display_name_str, curr_mode.format, curr_mode.w,
curr_mode.h, curr_mode.refresh_rate, orient};
m_current_display_modes[display_id] = new_mode;
DisplayMode new_mode = {display_id, display_name_str, curr_mode->format,
curr_mode->w, curr_mode->h, (int)curr_mode->refresh_rate,
orient};
m_current_display_modes.push_back(new_mode);
lg::info(
"[DISPLAY]: Found monitor {}, currently set to {}x{}@{}hz. Format: {}, Orientation: {}",
new_mode.display_name, new_mode.screen_width, new_mode.screen_height, new_mode.refresh_rate,
@ -378,26 +413,38 @@ void DisplayManager::update_video_modes() {
void DisplayManager::update_resolutions() {
lg::info("[DISPLAY] Enumerating resolutions");
// Enumerate display's display modes to get the resolutions
const auto active_display_id = get_active_display_id();
const auto active_refresh_rate = m_current_display_modes[active_display_id].refresh_rate;
auto num_display_modes = SDL_GetNumDisplayModes(active_display_id);
SDL_DisplayMode curr_mode;
const auto active_display_index = get_active_display_index();
if (active_display_index >= m_current_display_modes.size()) {
lg::error("Unable to enumerate resolutions, cant retrieve display mode");
}
const auto active_display_mode = m_current_display_modes.at(active_display_index);
const auto active_refresh_rate = active_display_mode.refresh_rate;
int num_display_modes = 0;
SDL_DisplayMode** modes =
SDL_GetFullscreenDisplayModes(active_display_mode.sdl_display_id, &num_display_modes);
if (!modes) {
sdl_util::log_error(
fmt::format("Unable to retrieve display modes for display id: {}", active_display_index));
return;
}
for (int i = 0; i < num_display_modes; i++) {
auto ok = SDL_GetDisplayMode(active_display_id, i, &curr_mode);
if (ok != 0) {
sdl_util::log_error(
fmt::format("unable to get display mode for display {}, index {}", active_display_id, i));
auto display_mode = modes[i];
if (!display_mode) {
sdl_util::log_error(fmt::format("unable to get display mode for display {}, index {}",
active_display_mode.sdl_display_id, i));
continue;
}
Resolution new_res = {curr_mode.w, curr_mode.h,
static_cast<float>(curr_mode.w) / static_cast<float>(curr_mode.h)};
Resolution new_res = {
display_mode->w, display_mode->h,
static_cast<float>(display_mode->w) / static_cast<float>(display_mode->h)};
// Skip resolutions that aren't using the current refresh rate, they won't work.
// For example if your monitor is currently set to `60hz` and the monitor _could_ support
// resolution X but only at `30hz`...then there's no reason for us to consider it as an option.
if (curr_mode.refresh_rate != active_refresh_rate) {
if (display_mode->refresh_rate != active_refresh_rate) {
lg::debug(
"[DISPLAY]: Skipping {}x{} as it requires {}hz but the monitor is currently set to {}hz",
curr_mode.w, curr_mode.h, curr_mode.refresh_rate, active_refresh_rate);
display_mode->w, display_mode->h, display_mode->refresh_rate, active_refresh_rate);
// Allow it for windowed mode though
m_available_window_sizes.push_back(new_res);
continue;

View File

@ -10,7 +10,7 @@
#include "game/settings/settings.h"
#include "game/system/hid/input_manager.h"
#include "third-party/SDL/include/SDL.h"
#include "third-party/SDL/include/SDL3/SDL.h"
/*
TODO:
@ -21,10 +21,11 @@ enum class WindowState { Minimized, Maximized, Restored };
enum class Orientation { Landscape, LandscapeFlipped, Portrait, PortraitFlipped, Unknown };
/// https://wiki.libsdl.org/SDL2/SDL_DisplayMode
/// https://wiki.libsdl.org/SDL3/SDL_DisplayMode
struct DisplayMode {
SDL_DisplayID sdl_display_id;
std::string display_name;
/// https://wiki.libsdl.org/SDL2/SDL_PixelFormatEnum
/// https://wiki.libsdl.org/SDL3/SDL_PixelFormat
uint32_t sdl_pixel_format;
int screen_width;
int screen_height;
@ -63,7 +64,7 @@ class DisplayManager {
/// event so it can be ran from the proper thread context (the graphics thread)
void process_ee_events();
int get_active_display_id() { return m_display_settings.display_id; }
int get_active_display_index() { return m_display_settings.display_id; }
bool is_window_active() { return m_window != nullptr; }
bool is_minimized() { return m_window_state == WindowState::Minimized; }
int get_window_width() { return m_window_width; }
@ -121,7 +122,7 @@ class DisplayManager {
// the only one that matters is the one the user _currently_ has configured
//
// ie. allowing someone to set 150fps on a monitor set to 60hz is not correct
std::unordered_map<int, DisplayMode> m_current_display_modes;
std::vector<DisplayMode> m_current_display_modes;
std::vector<Resolution> m_available_resolutions;
std::vector<Resolution> m_available_window_sizes;

View File

@ -6,26 +6,26 @@
#include "game/system/hid/sdl_util.h"
#include "third-party/SDL/include/SDL.h"
#include "third-party/SDL/include/SDL3/SDL.h"
InputModifiers::InputModifiers(const u16 sdl_mod_state) {
need_shift = sdl_mod_state & KMOD_SHIFT;
need_alt = sdl_mod_state & KMOD_ALT;
need_ctrl = sdl_mod_state & KMOD_CTRL;
need_meta = sdl_mod_state & KMOD_GUI;
need_shift = sdl_mod_state & SDL_KMOD_SHIFT;
need_alt = sdl_mod_state & SDL_KMOD_ALT;
need_ctrl = sdl_mod_state & SDL_KMOD_CTRL;
need_meta = sdl_mod_state & SDL_KMOD_GUI;
}
bool InputModifiers::has_necessary_modifiers(const u16 key_modifiers) const {
if (need_alt && ((key_modifiers & KMOD_ALT) == 0)) {
if (need_alt && ((key_modifiers & SDL_KMOD_ALT) == 0)) {
return false;
}
if (need_ctrl && ((key_modifiers & KMOD_CTRL) == 0)) {
if (need_ctrl && ((key_modifiers & SDL_KMOD_CTRL) == 0)) {
return false;
}
if (need_meta && ((key_modifiers & KMOD_GUI) == 0)) {
if (need_meta && ((key_modifiers & SDL_KMOD_GUI) == 0)) {
return false;
}
if (need_shift && ((key_modifiers & KMOD_SHIFT) == 0)) {
if (need_shift && ((key_modifiers & SDL_KMOD_SHIFT) == 0)) {
return false;
}
return true;
@ -70,62 +70,54 @@ void from_json(const json& j, InputBindingGroups& obj) {
json_deserialize_if_exists(buttons);
}
const std::vector<PadData::ButtonIndex> PAD_DATA_PRESSURE_INDEX_ORDER = {
PadData::ButtonIndex::DPAD_RIGHT, PadData::ButtonIndex::DPAD_LEFT,
PadData::ButtonIndex::DPAD_UP, PadData::ButtonIndex::DPAD_DOWN,
PadData::ButtonIndex::TRIANGLE, PadData::ButtonIndex::CIRCLE,
PadData::ButtonIndex::CROSS, PadData::ButtonIndex::SQUARE,
PadData::ButtonIndex::L1, PadData::ButtonIndex::R1,
PadData::ButtonIndex::L2, PadData::ButtonIndex::R2};
const InputBindingGroups DEFAULT_CONTROLLER_BINDS = InputBindingGroups(
CONTROLLER,
{{SDL_CONTROLLER_AXIS_LEFTX, {InputBinding(PadData::AnalogIndex::LEFT_X)}},
{SDL_CONTROLLER_AXIS_LEFTY, {InputBinding(PadData::AnalogIndex::LEFT_Y)}},
{SDL_CONTROLLER_AXIS_RIGHTX, {InputBinding(PadData::AnalogIndex::RIGHT_X)}},
{SDL_CONTROLLER_AXIS_RIGHTY, {InputBinding(PadData::AnalogIndex::RIGHT_Y)}}},
{{SDL_GAMEPAD_AXIS_LEFTX, {InputBinding(PadData::AnalogIndex::LEFT_X)}},
{SDL_GAMEPAD_AXIS_LEFTY, {InputBinding(PadData::AnalogIndex::LEFT_Y)}},
{SDL_GAMEPAD_AXIS_RIGHTX, {InputBinding(PadData::AnalogIndex::RIGHT_X)}},
{SDL_GAMEPAD_AXIS_RIGHTY, {InputBinding(PadData::AnalogIndex::RIGHT_Y)}}},
{
{SDL_CONTROLLER_AXIS_TRIGGERLEFT, {InputBinding(PadData::ButtonIndex::L2)}},
{SDL_CONTROLLER_AXIS_TRIGGERRIGHT, {InputBinding(PadData::ButtonIndex::R2)}},
{SDL_GAMEPAD_AXIS_LEFT_TRIGGER, {InputBinding(PadData::ButtonIndex::L2)}},
{SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, {InputBinding(PadData::ButtonIndex::R2)}},
},
{{SDL_CONTROLLER_BUTTON_A, {InputBinding(PadData::ButtonIndex::CROSS)}},
{SDL_CONTROLLER_BUTTON_B, {InputBinding(PadData::ButtonIndex::CIRCLE)}},
{SDL_CONTROLLER_BUTTON_X, {InputBinding(PadData::ButtonIndex::SQUARE)}},
{SDL_CONTROLLER_BUTTON_Y, {InputBinding(PadData::ButtonIndex::TRIANGLE)}},
{SDL_CONTROLLER_BUTTON_LEFTSTICK, {InputBinding(PadData::ButtonIndex::L3)}},
{SDL_CONTROLLER_BUTTON_RIGHTSTICK, {InputBinding(PadData::ButtonIndex::R3)}},
{SDL_CONTROLLER_BUTTON_BACK, {InputBinding(PadData::ButtonIndex::SELECT)}},
{SDL_CONTROLLER_BUTTON_START, {InputBinding(PadData::ButtonIndex::START)}},
{SDL_CONTROLLER_BUTTON_LEFTSHOULDER, {InputBinding(PadData::ButtonIndex::L1)}},
{SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, {InputBinding(PadData::ButtonIndex::R1)}},
{SDL_CONTROLLER_BUTTON_DPAD_UP, {InputBinding(PadData::ButtonIndex::DPAD_UP)}},
{SDL_CONTROLLER_BUTTON_DPAD_DOWN, {InputBinding(PadData::ButtonIndex::DPAD_DOWN)}},
{SDL_CONTROLLER_BUTTON_DPAD_LEFT, {InputBinding(PadData::ButtonIndex::DPAD_LEFT)}},
{SDL_CONTROLLER_BUTTON_DPAD_RIGHT, {InputBinding(PadData::ButtonIndex::DPAD_RIGHT)}}});
{{SDL_GAMEPAD_BUTTON_SOUTH, {InputBinding(PadData::ButtonIndex::CROSS)}},
{SDL_GAMEPAD_BUTTON_EAST, {InputBinding(PadData::ButtonIndex::CIRCLE)}},
{SDL_GAMEPAD_BUTTON_WEST, {InputBinding(PadData::ButtonIndex::SQUARE)}},
{SDL_GAMEPAD_BUTTON_NORTH, {InputBinding(PadData::ButtonIndex::TRIANGLE)}},
{SDL_GAMEPAD_BUTTON_LEFT_STICK, {InputBinding(PadData::ButtonIndex::L3)}},
{SDL_GAMEPAD_BUTTON_RIGHT_STICK, {InputBinding(PadData::ButtonIndex::R3)}},
{SDL_GAMEPAD_BUTTON_BACK, {InputBinding(PadData::ButtonIndex::SELECT)}},
{SDL_GAMEPAD_BUTTON_START, {InputBinding(PadData::ButtonIndex::START)}},
{SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, {InputBinding(PadData::ButtonIndex::L1)}},
{SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, {InputBinding(PadData::ButtonIndex::R1)}},
{SDL_GAMEPAD_BUTTON_DPAD_UP, {InputBinding(PadData::ButtonIndex::DPAD_UP)}},
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, {InputBinding(PadData::ButtonIndex::DPAD_DOWN)}},
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, {InputBinding(PadData::ButtonIndex::DPAD_LEFT)}},
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, {InputBinding(PadData::ButtonIndex::DPAD_RIGHT)}}});
const InputBindingGroups DEFAULT_KEYBOARD_BINDS =
InputBindingGroups(KEYBOARD,
{{SDLK_a, {InputBinding(PadData::AnalogIndex::LEFT_X, true)}},
{SDLK_d, {InputBinding(PadData::AnalogIndex::LEFT_X)}},
{SDLK_s, {InputBinding(PadData::AnalogIndex::LEFT_Y)}},
{SDLK_w, {InputBinding(PadData::AnalogIndex::LEFT_Y, true)}},
{SDLK_l, {InputBinding(PadData::AnalogIndex::RIGHT_X, true)}},
{SDLK_j, {InputBinding(PadData::AnalogIndex::RIGHT_X)}},
{SDLK_k, {InputBinding(PadData::AnalogIndex::RIGHT_Y)}},
{SDLK_i, {InputBinding(PadData::AnalogIndex::RIGHT_Y, true)}}},
{{SDLK_A, {InputBinding(PadData::AnalogIndex::LEFT_X, true)}},
{SDLK_D, {InputBinding(PadData::AnalogIndex::LEFT_X)}},
{SDLK_S, {InputBinding(PadData::AnalogIndex::LEFT_Y)}},
{SDLK_W, {InputBinding(PadData::AnalogIndex::LEFT_Y, true)}},
{SDLK_L, {InputBinding(PadData::AnalogIndex::RIGHT_X, true)}},
{SDLK_J, {InputBinding(PadData::AnalogIndex::RIGHT_X)}},
{SDLK_K, {InputBinding(PadData::AnalogIndex::RIGHT_Y)}},
{SDLK_I, {InputBinding(PadData::AnalogIndex::RIGHT_Y, true)}}},
{},
{{SDLK_SPACE, {InputBinding(PadData::ButtonIndex::CROSS)}},
{SDLK_e, {InputBinding(PadData::ButtonIndex::CIRCLE)}},
{SDLK_f, {InputBinding(PadData::ButtonIndex::SQUARE)}},
{SDLK_r, {InputBinding(PadData::ButtonIndex::TRIANGLE)}},
{SDLK_E, {InputBinding(PadData::ButtonIndex::CIRCLE)}},
{SDLK_F, {InputBinding(PadData::ButtonIndex::SQUARE)}},
{SDLK_R, {InputBinding(PadData::ButtonIndex::TRIANGLE)}},
{SDLK_COMMA, {InputBinding(PadData::ButtonIndex::L3)}},
{SDLK_PERIOD, {InputBinding(PadData::ButtonIndex::R3)}},
{SDLK_QUOTE, {InputBinding(PadData::ButtonIndex::SELECT)}},
{SDLK_APOSTROPHE, {InputBinding(PadData::ButtonIndex::SELECT)}},
{SDLK_RETURN, {InputBinding(PadData::ButtonIndex::START)}},
{SDLK_q, {InputBinding(PadData::ButtonIndex::L1)}},
{SDLK_o, {InputBinding(PadData::ButtonIndex::R1)}},
{SDLK_Q, {InputBinding(PadData::ButtonIndex::L1)}},
{SDLK_O, {InputBinding(PadData::ButtonIndex::R1)}},
{SDLK_1, {InputBinding(PadData::ButtonIndex::L2)}},
{SDLK_p, {InputBinding(PadData::ButtonIndex::R2)}},
{SDLK_P, {InputBinding(PadData::ButtonIndex::R2)}},
{SDLK_UP, {InputBinding(PadData::ButtonIndex::DPAD_UP)}},
{SDLK_DOWN, {InputBinding(PadData::ButtonIndex::DPAD_DOWN)}},
{SDLK_LEFT, {InputBinding(PadData::ButtonIndex::DPAD_LEFT)}},

View File

@ -11,11 +11,12 @@
#include "common/log/log.h"
#include "common/util/json_util.h"
#define GET_PRESSURE_BUTTON_DATA(button_name) \
{button_data.at(ButtonIndex::button_name), \
pressure_data.at(PressureIndex::button_name##_PRESSURE)};
/// A simple abstraction around the PS2 controller data with some convenience functions for
/// pulling specific data out if it's useful.
///
/// Pressure is always assumed to be the max, barely any input library handles pressure properly
/// and the VAST majority of controllers don't even support it either.
struct PadData {
enum AnalogIndex { LEFT_X = 0, LEFT_Y, RIGHT_X, RIGHT_Y = 3 };
@ -38,6 +39,22 @@ struct PadData {
SQUARE = 15
};
enum PressureIndex {
INVALID_PRESSURE = -1,
DPAD_RIGHT_PRESSURE = 0,
DPAD_LEFT_PRESSURE,
DPAD_UP_PRESSURE,
DPAD_DOWN_PRESSURE,
TRIANGLE_PRESSURE,
CIRCLE_PRESSURE,
CROSS_PRESSURE,
SQUARE_PRESSURE,
L1_PRESSURE,
R1_PRESSURE,
L2_PRESSURE,
R2_PRESSURE = 11
};
static const int ANALOG_NEUTRAL = 127;
// NOTE - store analog values as larger signed integers and then clamp them to their 0-255
@ -75,29 +92,62 @@ struct PadData {
std::clamp(analog_data.at(AnalogIndex::RIGHT_Y), 0, 255)};
}
std::array<bool, 16> button_data = {};
std::array<bool, 16> button_data = {false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false};
std::array<u8, 12> pressure_data = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
// Normal Buttons
bool select() const { return button_data.at(ButtonIndex::SELECT); };
bool l3() const { return button_data.at(ButtonIndex::L3); };
bool r3() const { return button_data.at(ButtonIndex::R3); };
bool start() const { return button_data.at(ButtonIndex::START); };
bool select() const { return button_data.at(static_cast<int>(ButtonIndex::SELECT)); };
bool l3() const { return button_data.at(static_cast<int>(ButtonIndex::L3)); };
bool r3() const { return button_data.at(static_cast<int>(ButtonIndex::R3)); };
bool start() const { return button_data.at(static_cast<int>(ButtonIndex::START)); };
// Pressure Buttons
std::pair<bool, u8> dpad_up() const { return {button_data.at(ButtonIndex::DPAD_UP), 255}; };
std::pair<bool, u8> dpad_right() const { return {button_data.at(ButtonIndex::DPAD_RIGHT), 255}; };
std::pair<bool, u8> dpad_down() const { return {button_data.at(ButtonIndex::DPAD_DOWN), 255}; };
std::pair<bool, u8> dpad_left() const { return {button_data.at(ButtonIndex::DPAD_LEFT), 255}; };
std::pair<bool, u8> dpad_up() const { return GET_PRESSURE_BUTTON_DATA(DPAD_UP); };
std::pair<bool, u8> dpad_right() const { return GET_PRESSURE_BUTTON_DATA(DPAD_RIGHT); };
std::pair<bool, u8> dpad_down() const { return GET_PRESSURE_BUTTON_DATA(DPAD_DOWN); };
std::pair<bool, u8> dpad_left() const { return GET_PRESSURE_BUTTON_DATA(DPAD_LEFT); };
std::pair<bool, u8> l2() const { return {button_data.at(ButtonIndex::L2), 255}; };
std::pair<bool, u8> r2() const { return {button_data.at(ButtonIndex::R2), 255}; };
std::pair<bool, u8> l1() const { return {button_data.at(ButtonIndex::L1), 255}; };
std::pair<bool, u8> r1() const { return {button_data.at(ButtonIndex::R1), 255}; };
std::pair<bool, u8> l2() const { return GET_PRESSURE_BUTTON_DATA(L2); };
std::pair<bool, u8> r2() const { return GET_PRESSURE_BUTTON_DATA(R2); };
std::pair<bool, u8> l1() const { return GET_PRESSURE_BUTTON_DATA(L1); };
std::pair<bool, u8> r1() const { return GET_PRESSURE_BUTTON_DATA(R1); };
std::pair<bool, u8> triangle() const { return {button_data.at(ButtonIndex::TRIANGLE), 255}; };
std::pair<bool, u8> circle() const { return {button_data.at(ButtonIndex::CIRCLE), 255}; };
std::pair<bool, u8> cross() const { return {button_data.at(ButtonIndex::CROSS), 255}; };
std::pair<bool, u8> square() const { return {button_data.at(ButtonIndex::SQUARE), 255}; };
std::pair<bool, u8> triangle() const { return GET_PRESSURE_BUTTON_DATA(TRIANGLE); };
std::pair<bool, u8> circle() const { return GET_PRESSURE_BUTTON_DATA(CIRCLE); };
std::pair<bool, u8> cross() const { return GET_PRESSURE_BUTTON_DATA(CROSS); };
std::pair<bool, u8> square() const { return GET_PRESSURE_BUTTON_DATA(SQUARE); };
PressureIndex button_index_to_pressure_index(ButtonIndex button_index) const {
switch (button_index) {
case ButtonIndex::DPAD_RIGHT:
return PressureIndex::DPAD_RIGHT_PRESSURE;
case ButtonIndex::DPAD_LEFT:
return PressureIndex::DPAD_LEFT_PRESSURE;
case ButtonIndex::DPAD_UP:
return PressureIndex::DPAD_UP_PRESSURE;
case ButtonIndex::DPAD_DOWN:
return PressureIndex::DPAD_DOWN_PRESSURE;
case ButtonIndex::TRIANGLE:
return PressureIndex::TRIANGLE_PRESSURE;
case ButtonIndex::CIRCLE:
return PressureIndex::CIRCLE_PRESSURE;
case ButtonIndex::CROSS:
return PressureIndex::CROSS_PRESSURE;
case ButtonIndex::SQUARE:
return PressureIndex::SQUARE_PRESSURE;
case ButtonIndex::L1:
return PressureIndex::L1_PRESSURE;
case ButtonIndex::R1:
return PressureIndex::R1_PRESSURE;
case ButtonIndex::L2:
return PressureIndex::L2_PRESSURE;
case ButtonIndex::R2:
return PressureIndex::R2_PRESSURE;
default:
return PressureIndex::INVALID_PRESSURE;
}
}
// Analog Simulation Tracking
// There exists a flaw with the described analog tracking approach described above, and that has
@ -141,10 +191,7 @@ struct PadData {
}
};
// order of pressure sensitive buttons in memory (not the same as their bit order...).
extern const std::vector<PadData::ButtonIndex> PAD_DATA_PRESSURE_INDEX_ORDER;
// https://wiki.libsdl.org/SDL2/SDL_Keymod
// https://wiki.libsdl.org/SDL3/SDL_Keymod
struct InputModifiers {
InputModifiers() = default;
InputModifiers(const u16 sdl_mod_state);
@ -317,11 +364,11 @@ struct InputBindingGroups {
void to_json(json& j, const InputBindingGroups& obj);
void from_json(const json& j, InputBindingGroups& obj);
/// https://wiki.libsdl.org/SDL2/SDL_GameControllerButton
/// https://wiki.libsdl.org/SDL3/SDL_GamepadButton
extern const InputBindingGroups DEFAULT_CONTROLLER_BINDS;
/// https://wiki.libsdl.org/SDL2/SDL_Keycode
/// https://wiki.libsdl.org/SDL3/SDL_Keycode
extern const InputBindingGroups DEFAULT_KEYBOARD_BINDS;
/// https://wiki.libsdl.org/SDL2/SDL_MouseButtonEvent
/// https://wiki.libsdl.org/SDL3/SDL_MouseButtonEvent
extern const InputBindingGroups DEFAULT_MOUSE_BINDS;
/// A CommandBinding by contrast is a way to map some arbitrary runtime command to

View File

@ -14,20 +14,31 @@
#include "game/graphics/pipelines/opengl.h"
#include "game/runtime.h"
#include "third-party/SDL/include/SDL3/SDL_hints.h"
#include "third-party/imgui/imgui.h"
InputManager::InputManager()
// Load user settings
: m_settings(std::make_shared<game_settings::InputSettings>(game_settings::InputSettings())) {
InputManager::InputManager(SDL_Window* window)
: m_window(window),
// Load user settings
m_settings(std::make_shared<game_settings::InputSettings>(game_settings::InputSettings())) {
prof().instant_event("ROOT");
{
auto p = scoped_prof("input_manager::init");
m_settings->load_settings();
#ifdef WIN32
if (!SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, "1")) {
sdl_util::log_error("Unable to set SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER to true!");
}
#else
if (!SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS3, "1")) {
sdl_util::log_error("Unable to set SDL_HINT_JOYSTICK_HIDAPI_PS3 to true!");
}
#endif
{
auto p = scoped_prof("input_manager::init::sdl_init_subsystem");
// initializing the controllers on startup can sometimes take a very long time
// so we isolate that to here instead
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0) {
if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD)) {
sdl_util::log_error(
"Could not initialize SDL Controller support, controllers will not work!");
}
@ -37,7 +48,7 @@ InputManager::InputManager()
std::string mapping_path =
(file_util::get_jak_project_dir() / "game" / "assets" / "sdl_controller_db.txt").string();
if (file_util::file_exists(mapping_path)) {
SDL_GameControllerAddMappingsFromFile(mapping_path.c_str());
SDL_AddGamepadMappingsFromFile(mapping_path.c_str());
} else {
lg::error("Could not find SDL Controller DB at path `{}`", mapping_path);
}
@ -46,7 +57,7 @@ InputManager::InputManager()
m_data[0] = std::make_shared<PadData>();
m_data[1] = std::make_shared<PadData>();
m_keyboard = KeyboardDevice(m_settings);
m_mouse = MouseDevice(m_settings);
m_mouse = MouseDevice(m_window, m_settings);
if (m_data.find(m_keyboard_and_mouse_port) == m_data.end()) {
m_data[m_keyboard_and_mouse_port] = std::make_shared<PadData>();
@ -78,14 +89,15 @@ void InputManager::refresh_device_list() {
// Enumerate devices
// TODO - if this was done on a separate thread, there would be no hitch in the game thread
// but of course, that presents other synchronization challenges.
const auto num_joysticks = SDL_NumJoysticks();
int num_joysticks = 0;
auto joysticks = SDL_GetJoysticks(&num_joysticks);
if (num_joysticks > 0) {
for (int i = 0; i < num_joysticks; i++) {
if (!SDL_IsGameController(i)) {
if (!SDL_IsGamepad(joysticks[i])) {
lg::error("Controller with device id {} is not avaiable via the GameController API", i);
continue;
}
auto controller = std::make_shared<GameController>(i, m_settings);
auto controller = std::make_shared<GameController>(joysticks[i], m_settings);
if (!controller->is_loaded()) {
lg::error("Unable to successfully connect to GameController with id {}, skipping", i);
continue;
@ -129,10 +141,10 @@ void InputManager::refresh_device_list() {
lg::warn(
"No active game controllers could be found or loaded successfully - inputs will not "
"work!");
m_settings->keyboard_temp_enabled = true;
m_settings->_keyboard_temp_enabled = true;
} else {
lg::info("Found {} controllers", m_available_controllers.size());
m_settings->keyboard_temp_enabled = false;
m_settings->_keyboard_temp_enabled = false;
}
}
}
@ -154,18 +166,22 @@ void InputManager::hide_cursor(const bool hide_cursor) {
}
// NOTE - seems like an SDL bug, but the cursor will be visible / locked to the center of the
// screen if you use the 'start menu' to exit the window / return to it (atleast in windowed mode)
auto ok = SDL_ShowCursor(hide_cursor ? SDL_DISABLE : SDL_ENABLE);
if (ok < 0) {
sdl_util::log_error("Unable to show/hide mouse cursor");
} else {
m_mouse_currently_hidden = hide_cursor;
if (hide_cursor && !SDL_HideCursor()) {
sdl_util::log_error("Unable to hide mouse cursor");
return;
}
if (!hide_cursor && !SDL_ShowCursor()) {
sdl_util::log_error("Unable to show mouse cursor");
return;
}
m_mouse_currently_hidden = hide_cursor;
}
void InputManager::process_sdl_event(const SDL_Event& event) {
// TODO - perhaps should handle `SDL_CONTROLLERDEVICEREMAPPED`?
// Detect controller connections and disconnects
if (sdl_util::is_any_event_type(event.type,
{SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED})) {
{SDL_EVENT_GAMEPAD_ADDED, SDL_EVENT_GAMEPAD_REMOVED})) {
lg::info("Controller added or removed. refreshing controller device list");
refresh_device_list();
}
@ -197,9 +213,9 @@ void InputManager::process_sdl_event(const SDL_Event& event) {
// Adjust mouse cursor visibility
if (m_auto_hide_mouse) {
if (event.type == SDL_MOUSEMOTION && !m_mouse.is_camera_being_controlled()) {
if (event.type == SDL_EVENT_MOUSE_MOTION && !m_mouse.is_camera_being_controlled()) {
hide_cursor(false);
} else if (event.type == SDL_KEYDOWN || event.type == SDL_CONTROLLERBUTTONDOWN) {
} else if (event.type == SDL_EVENT_KEY_DOWN || event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
hide_cursor(true);
}
}
@ -254,8 +270,8 @@ void InputManager::process_ee_events() {
ignore_background_controller_events(std::get<bool>(evt.param1));
break;
case EEInputEventType::UPDATE_RUMBLE:
update_rumble(std::get<int>(evt.param1), std::get<u8>(evt.param2),
std::get<u8>(evt.param3));
controller_send_rumble(std::get<int>(evt.param1), std::get<u8>(evt.param2),
std::get<u8>(evt.param3));
break;
case EEInputEventType::SET_CONTROLLER_LED:
set_controller_led(std::get<int>(evt.param1), std::get<u8>(evt.param2),
@ -268,6 +284,33 @@ void InputManager::process_ee_events() {
case EEInputEventType::SET_AUTO_HIDE_MOUSE:
set_auto_hide_mouse(std::get<bool>(evt.param1));
break;
case EEInputEventType::CONTROLLER_CLEAR_TRIGGER_EFFECT:
controller_clear_trigger_effect(
std::get<int>(evt.param1),
std::get<dualsense_effects::TriggerEffectOption>(evt.param2));
break;
case EEInputEventType::CONTROLLER_SEND_TRIGGER_EFFECT_FEEDBACK:
controller_send_trigger_effect_feedback(
std::get<int>(evt.param1), std::get<dualsense_effects::TriggerEffectOption>(evt.param2),
std::get<u8>(evt.param3), std::get<u8>(evt.param4));
break;
case EEInputEventType::CONTROLLER_SEND_TRIGGER_EFFECT_VIBRATE:
controller_send_trigger_effect_vibrate(
std::get<int>(evt.param1), std::get<dualsense_effects::TriggerEffectOption>(evt.param2),
std::get<u8>(evt.param3), std::get<u8>(evt.param4), std::get<u8>(evt.param5));
break;
case EEInputEventType::CONTROLLER_SEND_TRIGGER_EFFECT_WEAPON:
controller_send_trigger_effect_weapon(
std::get<int>(evt.param1), std::get<dualsense_effects::TriggerEffectOption>(evt.param2),
std::get<u8>(evt.param3), std::get<u8>(evt.param4), std::get<u8>(evt.param5));
break;
case EEInputEventType::CONTROLLER_SEND_TRIGGER_RUMBLE:
controller_send_trigger_rumble(std::get<int>(evt.param1), std::get<u16>(evt.param2),
std::get<u16>(evt.param3), std::get<u32>(evt.param4));
break;
case EEInputEventType::SET_TRIGGER_EFFECTS_ENABLED:
set_trigger_effects_enabled(std::get<bool>(evt.param1));
break;
}
ee_event_queue.pop();
}
@ -395,6 +438,113 @@ bool InputManager::controller_has_rumble(const int port) {
return m_available_controllers.at(id)->has_rumble();
}
bool InputManager::controller_has_pressure_sensitivity_support(const int port) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return false;
}
const auto id = m_controller_port_mapping.at(port);
if (id >= (int)m_available_controllers.size()) {
return false;
}
return m_available_controllers.at(id)->has_pressure_sensitivity_support();
}
bool InputManager::controller_has_trigger_effect_support(const int port) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return false;
}
const auto id = m_controller_port_mapping.at(port);
if (id >= (int)m_available_controllers.size()) {
return false;
}
return m_available_controllers.at(id)->has_trigger_effect_support();
}
int InputManager::controller_send_rumble(int port, u8 low_intensity, u8 high_intensity) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return 0;
}
return m_available_controllers.at(m_controller_port_mapping.at(port))
->send_rumble(low_intensity, high_intensity);
}
void InputManager::controller_send_trigger_rumble(const int port,
const u16 left_rumble,
const u16 right_rumble,
const u32 duration_ms) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return;
}
m_available_controllers.at(m_controller_port_mapping.at(port))
->send_trigger_rumble(left_rumble, right_rumble, duration_ms);
}
void InputManager::controller_clear_trigger_effect(const int port,
dualsense_effects::TriggerEffectOption option) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return;
}
const auto id = m_controller_port_mapping.at(port);
if (id >= (int)m_available_controllers.size()) {
return;
}
m_available_controllers.at(id)->clear_trigger_effect(option);
}
void InputManager::controller_send_trigger_effect_feedback(
const int port,
dualsense_effects::TriggerEffectOption option,
u8 position,
u8 strength) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return;
}
const auto id = m_controller_port_mapping.at(port);
if (id >= (int)m_available_controllers.size()) {
return;
}
m_available_controllers.at(id)->send_trigger_effect_feedback(option, position, strength);
}
void InputManager::controller_send_trigger_effect_vibrate(
const int port,
dualsense_effects::TriggerEffectOption option,
u8 position,
u8 amplitude,
u8 frequency) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return;
}
const auto id = m_controller_port_mapping.at(port);
if (id >= (int)m_available_controllers.size()) {
return;
}
m_available_controllers.at(id)->send_trigger_effect_vibrate(option, position, amplitude,
frequency);
}
void InputManager::controller_send_trigger_effect_weapon(
const int port,
dualsense_effects::TriggerEffectOption option,
u8 start_position,
u8 end_position,
u8 strength) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return;
}
const auto id = m_controller_port_mapping.at(port);
if (id >= (int)m_available_controllers.size()) {
return;
}
m_available_controllers.at(id)->send_trigger_effect_weapon(option, start_position, end_position,
strength);
}
bool InputManager::set_trigger_effects_enabled(bool enabled) {
controller_clear_trigger_effect(0, dualsense_effects::TriggerEffectOption::BOTH);
return m_settings->enable_trigger_effects = enabled;
};
void InputManager::enqueue_set_controller_led(const int port,
const u8 red,
const u8 green,
@ -421,14 +571,6 @@ void InputManager::enqueue_update_rumble(const int port,
ee_event_queue.push({EEInputEventType::UPDATE_RUMBLE, port, low_intensity, high_intensity, {}});
}
int InputManager::update_rumble(int port, u8 low_intensity, u8 high_intensity) {
if (m_controller_port_mapping.find(port) == m_controller_port_mapping.end()) {
return 0;
}
return m_available_controllers.at(m_controller_port_mapping.at(port))
->update_rumble(low_intensity, high_intensity);
}
void InputManager::enable_keyboard(const bool enabled) {
m_settings->keyboard_enabled = enabled;
if (!m_settings->keyboard_enabled) {
@ -534,6 +676,75 @@ void InputManager::enqueue_set_auto_hide_mouse(const bool auto_hide_mouse) {
ee_event_queue.push({EEInputEventType::SET_AUTO_HIDE_MOUSE, auto_hide_mouse, {}, {}, {}});
}
void InputManager::enqueue_controller_clear_trigger_effect(
const int port,
const dualsense_effects::TriggerEffectOption option) {
const std::lock_guard<std::mutex> lock(m_event_queue_mtx);
ee_event_queue.push({.type = EEInputEventType::CONTROLLER_CLEAR_TRIGGER_EFFECT,
.param1 = port,
.param2 = option});
}
void InputManager::enqueue_controller_send_trigger_effect_feedback(
const int port,
const dualsense_effects::TriggerEffectOption option,
const u8 position,
const u8 strength) {
const std::lock_guard<std::mutex> lock(m_event_queue_mtx);
ee_event_queue.push({.type = EEInputEventType::CONTROLLER_SEND_TRIGGER_EFFECT_FEEDBACK,
.param1 = port,
.param2 = option,
.param3 = position,
.param4 = strength});
}
void InputManager::enqueue_controller_send_trigger_effect_vibrate(
const int port,
const dualsense_effects::TriggerEffectOption option,
const u8 position,
const u8 amplitude,
const u8 frequency) {
const std::lock_guard<std::mutex> lock(m_event_queue_mtx);
ee_event_queue.push({.type = EEInputEventType::CONTROLLER_SEND_TRIGGER_EFFECT_VIBRATE,
.param1 = port,
.param2 = option,
.param3 = position,
.param4 = amplitude,
.param5 = frequency});
}
void InputManager::enqueue_controller_send_trigger_effect_weapon(
const int port,
const dualsense_effects::TriggerEffectOption option,
const u8 start_position,
const u8 end_position,
const u8 strength) {
const std::lock_guard<std::mutex> lock(m_event_queue_mtx);
ee_event_queue.push({.type = EEInputEventType::CONTROLLER_SEND_TRIGGER_EFFECT_WEAPON,
.param1 = port,
.param2 = option,
.param3 = start_position,
.param4 = end_position,
.param5 = strength});
}
void InputManager::enqueue_controller_send_trigger_rumble(const int port,
const u16 left_rumble,
const u16 right_rumble,
const u32 duration_ms) {
const std::lock_guard<std::mutex> lock(m_event_queue_mtx);
ee_event_queue.push({.type = EEInputEventType::CONTROLLER_SEND_TRIGGER_RUMBLE,
.param1 = port,
.param2 = left_rumble,
.param3 = right_rumble,
.param4 = duration_ms});
}
void InputManager::enqueue_set_trigger_effects_enabled(const bool enabled) {
const std::lock_guard<std::mutex> lock(m_event_queue_mtx);
ee_event_queue.push({.type = EEInputEventType::SET_TRIGGER_EFFECTS_ENABLED, .param1 = enabled});
}
void InputManager::set_auto_hide_mouse(const bool auto_hide_mouse) {
m_auto_hide_mouse = auto_hide_mouse;
if (!auto_hide_mouse) {

View File

@ -1,6 +1,5 @@
#pragma once
#include <array>
#include <memory>
#include <mutex>
#include <optional>
@ -11,14 +10,13 @@
#include "common/common_types.h"
#include "devices/dualsense_effects.h"
#include "devices/game_controller.h"
#include "devices/keyboard.h"
#include "devices/mouse.h"
#include "game/settings/settings.h"
#include "game/system/hid/input_bindings.h"
#include "third-party/SDL/include/SDL.h"
/// Central class that:
/// - keeps track of available input devices
/// - polls data from the input devices considered active
@ -30,19 +28,26 @@ class InputManager {
UPDATE_RUMBLE,
SET_CONTROLLER_LED,
UPDATE_MOUSE_OPTIONS,
SET_AUTO_HIDE_MOUSE
SET_AUTO_HIDE_MOUSE,
CONTROLLER_CLEAR_TRIGGER_EFFECT,
CONTROLLER_SEND_TRIGGER_EFFECT_FEEDBACK,
CONTROLLER_SEND_TRIGGER_EFFECT_VIBRATE,
CONTROLLER_SEND_TRIGGER_EFFECT_WEAPON,
CONTROLLER_SEND_TRIGGER_RUMBLE,
SET_TRIGGER_EFFECTS_ENABLED
};
struct EEInputEvent {
EEInputEventType type;
std::variant<bool, int> param1;
std::variant<bool, u8> param2;
std::variant<bool, u8> param3;
std::variant<u8> param4;
std::variant<bool, int> param1 = {};
std::variant<bool, u8, u16, dualsense_effects::TriggerEffectOption> param2 = {};
std::variant<bool, u8, u16> param3 = {};
std::variant<u8, u32> param4 = {};
std::variant<u8, u32> param5 = {};
};
public:
InputManager();
InputManager(SDL_Window* window);
~InputManager();
// Propagate and handle the SDL event, ignored it if it's not relevant
@ -74,6 +79,30 @@ class InputManager {
const bool control_camera,
const bool control_movement);
void enqueue_set_auto_hide_mouse(const bool auto_hide_mouse);
void enqueue_controller_clear_trigger_effect(const int port,
const dualsense_effects::TriggerEffectOption option);
void enqueue_controller_send_trigger_effect_feedback(
const int port,
const dualsense_effects::TriggerEffectOption option,
const u8 position,
const u8 strength);
void enqueue_controller_send_trigger_effect_vibrate(
const int port,
const dualsense_effects::TriggerEffectOption option,
const u8 position,
const u8 amplitude,
const u8 frequency);
void enqueue_controller_send_trigger_effect_weapon(
const int port,
const dualsense_effects::TriggerEffectOption option,
const u8 start_position,
const u8 end_position,
const u8 strength);
void enqueue_controller_send_trigger_rumble(const int port,
const u16 left_rumble,
const u16 right_rumble,
const u32 duration_ms);
void enqueue_set_trigger_effects_enabled(const bool enabled);
// These functions can be called from the EE but they only interact with
// the InputManager, so it shouldn't hurt (they don't need to be enqueued)
@ -90,6 +119,10 @@ class InputManager {
void set_controller_for_port(const int controller_id, const int port);
bool controller_has_led(const int port);
bool controller_has_rumble(const int port);
bool controller_has_pressure_sensitivity_support(const int port);
bool controller_has_trigger_effect_support(const int port);
int controller_send_rumble(const int port, const u8 low_intensity, const u8 high_intensity);
void enable_keyboard(const bool enabled);
bool get_waiting_for_bind() const { return m_waiting_for_bind.has_value(); }
void set_wait_for_bind(const InputDeviceType device_type,
@ -102,10 +135,16 @@ class InputManager {
bool auto_hiding_cursor() { return m_auto_hide_mouse || m_mouse.is_camera_being_controlled(); }
void hide_cursor(const bool hide_cursor);
bool is_keyboard_enabled() {
return m_settings->keyboard_enabled || m_settings->keyboard_temp_enabled;
return m_settings->keyboard_enabled || m_settings->_keyboard_temp_enabled;
}
bool is_pressure_sensitivity_enabled() { return m_settings->enable_pressure_sensitivity; }
bool set_pressure_sensitivity_enabled(bool enabled) {
return m_settings->enable_pressure_sensitivity = enabled;
}
bool are_trigger_effects_enabled() { return m_settings->enable_trigger_effects; }
private:
SDL_Window* m_window;
std::mutex m_event_queue_mtx;
std::queue<EEInputEvent> ee_event_queue;
@ -147,10 +186,30 @@ class InputManager {
void clear_inputs();
void ignore_background_controller_events(const bool ignore);
int update_rumble(const int port, const u8 low_intensity, const u8 high_intensity);
void set_controller_led(const int port, const u8 red, const u8 green, const u8 blue);
void update_mouse_options(const bool enabled,
const bool control_camera,
const bool control_movement);
void set_auto_hide_mouse(const bool auto_hide_mouse);
void controller_send_trigger_rumble(const int port,
const u16 left_rumble,
const u16 right_rumble,
const u32 duration_ms);
void controller_clear_trigger_effect(const int port,
dualsense_effects::TriggerEffectOption option);
void controller_send_trigger_effect_feedback(const int port,
dualsense_effects::TriggerEffectOption option,
u8 position,
u8 strength);
void controller_send_trigger_effect_vibrate(const int port,
dualsense_effects::TriggerEffectOption option,
u8 position,
u8 amplitude,
u8 frequency);
void controller_send_trigger_effect_weapon(const int port,
dualsense_effects::TriggerEffectOption option,
u8 start_position,
u8 end_position,
u8 strength);
bool set_trigger_effects_enabled(bool enabled);
};

View File

@ -2,18 +2,20 @@
#include "common/log/log.h"
#include "third-party/SDL/include/SDL.h"
#include "third-party/SDL/include/SDL3/SDL.h"
namespace sdl_util {
void log_error(const std::string& msg) {
std::string sdl_cause = SDL_GetError();
lg::error("SDL Error: {} - Cause: {}", msg, sdl_cause.empty() ? "n/a" : sdl_cause);
}
std::string log_and_return_error(const std::string& msg) {
std::string sdl_cause = SDL_GetError();
lg::error("SDL Error: {} - Cause: {}", msg, sdl_cause.empty() ? "n/a" : sdl_cause);
return sdl_cause;
}
bool is_any_event_type(uint32_t event_type, const std::vector<uint32_t>& allowed_types) {
for (const auto& allowed_type : allowed_types) {
if (allowed_type == event_type) {
@ -22,12 +24,7 @@ bool is_any_event_type(uint32_t event_type, const std::vector<uint32_t>& allowed
}
return false;
}
SDL_bool sdl_bool(const bool val) {
return val ? SDL_TRUE : SDL_FALSE;
}
bool from_sdl_bool(const SDL_bool val) {
return val == SDL_TRUE ? true : false;
}
bool is_SDL_GUID_zero(SDL_GUID guid) {
for (int i = 0; i < 16; i++) {
if (guid.data[i] != 0) {
@ -83,7 +80,7 @@ std::string get_mouse_button_name(const int sdl_mouse_button_id, InputModifiers
}
std::string get_keyboard_button_name(const int sdl_key_code, InputModifiers modifiers) {
const auto result = SDL_GetKeyName((SDL_KeyCode)sdl_key_code);
const auto result = SDL_GetKeyName((SDL_Keycode)sdl_key_code);
if (!result) {
return "Unknown";
}
@ -92,14 +89,14 @@ std::string get_keyboard_button_name(const int sdl_key_code, InputModifiers modi
return fmt::to_string(fmt::join(tokens, " + "));
}
std::string get_controller_button_name(const int sdl_button_id) {
const auto result = SDL_GameControllerGetStringForButton((SDL_GameControllerButton)sdl_button_id);
const auto result = SDL_GetGamepadStringForButton((SDL_GamepadButton)sdl_button_id);
if (!result) {
return "Unknown";
}
return result;
}
std::string get_controller_axis_name(const int sdl_axis_id) {
const auto result = SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)sdl_axis_id);
const auto result = SDL_GetGamepadStringForAxis((SDL_GamepadAxis)sdl_axis_id);
if (!result) {
return "Unknown";
}

View File

@ -5,14 +5,12 @@
#include "input_bindings.h"
#include "third-party/SDL/include/SDL.h"
#include "third-party/SDL/include/SDL3/SDL.h"
namespace sdl_util {
void log_error(const std::string& msg = "");
std::string log_and_return_error(const std::string& msg = "");
bool is_any_event_type(uint32_t event_type, const std::vector<uint32_t>& allowed_types);
SDL_bool sdl_bool(const bool val);
bool from_sdl_bool(const SDL_bool val);
bool is_SDL_GUID_zero(SDL_GUID guid);
std::string get_mouse_button_name(const int sdl_mouse_button_id, InputModifiers modifiers);

View File

@ -793,6 +793,7 @@
(input-opts-binds-unknown #x1615)
(progress-no-other-resolution-options #x1616)
(input-opts-controller-led-reflect-heat #x1617)
(input-opts-controller-pressure-sensitivity #x1618)
;; GAME-TEXT-ID ENUM ENDS
)

View File

@ -481,6 +481,21 @@
(define-extern pc-reset-bindings-to-defaults! (function int int none))
(define-extern pc-set-auto-hide-cursor! (function symbol none))
(define-extern pc-get-pressure-sensitivity-enabled? (function symbol))
(define-extern pc-set-pressure-sensitivity-enabled! (function symbol none))
(define-extern pc-current-controller-has-pressure-sensitivity? (function symbol))
(define-extern pc-current-controller-has-trigger-effect-support? (function symbol))
(define-extern pc-get-trigger-effects-enabled? (function symbol))
(define-extern pc-set-trigger-effects-enabled! (function symbol none))
(defenum pc-trigger-effect-option
(left 0)
(right 1)
(both 2))
(define-extern pc-clear-trigger-effect! (function pc-trigger-effect-option none))
(define-extern pc-send-trigger-effect-feedback! (function pc-trigger-effect-option int int none))
(define-extern pc-send-trigger-effect-vibrate! (function pc-trigger-effect-option int int int none))
(define-extern pc-send-trigger-effect-weapon! (function pc-trigger-effect-option int int int none))
(define-extern pc-send-trigger-rumble! (function int int int none))
;; Display Related Functions
(define-extern pc-get-display-mode (function symbol))

View File

@ -662,7 +662,9 @@
;; if saved settings are corrupted or not found, the object will be fully reset to use all defaults
(load-settings obj)
;; any post-operations that need to be done after loading
;; remove these once jak 1's menu is finally modernized, need this for state in the menu code...
(set! (-> obj keyboard-enabled?) (pc-get-keyboard-enabled?))
(set! (-> obj pressure-sensitivity-enabled?) (pc-get-pressure-sensitivity-enabled?))
(update-mouse-controls! obj)
obj)

View File

@ -145,6 +145,7 @@
(controller-led-color rgbaf :inline)
(stick-deadzone float) ;; analog stick deadzone. 0-1
(keyboard-enabled? symbol) ;; NOTE - this is here solely to satisfy jak 1's menu design, the setting has been moved into `input-settings.json`
(pressure-sensitivity-enabled? symbol) ;; NOTE - this is here solely to satisfy jak 1's menu design, the setting has been moved into `input-settings.json`
(mouse-enabled? symbol)
(mouse-camera? symbol)
(mouse-xsens float)
@ -363,6 +364,7 @@
(set! (-> obj controller-led-max-brightness) 1.0))
(when (or (= device 'all) (= device 'input))
(set! (-> obj keyboard-enabled?) #f)
(set! (-> obj pressure-sensitivity-enabled?) #f)
(set! (-> obj mouse-enabled?) #f)
(set! (-> obj auto-hide-cursor?) #t))
(when (or (= device 'all) (= device 'mouse))

View File

@ -435,6 +435,20 @@
:option-disabled-func
(lambda ()
(not (pc-current-controller-has-led?))))
(new 'static
'game-option
:option-type (game-option-type on-off)
:name (text-id input-opts-controller-pressure-sensitivity)
:scale #t
:on-change
(lambda ((val object))
(let ((val-sym (the-as symbol val)))
(pc-set-pressure-sensitivity-enabled! val-sym)
(set! (-> *pc-settings* pressure-sensitivity-enabled?) val-sym)
(none)))
:option-disabled-func
(lambda ()
(not (pc-current-controller-has-pressure-sensitivity?))))
(new 'static
'game-option
:option-type (game-option-type confirmation)
@ -2121,6 +2135,7 @@
(set! (-> *controller-options* 4 value-to-modify) (&-> *pc-settings* controller-led-hp?))
(set! (-> *controller-options* 5 value-to-modify) (&-> *pc-settings* controller-led-eco?))
(set! (-> *controller-options* 6 value-to-modify) (&-> *pc-settings* controller-led-heat?))
(set! (-> *controller-options* 7 value-to-modify) (&-> *pc-settings* pressure-sensitivity-enabled?))
(set! (-> *mouse-options* 0 value-to-modify) (&-> *pc-settings* mouse-camera?))
(set! (-> *mouse-options* 1 value-to-modify) (&-> *pc-settings* mouse-xsens))
(set! (-> *mouse-options* 2 value-to-modify) (&-> *pc-settings* mouse-ysens))

View File

@ -620,6 +620,11 @@
(seek! (-> this eco-pill-dark) 0.0 (- arg1))
)
)
;; og:preserve-this trigger effects
(when (pc-get-trigger-effects-enabled?)
(if (= (-> *FACT-bank* eco-pill-dark-max-default) (-> this eco-pill-dark))
(pc-send-trigger-effect-feedback! (pc-trigger-effect-option left) 0 4)
(pc-send-trigger-rumble! 16383 0 15)))
(-> this eco-pill-dark)
)
(('fuel-cell)

View File

@ -94,6 +94,8 @@ The cpad-set-buzz! function can be used for vibration.
)
)
(define-extern gun-trigger-buttons-swap! (function cpad-info none))
;; decomp begins
(deftype scf-time (structure)
@ -391,6 +393,7 @@ The cpad-set-buzz! function can be used for vibration.
(set! (-> pad old-righty 0) (-> pad righty))
(cpad-get-data pad)
(adjust-to-screen-flip pad)
(gun-trigger-buttons-swap! pad)
(cond
((not (logtest? (-> pad valid) 128))
(dotimes (buzz-i 2)

View File

@ -194,6 +194,9 @@
(cond
((zero? v1-0)
(sound-play "blue-shot-fire")
;; og:preserve-this trigger effects
(when (and (pc-get-trigger-effects-enabled?) (-> *pc-settings* controller-swap-r1-r2?))
(pc-send-trigger-rumble! 0 16383 25))
)
((= v1-0 (projectile-options lose-altitude))
(sound-play "blue-shot-hit")

View File

@ -400,6 +400,9 @@
(go-virtual impact)
)
(sound-play "pmkr-fire" :id (-> self fire-sound) :position (-> self root trans))
;; og:preserve-this trigger effects
(when (and (pc-get-trigger-effects-enabled?) (-> *pc-settings* controller-swap-r1-r2?))
(pc-send-trigger-rumble! 0 32767 50))
(sound-play "pmkr-trail" :id (-> self trail-sound) :position (-> self root trans))
)
)

View File

@ -23,6 +23,25 @@
(gutflags-4)
)
(defun gun-trigger-buttons-swap! ((obj cpad-info))
;; og:preserve-this swapping r1 and r2 when gun is out
(when (-> *pc-settings* controller-swap-r1-r2?)
;; r1 = 11th bit and 9st index for pressure
;; r2 = 9th bit and 11nd index for pressure
(let ((r1-pressed? (logtest? (-> obj button0) (pad-buttons r1)))
(r1-pressure (-> obj abutton (abutton-idx r1)))
(r2-pressed? (logtest? (-> obj button0) (pad-buttons r2)))
(r2-pressure (-> obj abutton (abutton-idx r2))))
(when r1-pressed?
(logclear! (-> obj button0) (pad-buttons r1))
(logior! (-> obj button0) (pad-buttons r2)))
(when r2-pressed?
(logclear! (-> obj button0) (pad-buttons r2))
(logior! (-> obj button0) (pad-buttons r1)))
(set! (-> obj abutton (abutton-idx r1)) r2-pressure)
(set! (-> obj abutton (abutton-idx r2)) r1-pressure)))
(none))
;; DECOMP BEGINS
(deftype gun (process-drawable)

View File

@ -569,6 +569,9 @@
)
(draw-beam (-> *part-id-table* 187) (-> self start-pos) (-> self start-dir) #f #t)
(sound-play "red-shot-fire")
;; og:preserve-this trigger effects
(when (and (pc-get-trigger-effects-enabled?) (-> *pc-settings* controller-swap-r1-r2?))
(pc-send-trigger-rumble! 0 32767 100))
(vector-float*! (-> self root transv) (-> self start-dir) 61440.0)
(the-as gun-red-shot (if (gun-red-shot-method-24 self)
(go-virtual blocked)

View File

@ -230,6 +230,9 @@
(cond
((zero? v1-0)
(sound-play "yellow-shot-fir")
;; og:preserve-this trigger effects
(when (and (pc-get-trigger-effects-enabled?) (-> *pc-settings* controller-swap-r1-r2?))
(pc-send-trigger-rumble! 0 16383 25))
)
((= v1-0 (projectile-options lose-altitude))
(sound-play "yellow-gun-burn")

View File

@ -91,6 +91,9 @@
(remove-setting! 'string-spline-max-move-player)
(remove-setting! 'string-spline-accel-player)
(sound-stop (-> self darkjak tone))
;; og:preserve-this trigger effects
(when (pc-get-trigger-effects-enabled?)
(pc-clear-trigger-effect! (pc-trigger-effect-option left)))
)
0
(none)
@ -287,6 +290,8 @@
)
)
:code (behavior ((arg0 darkjak-stage))
(when (pc-get-trigger-effects-enabled?)
(pc-send-trigger-rumble! 32767 0 100))
(send-event (handle->process (-> self notify)) 'notify 'attack 15)
(if (and (focus-test? self dark) (nonzero? (-> self darkjak)))
(go target-darkjak-giant)

View File

@ -377,6 +377,9 @@
(-> v1-16 id)
)
(set! (-> self gun active?) #f)
;; og:preserve-this trigger effects
(when (and (pc-get-trigger-effects-enabled?) (-> *pc-settings* controller-swap-r1-r2?))
(pc-clear-trigger-effect! (pc-trigger-effect-option right)))
(cond
((and (not (logtest? (surface-flag gun-fast-exit) (-> self control current-surface flags)))
(not (logtest? (-> self focus-status) (focus-status dead)))
@ -632,6 +635,19 @@
)
)
(set! (-> self game gun-type) (the-as pickup-type arg0))
;; og:preserve-this trigger effects
(when (and (pc-get-trigger-effects-enabled?) (-> *pc-settings* controller-swap-r1-r2?))
(case (-> self game gun-type)
(((pickup-type eco-red))
(pc-send-trigger-effect-feedback! (pc-trigger-effect-option right) 0 4))
(((pickup-type eco-yellow))
(pc-send-trigger-effect-weapon! (pc-trigger-effect-option right) 2 4 4))
(((pickup-type eco-blue))
(pc-send-trigger-effect-vibrate! (pc-trigger-effect-option right) 0 4 30))
(((pickup-type eco-dark))
(pc-send-trigger-effect-feedback! (pc-trigger-effect-option right) 0 2))))
(set! (-> self gun track-turnv-range) 81920.0)
(set! (-> self gun track-tilt-range) 0.0)
(set! (-> self gun track-turn-range) 0.0)

View File

@ -844,6 +844,9 @@
(language-name-czech #x1347)
(language-name-croatian #x1348)
(language-name-galician #x1349)
(progress-controller-options-enable-pressure-sensitivity #x134a)
(progress-controller-options-swap-r1-r2 #x134b)
(progress-controller-options-enable-trigger-effects #x134c)
)
;; ---text-id

View File

@ -209,6 +209,21 @@
(define-extern pc-ignore-background-controller-events! (function symbol none))
(define-extern pc-reset-bindings-to-defaults! (function int int none))
(define-extern pc-set-auto-hide-cursor! (function symbol none))
(define-extern pc-get-pressure-sensitivity-enabled? (function symbol))
(define-extern pc-set-pressure-sensitivity-enabled! (function symbol none))
(define-extern pc-current-controller-has-pressure-sensitivity? (function symbol))
(define-extern pc-current-controller-has-trigger-effect-support? (function symbol))
(define-extern pc-get-trigger-effects-enabled? (function symbol))
(define-extern pc-set-trigger-effects-enabled! (function symbol none))
(defenum pc-trigger-effect-option
(left 0)
(right 1)
(both 2))
(define-extern pc-clear-trigger-effect! (function pc-trigger-effect-option none))
(define-extern pc-send-trigger-effect-feedback! (function pc-trigger-effect-option int int none))
(define-extern pc-send-trigger-effect-vibrate! (function pc-trigger-effect-option int int int none))
(define-extern pc-send-trigger-effect-weapon! (function pc-trigger-effect-option int int int none))
(define-extern pc-send-trigger-rumble! (function int int int none))
;; Display Related Functions
(define-extern pc-get-display-mode (function symbol))

View File

@ -102,6 +102,7 @@
;; other
(controller-led-status? symbol)
(controller-swap-r1-r2? symbol)
(speedrunner-mode-custom-bind uint32)
(memcard-subtitles? symbol)
@ -202,6 +203,7 @@
(when (or (= device 'all) (= device 'controller))
(set! (-> obj controller-led-status?) #t)
(set! (-> obj controller-swap-r1-r2?) #f)
)
0)

View File

@ -762,6 +762,7 @@
(("text-language") (set! (-> obj text-language) (the-as pc-language (file-stream-read-int file))))
(("subtitle-language") (set! (-> obj subtitle-language) (the-as pc-language (file-stream-read-int file))))
(("controller-led-status?") (set! (-> obj controller-led-status?) (file-stream-read-symbol file)))
(("controller-swap-r1-r2?") (set! (-> obj controller-swap-r1-r2?) (file-stream-read-symbol file)))
(("speedrunner-mode-custom-bind") (set! (-> obj speedrunner-mode-custom-bind) (file-stream-read-int file)))
(("cheats") (set! (-> obj cheats) (the-as pc-cheats (file-stream-read-int file))))
(("cheats-revealed") (set! (-> obj cheats-revealed) (the-as pc-cheats (file-stream-read-int file))))
@ -817,6 +818,7 @@
(format file " (text-language ~D)~%" (-> obj text-language))
(format file " (subtitle-language ~D)~%" (-> obj text-language))
(format file " (controller-led-status? ~A)~%" (-> obj controller-led-status?))
(format file " (controller-swap-r1-r2? ~A)~%" (-> obj controller-swap-r1-r2?))
(format file " (speedrunner-mode-custom-bind ~D)~%" (-> obj speedrunner-mode-custom-bind))
(format file " (cheats #x~x)~%" (-> obj cheats))
(format file " (cheats-revealed #x~x)~%" (-> obj cheats-revealed))

View File

@ -221,10 +221,34 @@ This gives us more freedom to write code how we want.
:on-confirm (lambda ((val symbol))
(set! (-> *pc-settings* controller-led-eco?) val)
(pc-settings-save)))
(new 'static 'menu-generic-boolean-option
:name (text-id progress-controller-options-enable-pressure-sensitivity)
:should-disable? (lambda () (not (pc-current-controller-has-pressure-sensitivity?)))
:truthy-text (text-id progress-on)
:falsey-text (text-id progress-off)
:get-value-fn (lambda () (pc-get-pressure-sensitivity-enabled?))
:on-confirm (lambda ((val symbol)) (pc-set-pressure-sensitivity-enabled! val)))
(new 'static 'menu-generic-boolean-option
:name (text-id progress-controller-options-swap-r1-r2)
:truthy-text (text-id progress-on)
:falsey-text (text-id progress-off)
:get-value-fn (lambda () (-> *pc-settings* controller-swap-r1-r2?))
:on-confirm (lambda ((val symbol))
(set! (-> *pc-settings* controller-swap-r1-r2?) val)
(pc-settings-save)))
(new 'static 'menu-generic-boolean-option
:name (text-id progress-controller-options-enable-trigger-effects)
:should-disable? (lambda () (not (pc-current-controller-has-trigger-effect-support?)))
:truthy-text (text-id progress-on)
:falsey-text (text-id progress-off)
:get-value-fn (lambda () (pc-get-trigger-effects-enabled?))
:on-confirm (lambda ((val symbol)) (pc-set-trigger-effects-enabled! val)))
(new 'static 'menu-generic-confirm-option
:name (text-id progress-restore-defaults)
:on-confirm (lambda ((val symbol))
(reset-input *pc-settings* 'controller #t)
(pc-set-pressure-sensitivity-enabled! #f)
(pc-set-trigger-effects-enabled! #f)
(set-ignore-controller-in-bg! *pc-settings* (-> *pc-settings* ignore-controller-win-unfocused?))
(pc-settings-save))))
(new 'static 'menu-generic-boolean-option
@ -533,7 +557,7 @@ This gives us more freedom to write code how we want.
(let ((name (pc-get-display-name index *pc-cpp-temp-string*)))
(if name
(string-format "(~D) ~S" index *pc-cpp-temp-string*)
(string-format "Display ~D" index))
(string-format "Dis~+7Vp~-7Vla~+7Vy~-7V ~D" index))
))
:on-confirm (lambda ((index int) (the-progress progress))
(pc-set-display-id! index))

View File

@ -196,6 +196,11 @@
(define-extern pc-ignore-background-controller-events! (function symbol none))
(define-extern pc-reset-bindings-to-defaults! (function int int none))
(define-extern pc-set-auto-hide-cursor! (function symbol none))
(define-extern pc-get-pressure-sensitivity-enabled? (function symbol))
(define-extern pc-set-pressure-sensitivity-enabled! (function symbol none))
(define-extern pc-current-controller-has-trigger-effect-support? (function symbol))
(define-extern pc-get-trigger-effects-enabled? (function symbol))
(define-extern pc-set-trigger-effects-enabled! (function symbol none))
;; Display Related Functions
(define-extern pc-get-display-mode (function symbol))

1
third-party/SDL/.clang-format generated vendored
View File

@ -82,6 +82,7 @@ ForEachMacros:
"spa_list_for_each",
"spa_list_for_each_safe",
"wl_list_for_each",
"wl_list_for_each_safe",
"wl_array_for_each",
"udev_list_entry_foreach",
]

59
third-party/SDL/.clang-tidy generated vendored Normal file
View File

@ -0,0 +1,59 @@
---
Checks: >
-*,
bugprone-assert-side-effect,
bugprone-assignment-in-if-condition,
bugprone-bool-pointer-implicit-conversion,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-infinite-loop,
bugprone-integer-division,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-not-null-terminated-result,
bugprone-posix-return,
bugprone-redundant-branch-condition,
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-memset-usage,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-too-small-loop-variable,
bugprone-unused-return-value,
cert-err33-c,
clang-analyzer-core.*,
clang-analyzer-valist.*,
clang-analyzer-unix.Malloc,
clang-diagnostic-*,
google-readability-casting,
misc-misleading-bidirectional,
misc-misleading-identifier,
misc-misplaced-const,
misc-redundant-expression,
objc-*,
performance-type-promotion-in-math-fn,
readability-avoid-const-params-in-decls,
readability-braces-around-statements,
readability-const-return-type,
readability-duplicate-include,
readability-inconsistent-declaration-parameter-name,
readability-misplaced-array-index,
readability-non-const-parameter,
readability-redundant-control-flow,
readability-redundant-declaration,
readability-redundant-function-ptr-dereference,
readability-redundant-preprocessor,
readability-simplify-boolean-expr
CheckOptions:
- key: bugprone-assert-side-effect.AssertMacros
value: "SDL_assert, SDL_assert_release, SDL_assert_paranoid, SDL_assert_always, SDL_COMPILE_TIME_ASSERT"
- key: bugprone-misplaced-widening-cast.CheckImplicitCasts
value: true
- key: bugprone-not-null-terminated-result.WantToUseSafeFunctions
value: false # Do not recommend _s functions
FormatStyle: "file"
HeaderFilterRegex: "*.h$"
WarningsAsErrors: ""

32
third-party/SDL/.editorconfig generated vendored
View File

@ -4,7 +4,7 @@
root = true
[*.{c,cg,cpp,gradle,h,java,m,metal,pl,py,S,sh,txt}]
[*.{c,cc,cg,cpp,gradle,h,java,m,metal,pl,py,S,sh,txt}]
indent_size = 4
indent_style = space
insert_final_newline = true
@ -13,42 +13,29 @@ trim_trailing_whitespace = true
[*.{html,js,json,m4,yml,yaml,vcxproj,vcxproj.filters}]
indent_size = 2
indent_style = space
trim_tailing_whitespace = true
[*.xml]
indent_size = 4
indent_style = space
[{CMakeLists.txt,sdl2-config*.cmake.in,cmake/*.cmake}]
[{CMakeLists.txt,cmake/*.cmake}]
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[{cmake_uninstall.cmake.in,test/CMakeLists.txt}]
indent_size = 4
indent_style = space
[configure.ac]
# Inconsistently 2-, 4- or occasionally 3-space indented, but mostly 4,
# so let's use 4 for new code
[{cmake/cmake_uninstall.cmake.in,test/CMakeLists.txt,cmake/SDL3Config.cmake.in}]
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[{Makefile.*,*.mk,*.sln,*.pbxproj,*.plist}]
indent_size = 8
indent_style = tab
tab_width = 8
[Makefile.os2]
indent_size = 4
indent_style = space
[test/Makefile.os2]
indent_size = 2
indent_style = space
[{src/core/os2/geniconv/makefile,src/core/os2/geniconv/os2cp.c}]
indent_size = 2
indent_style = space
[src/joystick/controller_type.*]
indent_style = tab
@ -77,3 +64,6 @@ tab_width = 4
[{*.bat,*.rc}]
end_of_line = crlf
[*.cocci]
insert_final_newline = true

View File

@ -0,0 +1,82 @@
name: 'Setup GDK (Game Development Kit) for Windows Desktop'
description: 'Download GDK and install into MSBuild'
inputs:
# Keep edition and ref in sync!
edition:
description: 'GDK edition'
default: '240601' # YYMMUU (Year Month Update)
ref:
description: 'Git reference'
default: 'June_2024_Update_1'
folder:
description: 'Folder where to create Directory.Build.props'
required: true
default: '${{ github.workspace }}'
runs:
using: 'composite'
steps:
- uses: actions/setup-python@main
with:
python-version: 3.x
- name: 'Calculate variables'
id: calc
shell: pwsh
run: |
$vs_folder=@(vswhere -latest -property installationPath)
echo "vs-folder=${vs_folder}" >> $Env:GITHUB_OUTPUT
echo "gdk-path=${{ runner.temp }}\GDK-${{ inputs.edition }}" >> $Env:GITHUB_OUTPUT
echo "cache-key=gdk-${{ inputs.ref }}-${{ inputs.edition }}" >> $Env:GITHUB_OUTPUT
- name: 'Restore cached GDK'
id: cache-restore
uses: actions/cache/restore@v4
with:
path: '${{ steps.calc.outputs.gdk-path }}'
key: ${{ steps.calc.outputs.cache-key }}
- name: 'Download GDK'
if: ${{ !steps.cache-restore.outputs.cache-hit }}
shell: pwsh
run: |
python build-scripts/setup-gdk-desktop.py `
--download `
--temp-folder "${{ runner.temp }}" `
--gdk-path="${{ steps.calc.outputs.gdk-path }}" `
--ref-edition "${{ inputs.ref }},${{ inputs.edition }}" `
--vs-folder="${{ steps.calc.outputs.vs-folder }}" `
--no-user-props
- name: 'Extract GDK'
if: ${{ !steps.cache-restore.outputs.cache-hit }}
shell: pwsh
run: |
python build-scripts/setup-gdk-desktop.py `
--extract `
--ref-edition "${{ inputs.ref }},${{ inputs.edition }}" `
--temp-folder "${{ runner.temp }}" `
--gdk-path="${{ steps.calc.outputs.gdk-path }}" `
--vs-folder="${{ steps.calc.outputs.vs-folder }}" `
--no-user-props
- name: 'Cache GDK'
if: ${{ !steps.cache-restore.outputs.cache-hit }}
uses: actions/cache/save@v4
with:
path: '${{ steps.calc.outputs.gdk-path }}'
key: ${{ steps.calc.outputs.cache-key }}
- name: 'Copy MSBuild files into GDK'
shell: pwsh
run: |
python build-scripts/setup-gdk-desktop.py `
--ref-edition "${{ inputs.ref }},${{ inputs.edition }}" `
--gdk-path="${{ steps.calc.outputs.gdk-path }}" `
--vs-folder="${{ steps.calc.outputs.vs-folder }}" `
--copy-msbuild `
--no-user-props
- name: 'Write user props'
shell: pwsh
run: |
python build-scripts/setup-gdk-desktop.py `
--ref-edition "${{ inputs.ref }},${{ inputs.edition }}" `
--temp-folder "${{ runner.temp }}" `
--vs-folder="${{ steps.calc.outputs.vs-folder }}" `
--gdk-path="${{ steps.calc.outputs.gdk-path }}" `
"--props-folder=${{ inputs.folder }}"

View File

@ -0,0 +1,53 @@
name: 'Setup LoongArch64 toolchain'
description: 'Download Linux LoongArch64 toolchain and set output variables'
inputs:
version:
description: 'LoongArch64 version'
default: '2023.08.08'
outputs:
prefix:
description: "LoongArch toolchain prefix"
value: ${{ steps.final.outputs.prefix }}
cc:
description: "LoongArch C compiler"
value: ${{ steps.final.outputs.cc }}
cxx:
description: "LoongArch C++ compiler"
value: ${{ steps.final.outputs.cxx }}
runs:
using: 'composite'
steps:
- uses: actions/cache/restore@v4
id: restore-cache
with:
path: /opt/cross-tools
key: loongarch64-${{ inputs.version }}
- name: 'Download LoongArch64 gcc+glibc toolchain'
if: ${{ !steps.restore-cache.outputs.cache-hit }}
shell: bash
run: |
url="https://github.com/loongson/build-tools/releases/download/${{ inputs.version }}/CLFS-loongarch64-8.1-x86_64-cross-tools-gcc-glibc.tar.xz"
wget "$url" -O /tmp/toolchain.tar.xz
mkdir -p /opt
tar -C /opt -x -f /tmp/toolchain.tar.xz
- uses: actions/cache/save@v4
if: ${{ !steps.restore-cache.outputs.cache-hit }}
with:
path: /opt/cross-tools
key: loongarch64-${{ inputs.version }}
- name: 'Set output vars'
id: final
shell: bash
run: |
prefix=/opt/cross-tools
echo "prefix=${prefix}" >> $GITHUB_OUTPUT
cc="${prefix}/bin/loongarch64-unknown-linux-gnu-gcc"
cxx="${prefix}/bin/loongarch64-unknown-linux-gnu-g++"
echo "cc=${cc}" >> $GITHUB_OUTPUT
echo "cxx=${cxx}" >> $GITHUB_OUTPUT
echo "LOONGARCH64_CC=${cc}" >>$GITHUB_ENV
echo "LOONGARCH64_CXX=${cxx}" >>$GITHUB_ENV

View File

@ -0,0 +1,71 @@
name: 'Setup libusb for MSVC'
description: 'Download libusb sdk for MSVC, and set output/environment variables'
inputs:
version:
description: 'libusb version'
required: true
default: '1.0.27'
arch:
description: "libusb architecture (x86 or x64)"
rqeuired: true
outputs:
root:
description: "libusb root directory"
value: ${{ steps.final.outputs.root }}
runs:
using: 'composite'
steps:
- name: 'Restore cached libusb-${{ inputs.version }}.7z'
id: cache-restore
uses: actions/cache/restore@v4
with:
path: 'C:\temp\libusb-${{ inputs.version }}.7z'
key: libusb-msvc-${{ inputs.version }}
- name: 'Download libusb ${{ inputs.version }}'
if: ${{ !steps.cache-restore.outputs.cache-hit }}
shell: pwsh
run: |
Invoke-WebRequest "https://github.com/libusb/libusb/releases/download/v${{ inputs.version }}/libusb-${{ inputs.version }}.7z" -OutFile "C:\temp\libusb-${{ inputs.version }}.7z"
- name: 'Cache libusb-${{ inputs.version }}.7z'
if: ${{ !steps.cache-restore.outputs.cache-hit }}
uses: actions/cache/save@v4
with:
path: 'C:\temp\libusb-${{ inputs.version }}.7z'
key: libusb-msvc-${{ inputs.version }}
- name: 'Extract libusb'
shell: pwsh
run: |
7z "-oC:\temp\libusb-${{ inputs.version }}" x "C:\temp\libusb-${{ inputs.version }}.7z"
- name: 'Set output vars'
id: final
shell: pwsh
run: |
if ('${{ inputs.arch }}' -eq 'x86') {
$archdir = "MS32";
} elseif ('${{ inputs.arch }}' -eq 'x64') {
$archdir = "MS64";
} else {
write-host "Invalid arch=${{ inputs.arch }}"
exit 1
}
$libusb_incdir = "C:\temp\libusb-${{ inputs.version }}\include";
$libusb_libdir = "C:\temp\libusb-${{ inputs.version }}\VS2022\${archdir}\dll";
$libusb_header = "${libusb_incdir}\libusb.h";
$libusb_implib = "${libusb_libdir}\libusb-1.0.lib";
$libusb_dll = "${libusb_libdir}\libusb-1.0.dll";
if (!(Test-Path "${libusb_header}")) {
write-host "${libusb_header} does not exist!"
exit 1
}
if (!(Test-Path "${libusb_implib}")){
write-host "${libusb_implib} does not exist!"
exit 1
}
if (!(Test-Path "${libusb_dll}")) {
write-host "${libusb_dll} does not exist!"
exit 1
}
echo "root=${libusb_incdir};${libusb_libdir}" >> $env:GITHUB_OUTPUT
echo "LibUSB_ROOT=${libusb_incdir};${libusb_libdir}" >> $env:GITHUB_ENV

62
third-party/SDL/.github/actions/setup-ninja/action.yml generated vendored Normal file
View File

@ -0,0 +1,62 @@
name: 'Setup ninja'
description: 'Download ninja and add it to the PATH environment variable'
inputs:
version:
description: 'Ninja version'
default: '1.12.1'
runs:
using: 'composite'
steps:
- name: 'Calculate variables'
id: calc
shell: sh
run: |
case "${{ runner.os }}-${{ runner.arch }}" in
"Linux-X86" | "Linux-X64")
archive="ninja-linux.zip"
;;
"Linux-ARM64")
archive="ninja-linux-aarch64.zip"
;;
"macOS-X86" | "macOS-X64" | "macOS-ARM64")
archive="ninja-mac.zip"
;;
"Windows-X86" | "Windows-X64")
archive="ninja-win.zip"
;;
"Windows-ARM64")
archive="ninja-winarm64.zip"
;;
*)
echo "Unsupported ${{ runner.os }}-${{ runner.arch }}"
exit 1;
;;
esac
echo "archive=${archive}" >> ${GITHUB_OUTPUT}
echo "cache-key=${archive}-${{ inputs.version }}-${{ runner.os }}-${{ runner.arch }}" >> ${GITHUB_OUTPUT}
- name: 'Restore cached ${{ steps.calc.outputs.archive }}'
id: cache-restore
uses: actions/cache/restore@v4
with:
path: '${{ runner.temp }}/${{ steps.calc.outputs.archive }}'
key: ${{ steps.calc.outputs.cache-key }}
- name: 'Download ninja ${{ inputs.version }} for ${{ runner.os }} (${{ runner.arch }})'
if: ${{ !steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false' }}
shell: pwsh
run: |
Invoke-WebRequest "https://github.com/ninja-build/ninja/releases/download/v${{ inputs.version }}/${{ steps.calc.outputs.archive }}" -OutFile "${{ runner.temp }}/${{ steps.calc.outputs.archive }}"
- name: 'Cache ${{ steps.calc.outputs.archive }}'
if: ${{ !steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false' }}
uses: actions/cache/save@v4
with:
path: '${{ runner.temp }}/${{ steps.calc.outputs.archive }}'
key: ${{ steps.calc.outputs.cache-key }}
- name: 'Extract ninja'
shell: pwsh
run: |
7z "-o${{ runner.temp }}/ninja-${{ inputs.version }}-${{ runner.arch }}" x "${{ runner.temp }}/${{ steps.calc.outputs.archive }}"
- name: 'Set output variables'
id: final
shell: pwsh
run: |
echo "${{ runner.temp }}/ninja-${{ inputs.version }}-${{ runner.arch }}" >> $env:GITHUB_PATH

View File

@ -0,0 +1,93 @@
name: 'Setup GLES for PlayStation Vita'
description: 'Download GLES for VITA (PVR or PIB), and copy it into the vita sdk'
inputs:
pib-version:
description: 'PIB version'
default: '1.1.4'
pvr-version:
description: 'PVR_PSP2 version'
default: '3.9'
type:
description: '"pib" or "pvr"'
default: ''
runs:
using: 'composite'
steps:
- name: 'Calculate variables'
id: calc
shell: sh
run: |
if test "x${VITASDK}" = "x"; then
echo "VITASDK must be defined"
exit 1;
fi
case "x${{ inputs.type }}" in
"xpvr")
echo "cache-key=SDL-vita-gles-pvr-${{ inputs.pvr-version}}" >> ${GITHUB_OUTPUT}
;;
"xpib")
echo "cache-key=SDL-vita-gles-pib-${{ inputs.pib-version}}" >> ${GITHUB_OUTPUT}
;;
*)
echo "Invalid type. Must be 'pib' or 'pvr'."
exit 1
;;
esac
- uses: actions/cache/restore@v4
id: restore-cache
with:
path: /vita/dependencies
key: '${{ steps.calc.outputs.cache-key }}'
- name: 'Download PVR_PSP2 (GLES)'
if: ${{ !steps.restore-cache.outputs.cache-hit && inputs.type == 'pvr' }}
shell: sh
run: |
pvr_psp2_version=${{ inputs.pvr-version }}
mkdir -p /vita/dependencies/include
mkdir -p /vita/dependencies/lib
# Configure PVR_PSP2 headers
wget https://github.com/GrapheneCt/PVR_PSP2/archive/refs/tags/v$pvr_psp2_version.zip -P/tmp
unzip /tmp/v$pvr_psp2_version.zip -d/tmp
cp -r /tmp/PVR_PSP2-$pvr_psp2_version/include/* /vita/dependencies/include
rm /tmp/v$pvr_psp2_version.zip
# include guard of PVR_PSP2's khrplatform.h does not match the usual one
sed -i -e s/__drvkhrplatform_h_/__khrplatform_h_/ /vita/dependencies/include/KHR/khrplatform.h
# Configure PVR_PSP2 stub libraries
wget https://github.com/GrapheneCt/PVR_PSP2/releases/download/v$pvr_psp2_version/vitasdk_stubs.zip -P/tmp
unzip /tmp/vitasdk_stubs.zip -d/tmp/pvr_psp2_stubs
find /tmp/pvr_psp2_stubs -type f -name "*.a" -exec cp {} /vita/dependencies/lib \;
rm /tmp/vitasdk_stubs.zip
rm -rf /tmp/pvr_psp2_stubs
- name: 'Download gl4es4vita (OpenGL)'
if: ${{ !steps.restore-cache.outputs.cache-hit && inputs.type == 'pib' }}
shell: sh
run: |
gl4es4vita_version=${{ inputs.pib-version }}
mkdir -p /vita/dependencies/include
mkdir -p /vita/dependencies/lib
# Configure gl4es4vita headers
wget https://github.com/SonicMastr/gl4es4vita/releases/download/v$gl4es4vita_version-vita/include.zip -P/tmp
unzip -o /tmp/include.zip -d/vita/dependencies/include
rm /tmp/include.zip
# Configure gl4es4vita stub libraries
wget https://github.com/SonicMastr/gl4es4vita/releases/download/v$gl4es4vita_version-vita/vitasdk_stubs.zip -P/tmp
unzip /tmp/vitasdk_stubs.zip -d/vita/dependencies/lib
- uses: actions/cache/save@v4
if: ${{ !steps.restore-cache.outputs.cache-hit }}
with:
path: /vita/dependencies
key: '${{ steps.calc.outputs.cache-key }}'
- name: Copy PVR_PSP2 (GLES) or gl4es4vita (OpenGL) to vita toolchain dir
shell: sh
run: |
cp -rv /vita/dependencies/* ${VITASDK}/arm-vita-eabi

View File

@ -1,81 +0,0 @@
name: Build (Android)
on: [push, pull_request]
jobs:
android:
name: ${{ matrix.platform.name }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- { name: Android.mk }
- { name: CMake, cmake: 1, android_abi: "arm64-v8a", android_platform: 23, arch: "aarch64" }
steps:
- uses: actions/checkout@v3
- uses: nttld/setup-ndk@v1
id: setup_ndk
with:
ndk-version: r21e
- name: Build (Android.mk)
if: ${{ matrix.platform.name == 'Android.mk' }}
run: |
./build-scripts/androidbuildlibs.sh
- name: Setup (CMake)
if: ${{ matrix.platform.name == 'CMake' }}
run: |
sudo apt-get update
sudo apt-get install ninja-build pkg-config
- name: Configure (CMake)
if: ${{ matrix.platform.name == 'CMake' }}
run: |
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=${{ steps.setup_ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake \
-DSDL_WERROR=ON \
-DANDROID_PLATFORM=${{ matrix.platform.android_platform }} \
-DANDROID_ABI=${{ matrix.platform.android_abi }} \
-DSDL_STATIC_PIC=ON \
-DSDL_VENDOR_INFO="Github Workflow" \
-DCMAKE_INSTALL_PREFIX=prefix \
-DCMAKE_BUILD_TYPE=Release \
-GNinja
- name: Build (CMake)
if: ${{ matrix.platform.name == 'CMake' }}
run: |
cmake --build build --config Release --parallel --verbose
- name: Install (CMake)
if: ${{ matrix.platform.name == 'CMake' }}
run: |
cmake --install build --config Release
echo "SDL2_DIR=$(pwd)/prefix" >> $GITHUB_ENV
( cd prefix; find ) | LC_ALL=C sort -u
- name: Verify CMake configuration files
if: ${{ matrix.platform.name == 'CMake' }}
run: |
cmake -S cmake/test -B cmake_config_build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=${{ steps.setup_ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake \
-DANDROID_PLATFORM=${{ matrix.platform.android_platform }} \
-DANDROID_ABI=${{ matrix.platform.android_abi }} \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }}
cmake --build cmake_config_build --verbose
- name: Verify sdl2-config
if: ${{ matrix.platform.name == 'CMake' }}
run: |
export CC="${{ steps.setup_ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=${{ matrix.platform.arch }}-none-linux-androideabi${{ matrix.platform.android_platform }}"
export PATH=${{ env.SDL2_DIR }}/bin:$PATH
cmake/test/test_sdlconfig.sh
- name: Verify sdl2.pc
if: ${{ matrix.platform.name == 'CMake' }}
run: |
export CC="${{ steps.setup_ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=${{ matrix.platform.arch }}-none-linux-androideabi${{ matrix.platform.android_platform }}"
export PKG_CONFIG_PATH=${{ env.SDL2_DIR }}/lib/pkgconfig
cmake/test/test_pkgconfig.sh
- name: Verify Android.mk
if: ${{ matrix.platform.name == 'CMake' }}
run: |
export NDK_MODULE_PATH=${{ env.SDL2_DIR }}/share/ndk-modules
ndk-build -C ${{ github.workspace }}/cmake/test APP_PLATFORM=android-${{ matrix.platform.android_platform }} APP_ABI=${{ matrix.platform.android_abi }} NDK_OUT=$PWD NDK_LIBS_OUT=$PWD V=1

48
third-party/SDL/.github/workflows/build.yml generated vendored Normal file
View File

@ -0,0 +1,48 @@
name: 'Build (All)'
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
controller:
name: 'Create test plan'
runs-on: 'ubuntu-latest'
outputs:
platforms-level1: ${{ steps.plan.outputs.platforms-level1 }}
platforms-others: ${{ steps.plan.outputs.platforms-others }}
steps:
- uses: actions/setup-python@main
with:
python-version: 3.x
- uses: actions/checkout@main
with:
sparse-checkout: '.github/workflows/create-test-plan.py'
- name: 'Create plan'
id: plan
run: |
# Adding [sdl-ci-filter GLOB] to the commit message will limit the jobs
# e.g. [sdl-ci-filter msvc-*]
EOF=$(openssl rand -hex 32)
cat >/tmp/commit_message.txt <<$EOF
${{ github.event.head_commit.message }}
$EOF
python .github/workflows/create-test-plan.py \
--github-variable-prefix platforms \
--github-ci \
--verbose \
${{ (github.repository_owner != 'libsdl-org' && '--no-artifact') || '' }} \
--commit-message-file /tmp/commit_message.txt
level1:
needs: [controller]
uses: './.github/workflows/generic.yml'
with:
platforms: ${{ needs.controller.outputs.platforms-level1 }}
level2:
needs: [controller, level1]
uses: './.github/workflows/generic.yml'
with:
platforms: ${{ needs.controller.outputs.platforms-others }}

View File

@ -1,51 +0,0 @@
name: Build (C/P Actions)
on: [push, pull_request]
jobs:
freebsd:
runs-on: ubuntu-latest
name: FreeBSD
timeout-minutes: 30
steps:
- uses: actions/checkout@v3
- name: Build
uses: cross-platform-actions/action@v0.19.1
with:
operating_system: freebsd
version: '13.2'
shell: bash
run: |
sudo pkg update
sudo pkg install -y \
gmake \
pkgconf \
libXcursor \
libXext \
libXinerama \
libXi \
libXfixes \
libXrandr \
libXScrnSaver \
libXxf86vm \
wayland \
wayland-protocols \
libxkbcommon \
mesa-libs \
libglvnd \
evdev-proto \
libinotify \
alsa-lib \
jackit \
pipewire \
pulseaudio \
sndio \
dbus \
zh-fcitx \
ibus \
libudev-devd
mkdir build_autotools
export CPPFLAGS="-I/usr/local/include"
export LDFLAGS="-L/usr/local/lib"
(cd build_autotools && ../configure --disable-static)
gmake -C build_autotools -j`sysctl -n hw.ncpu` V=1

834
third-party/SDL/.github/workflows/create-test-plan.py generated vendored Normal file
View File

@ -0,0 +1,834 @@
#!/usr/bin/env python
import argparse
import dataclasses
import fnmatch
from enum import Enum
import json
import logging
import os
import re
from typing import Optional
logger = logging.getLogger(__name__)
class AppleArch(Enum):
Aarch64 = "aarch64"
X86_64 = "x86_64"
class MsvcArch(Enum):
X86 = "x86"
X64 = "x64"
Arm32 = "arm"
Arm64 = "arm64"
class JobOs(Enum):
WindowsLatest = "windows-latest"
UbuntuLatest = "ubuntu-latest"
MacosLatest = "macos-latest"
Ubuntu20_04 = "ubuntu-20.04"
Ubuntu22_04 = "ubuntu-22.04"
Ubuntu24_04 = "ubuntu-24.04"
Ubuntu24_04_arm = "ubuntu-24.04-arm"
Macos13 = "macos-13"
class SdlPlatform(Enum):
Android = "android"
Emscripten = "emscripten"
Haiku = "haiku"
LoongArch64 = "loongarch64"
Msys2 = "msys2"
Linux = "linux"
MacOS = "macos"
Ios = "ios"
Tvos = "tvos"
Msvc = "msvc"
N3ds = "n3ds"
PowerPC = "powerpc"
PowerPC64 = "powerpc64"
Ps2 = "ps2"
Psp = "psp"
Vita = "vita"
Riscos = "riscos"
FreeBSD = "freebsd"
NetBSD = "netbsd"
class Msys2Platform(Enum):
Mingw32 = "mingw32"
Mingw64 = "mingw64"
Clang32 = "clang32"
Clang64 = "clang64"
Ucrt64 = "ucrt64"
class IntelCompiler(Enum):
Icc = "icc"
Icx = "icx"
class VitaGLES(Enum):
Pib = "pib"
Pvr = "pvr"
@dataclasses.dataclass(slots=True)
class JobSpec:
name: str
os: JobOs
platform: SdlPlatform
artifact: Optional[str]
container: Optional[str] = None
no_cmake: bool = False
xcode: bool = False
android_mk: bool = False
android_gradle: bool = False
lean: bool = False
android_arch: Optional[str] = None
android_abi: Optional[str] = None
android_platform: Optional[int] = None
msys2_platform: Optional[Msys2Platform] = None
intel: Optional[IntelCompiler] = None
apple_framework: Optional[bool] = None
apple_archs: Optional[set[AppleArch]] = None
msvc_project: Optional[str] = None
msvc_arch: Optional[MsvcArch] = None
clang_cl: bool = False
gdk: bool = False
vita_gles: Optional[VitaGLES] = None
JOB_SPECS = {
"msys2-mingw32": JobSpec(name="Windows (msys2, mingw32)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw32", msys2_platform=Msys2Platform.Mingw32, ),
"msys2-mingw64": JobSpec(name="Windows (msys2, mingw64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64", msys2_platform=Msys2Platform.Mingw64, ),
"msys2-clang32": JobSpec(name="Windows (msys2, clang32)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw32-clang", msys2_platform=Msys2Platform.Clang32, ),
"msys2-clang64": JobSpec(name="Windows (msys2, clang64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64-clang", msys2_platform=Msys2Platform.Clang64, ),
"msys2-ucrt64": JobSpec(name="Windows (msys2, ucrt64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64-ucrt", msys2_platform=Msys2Platform.Ucrt64, ),
"msvc-x64": JobSpec(name="Windows (MSVC, x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-x64", msvc_arch=MsvcArch.X64, msvc_project="VisualC/SDL.sln", ),
"msvc-x86": JobSpec(name="Windows (MSVC, x86)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-x86", msvc_arch=MsvcArch.X86, msvc_project="VisualC/SDL.sln", ),
"msvc-clang-x64": JobSpec(name="Windows (MSVC, clang-cl x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-clang-cl-x64", msvc_arch=MsvcArch.X64, clang_cl=True, ),
"msvc-clang-x86": JobSpec(name="Windows (MSVC, clang-cl x86)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-clang-cl-x86", msvc_arch=MsvcArch.X86, clang_cl=True, ),
"msvc-arm32": JobSpec(name="Windows (MSVC, ARM)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-arm32", msvc_arch=MsvcArch.Arm32, ),
"msvc-arm64": JobSpec(name="Windows (MSVC, ARM64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-arm64", msvc_arch=MsvcArch.Arm64, ),
"msvc-gdk-x64": JobSpec(name="GDK (MSVC, x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-GDK", msvc_arch=MsvcArch.X64, msvc_project="VisualC-GDK/SDL.sln", gdk=True, no_cmake=True, ),
"ubuntu-20.04": JobSpec(name="Ubuntu 20.04", os=JobOs.Ubuntu20_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu20.04", ),
"ubuntu-22.04": JobSpec(name="Ubuntu 22.04", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04", ),
"ubuntu-24.04-arm64": JobSpec(name="Ubuntu 24.04 (ARM64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-ubuntu24.04-arm64", ),
"steamrt-sniper": JobSpec(name="Steam Linux Runtime (Sniper)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-slrsniper", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta", ),
"ubuntu-intel-icx": JobSpec(name="Ubuntu 20.04 (Intel oneAPI)", os=JobOs.Ubuntu20_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu20.04-oneapi", intel=IntelCompiler.Icx, ),
"ubuntu-intel-icc": JobSpec(name="Ubuntu 20.04 (Intel Compiler)", os=JobOs.Ubuntu20_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu20.04-icc", intel=IntelCompiler.Icc, ),
"macos-framework-x64": JobSpec(name="MacOS (Framework) (x64)", os=JobOs.Macos13, platform=SdlPlatform.MacOS, artifact="SDL-macos-framework", apple_framework=True, apple_archs={AppleArch.Aarch64, AppleArch.X86_64, }, xcode=True, ),
"macos-framework-arm64": JobSpec(name="MacOS (Framework) (arm64)", os=JobOs.MacosLatest, platform=SdlPlatform.MacOS, artifact=None, apple_framework=True, apple_archs={AppleArch.Aarch64, AppleArch.X86_64, }, ),
"macos-gnu-arm64": JobSpec(name="MacOS (GNU prefix)", os=JobOs.MacosLatest, platform=SdlPlatform.MacOS, artifact="SDL-macos-arm64-gnu", apple_framework=False, apple_archs={AppleArch.Aarch64, }, ),
"ios": JobSpec(name="iOS (CMake & xcode)", os=JobOs.MacosLatest, platform=SdlPlatform.Ios, artifact="SDL-ios-arm64", xcode=True, ),
"tvos": JobSpec(name="tvOS (CMake & xcode)", os=JobOs.MacosLatest, platform=SdlPlatform.Tvos, artifact="SDL-tvos-arm64", xcode=True, ),
"android-cmake": JobSpec(name="Android (CMake)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Android, artifact="SDL-android-arm64", android_abi="arm64-v8a", android_arch="aarch64", android_platform=23, ),
"android-cmake-lean": JobSpec(name="Android (CMake, lean)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Android, artifact="SDL-lean-android-arm64", android_abi="arm64-v8a", android_arch="aarch64", android_platform=23, lean=True, ),
"android-mk": JobSpec(name="Android (Android.mk)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Android, artifact=None, no_cmake=True, android_mk=True, ),
"android-gradle": JobSpec(name="Android (Gradle)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Android, artifact=None, no_cmake=True, android_gradle=True, ),
"emscripten": JobSpec(name="Emscripten", os=JobOs.UbuntuLatest, platform=SdlPlatform.Emscripten, artifact="SDL-emscripten", ),
"haiku": JobSpec(name="Haiku", os=JobOs.UbuntuLatest, platform=SdlPlatform.Haiku, artifact="SDL-haiku-x64", container="ghcr.io/haiku/cross-compiler:x86_64-r1beta5", ),
"loongarch64": JobSpec(name="LoongArch64", os=JobOs.UbuntuLatest, platform=SdlPlatform.LoongArch64, artifact="SDL-loongarch64", ),
"n3ds": JobSpec(name="Nintendo 3DS", os=JobOs.UbuntuLatest, platform=SdlPlatform.N3ds, artifact="SDL-n3ds", container="devkitpro/devkitarm:latest", ),
"ppc": JobSpec(name="PowerPC", os=JobOs.UbuntuLatest, platform=SdlPlatform.PowerPC, artifact="SDL-ppc", container="dockcross/linux-ppc:latest", ),
"ppc64": JobSpec(name="PowerPC64", os=JobOs.UbuntuLatest, platform=SdlPlatform.PowerPC64, artifact="SDL-ppc64le", container="dockcross/linux-ppc64le:latest", ),
"ps2": JobSpec(name="Sony PlayStation 2", os=JobOs.UbuntuLatest, platform=SdlPlatform.Ps2, artifact="SDL-ps2", container="ps2dev/ps2dev:latest", ),
"psp": JobSpec(name="Sony PlayStation Portable", os=JobOs.UbuntuLatest, platform=SdlPlatform.Psp, artifact="SDL-psp", container="pspdev/pspdev:latest", ),
"vita-pib": JobSpec(name="Sony PlayStation Vita (GLES w/ pib)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Vita, artifact="SDL-vita-pib", container="vitasdk/vitasdk:latest", vita_gles=VitaGLES.Pib, ),
"vita-pvr": JobSpec(name="Sony PlayStation Vita (GLES w/ PVR_PSP2)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Vita, artifact="SDL-vita-pvr", container="vitasdk/vitasdk:latest", vita_gles=VitaGLES.Pvr, ),
"riscos": JobSpec(name="RISC OS", os=JobOs.UbuntuLatest, platform=SdlPlatform.Riscos, artifact="SDL-riscos", container="riscosdotinfo/riscos-gccsdk-4.7:latest", ),
"netbsd": JobSpec(name="NetBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.NetBSD, artifact="SDL-netbsd-x64", ),
"freebsd": JobSpec(name="FreeBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.FreeBSD, artifact="SDL-freebsd-x64", ),
}
class StaticLibType(Enum):
MSVC = "SDL3-static.lib"
A = "libSDL3.a"
class SharedLibType(Enum):
WIN32 = "SDL3.dll"
SO_0 = "libSDL3.so.0"
SO = "libSDL3.so"
DYLIB = "libSDL3.0.dylib"
FRAMEWORK = "SDL3.framework/Versions/A/SDL3"
@dataclasses.dataclass(slots=True)
class JobDetails:
name: str
key: str
os: str
platform: str
artifact: str
no_cmake: bool
build_tests: bool = True
container: str = ""
cmake_build_type: str = "RelWithDebInfo"
shell: str = "sh"
sudo: str = "sudo"
cmake_config_emulator: str = ""
apk_packages: list[str] = dataclasses.field(default_factory=list)
apt_packages: list[str] = dataclasses.field(default_factory=list)
brew_packages: list[str] = dataclasses.field(default_factory=list)
cmake_toolchain_file: str = ""
cmake_arguments: list[str] = dataclasses.field(default_factory=list)
cmake_build_arguments: list[str] = dataclasses.field(default_factory=list)
clang_tidy: bool = True
cppflags: list[str] = dataclasses.field(default_factory=list)
cc: str = ""
cxx: str = ""
cflags: list[str] = dataclasses.field(default_factory=list)
cxxflags: list[str] = dataclasses.field(default_factory=list)
ldflags: list[str] = dataclasses.field(default_factory=list)
pollute_directories: list[str] = dataclasses.field(default_factory=list)
use_cmake: bool = True
shared: bool = True
static: bool = True
shared_lib: Optional[SharedLibType] = None
static_lib: Optional[StaticLibType] = None
run_tests: bool = True
test_pkg_config: bool = True
cc_from_cmake: bool = False
source_cmd: str = ""
pretest_cmd: str = ""
java: bool = False
android_apks: list[str] = dataclasses.field(default_factory=list)
android_ndk: bool = False
android_mk: bool = False
android_gradle: bool = False
minidump: bool = False
intel: bool = False
msys2_msystem: str = ""
msys2_env: str = ""
msys2_no_perl: bool = False
werror: bool = True
msvc_vcvars_arch: str = ""
msvc_vcvars_sdk: str = ""
msvc_project: str = ""
msvc_project_flags: list[str] = dataclasses.field(default_factory=list)
setup_ninja: bool = False
setup_libusb_arch: str = ""
xcode_sdk: str = ""
cpactions: bool = False
setup_gdk_folder: str = ""
cpactions_os: str = ""
cpactions_version: str = ""
cpactions_arch: str = ""
cpactions_setup_cmd: str = ""
cpactions_install_cmd: str = ""
setup_vita_gles_type: str = ""
check_sources: bool = False
setup_python: bool = False
pypi_packages: list[str] = dataclasses.field(default_factory=list)
def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
data = {
"name": self.name,
"key": self.key,
"os": self.os,
"container": self.container if self.container else "",
"platform": self.platform,
"artifact": self.artifact,
"enable-artifacts": enable_artifacts,
"shell": self.shell,
"msys2-msystem": self.msys2_msystem,
"msys2-env": self.msys2_env,
"msys2-no-perl": self.msys2_no_perl,
"android-ndk": self.android_ndk,
"java": self.java,
"intel": self.intel,
"apk-packages": my_shlex_join(self.apk_packages),
"apt-packages": my_shlex_join(self.apt_packages),
"test-pkg-config": self.test_pkg_config,
"brew-packages": my_shlex_join(self.brew_packages),
"pollute-directories": my_shlex_join(self.pollute_directories),
"no-cmake": self.no_cmake,
"build-tests": self.build_tests,
"source-cmd": self.source_cmd,
"pretest-cmd": self.pretest_cmd,
"cmake-config-emulator": self.cmake_config_emulator,
"cc": self.cc,
"cxx": self.cxx,
"cflags": my_shlex_join(self.cppflags + self.cflags),
"cxxflags": my_shlex_join(self.cppflags + self.cxxflags),
"ldflags": my_shlex_join(self.ldflags),
"cmake-toolchain-file": self.cmake_toolchain_file,
"clang-tidy": self.clang_tidy,
"cmake-arguments": my_shlex_join(self.cmake_arguments),
"cmake-build-arguments": my_shlex_join(self.cmake_build_arguments),
"shared": self.shared,
"static": self.static,
"shared-lib": self.shared_lib.value if self.shared_lib else None,
"static-lib": self.static_lib.value if self.static_lib else None,
"cmake-build-type": self.cmake_build_type,
"run-tests": self.run_tests,
"android-apks": my_shlex_join(self.android_apks),
"android-gradle": self.android_gradle,
"android-mk": self.android_mk,
"werror": self.werror,
"sudo": self.sudo,
"msvc-vcvars-arch": self.msvc_vcvars_arch,
"msvc-vcvars-sdk": self.msvc_vcvars_sdk,
"msvc-project": self.msvc_project,
"msvc-project-flags": my_shlex_join(self.msvc_project_flags),
"setup-ninja": self.setup_ninja,
"setup-libusb-arch": self.setup_libusb_arch,
"cc-from-cmake": self.cc_from_cmake,
"xcode-sdk": self.xcode_sdk,
"cpactions": self.cpactions,
"cpactions-os": self.cpactions_os,
"cpactions-version": self.cpactions_version,
"cpactions-arch": self.cpactions_arch,
"cpactions-setup-cmd": self.cpactions_setup_cmd,
"cpactions-install-cmd": self.cpactions_install_cmd,
"setup-vita-gles-type": self.setup_vita_gles_type,
"setup-gdk-folder": self.setup_gdk_folder,
"check-sources": self.check_sources,
"setup-python": self.setup_python,
"pypi-packages": my_shlex_join(self.pypi_packages),
}
return {k: v for k, v in data.items() if v != ""}
def my_shlex_join(s):
def escape(s):
if s[:1] == "'" and s[-1:] == "'":
return s
if set(s).intersection(set("; \t")):
return f'"{s}"'
return s
return " ".join(escape(s))
def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDetails:
job = JobDetails(
name=spec.name,
key=key,
os=spec.os.value,
artifact=spec.artifact or "",
container=spec.container or "",
platform=spec.platform.value,
sudo="sudo",
no_cmake=spec.no_cmake,
)
if job.os.startswith("ubuntu"):
job.apt_packages.extend([
"ninja-build",
"pkg-config",
])
pretest_cmd = []
if trackmem_symbol_names:
pretest_cmd.append("export SDL_TRACKMEM_SYMBOL_NAMES=1")
else:
pretest_cmd.append("export SDL_TRACKMEM_SYMBOL_NAMES=0")
win32 = spec.platform in (SdlPlatform.Msys2, SdlPlatform.Msvc)
fpic = None
build_parallel = True
if spec.lean:
job.cppflags.append("-DSDL_LEAN_AND_MEAN=1")
if win32:
job.cmake_arguments.append("-DSDLTEST_PROCDUMP=ON")
job.minidump = True
if spec.intel is not None:
match spec.intel:
case IntelCompiler.Icx:
job.cc = "icx"
job.cxx = "icpx"
case IntelCompiler.Icc:
job.cc = "icc"
job.cxx = "icpc"
job.cppflags.append("-diag-disable=10441")
job.clang_tidy = False
case _:
raise ValueError(f"Invalid intel={spec.intel}")
job.source_cmd = f"source /opt/intel/oneapi/setvars.sh;"
job.intel = True
job.shell = "bash"
job.cmake_arguments.extend((
f"-DCMAKE_C_COMPILER={job.cc}",
f"-DCMAKE_CXX_COMPILER={job.cxx}",
"-DCMAKE_SYSTEM_NAME=Linux",
))
match spec.platform:
case SdlPlatform.Msvc:
job.setup_ninja = not spec.gdk
job.clang_tidy = False # complains about \threadsafety: "unknown command tag name [clang-diagnostic-documentation-unknown-command]"
job.msvc_project = spec.msvc_project if spec.msvc_project else ""
job.msvc_project_flags.append("-p:TreatWarningsAsError=true")
job.test_pkg_config = False
job.shared_lib = SharedLibType.WIN32
job.static_lib = StaticLibType.MSVC
job.cmake_arguments.extend((
"-DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=ProgramDatabase",
"-DCMAKE_EXE_LINKER_FLAGS=-DEBUG",
"-DCMAKE_SHARED_LINKER_FLAGS=-DEBUG",
))
job.cmake_arguments.append("'-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>'")
if spec.clang_cl:
job.cmake_arguments.extend((
"-DCMAKE_C_COMPILER=clang-cl",
"-DCMAKE_CXX_COMPILER=clang-cl",
))
match spec.msvc_arch:
case MsvcArch.X86:
job.cflags.append("/clang:-m32")
job.ldflags.append("/MACHINE:X86")
case MsvcArch.X64:
job.cflags.append("/clang:-m64")
job.ldflags.append("/MACHINE:X64")
case _:
raise ValueError(f"Unsupported clang-cl architecture (arch={spec.msvc_arch})")
if spec.msvc_project:
match spec.msvc_arch:
case MsvcArch.X86:
msvc_platform = "Win32"
case MsvcArch.X64:
msvc_platform = "x64"
case _:
raise ValueError(f"Unsupported vcxproj architecture (arch={spec.msvc_arch})")
if spec.gdk:
msvc_platform = f"Gaming.Desktop.{msvc_platform}"
job.msvc_project_flags.append(f"-p:Platform={msvc_platform}")
match spec.msvc_arch:
case MsvcArch.X86:
job.msvc_vcvars_arch = "x64_x86"
case MsvcArch.X64:
job.msvc_vcvars_arch = "x64"
case MsvcArch.Arm32:
job.msvc_vcvars_arch = "x64_arm"
job.msvc_vcvars_sdk = "10.0.22621.0" # 10.0.26100.0 dropped ARM32 um and ucrt libraries
job.run_tests = False
case MsvcArch.Arm64:
job.msvc_vcvars_arch = "x64_arm64"
job.run_tests = False
if spec.gdk:
job.setup_gdk_folder = "VisualC-GDK"
else:
match spec.msvc_arch:
case MsvcArch.X86:
job.setup_libusb_arch = "x86"
case MsvcArch.X64:
job.setup_libusb_arch = "x64"
case SdlPlatform.Linux:
if spec.name.startswith("Ubuntu"):
assert spec.os.value.startswith("ubuntu-")
job.apt_packages.extend((
"gnome-desktop-testing",
"libasound2-dev",
"libpulse-dev",
"libaudio-dev",
"libjack-dev",
"libsndio-dev",
"libusb-1.0-0-dev",
"libx11-dev",
"libxext-dev",
"libxrandr-dev",
"libxcursor-dev",
"libxfixes-dev",
"libxi-dev",
"libxss-dev",
"libwayland-dev",
"libxkbcommon-dev",
"libdrm-dev",
"libgbm-dev",
"libgl1-mesa-dev",
"libgles2-mesa-dev",
"libegl1-mesa-dev",
"libdbus-1-dev",
"libibus-1.0-dev",
"libudev-dev",
"fcitx-libs-dev",
))
match = re.match(r"ubuntu-(?P<year>[0-9]+)\.(?P<month>[0-9]+).*", spec.os.value)
ubuntu_year, ubuntu_month = [int(match["year"]), int(match["month"])]
if ubuntu_year >= 22:
job.apt_packages.extend(("libpipewire-0.3-dev", "libdecor-0-dev"))
job.apt_packages.extend((
"libunwind-dev", # For SDL_test memory tracking
))
if trackmem_symbol_names:
# older libunwind is slow
job.cmake_arguments.append("-DSDLTEST_TIMEOUT_MULTIPLIER=2")
job.shared_lib = SharedLibType.SO_0
job.static_lib = StaticLibType.A
fpic = True
case SdlPlatform.Ios | SdlPlatform.Tvos:
job.brew_packages.extend([
"ninja",
])
job.clang_tidy = False
job.run_tests = False
job.test_pkg_config = False
job.shared_lib = SharedLibType.DYLIB
job.static_lib = StaticLibType.A
match spec.platform:
case SdlPlatform.Ios:
if spec.xcode:
job.xcode_sdk = 'iphoneos'
job.cmake_arguments.extend([
"-DCMAKE_SYSTEM_NAME=iOS",
"-DCMAKE_OSX_ARCHITECTURES=\"arm64\"",
"-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0",
])
case SdlPlatform.Tvos:
if spec.xcode:
job.xcode_sdk = 'appletvos'
job.cmake_arguments.extend([
"-DCMAKE_SYSTEM_NAME=tvOS",
"-DCMAKE_OSX_ARCHITECTURES=\"arm64\"",
"-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0",
])
case SdlPlatform.MacOS:
if spec.apple_framework:
job.static = False
job.clang_tidy = False
job.test_pkg_config = False
job.cmake_arguments.extend((
"'-DCMAKE_OSX_ARCHITECTURES=x86_64;arm64'",
"-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13",
"-DSDL_FRAMEWORK=ON",
))
job.shared_lib = SharedLibType.FRAMEWORK
else:
job.clang_tidy = True
job.cmake_arguments.extend((
"-DCMAKE_OSX_ARCHITECTURES=arm64",
"-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13",
"-DCLANG_TIDY_BINARY=$(brew --prefix llvm)/bin/clang-tidy",
))
job.shared_lib = SharedLibType.DYLIB
job.static_lib = StaticLibType.A
job.apt_packages = []
job.brew_packages.append("ninja")
if job.clang_tidy:
job.brew_packages.append("llvm")
if spec.xcode:
job.xcode_sdk = "macosx"
case SdlPlatform.Android:
job.android_gradle = spec.android_gradle
job.android_mk = spec.android_mk
job.run_tests = False
job.shared_lib = SharedLibType.SO
job.static_lib = StaticLibType.A
if spec.android_mk or not spec.no_cmake:
job.android_ndk = True
if spec.android_gradle or not spec.no_cmake:
job.java = True
if spec.android_mk or spec.android_gradle:
job.apt_packages = []
if not spec.no_cmake:
job.cmake_arguments.extend((
f"-DANDROID_PLATFORM={spec.android_platform}",
f"-DANDROID_ABI={spec.android_abi}",
))
job.cmake_toolchain_file = "${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake"
job.cc = f"${{ANDROID_NDK_HOME}}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target={spec.android_arch}-none-linux-androideabi{spec.android_platform}"
job.android_apks = [
"testaudiorecording-apk",
"testautomation-apk",
"testcontroller-apk",
"testmultiaudio-apk",
"testsprite-apk",
]
case SdlPlatform.Emscripten:
job.clang_tidy = False # clang-tidy does not understand -gsource-map
job.shared = False
job.cmake_config_emulator = "emcmake"
job.cmake_build_type = "Debug"
job.test_pkg_config = False
job.cmake_arguments.extend((
"-DSDLTEST_BROWSER=chrome",
"-DSDLTEST_TIMEOUT_MULTIPLIER=4",
"-DSDLTEST_CHROME_BINARY=${CHROME_BINARY}",
))
job.cflags.extend((
"-gsource-map",
"-ffile-prefix-map=${PWD}=/SDL",
))
job.ldflags.extend((
"--source-map-base", "/",
))
pretest_cmd.extend((
"# Start local HTTP server",
"cmake --build build --target serve-sdl-tests --verbose &",
"chrome --version",
"chromedriver --version",
))
job.static_lib = StaticLibType.A
job.setup_python = True
job.pypi_packages.append("selenium")
case SdlPlatform.Ps2:
build_parallel = False
job.shared = False
job.sudo = ""
job.apt_packages = []
job.apk_packages = ["cmake", "gmp", "mpc1", "mpfr4", "ninja", "pkgconf", "git", ]
job.cmake_toolchain_file = "${PS2DEV}/ps2sdk/ps2dev.cmake"
job.clang_tidy = False
job.run_tests = False
job.shared = False
job.cc = "mips64r5900el-ps2-elf-gcc"
job.ldflags = ["-L${PS2DEV}/ps2sdk/ee/lib", "-L${PS2DEV}/gsKit/lib", "-L${PS2DEV}/ps2sdk/ports/lib", ]
job.static_lib = StaticLibType.A
case SdlPlatform.Psp:
build_parallel = False
job.sudo = ""
job.apt_packages = []
job.apk_packages = ["cmake", "gmp", "mpc1", "mpfr4", "ninja", "pkgconf", ]
job.cmake_toolchain_file = "${PSPDEV}/psp/share/pspdev.cmake"
job.clang_tidy = False
job.run_tests = False
job.shared = False
job.cc = "psp-gcc"
job.ldflags = ["-L${PSPDEV}/lib", "-L${PSPDEV}/psp/lib", "-L${PSPDEV}/psp/sdk/lib", ]
job.pollute_directories = ["${PSPDEV}/include", "${PSPDEV}/psp/include", "${PSPDEV}/psp/sdk/include", ]
job.static_lib = StaticLibType.A
case SdlPlatform.Vita:
job.sudo = ""
job.apt_packages = []
job.apk_packages = ["cmake", "ninja", "pkgconf", "bash", "tar"]
job.cmake_toolchain_file = "${VITASDK}/share/vita.toolchain.cmake"
assert spec.vita_gles is not None
job.setup_vita_gles_type = {
VitaGLES.Pib: "pib",
VitaGLES.Pvr: "pvr",
}[spec.vita_gles]
job.cmake_arguments.extend((
f"-DVIDEO_VITA_PIB={ 'true' if spec.vita_gles == VitaGLES.Pib else 'false' }",
f"-DVIDEO_VITA_PVR={ 'true' if spec.vita_gles == VitaGLES.Pvr else 'false' }",
"-DSDL_ARMNEON=ON",
"-DSDL_ARMSIMD=ON",
))
# Fix vita.toolchain.cmake (https://github.com/vitasdk/vita-toolchain/pull/253)
job.source_cmd = r"""sed -i -E "s#set\\( PKG_CONFIG_EXECUTABLE \"\\$\\{VITASDK}/bin/arm-vita-eabi-pkg-config\" \\)#set\\( PKG_CONFIG_EXECUTABLE \"${VITASDK}/bin/arm-vita-eabi-pkg-config\" CACHE PATH \"Path of pkg-config executable\" \\)#" ${VITASDK}/share/vita.toolchain.cmake"""
job.clang_tidy = False
job.run_tests = False
job.shared = False
job.cc = "arm-vita-eabi-gcc"
job.static_lib = StaticLibType.A
case SdlPlatform.Haiku:
fpic = False
job.run_tests = False
job.cc = "x86_64-unknown-haiku-gcc"
job.cxx = "x86_64-unknown-haiku-g++"
job.sudo = ""
job.cmake_arguments.extend((
f"-DCMAKE_C_COMPILER={job.cc}",
f"-DCMAKE_CXX_COMPILER={job.cxx}",
"-DSDL_UNIX_CONSOLE_BUILD=ON",
))
job.shared_lib = SharedLibType.SO_0
job.static_lib = StaticLibType.A
case SdlPlatform.PowerPC64 | SdlPlatform.PowerPC:
# FIXME: Enable SDL_WERROR
job.werror = False
job.clang_tidy = False
job.run_tests = False
job.sudo = ""
job.apt_packages = []
job.shared_lib = SharedLibType.SO_0
job.static_lib = StaticLibType.A
job.cmake_arguments.extend((
"-DSDL_UNIX_CONSOLE_BUILD=ON",
))
case SdlPlatform.LoongArch64:
job.run_tests = False
job.cc = "${LOONGARCH64_CC}"
job.cxx = "${LOONGARCH64_CXX}"
job.cmake_arguments.extend((
f"-DCMAKE_C_COMPILER={job.cc}",
f"-DCMAKE_CXX_COMPILER={job.cxx}",
"-DSDL_UNIX_CONSOLE_BUILD=ON",
"-DCMAKE_SYSTEM_NAME=Linux",
))
job.shared_lib = SharedLibType.SO_0
job.static_lib = StaticLibType.A
case SdlPlatform.N3ds:
job.shared = False
job.apt_packages = ["ninja-build", "binutils"]
job.clang_tidy = False
job.run_tests = False
job.cc_from_cmake = True
job.cmake_toolchain_file = "${DEVKITPRO}/cmake/3DS.cmake"
job.static_lib = StaticLibType.A
case SdlPlatform.Msys2:
job.shell = "msys2 {0}"
assert spec.msys2_platform
job.msys2_msystem = spec.msys2_platform.value
job.msys2_env = {
"mingw32": "mingw-w64-i686",
"mingw64": "mingw-w64-x86_64",
"clang32": "mingw-w64-clang-i686",
"clang64": "mingw-w64-clang-x86_64",
"ucrt64": "mingw-w64-ucrt-x86_64",
}[spec.msys2_platform.value]
job.msys2_no_perl = spec.msys2_platform in (Msys2Platform.Mingw32, Msys2Platform.Clang32)
job.shared_lib = SharedLibType.WIN32
job.static_lib = StaticLibType.A
case SdlPlatform.Riscos:
# FIXME: Enable SDL_WERROR
job.werror = False
job.apt_packages = ["cmake", "ninja-build"]
job.test_pkg_config = False
job.shared = False
job.run_tests = False
job.sudo = ""
job.cmake_arguments.extend((
"-DRISCOS:BOOL=ON",
"-DCMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON",
"-DSDL_GCC_ATOMICS:BOOL=OFF",
))
job.cmake_toolchain_file = "/home/riscos/env/toolchain-riscos.cmake"
job.static_lib = StaticLibType.A
case SdlPlatform.FreeBSD | SdlPlatform.NetBSD:
job.cpactions = True
job.no_cmake = True
job.run_tests = False
job.apt_packages = []
job.shared_lib = SharedLibType.SO_0
job.static_lib = StaticLibType.A
match spec.platform:
case SdlPlatform.FreeBSD:
job.cpactions_os = "freebsd"
job.cpactions_version = "14.2"
job.cpactions_arch = "x86-64"
job.cpactions_setup_cmd = "sudo pkg update"
job.cpactions_install_cmd = "sudo pkg install -y cmake ninja pkgconf libXcursor libXext libXinerama libXi libXfixes libXrandr libXScrnSaver libXxf86vm wayland wayland-protocols libxkbcommon mesa-libs libglvnd evdev-proto libinotify alsa-lib jackit pipewire pulseaudio sndio dbus zh-fcitx ibus libudev-devd"
job.cmake_arguments.extend((
"-DSDL_CHECK_REQUIRED_INCLUDES=/usr/local/include",
"-DSDL_CHECK_REQUIRED_LINK_OPTIONS=-L/usr/local/lib",
))
case SdlPlatform.NetBSD:
job.cpactions_os = "netbsd"
job.cpactions_version = "10.1"
job.cpactions_arch = "x86-64"
job.cpactions_setup_cmd = "export PATH=\"/usr/pkg/sbin:/usr/pkg/bin:/sbin:$PATH\"; export PKG_CONFIG_PATH=\"/usr/pkg/lib/pkgconfig\";export PKG_PATH=\"https://cdn.netBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r|cut -f \"1 2\" -d.)/All/\";echo \"PKG_PATH=$PKG_PATH\";echo \"uname -a -> \"$(uname -a)\"\";sudo -E sysctl -w security.pax.aslr.enabled=0;sudo -E sysctl -w security.pax.aslr.global=0;sudo -E pkgin clean;sudo -E pkgin update"
job.cpactions_install_cmd = "sudo -E pkgin -y install cmake dbus pkgconf ninja-build pulseaudio libxkbcommon wayland wayland-protocols libinotify libusb1"
case _:
raise ValueError(f"Unsupported platform={spec.platform}")
if "ubuntu" in spec.name.lower():
job.check_sources = True
job.setup_python = True
if not build_parallel:
job.cmake_build_arguments.append("-j1")
if job.cflags:
job.cmake_arguments.append(f"-DCMAKE_C_FLAGS=\"{my_shlex_join(job.cflags)}\"")
if job.cxxflags:
job.cmake_arguments.append(f"-DCMAKE_CXX_FLAGS=\"{my_shlex_join(job.cxxflags)}\"")
if job.ldflags:
job.cmake_arguments.append(f"-DCMAKE_SHARED_LINKER_FLAGS=\"{my_shlex_join(job.ldflags)}\"")
job.cmake_arguments.append(f"-DCMAKE_EXE_LINKER_FLAGS=\"{my_shlex_join(job.ldflags)}\"")
job.pretest_cmd = "\n".join(pretest_cmd)
def tf(b):
return "ON" if b else "OFF"
if fpic is not None:
job.cmake_arguments.append(f"-DCMAKE_POSITION_INDEPENDENT_CODE={tf(fpic)}")
if job.no_cmake:
job.cmake_arguments = []
return job
def spec_to_platform(spec: JobSpec, key: str, enable_artifacts: bool, trackmem_symbol_names: bool) -> dict[str, str|bool]:
logger.info("spec=%r", spec)
job = spec_to_job(spec, key=key, trackmem_symbol_names=trackmem_symbol_names)
logger.info("job=%r", job)
platform = job.to_workflow(enable_artifacts=enable_artifacts)
logger.info("platform=%r", platform)
return platform
def main():
parser = argparse.ArgumentParser(allow_abbrev=False)
parser.add_argument("--github-variable-prefix", default="platforms")
parser.add_argument("--github-ci", action="store_true")
parser.add_argument("--verbose", action="store_true")
parser.add_argument("--commit-message-file")
parser.add_argument("--no-artifact", dest="enable_artifacts", action="store_false")
parser.add_argument("--trackmem-symbol-names", dest="trackmem_symbol_names", action="store_true")
args = parser.parse_args()
logging.basicConfig(level=logging.INFO if args.verbose else logging.WARNING)
remaining_keys = set(JOB_SPECS.keys())
all_level_keys = (
# Level 1
(
"haiku",
),
)
filters = []
if args.commit_message_file:
with open(args.commit_message_file, "r") as f:
commit_message = f.read()
for m in re.finditer(r"\[sdl-ci-filter (.*)]", commit_message, flags=re.M):
filters.append(m.group(1).strip(" \t\n\r\t'\""))
if re.search(r"\[sdl-ci-artifacts?]", commit_message, flags=re.M):
args.enable_artifacts = True
if re.search(r"\[sdl-ci-(full-)?trackmem(-symbol-names)?]", commit_message, flags=re.M):
args.trackmem_symbol_names = True
if not filters:
filters.append("*")
logger.info("filters: %r", filters)
all_level_platforms = {}
all_platforms = {key: spec_to_platform(spec, key=key, enable_artifacts=args.enable_artifacts, trackmem_symbol_names=args.trackmem_symbol_names) for key, spec in JOB_SPECS.items()}
for level_i, level_keys in enumerate(all_level_keys, 1):
level_key = f"level{level_i}"
logger.info("Level %d: keys=%r", level_i, level_keys)
assert all(k in remaining_keys for k in level_keys)
level_platforms = tuple(all_platforms[key] for key in level_keys)
remaining_keys.difference_update(level_keys)
all_level_platforms[level_key] = level_platforms
logger.info("=" * 80)
logger.info("Keys before filter: %r", remaining_keys)
filtered_remaining_keys = set()
for filter in filters:
filtered_remaining_keys.update(fnmatch.filter(remaining_keys, filter))
logger.info("Keys after filter: %r", filtered_remaining_keys)
remaining_keys = filtered_remaining_keys
logger.info("Remaining: %r", remaining_keys)
all_level_platforms["others"] = tuple(all_platforms[key] for key in remaining_keys)
if args.github_ci:
for level, platforms in all_level_platforms.items():
platforms_json = json.dumps(platforms)
txt = f"{args.github_variable_prefix}-{level}={platforms_json}"
logger.info("%s", txt)
if "GITHUB_OUTPUT" in os.environ:
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
f.write(txt)
f.write("\n")
else:
logger.warning("GITHUB_OUTPUT not defined")
return 0
if __name__ == "__main__":
raise SystemExit(main())

View File

@ -1,45 +0,0 @@
name: Build (Emscripten)
on: [push, pull_request]
jobs:
emscripten:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: mymindstorm/setup-emsdk@v12
with:
version: 3.1.35
- name: Install ninja
run: |
sudo apt-get -y update
sudo apt-get install -y ninja-build
- name: Configure CMake
run: |
emcmake cmake -S . -B build \
-DSDL_WERROR=ON \
-DSDL_TESTS=ON \
-DSDL_INSTALL_TESTS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=prefix \
-GNinja
- name: Build
run: cmake --build build/ --verbose
- name: Run build-time tests
run: |
set -eu
export SDL_TESTS_QUICK=1
# FIXME: enable Emscripten build time tests
# ctest -VV --test-dir build/
- name: Install
run: |
echo "SDL2_DIR=$(pwd)/prefix" >> $GITHUB_ENV
cmake --install build/
- name: Verify CMake configuration files
run: |
emcmake cmake -S cmake/test -B cmake_config_build \
-DCMAKE_BUILD_TYPE=Release \
-DSDL_VENDOR_INFO="Github Workflow" \
-DTEST_SHARED=FALSE \
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }}
cmake --build cmake_config_build --verbose

389
third-party/SDL/.github/workflows/generic.yml generated vendored Normal file
View File

@ -0,0 +1,389 @@
name: 'Build'
run-name: 'Configure, Build and Test SDL'
on:
workflow_call:
inputs:
platforms:
description: 'JSON-encoded test properties'
type: string
required: true
jobs:
build:
name: ${{ matrix.platform.name }}
runs-on: ${{ matrix.platform.os }}
container: ${{ matrix.platform.container }}
defaults:
run:
shell: ${{ matrix.platform.shell }}
strategy:
fail-fast: false
matrix:
platform: ${{ fromJSON(inputs.platforms) }}
steps:
- name: 'Set up MSYS2'
if: ${{ matrix.platform.platform == 'msys2' }}
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.platform.msys2-msystem }}
install: >-
${{ matrix.platform.msys2-env }}-cc
${{ matrix.platform.msys2-env }}-cmake
${{ matrix.platform.msys2-env }}-ninja
${{ (!matrix.platform.msys2-no-perl && format('{0}-perl', matrix.platform.msys2-env)) || '' }}
${{ matrix.platform.msys2-env }}-pkg-config
${{ matrix.platform.msys2-env }}-clang-tools-extra
- name: 'About this job'
run: |
echo "key=${{ matrix.platform.key }}"
echo "name=${{ matrix.platform.name }}"
echo "os=${{ matrix.platform.os }}"
echo ""
echo "Add [sdl-ci-filter ${{ matrix.platform.key }}] to your commit message to reduce the number of jobs."
- uses: actions/checkout@v4
- name: 'Set up ninja'
if: ${{ matrix.platform.setup-ninja }}
uses: ./.github/actions/setup-ninja
- name: 'Set up libusb for MSVC'
if: ${{ matrix.platform.setup-libusb-arch != '' }}
uses: ./.github/actions/setup-msvc-libusb
with:
arch: ${{ matrix.platform.setup-libusb-arch }}
- uses: mymindstorm/setup-emsdk@v14
if: ${{ matrix.platform.platform == 'emscripten' }}
with:
version: 3.1.35
- uses: browser-actions/setup-chrome@v1
id: setup-chrome
if: ${{ matrix.platform.platform == 'emscripten' }}
with:
install-chromedriver: true
- name: 'Add chrome to PATH'
if: ${{ matrix.platform.platform == 'emscripten' }}
run: |
chrome_dir="$(dirname "${{ steps.setup-chrome.outputs.chrome-path }}")"
chromedriver_dir="$(dirname "${{ steps.setup-chrome.outputs.chromedriver-path }}")"
echo "CHROME_BINARY=${{ steps.setup-chrome.outputs.chrome-path }}" >>$GITHUB_ENV
echo "CHROMEDRIVER_BINARY=${{ steps.setup-chrome.outputs.chromedriver-path }}" >>$GITHUB_ENV
echo "chrome_dir=${chrome_dir}"
echo "chromedriver_dir=${chromedriver_dir}"
echo "${chrome_dir}" >>${GITHUB_PATH}
echo "${chromedriver_dir}" >>${GITHUB_PATH}
- uses: nttld/setup-ndk@v1
if: ${{ matrix.platform.android-ndk }}
id: setup-ndk
with:
local-cache: true
ndk-version: r21e
- name: 'Configure Android NDK variables'
if: ${{ matrix.platform.android-ndk }}
shell: sh
run: |
# We cannot use GitHub expressions in the controller job
echo "ANDROID_NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}" >>$GITHUB_ENV
- uses: actions/setup-java@v4
if: ${{ matrix.platform.java }}
with:
distribution: 'temurin'
java-version: '17'
- uses: ilammy/msvc-dev-cmd@v1
if: ${{ matrix.platform.platform == 'msvc' }}
with:
arch: ${{ matrix.platform.msvc-vcvars-arch }}
sdk: ${{ matrix.platform.msvc-vcvars-sdk }}
- name: 'Set up Windows GDK Desktop'
uses: ./.github/actions/setup-gdk-desktop
if: ${{ matrix.platform.setup-gdk-folder != '' }}
with:
folder: '${{ matrix.platform.setup-gdk-folder }}'
- name: 'Set up LoongArch64 toolchain'
uses: ./.github/actions/setup-loongarch64-toolchain
id: setup-loongarch64-toolchain
if: ${{ matrix.platform.platform == 'loongarch64' }}
- name: 'Setup Intel oneAPI toolchain'
id: intel
if: ${{ matrix.platform.intel }}
run: |
# Download the key to system keyring
wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \
| gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null
# Add signed entry to apt sources and configure the APT client to use Intel repository:
echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
# Update package list
sudo apt-get update -y
# Install oneAPI
sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
- name: 'Install apk packages'
if: ${{ matrix.platform.apk-packages != '' }}
run: |
${{ matrix.platform.sudo }} apk update
${{ matrix.platform.sudo }} apk add ${{ matrix.platform.apk-packages }}
- name: 'Install apt packages'
if: ${{ matrix.platform.apt-packages != '' }}
run: |
${{ matrix.platform.sudo }} apt-get update
${{ matrix.platform.sudo }} apt-get install -y ${{ matrix.platform.apt-packages }}
- name: 'Install brew packages'
if: ${{ matrix.platform.brew-packages != '' }}
run: |
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
brew update
brew install ${{ matrix.platform.brew-packages }}
- name: 'Setup Python'
uses: 'actions/setup-python@main'
if: ${{ matrix.platform.setup-python }}
with:
python-version: '3.x'
- name: 'Install PyPI packages'
if: ${{ matrix.platform.pypi-packages != '' }}
run: |
python -m pip install --user ${{ matrix.platform.pypi-packages }}
- name: 'Set up GLES for VITA' # Must be after apk
if: ${{ matrix.platform.setup-vita-gles-type != '' }}
uses: ./.github/actions/setup-vita-gles
with:
type: ${{ matrix.platform.setup-vita-gles-type }}
- name: 'Pollute toolchain with "bad" SDL headers'
if: ${{ matrix.platform.pollute-directories != '' }}
#shell: ${{ matrix.platform.shell }}
run: |
# Create "bad" SDL headers in the toolchain.
# SDL sources should not use these.
for include in ${{ matrix.platform.pollute-directories }}; do
toolchain_directory="${include}/SDL3"
echo "Creating directory ${toolchain_directory}"
mkdir -p "${toolchain_directory}/SDL3"
for header in include/SDL3/*.h; do
dest="${toolchain_directory}/SDL3/$(basename "${header}")"
echo "Creating ${dest}"
echo '#error "System SDL headers must not be used by build system"' >"$dest"
done
done
- name: 'Configure (CMake)'
if: ${{ !matrix.platform.no-cmake }}
#shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -GNinja \
-Wdeprecated -Wdev -Werror \
${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
-DSDL_WERROR=${{ matrix.platform.werror }} \
-DSDL_EXAMPLES=${{ matrix.platform.build-tests }} \
-DSDL_TESTS=${{ matrix.platform.build-tests }} \
-DSDLTEST_TRACKMEM=ON \
-DSDL_INSTALL_TESTS=${{ matrix.platform.build-tests }} \
-DSDL_CLANG_TIDY=${{ matrix.platform.clang-tidy }} \
-DSDL_INSTALL_DOCS=ON \
-DSDL_INSTALL_CPACK=ON \
-DSDL_INSTALL_DOCS=ON \
${{ matrix.platform.cmake-arguments }} \
-DSDL_SHARED=${{ matrix.platform.shared }} \
-DSDL_STATIC=${{ matrix.platform.static }} \
-DSDL_VENDOR_INFO="Github Workflow" \
-DCMAKE_INSTALL_PREFIX=prefix \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_BUILD_TYPE=${{ matrix.platform.cmake-build-type }}
- name: 'Build (CMake)'
id: build
if: ${{ !matrix.platform.no-cmake }}
# shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
cmake --build build --config ${{ matrix.platform.cmake-build-type }} --verbose -- ${{ matrix.platform.cmake-build-arguments }}
- name: 'Verify SDL_REVISION'
if: ${{ !matrix.platform.no-cmake }}
run: |
echo "This should show us the SDL_REVISION"
echo "Shared library:"
${{ (matrix.platform.shared-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
echo "Static library:"
${{ (matrix.platform.static-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
- name: 'Run build-time tests (CMake)'
id: tests
if: ${{ !matrix.platform.no-cmake && matrix.platform.run-tests }}
# shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
${{ matrix.platform.pretest-cmd }}
set -eu
export SDL_TESTS_QUICK=1
ctest -VV --test-dir build/ -j2
- name: "Build test apk's (CMake)"
id: apks
if: ${{ always() && steps.build.outcome == 'success' && matrix.platform.android-apks != '' }}
# shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
cmake --build build --config ${{ matrix.platform.cmake-build-type }} \
--target \
${{ matrix.platform.android-apks }} \
--verbose \
-- ${{ matrix.platform.cmake-build-arguments }}
- name: 'Install (CMake)'
id: install
if: ${{ always() && steps.build.outcome == 'success' }}
# shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
cmake --install build --config ${{ matrix.platform.cmake-build-type }}
echo "prefix=$(pwd)/prefix" >> $GITHUB_OUTPUT
( cd prefix; find . ) | LC_ALL=C sort -u
- name: 'Package (CPack)'
id: package
if: ${{ always() && steps.build.outcome == 'success' }}
# shell: ${{ matrix.platform.shell }}
run: |
# DMG creation on macOS occasionally fails, so try multiple times
# https://gitlab.kitware.com/cmake/cmake/-/issues/25671
success=0
max_tries=10
for i in $(seq $max_tries); do
cmake --build build/ --config ${{ matrix.platform.cmake-build-type }} --target package -- ${{ matrix.platform.cmake-build-arguments }} && success=1
if test $success = 1; then
break
fi
echo "Package creation failed. Sleep 1 second and try again."
sleep 1
done
if test $success = 0; then
echo "Package creation failed after $max_tries attempts."
exit 1
fi
- name: 'Verify CMake configuration files'
if: ${{ steps.install.outcome == 'success' }}
# shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
${{ matrix.platform.cmake-config-emulator }} cmake -S cmake/test -B cmake_test_build -GNinja \
${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
-DTEST_SHARED=${{ matrix.platform.shared }} \
-DTEST_STATIC=${{ matrix.platform.static }} \
${{ matrix.platform.cmake-arguments }} \
-DCMAKE_BUILD_TYPE=${{ matrix.platform.cmake-build-type }} \
-DCMAKE_PREFIX_PATH="${{ steps.install.outputs.prefix }}"
cmake --build cmake_test_build --verbose --config ${{ matrix.platform.cmake-build-type }} -- ${{ matrix.platform.cmake-build-arguments }}
- name: 'Extract CC/CXX/CFLAGS/CXXFLAGS from CMake toolchain'
if: ${{ steps.install.outcome == 'success' && matrix.platform.cc-from-cmake }}
# shell: ${{ matrix.platform.shell }}
run: |
cmake -S .github/cmake -B /tmp/cmake_extract \
${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
-DCMAKE_BUILD_TYPE=${{ matrix.platform.cmake-build-type }} \
-DVAR_PATH=/tmp/env.txt
cat /tmp/env.txt >> $GITHUB_ENV
- name: 'Verify sdl3.pc'
# shell: ${{ matrix.platform.shell }}
if: ${{ steps.install.outcome == 'success' && matrix.platform.test-pkg-config }}
run: |
${{ matrix.platform.source-cmd }}
${{ matrix.platform.cc && format('export CC="{0}"', matrix.platform.cc) || '' }}
${{ matrix.platform.cflags && format('export CFLAGS="{0}"', matrix.platform.cflags) || '' }}
${{ matrix.platform.ldflags && format('export LDFLAGS="{0}"', matrix.platform.ldflags) || '' }}
export PKG_CONFIG_PATH=${{ steps.install.outputs.prefix }}/lib/pkgconfig
cmake/test/test_pkgconfig.sh
- name: 'Build (cross-platform-actions, BSD)'
id: cpactions
if: ${{ matrix.platform.cpactions }}
uses: cross-platform-actions/action@v0.27.0
with:
operating_system: '${{ matrix.platform.cpactions-os }}'
architecture: '${{ matrix.platform.cpactions-arch }}'
version: '${{ matrix.platform.cpactions-version }}'
run: |
${{ matrix.platform.cpactions-setup-cmd }}
${{ matrix.platform.cpactions-install-cmd }}
cmake -S . -B build -GNinja \
${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
-Wdeprecated -Wdev -Werror \
-DSDL_WERROR=${{ matrix.platform.werror }} \
-DSDL_INSTALL_DOCS=ON \
${{ matrix.platform.cmake-arguments }} \
-DSDL_SHARED=${{ matrix.platform.shared }} \
-DSDL_STATIC=${{ matrix.platform.static }} \
-DSDL_VENDOR_INFO="Github Workflow" \
-DCMAKE_INSTALL_PREFIX=prefix \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_BUILD_TYPE=${{ matrix.platform.cmake-build-type }}
cmake --build build/ --config ${{ matrix.platform.cmake-build-type }} --verbose
cmake --build build/ --config ${{ matrix.platform.cmake-build-type }} --target package
cmake --build build/ --config ${{ matrix.platform.cmake-build-type }} --target clean
rm -rf build/dist/_CPack_Packages
rm -rf build/CMakeFiles
rm -rf build/docs
- name: Add msbuild to PATH
id: setup-msbuild
if: ${{ matrix.platform.msvc-project != '' }}
uses: microsoft/setup-msbuild@v2
- name: Build msbuild
if: ${{ matrix.platform.msvc-project != '' }}
run: |
"$(cygpath -u '${{ steps.setup-msbuild.outputs.msbuildPath }}\msbuild.exe')" ${{ matrix.platform.msvc-project }} -m -p:BuildInParallel=true -p:Configuration=Release ${{ matrix.platform.msvc-project-flags }}
- name: 'Build (Android.mk)'
if: ${{ matrix.platform.android-mk }}
run: |
./build-scripts/androidbuildlibs.sh
- name: 'Create Gradle project (Android)'
if: ${{ matrix.platform.android-gradle }}
run: |
for folder in build-ndk-build build-cmake; do
python build-scripts/create-android-project.py \
--output "${folder}" \
--variant copy \
org.libsdl.testspriteminimal \
test/testspriteminimal.c test/icon.h
done
echo ""
echo "Project contents:"
echo ""
find "build-ndk-build/org.libsdl.testspriteminimal"
- name: 'Build Android app (Gradle & ndk-build)'
if: ${{ matrix.platform.android-gradle }}
run: |
cd build-ndk-build/org.libsdl.testspriteminimal
./gradlew -i assembleRelease
- name: 'Build Android app (Gradle & CMake)'
if: ${{ matrix.platform.android-gradle }}
run: |
cd build-cmake/org.libsdl.testspriteminimal
./gradlew -i assembleRelease -PBUILD_WITH_CMAKE=1
- name: 'Build (xcode)'
if: ${{ matrix.platform.xcode-sdk != '' }}
run: |
xcodebuild -project Xcode/SDL/SDL.xcodeproj -target SDL3 -configuration Release -sdk ${{ matrix.platform.xcode-sdk }} clean build
- name: 'Check Sources'
if: ${{ matrix.platform.check-sources }}
run: |
set -e
build-scripts/test-versioning.sh
python build-scripts/check_android_jni.py
python build-scripts/check_stdlib_usage.py
- name: 'Upload binary package'
uses: actions/upload-artifact@v4
if: ${{ always() && matrix.platform.artifact != '' && (steps.package.outcome == 'success' || steps.cpactions.outcome == 'success') && (matrix.platform.enable-artifacts || steps.tests.outcome == 'failure') }}
with:
if-no-files-found: error
name: '${{ matrix.platform.artifact }}'
path: |
build/dist/SDL3*
build/include*
- name: 'Upload minidumps'
uses: actions/upload-artifact@v4
if: ${{ always() && steps.tests.outcome == 'failure' && (matrix.platform.platform == 'msvc' || matrix.platform.platform == 'msys2') }}
with:
if-no-files-found: ignore
name: '${{ matrix.platform.artifact }}-minidumps'
path: build/**/*.dmp
- name: "Upload Android test apk's"
uses: actions/upload-artifact@v4
if: ${{ matrix.platform.enable-artifacts && always() && matrix.platform.artifact != '' && steps.apks.outcome == 'success' }}
with:
if-no-files-found: error
name: '${{ matrix.platform.artifact }}-apks'
path: build/test/*.apk

View File

@ -1,20 +0,0 @@
name: Build (iOS/tvOS)
on: [push, pull_request]
jobs:
Build:
name: ${{ matrix.platform.name }}
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
platform:
- { name: iOS, target: Static Library-iOS, sdk: iphoneos }
- { name: tvOS, target: Static Library-tvOS, sdk: appletvos }
steps:
- uses: actions/checkout@v3
- name: Build
run: xcodebuild -project Xcode/SDL/SDL.xcodeproj -target '${{ matrix.platform.target }}' -configuration Release -sdk ${{ matrix.platform.sdk }} clean build

View File

@ -1,240 +0,0 @@
name: Build
on: [push, pull_request]
jobs:
Build:
name: ${{ matrix.platform.name }}
runs-on: ${{ matrix.platform.os }}
defaults:
run:
shell: ${{ matrix.platform.shell }}
strategy:
fail-fast: false
matrix:
platform:
- { name: Windows (mingw32), os: windows-latest, shell: 'msys2 {0}', msystem: mingw32, msys-env: mingw-w64-i686 }
- { name: Windows (mingw64), os: windows-latest, shell: 'msys2 {0}', msystem: mingw64, msys-env: mingw-w64-x86_64 }
- { name: Windows (clang32), os: windows-latest, shell: 'msys2 {0}', msystem: clang32, msys-env: mingw-w64-clang-i686 }
- { name: Windows (clang64), os: windows-latest, shell: 'msys2 {0}', msystem: clang64, msys-env: mingw-w64-clang-x86_64 }
- { name: Windows (ucrt64), os: windows-latest, shell: 'msys2 {0}', msystem: ucrt64, msys-env: mingw-w64-ucrt-x86_64 }
- { name: Ubuntu 20.04 (CMake), os: ubuntu-20.04, shell: sh }
- { name: Ubuntu 20.04 (autotools), os: ubuntu-20.04, shell: sh, autotools: true }
- { name: Intel oneAPI (Ubuntu 20.04), os: ubuntu-20.04, shell: bash, artifact: 'SDL-ubuntu20.04-oneapi', intel: true,
source_cmd: 'source /opt/intel/oneapi/setvars.sh; export CC=icx; export CXX=icx;'}
- { name: Intel Compiler (Ubuntu 20.04), os: ubuntu-20.04, shell: bash, artifact: 'SDL-ubuntu20.04-icc', intel: true, cmake: '-DSDL_CLANG_TIDY=OFF',
source_cmd: 'source /opt/intel/oneapi/setvars.sh; export CC=icc; export CXX=icpc; export CFLAGS=-diag-disable=10441; export CXXFLAGS=-diag-disable=10441; '}
- { name: Ubuntu 22.04 (CMake), os: ubuntu-22.04, shell: sh }
- { name: Ubuntu 22.04 (autotools), os: ubuntu-22.04, shell: sh, autotools: true }
- { name: MacOS (CMake), os: macos-latest, shell: sh, cmake: '-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"' }
- { name: MacOS (autotools), os: macos-latest, shell: sh, autotools: true }
steps:
- name: Set up MSYS2
if: matrix.platform.shell == 'msys2 {0}'
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.platform.msystem }}
install: >-
${{ matrix.platform.msys-env }}-cc
${{ matrix.platform.msys-env }}-cmake
${{ matrix.platform.msys-env }}-ninja
${{ matrix.platform.msys-env }}-pkg-config
- name: Setup Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install build-essential git make autoconf automake libtool \
pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev \
libaudio-dev libjack-dev libsndio-dev libsamplerate0-dev libx11-dev libxext-dev \
libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libwayland-dev \
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
- name: Setup extra Ubuntu 22.04 dependencies
if: matrix.platform.os == 'ubuntu-22.04'
run: |
sudo apt-get install libpipewire-0.3-dev libdecor-0-dev
- name: Setup Macos dependencies
if: runner.os == 'macOS'
run: |
brew install \
ninja \
pkg-config
- name: Setup Intel oneAPI
if: matrix.platform.intel
run: |
# Download the key to system keyring
wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \
| gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null
# Add signed entry to apt sources and configure the APT client to use Intel repository:
echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
# Update package list
sudo apt-get update -y
# Install oneAPI
sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
- uses: actions/checkout@v3
- name: Check that versioning is consistent
# We only need to run this once: arbitrarily use the Linux/CMake build
if: "runner.os == 'Linux' && ! matrix.platform.autotools"
run: ./build-scripts/test-versioning.sh
- name: Configure (CMake)
if: "! matrix.platform.autotools"
run: |
${{ matrix.platform.source_cmd }}
cmake -S . -B build -G Ninja \
-DSDL_TESTS=ON \
-DSDL_WERROR=ON \
-DSDL_INSTALL_TESTS=ON \
-DSDL_VENDOR_INFO="Github Workflow" \
-DCMAKE_INSTALL_PREFIX=cmake_prefix \
-DCMAKE_BUILD_TYPE=Release \
${{ matrix.platform.cmake }}
- name: Build (CMake)
if: "! matrix.platform.autotools"
run: |
${{ matrix.platform.source_cmd }}
cmake --build build/ --config Release --verbose --parallel
- name: Run build-time tests (CMake)
if: "! matrix.platform.autotools"
run: |
${{ matrix.platform.source_cmd }}
set -eu
export SDL_TESTS_QUICK=1
ctest -VV --test-dir build/ -j2
if test "${{ runner.os }}" = "Linux"; then
# This should show us the SDL_REVISION
strings build/libSDL2-2.0.so.0 | grep SDL-
fi
- name: Install (CMake)
if: "! matrix.platform.autotools"
run: |
set -eu
cmake --install build/ --config Release
echo "SDL2_DIR=$(pwd)/cmake_prefix" >> $GITHUB_ENV
( cd cmake_prefix; find ) | LC_ALL=C sort -u
- name: Configure (Autotools)
if: matrix.platform.autotools
run: |
${{ matrix.platform.source_cmd }}
set -eu
rm -fr build-autotools
mkdir build-autotools
./autogen.sh
(
cd build-autotools
${{ github.workspace }}/configure \
--enable-vendor-info="Github Workflow" \
--enable-werror \
--prefix=${{ github.workspace }}/autotools_prefix \
)
if test "${{ runner.os }}" != "macOS" ; then
curdir="$(pwd)"
multiarch="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
(
mkdir -p build-autotools/test
cd build-autotools/test
${{ github.workspace }}/test/configure \
--enable-werror \
--x-includes=/usr/include \
--x-libraries="/usr/lib/${multiarch}" \
--prefix=${{ github.workspace }}/autotools_prefix \
SDL_CFLAGS="-I${curdir}/include" \
SDL_LIBS="-L${curdir}/build-autotools/build/.libs -lSDL2" \
ac_cv_lib_SDL2_ttf_TTF_Init=no \
${NULL+}
)
fi
- name: Build (Autotools)
if: matrix.platform.autotools
run: |
${{ matrix.platform.source_cmd }}
set -eu
parallel="$(getconf _NPROCESSORS_ONLN)"
make -j"${parallel}" -C build-autotools V=1
if test "${{ runner.os }}" != "macOS" ; then
make -j"${parallel}" -C build-autotools/test V=1
fi
- name: Run build-time tests (Autotools)
if: ${{ matrix.platform.autotools && (runner.os != 'macOS') }}
run: |
${{ matrix.platform.source_cmd }}
set -eu
curdir="$(pwd)"
parallel="$(getconf _NPROCESSORS_ONLN)"
export SDL_TESTS_QUICK=1
make -j"${parallel}" -C build-autotools/test check LD_LIBRARY_PATH="${curdir}/build-autotools/build/.libs"
if test "${{ runner.os }}" = "Linux"; then
# This should show us the SDL_REVISION
strings "${curdir}/build-autotools/build/.libs/libSDL2-2.0.so.0" | grep SDL-
fi
- name: Install (Autotools)
if: matrix.platform.autotools
run: |
${{ matrix.platform.source_cmd }}
set -eu
curdir="$(pwd)"
parallel="$(getconf _NPROCESSORS_ONLN)"
make -j"${parallel}" -C build-autotools install V=1
if test "${{ runner.os }}" != "macOS" ; then
make -j"${parallel}" -C build-autotools/test install V=1
fi
( cd autotools_prefix; find . ) | LC_ALL=C sort -u
echo "SDL2_DIR=$(pwd)/autotools_prefix" >> $GITHUB_ENV
- name: Verify CMake configuration files
run: |
${{ matrix.platform.source_cmd }}
cmake -S cmake/test -B cmake_config_build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }}
cmake --build cmake_config_build --verbose
- name: Verify sdl2-config
run: |
${{ matrix.platform.source_cmd }}
export PATH=${{ env.SDL2_DIR }}/bin:$PATH
cmake/test/test_sdlconfig.sh
- name: Verify sdl2.pc
run: |
${{ matrix.platform.source_cmd }}
export PKG_CONFIG_PATH=${{ env.SDL2_DIR }}/lib/pkgconfig
cmake/test/test_pkgconfig.sh
- name: Distcheck (Autotools)
if: matrix.platform.autotools
run: |
set -eu
parallel="$(getconf _NPROCESSORS_ONLN)"
make -j"${parallel}" -C build-autotools dist V=1
# Similar to Automake `make distcheck`: check that the tarball
# release is sufficient to do a new build
mkdir distcheck
tar -C distcheck -zxf build-autotools/SDL2-*.tar.gz
( cd distcheck/SDL2-* && ./configure )
make -j"${parallel}" -C distcheck/SDL2-*
- name: Run installed-tests (Autotools)
if: "runner.os == 'Linux' && matrix.platform.autotools"
run: |
${{ matrix.platform.source_cmd }}
set -eu
parallel="$(getconf _NPROCESSORS_ONLN)"
sudo make -j"${parallel}" -C build-autotools install
sudo make -j"${parallel}" -C build-autotools/test install
export SDL_TESTS_QUICK=1
# We need to set LD_LIBRARY_PATH because it isn't in the default
# linker search path. We don't need to set XDG_DATA_DIRS for
# ginsttest-runner, because /usr/local/share *is* in the default
# search path for that.
env --chdir=/ \
LD_LIBRARY_PATH=/usr/local/lib \
SDL_AUDIODRIVER=dummy \
SDL_VIDEODRIVER=dummy \
ginsttest-runner --tap SDL2

View File

@ -1,80 +0,0 @@
name: Build (MSVC)
on: [push, pull_request]
jobs:
Build:
name: ${{ matrix.platform.name }}
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
platform:
- { name: Windows (x64), flags: -A x64, project: VisualC/SDL.sln, projectflags: '/p:Platform=x64' }
- { name: Windows (x86), flags: -A Win32, project: VisualC/SDL.sln, projectflags: '/p:Platform=Win32' }
- { name: Windows static VCRT (x64), flags: -A x64 -DSDL_FORCE_STATIC_VCRT=ON }
- { name: Windows static VCRT (x86), flags: -A Win32 -DSDL_FORCE_STATIC_VCRT=ON }
- { name: Windows (clang-cl x64), flags: -T ClangCL -A x64 }
- { name: Windows (clang-cl x86), flags: -T ClangCL -A Win32 }
- { name: Windows (ARM), flags: -A ARM }
- { name: Windows (ARM64), flags: -A ARM64 }
- { name: UWP (x64), flags: -A x64 -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0" -DSDL_TESTS=OFF, nowerror: true,
project: VisualC-WinRT/SDL-UWP.sln, projectflags: '/p:Platform=x64 /p:WindowsTargetPlatformVersion=10.0.17763.0' }
steps:
- uses: actions/checkout@v3
- name: Create CMake project using SDL as a subproject
shell: python
run: |
import os
import textwrap
srcdir = r"${{ github.workspace }}".replace("\\", "/")
builddir = f"{ srcdir }/build"
os.makedirs(builddir)
with open(f"{ builddir }/CMakeLists.txt", "w") as f:
f.write(textwrap.dedent(f"""\
# Always build .PDB symbol file
set(CMAKE_POLICY_DEFAULT_CMP0141 "NEW" CACHE STRING "MSVC debug information format flags are selected by an abstraction")
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase" CACHE STRING "MSVC debug information format")
set(CMAKE_EXE_LINKER_FLAGS "-DEBUG" CACHE STRING "Linker flags for executables")
set(CMAKE_SHARED_LINKER_FLAGS "-DEBUG" CACHE STRING "Linker flag for shared libraries")
cmake_minimum_required(VERSION 3.0...3.25)
project(sdl_user)
enable_testing()
add_subdirectory("{ srcdir }" SDL)
"""))
- name: Configure (CMake)
run: cmake -S build -B build `
-DSDL_WERROR=${{ !matrix.platform.nowerror }} `
-DSDL_TESTS=ON `
-DSDL_INSTALL_TESTS=ON `
-DSDL_VENDOR_INFO="Github Workflow" `
-DSDL2_DISABLE_INSTALL=OFF `
${{ matrix.platform.flags }} `
-DCMAKE_INSTALL_PREFIX=prefix
- name: Build (CMake)
run: cmake --build build/ --config Release --parallel
- name: Run build-time tests
if: "! contains(matrix.platform.name, 'ARM')"
run: |
$env:SDL_TESTS_QUICK=1
ctest -VV --test-dir build/ -C Release -j2
- name: Install (CMake)
run: |
echo "SDL2_DIR=$Env:GITHUB_WORKSPACE/prefix" >> $Env:GITHUB_ENV
cmake --install build/
- name: Verify CMake configuration files
if: ${{ !contains(matrix.platform.name, 'UWP') }} # FIXME: cmake/test/CMakeLists.txt should support UWP
run: |
cmake -S cmake/test -B cmake_config_build `
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }} `
${{ matrix.platform.flags }}
cmake --build cmake_config_build --config Release
- name: Add msbuild to PATH
if: ${{ matrix.platform.project != '' }}
uses: microsoft/setup-msbuild@v1.1.3
- name: Build msbuild
if: ${{ matrix.platform.project != '' }}
run: msbuild ${{ matrix.platform.project }} /m /p:BuildInParallel=true /p:Configuration=Release ${{ matrix.platform.projectflags }}

View File

@ -1,55 +0,0 @@
name: Build (Nintendo 3DS)
on: [push, pull_request]
jobs:
n3ds:
runs-on: ubuntu-latest
container:
image: devkitpro/devkitarm:latest
steps:
- uses: actions/checkout@v3
- name: Install build requirements
run: |
apt update
apt install ninja-build
- name: Configure CMake
run: |
cmake -S . -B build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/3DS.cmake \
-DSDL_WERROR=ON \
-DSDL_TESTS=ON \
-DSDL_INSTALL_TESTS=ON \
-DSDL_VENDOR_INFO="Github Workflow" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=prefix
- name: Build
run: cmake --build build --verbose
- name: Install CMake
run: |
echo "SDL2_DIR=$(pwd)/prefix" >> $GITHUB_ENV
cmake --install build/
( cd prefix; find ) | LC_ALL=C sort -u
- name: Verify CMake configuration files
run: |
cmake -S cmake/test -B cmake_config_build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/3DS.cmake \
-DTEST_SHARED=FALSE \
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }} \
-DCMAKE_BUILD_TYPE=Release
cmake --build cmake_config_build --verbose
- name: Extract CC/CXX/CFLAGS/CXXFLAGS from CMake toolchain
run: |
cmake -S .github/cmake -B /tmp/cmake_extract \
-DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/3DS.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DVAR_PATH=/tmp/n3ds_env.txt
cat /tmp/n3ds_env.txt >> $GITHUB_ENV
- name: Verify sdl2-config
run: |
export PATH=${{ env.SDL2_DIR }}/bin:$PATH
cmake/test/test_sdlconfig.sh
- name: Verify sdl2.pc
run: |
export PKG_CONFIG_PATH=${{ env.SDL2_DIR }}/lib/pkgconfig
cmake/test/test_pkgconfig.sh

View File

@ -1,73 +0,0 @@
name: Build (Sony Playstation 2)
on: [push, pull_request]
jobs:
ps2:
runs-on: ubuntu-latest
container: ps2dev/ps2dev:latest
steps:
- uses: actions/checkout@v3
- name: Setup dependencies
run: |
apk update
apk add cmake gmp mpc1 mpfr4 ninja pkgconf make git
# To be removed once ps2_drivers is part of PS2DEV
- name: Install ps2_drivers lib
run: |
git clone https://github.com/fjtrujy/ps2_drivers.git
cd ps2_drivers
make -j $(getconf _NPROCESSORS_ONLN) clean
make -j $(getconf _NPROCESSORS_ONLN)
make -j $(getconf _NPROCESSORS_ONLN) install
- name: Configure (CMake)
run: |
cmake -S . -B build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=$PS2DEV/ps2sdk/ps2dev.cmake \
-DSDL_WERROR=ON \
-DSDL_TESTS=ON \
-DCMAKE_INSTALL_PREFIX=cmake_prefix \
-DCMAKE_BUILD_TYPE=Release
- name: Build
run: cmake --build build --config Release --verbose --parallel
- name: Install (CMake)
run: |
set -eu
cmake --install build/ --config Release
echo "SDL2_DIR=$(pwd)/cmake_prefix" >> $GITHUB_ENV
( cd cmake_prefix; find ) | LC_ALL=C sort -u
- name: Verify CMake configuration files
run: |
cmake -S cmake/test -B cmake_config_build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=$PS2DEV/ps2sdk/ps2dev.cmake \
-DTEST_SHARED=FALSE \
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }} \
-DCMAKE_BUILD_TYPE=Release
cmake --build cmake_config_build --verbose
- name: Verify sdl2-config
run: |
export CC=mips64r5900el-ps2-elf-gcc
export LDFLAGS="-L$PS2DEV/ps2sdk/ee/lib -L$PS2DEV/gsKit/lib -L$PS2DEV/ps2sdk/ports/lib"
export PATH=${{ env.SDL2_DIR }}/bin:$PATH
cmake/test/test_sdlconfig.sh
- name: Verify sdl2.pc
run: |
export CC=mips64r5900el-ps2-elf-gcc
export LDFLAGS="-L$PS2DEV/ps2sdk/ee/lib -L$PS2DEV/gsKit/lib -L$PS2DEV/ps2sdk/ports/lib"
export PKG_CONFIG_PATH=${{ env.SDL2_DIR }}/lib/pkgconfig
cmake/test/test_pkgconfig.sh
- name: Get short SHA
id: slug
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
- name: Upload artifacts
if: ${{ success() }}
uses: actions/upload-artifact@v3
with:
name: tests-${{ steps.slug.outputs.sha8 }}
path: |
build/test

View File

@ -1,50 +0,0 @@
name: Build (Sony Playstation Portable)
on: [push, pull_request]
jobs:
psp:
runs-on: ubuntu-latest
container: pspdev/pspdev:latest
steps:
- uses: actions/checkout@v3
- name: Setup dependencies
run: |
apk update
apk add cmake gmp mpc1 mpfr4 make pkgconf
- name: Configure CMake
run: |
cmake -S . -B build \
-DCMAKE_TOOLCHAIN_FILE=$PSPDEV/psp/share/pspdev.cmake \
-DSDL_WERROR=ON \
-DSDL_TESTS=ON \
-DSDL_INSTALL_TESTS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=prefix
- name: Build
run: cmake --build build --config Release
- name: Install
run: |
echo "SDL2_DIR=$(pwd)/prefix" >> $GITHUB_ENV
cmake --install build --config Release
( cd prefix; find ) | LC_ALL=C sort -u
- name: Verify CMake configuration files
run: |
cmake -S cmake/test -B cmake_config_build \
-DCMAKE_TOOLCHAIN_FILE=$PSPDEV/psp/share/pspdev.cmake \
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }} \
-DTEST_SHARED=FALSE \
-DCMAKE_BUILD_TYPE=Release
cmake --build cmake_config_build --verbose
- name: Verify sdl2-config
run: |
export CC=psp-gcc
export LDFLAGS="-L$PSPDEV/lib -L$PSPDEV/psp/lib -L$PSPDEV/psp/sdk/lib"
export PATH=${{ env.SDL2_DIR }}/bin:$PATH
cmake/test/test_sdlconfig.sh
- name: Verify sdl2.pc
run: |
export CC=psp-gcc
export LDFLAGS="-L$PSPDEV/lib -L$PSPDEV/psp/lib -L$PSPDEV/psp/sdk/lib"
export PKG_CONFIG_PATH=${{ env.SDL2_DIR }}/lib/pkgconfig
cmake/test/test_pkgconfig.sh

652
third-party/SDL/.github/workflows/release.yml generated vendored Normal file
View File

@ -0,0 +1,652 @@
name: 'release'
run-name: 'Create SDL release artifacts for ${{ inputs.commit }}'
on:
workflow_dispatch:
inputs:
commit:
description: 'Commit of SDL'
required: true
jobs:
src:
runs-on: ubuntu-latest
outputs:
project: ${{ steps.releaser.outputs.project }}
version: ${{ steps.releaser.outputs.version }}
src-tar-gz: ${{ steps.releaser.outputs.src-tar-gz }}
src-tar-xz: ${{ steps.releaser.outputs.src-tar-xz }}
src-zip: ${{ steps.releaser.outputs.src-zip }}
steps:
- name: 'Set up Python'
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 'Fetch build-release.py'
uses: actions/checkout@v4
with:
sparse-checkout: 'build-scripts/build-release.py'
- name: 'Set up SDL sources'
uses: actions/checkout@v4
with:
path: 'SDL'
fetch-depth: 0
- name: 'Build Source archive'
id: releaser
shell: bash
run: |
python build-scripts/build-release.py \
--actions source \
--commit ${{ inputs.commit }} \
--root "${{ github.workspace }}/SDL" \
--github \
--debug
- name: 'Store source archives'
uses: actions/upload-artifact@v4
with:
name: sources
path: '${{ github.workspace}}/dist'
- name: 'Generate summary'
run: |
echo "Run the following commands to download all artifacts:" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "mkdir -p /tmp/${{ steps.releaser.outputs.project }}-${{ steps.releaser.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "cd /tmp/${{ steps.releaser.outputs.project }}-${{ steps.releaser.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "gh run -R ${{ github.repository }} download ${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
linux-verify:
needs: [src]
runs-on: ubuntu-latest
steps:
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Unzip ${{ needs.src.outputs.src-zip }}'
id: zip
run: |
mkdir /tmp/zipdir
cd /tmp/zipdir
unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}"
echo "path=/tmp/zipdir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Untar ${{ needs.src.outputs.src-tar-gz }}'
id: tar
run: |
mkdir -p /tmp/tardir
tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}"
echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Compare contents of ${{ needs.src.outputs.src-zip }} and ${{ needs.src.outputs.src-tar-gz }}'
run: |
diff /tmp/zipdir /tmp/tardir
- name: 'Test versioning'
shell: bash
run: |
${{ steps.tar.outputs.path }}/build-scripts/test-versioning.sh
- name: 'Install Linux dependencies'
run: |
sudo apt-get update -y
sudo apt-get install -y \
gnome-desktop-testing libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev \
libusb-1.0-0-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev \
libxss-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
- name: 'CMake (configure + build + tests + examples)'
run: |
cmake -S ${{ steps.tar.outputs.path }} -B /tmp/build -DSDL_TEST_LIBRARY=TRUE -DSDL_TESTS=TRUE -DSDL_EXAMPLES=TRUE
cmake --build /tmp/build --verbose
ctest --test-dir /tmp/build --no-tests=error --output-on-failure
dmg:
needs: [src]
runs-on: macos-latest
outputs:
dmg: ${{ steps.releaser.outputs.dmg }}
steps:
- name: 'Set up Python'
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 'Fetch build-release.py'
uses: actions/checkout@v4
with:
sparse-checkout: 'build-scripts/build-release.py'
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Untar ${{ needs.src.outputs.src-tar-gz }}'
id: tar
run: |
mkdir -p "${{ github.workspace }}/tardir"
tar -C "${{ github.workspace }}/tardir" -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}"
echo "path=${{ github.workspace }}/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Build SDL3.dmg'
id: releaser
shell: bash
run: |
python build-scripts/build-release.py \
--actions dmg \
--commit ${{ inputs.commit }} \
--root "${{ steps.tar.outputs.path }}" \
--github \
--debug
- name: 'Store DMG image file'
uses: actions/upload-artifact@v4
with:
name: dmg
path: '${{ github.workspace }}/dist'
dmg-verify:
needs: [dmg, src]
runs-on: macos-latest
steps:
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Download ${{ needs.dmg.outputs.dmg }}'
uses: actions/download-artifact@v4
with:
name: dmg
path: '${{ github.workspace }}'
- name: 'Untar ${{ needs.src.outputs.src-tar-gz }}'
id: src
run: |
mkdir -p /tmp/tardir
tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}"
echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Mount ${{ needs.dmg.outputs.dmg }}'
id: mount
run: |
hdiutil attach '${{ github.workspace }}/${{ needs.dmg.outputs.dmg }}'
mount_point="/Volumes/${{ needs.src.outputs.project }}"
if [ ! -d "$mount_point/${{ needs.src.outputs.project }}.xcframework" ]; then
echo "Cannot find ${{ needs.src.outputs.project }}.xcframework!"
exit 1
fi
echo "mount_point=$mount_point">>$GITHUB_OUTPUT
- name: 'CMake (configure + build) Darwin'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DTEST_FULL=FALSE \
-DTEST_STATIC=FALSE \
-DTEST_TEST=FALSE \
-DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \
-DCMAKE_SYSTEM_NAME=Darwin \
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 \
-Werror=dev \
-B build_darwin
cmake --build build_darwin --config Release --verbose
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DTEST_FULL=FALSE \
-DTEST_STATIC=FALSE \
-DTEST_TEST=FALSE \
-DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}/SDL3.xcframework/macos-arm64_x86_64" \
-DCMAKE_SYSTEM_NAME=Darwin \
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 \
-Werror=dev \
-B build_darwin_2
cmake --build build_darwin --config Release --verbose
- name: 'CMake (configure + build) iOS'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DTEST_FULL=FALSE \
-DTEST_STATIC=FALSE \
-DTEST_TEST=FALSE \
-DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_OSX_ARCHITECTURES="arm64" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-Werror=dev \
-B build_ios
cmake --build build_ios --config Release --verbose
- name: 'CMake (configure + build) tvOS'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DTEST_FULL=FALSE \
-DTEST_STATIC=FALSE \
-DTEST_TEST=FALSE \
-DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \
-DCMAKE_SYSTEM_NAME=tvOS \
-DCMAKE_OSX_ARCHITECTURES="arm64" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-Werror=dev \
-B build_tvos
cmake --build build_tvos --config Release --verbose
- name: 'CMake (configure + build) iOS simulator'
run: |
sysroot=$(xcodebuild -version -sdk iphonesimulator Path)
echo "sysroot=$sysroot"
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DTEST_FULL=FALSE \
-DTEST_STATIC=FALSE \
-DTEST_TEST=FALSE \
-DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
-DCMAKE_OSX_SYSROOT="${sysroot}" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-Werror=dev \
-B build_ios_simulator
cmake --build build_ios_simulator --config Release --verbose
- name: 'CMake (configure + build) tvOS simulator'
run: |
sysroot=$(xcodebuild -version -sdk appletvsimulator Path)
echo "sysroot=$sysroot"
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DTEST_FULL=FALSE \
-DTEST_STATIC=FALSE \
-DTEST_TEST=FALSE \
-DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \
-DCMAKE_SYSTEM_NAME=tvOS \
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
-DCMAKE_OSX_SYSROOT="${sysroot}" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-Werror=dev \
-B build_tvos_simulator
cmake --build build_tvos_simulator --config Release --verbose
msvc:
needs: [src]
runs-on: windows-2019
outputs:
VC-x86: ${{ steps.releaser.outputs.VC-x86 }}
VC-x64: ${{ steps.releaser.outputs.VC-x64 }}
VC-arm64: ${{ steps.releaser.outputs.VC-arm64 }}
VC-devel: ${{ steps.releaser.outputs.VC-devel }}
steps:
- name: 'Set up Python'
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 'Fetch build-release.py'
uses: actions/checkout@v4
with:
sparse-checkout: 'build-scripts/build-release.py'
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Unzip ${{ needs.src.outputs.src-zip }}'
id: zip
run: |
New-Item C:\temp -ItemType Directory -ErrorAction SilentlyContinue
cd C:\temp
unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}"
echo "path=C:\temp\${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$Env:GITHUB_OUTPUT
- name: 'Build MSVC binary archives'
id: releaser
run: |
python build-scripts/build-release.py `
--actions msvc `
--commit ${{ inputs.commit }} `
--root "${{ steps.zip.outputs.path }}" `
--github `
--debug
- name: 'Store MSVC archives'
uses: actions/upload-artifact@v4
with:
name: win32
path: '${{ github.workspace }}/dist'
msvc-verify:
needs: [msvc, src]
runs-on: windows-latest
steps:
- name: 'Fetch .github/actions/setup-ninja/action.yml'
uses: actions/checkout@v4
with:
sparse-checkout: '.github/actions/setup-ninja/action.yml'
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Download MSVC binaries'
uses: actions/download-artifact@v4
with:
name: win32
path: '${{ github.workspace }}'
- name: 'Unzip ${{ needs.src.outputs.src-zip }}'
id: src
run: |
mkdir '${{ github.workspace }}/sources'
cd '${{ github.workspace }}/sources'
unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}"
echo "path=${{ github.workspace }}/sources/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$env:GITHUB_OUTPUT
- name: 'Unzip ${{ needs.msvc.outputs.VC-devel }}'
id: bin
run: |
mkdir '${{ github.workspace }}/vc'
cd '${{ github.workspace }}/vc'
unzip "${{ github.workspace }}/${{ needs.msvc.outputs.VC-devel }}"
echo "path=${{ github.workspace }}/vc/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$env:GITHUB_OUTPUT
- name: Set up ninja
uses: ./.github/actions/setup-ninja
- name: 'Configure vcvars x86'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64_x86
- name: 'CMake (configure + build + tests) x86'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" `
-B build_x86 `
-GNinja `
-DCMAKE_BUILD_TYPE=Debug `
-Werror=dev `
-DTEST_FULL=TRUE `
-DTEST_STATIC=FALSE `
-DTEST_SHARED=TRUE `
-DTEST_TEST=TRUE `
-DCMAKE_SUPPRESS_REGENERATION=TRUE `
-DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}"
Start-Sleep -Seconds 2
cmake --build build_x86 --config Release --verbose
ctest --test-dir build_x86 --no-tests=error -C Release --output-on-failure
- name: 'Configure vcvars x64'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: 'CMake (configure + build + tests) x64'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" `
-B build_x64 `
-GNinja `
-DCMAKE_BUILD_TYPE=Debug `
-Werror=dev `
-DTEST_FULL=TRUE `
-DTEST_STATIC=FALSE `
-DTEST_SHARED=TRUE `
-DTEST_TEST=TRUE `
-DCMAKE_SUPPRESS_REGENERATION=TRUE `
-DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}"
Start-Sleep -Seconds 2
cmake --build build_x64 --config Release --verbose
ctest --test-dir build_x64 --no-tests=error -C Release --output-on-failure
- name: 'Configure vcvars arm64'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64_arm64
- name: 'CMake (configure + build) arm64'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" `
-B build_arm64 `
-GNinja `
-DCMAKE_BUILD_TYPE=Debug `
-Werror=dev `
-DTEST_FULL=TRUE `
-DTEST_STATIC=FALSE `
-DTEST_SHARED=TRUE `
-DTEST_TEST=TRUE `
-DCMAKE_SUPPRESS_REGENERATION=TRUE `
-DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}"
Start-Sleep -Seconds 2
cmake --build build_arm64 --config Release --verbose
- name: 'CMake (configure + build) arm64ec'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" `
-B build_arm64ec `
-GNinja `
-DCMAKE_BUILD_TYPE=Debug `
-Werror=dev `
-DTEST_FULL=TRUE `
-DTEST_STATIC=FALSE `
-DTEST_SHARED=TRUE `
-DTEST_TEST=TRUE `
-DSDL_DISABLE_AVX=TRUE `
-DSDL_DISABLE_AVX2=TRUE `
-DSDL_DISABLE_AVX512F=TRUE `
-DCMAKE_SUPPRESS_REGENERATION=TRUE `
-DCMAKE_C_FLAGS="/arm64EC" `
-DCMAKE_CXX_FLAGS="/arm64EC" `
-DCMAKE_EXE_LINKER_FLAGS="/MACHINE:ARM64EC" `
-DCMAKE_SHARED_LINKER_FLAGS="/MACHINE:ARM64EC" `
-DCMAKE_STATIC_LINKER_FLAGS="/MACHINE:ARM64EC" `
-DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}"
Start-Sleep -Seconds 2
cmake --build build_arm64ec --config Release --verbose
mingw:
needs: [src]
runs-on: ubuntu-24.04 # FIXME: current ubuntu-latest ships an outdated mingw, replace with ubuntu-latest once 24.04 becomes the new default
outputs:
mingw-devel-tar-gz: ${{ steps.releaser.outputs.mingw-devel-tar-gz }}
mingw-devel-tar-xz: ${{ steps.releaser.outputs.mingw-devel-tar-xz }}
steps:
- name: 'Set up Python'
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 'Fetch build-release.py'
uses: actions/checkout@v4
with:
sparse-checkout: 'build-scripts/build-release.py'
- name: 'Install Mingw toolchain'
run: |
sudo apt-get update -y
sudo apt-get install -y gcc-mingw-w64 g++-mingw-w64 ninja-build
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Untar ${{ needs.src.outputs.src-tar-gz }}'
id: tar
run: |
mkdir -p /tmp/tardir
tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}"
echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Build MinGW binary archives'
id: releaser
run: |
python build-scripts/build-release.py \
--actions mingw \
--commit ${{ inputs.commit }} \
--root "${{ steps.tar.outputs.path }}" \
--github \
--debug
- name: 'Store MinGW archives'
uses: actions/upload-artifact@v4
with:
name: mingw
path: '${{ github.workspace }}/dist'
mingw-verify:
needs: [mingw, src]
runs-on: ubuntu-latest
steps:
- name: 'Install Mingw toolchain'
run: |
sudo apt-get update -y
sudo apt-get install -y gcc-mingw-w64 g++-mingw-w64 ninja-build
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Download MinGW binaries'
uses: actions/download-artifact@v4
with:
name: mingw
path: '${{ github.workspace }}'
- name: 'Untar ${{ needs.src.outputs.src-tar-gz }}'
id: src
run: |
mkdir -p /tmp/tardir
tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}"
echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Untar ${{ needs.mingw.outputs.mingw-devel-tar-gz }}'
id: bin
run: |
mkdir -p /tmp/mingw-tardir
tar -C /tmp/mingw-tardir -v -x -f "${{ github.workspace }}/${{ needs.mingw.outputs.mingw-devel-tar-gz }}"
echo "path=/tmp/mingw-tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'CMake (configure + build) i686'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DCMAKE_BUILD_TYPE="Release" \
-DTEST_FULL=TRUE \
-DTEST_STATIC=FALSE \
-DTEST_TEST=TRUE \
-DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}" \
-DCMAKE_TOOLCHAIN_FILE="${{ steps.src.outputs.path }}/build-scripts/cmake-toolchain-mingw64-i686.cmake" \
-DCMAKE_C_FLAGS="-DSDL_DISABLE_SSE4_2" \
-Werror=dev \
-B build_x86
cmake --build build_x86 --config Release --verbose
- name: 'CMake (configure + build) x86_64'
run: |
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DCMAKE_BUILD_TYPE="Release" \
-DTEST_FULL=TRUE \
-DTEST_STATIC=false \
-DTEST_TEST=TRUE \
-DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}" \
-DCMAKE_TOOLCHAIN_FILE="${{ steps.src.outputs.path }}/build-scripts/cmake-toolchain-mingw64-x86_64.cmake" \
-DCMAKE_C_FLAGS="-DSDL_DISABLE_SSE4_2" \
-Werror=dev \
-B build_x64
cmake --build build_x64 --config Release --verbose
android:
needs: [src]
runs-on: ubuntu-latest
outputs:
android-aar: ${{ steps.releaser.outputs.android-aar }}
steps:
- name: 'Set up Python'
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 'Fetch build-release.py'
uses: actions/checkout@v4
with:
sparse-checkout: 'build-scripts/build-release.py'
- name: 'Setup Android NDK'
uses: nttld/setup-ndk@v1
with:
local-cache: true
ndk-version: r21e
- name: 'Setup Java JDK'
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '11'
- name: 'Install ninja'
run: |
sudo apt-get update -y
sudo apt-get install -y ninja-build
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Untar ${{ needs.src.outputs.src-tar-gz }}'
id: tar
run: |
mkdir -p /tmp/tardir
tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}"
echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Build Android prefab binary archive(s)'
id: releaser
run: |
python build-scripts/build-release.py \
--actions android \
--commit ${{ inputs.commit }} \
--root "${{ steps.tar.outputs.path }}" \
--github \
--debug
- name: 'Store Android archive(s)'
uses: actions/upload-artifact@v4
with:
name: android
path: '${{ github.workspace }}/dist'
android-verify:
needs: [android, src]
runs-on: ubuntu-latest
steps:
- name: 'Set up Python'
uses: actions/setup-python@v5
with:
python-version: '3.11'
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: 'Download source archives'
uses: actions/download-artifact@v4
with:
name: sources
path: '${{ github.workspace }}'
- name: 'Download Android .aar archive'
uses: actions/download-artifact@v4
with:
name: android
path: '${{ github.workspace }}'
- name: 'Untar ${{ needs.src.outputs.src-tar-gz }}'
id: src
run: |
mkdir -p /tmp/tardir
tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}"
echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT
- name: 'Extract Android SDK from AAR'
id: sdk
run: |
cd /tmp
unzip "${{ github.workspace }}/${{ needs.android.outputs.android-aar }}"
python "${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}.aar" -o /tmp/SDL3-android
echo "prefix=/tmp/SDL3-android" >>$GITHUB_OUTPUT
echo "sdl3-aar=/tmp/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}.aar" >>$GITHUB_OUTPUT
- name: 'CMake (configure + build) x86, x64, arm32, arm64'
run: |
android_abis="x86 x86_64 armeabi-v7a arm64-v8a"
for android_abi in ${android_abis}; do
echo "Configuring ${android_abi}..."
cmake -S "${{ steps.src.outputs.path }}/cmake/test" \
-DTEST_FULL=TRUE \
-DTEST_STATIC=FALSE \
-DTEST_TEST=TRUE \
-DCMAKE_PREFIX_PATH="${{ steps.sdk.outputs.prefix }}" \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=${android_abi} \
-DCMAKE_BUILD_TYPE=Release \
-B "${android_abi}"
echo "Building ${android_abi}..."
cmake --build "${android_abi}" --config Release --verbose
done
- name: 'Create gradle project'
id: create-gradle-project
run: |
python ${{ steps.src.outputs.path }}/build-scripts/create-android-project.py \
org.libsdl.testspriteminimal \
${{ steps.src.outputs.path }}/test/testspriteminimal.c \
${{ steps.src.outputs.path }}/test/icon.h \
--variant aar \
--output "/tmp/projects"
echo "path=/tmp/projects/org.libsdl.testspriteminimal" >>$GITHUB_OUTPUT
- name: 'Copy SDL3 aar into Gradle project'
run: |
cp "${{ steps.sdk.outputs.sdl3-aar }}" "${{ steps.create-gradle-project.outputs.path }}/app/libs"
echo ""
echo "Project contents:"
echo ""
find "${{ steps.create-gradle-project.outputs.path }}"
- name: 'Build app (Gradle & CMake)'
run: |
cd "${{ steps.create-gradle-project.outputs.path }}"
./gradlew -i assembleRelease -Pandroid.native.buildOutput=verbose -PBUILD_WITH_CMAKE=1
- name: 'Build app (Gradle & ndk-build)'
run: |
cd "${{ steps.create-gradle-project.outputs.path }}"
./gradlew -i assembleRelease -Pandroid.native.buildOutput=verbose

View File

@ -1,68 +0,0 @@
name: Build (RISC OS)
on: [push, pull_request]
jobs:
Build:
name: ${{ matrix.platform.name }}
runs-on: ubuntu-latest
container: riscosdotinfo/riscos-gccsdk-4.7:latest
strategy:
fail-fast: false
matrix:
platform:
- { name: autotools, test_args: '-DTEST_SHARED=FALSE' } # FIXME: autotools should build and install shared libraries
- { name: CMake }
steps:
- name: Setup dependencies
run: apt-get update && apt-get install -y cmake ninja-build
- uses: actions/checkout@v3
- name: Configure (autotools)
if: ${{ contains(matrix.platform.name, 'autotools') }}
run: |
mkdir build_autotools
cd build_autotools
../configure \
--host=arm-unknown-riscos \
--disable-gcc-atomics \
--prefix=${{ github.workspace }}/prefix_autotools
- name: Build (autotools)
if: ${{ contains(matrix.platform.name, 'autotools') }}
run: make -C build_autotools -j`nproc` V=1
- name: Install (autotools)
if: ${{ contains(matrix.platform.name, 'autotools') }}
run: |
echo "SDL2_DIR=${{ github.workspace }}/prefix_autotools" >> $GITHUB_ENV
make -C build_autotools install
( cd ${{ github.workspace }}/prefix_autotools; find ) | LC_ALL=C sort -u
- name: Configure (CMake)
if: ${{ contains(matrix.platform.name, 'CMake') }}
run: |
cmake -S . -B build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=/home/riscos/env/toolchain-riscos.cmake \
-DRISCOS=ON \
-DSDL_GCC_ATOMICS=OFF \
-DSDL_TESTS=ON \
-DSDL_INSTALL_TESTS=ON \
-DSDL_VENDOR_INFO="Github Workflow" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/prefix_cmake
- name: Build (CMake)
if: ${{ contains(matrix.platform.name, 'CMake') }}
run: cmake --build build --verbose
- name: Install (CMake)
if: ${{ contains(matrix.platform.name, 'CMake') }}
run: |
echo "SDL2_DIR=${{ github.workspace }}/prefix_cmake" >> $GITHUB_ENV
cmake --install build/
( cd ${{ github.workspace }}/prefix_cmake; find ) | LC_ALL=C sort -u
- name: Verify CMake configuration files
run: |
cmake -S cmake/test -B cmake_config_build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=/home/riscos/env/toolchain-riscos.cmake \
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }} \
-DCMAKE_BUILD_TYPE=Release \
${{ matrix.platform.test_args }}
cmake --build cmake_config_build --verbose

View File

@ -1,95 +0,0 @@
name: Build (Sony Playstation Vita)
on: [push, pull_request]
defaults:
run:
shell: sh
jobs:
vita:
name: ${{ matrix.platform.name }}
runs-on: ubuntu-latest
container:
image: vitasdk/vitasdk:latest
strategy:
fail-fast: false
matrix:
platform:
- { name: GLES (pib), os: windows-latest, pib: true }
- { name: GLES (PVR_PSP2 + gl4es4vita), os: windows-latest, pvr: true }
steps:
- uses: actions/checkout@v3
- name: Install build requirements
run: |
apk update
apk add cmake ninja pkgconf bash
- name: Configure PVR_PSP2 (GLES)
if: ${{ !!matrix.platform.pvr }}
run: |
pvr_psp2_version=3.9
# Configure PVR_PSP2 headers
wget https://github.com/GrapheneCt/PVR_PSP2/archive/refs/tags/v$pvr_psp2_version.zip -P/tmp
unzip /tmp/v$pvr_psp2_version.zip -d/tmp
cp -r /tmp/PVR_PSP2-$pvr_psp2_version/include/* ${VITASDK}/arm-vita-eabi/include
rm /tmp/v$pvr_psp2_version.zip
# Configure PVR_PSP2 stub libraries
wget https://github.com/GrapheneCt/PVR_PSP2/releases/download/v$pvr_psp2_version/vitasdk_stubs.zip -P/tmp
unzip /tmp/vitasdk_stubs.zip -d/tmp/pvr_psp2_stubs
find /tmp/pvr_psp2_stubs -type f -name "*.a" -exec cp {} ${VITASDK}/arm-vita-eabi/lib \;
rm /tmp/vitasdk_stubs.zip
rm -rf /tmp/pvr_psp2_stubs
- name: Configure gl4es4vita (OpenGL)
if: ${{ !!matrix.platform.pvr }}
run: |
gl4es4vita_version=1.1.4
# Configure gl4es4vita headers
wget https://github.com/SonicMastr/gl4es4vita/releases/download/v$gl4es4vita_version-vita/include.zip -P/tmp
unzip -o /tmp/include.zip -d${VITASDK}/arm-vita-eabi/include
rm /tmp/include.zip
# Configure gl4es4vita stub libraries
wget https://github.com/SonicMastr/gl4es4vita/releases/download/v$gl4es4vita_version-vita/vitasdk_stubs.zip -P/tmp
unzip /tmp/vitasdk_stubs.zip -d${VITASDK}/arm-vita-eabi/lib
- name: Configure CMake
run: |
cmake -S . -B build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake \
-DVIDEO_VITA_PIB=${{ !!matrix.platform.pib }} \
-DVIDEO_VITA_PVR=${{ !!matrix.platform.pvr }} \
-DSDL_WERROR=ON \
-DSDL_TESTS=ON \
-DSDL_INSTALL_TESTS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=prefix
- name: Build
run: cmake --build build --verbose
- name: Install CMake
run: |
echo "SDL2_DIR=$(pwd)/prefix" >> $GITHUB_ENV
cmake --install build/
( cd prefix; find ) | LC_ALL=C sort -u
- name: Verify CMake configuration files
run: |
cmake -S cmake/test -B cmake_config_build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake \
-DTEST_SHARED=FALSE \
-DCMAKE_PREFIX_PATH=${{ env.SDL2_DIR }} \
-DCMAKE_BUILD_TYPE=Release
cmake --build cmake_config_build --verbose
- name: Verify sdl2-config
run: |
export CC=arm-vita-eabi-gcc
export PATH=${{ env.SDL2_DIR }}/bin:$PATH
cmake/test/test_sdlconfig.sh
- name: Verify sdl2.pc
run: |
export CC=arm-vita-eabi-gcc
export PKG_CONFIG_PATH=${{ env.SDL2_DIR }}/lib/pkgconfig
cmake/test/test_pkgconfig.sh

View File

@ -1,35 +0,0 @@
name: Build (OpenWatcom)
on: [push, pull_request]
jobs:
os2:
name: ${{ matrix.platform.name }}
runs-on: windows-latest
strategy:
matrix:
platform:
- { name: Windows, makefile: Makefile.w32 }
- { name: OS/2, makefile: Makefile.os2 }
steps:
- uses: actions/checkout@v3
- uses: open-watcom/setup-watcom@v0
- name: Build SDL2
run: |
wmake -f ${{ matrix.platform.makefile }} ENABLE_WERROR=1
- name: Build tests
run: |
cd test && wmake -f ${{ matrix.platform.makefile }} ENABLE_WERROR=1
cd ..
- name: Run tests
if: "matrix.platform.makefile == 'Makefile.w32'"
run: |
cd test && wmake -f ${{ matrix.platform.makefile }} check-quick
cd ..
- name: distclean
run: |
wmake -f ${{ matrix.platform.makefile }} distclean
cd test && wmake -f ${{ matrix.platform.makefile }} distclean
cd ..

111
third-party/SDL/.gitignore generated vendored
View File

@ -1,21 +1,9 @@
aclocal.m4
autom4te*
config.cache
config.log
config.status
libtool
Makefile
Makefile.rules
sdl2-config
sdl2-config.cmake
sdl2-config-version.cmake
sdl2.pc
SDL2.spec
build
gen
Build
buildbot
build/
build-*/
!build-scripts/
buildbot/
/VERSION.txt
__pycache__
*.so
*.so.*
@ -41,13 +29,27 @@ buildbot
*.rej
# for CMake
.cmake
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
cmake_uninstall.cmake
SDL2ConfigVersion.cmake
install_manifest.txt
*Targets.cmake
*Config.cmake
*ConfigVersion.cmake
CTestTestfile.cmake
Testing
compile_commands.json
.cache/
/include-config-*
/include-revision
/Makefile
.ninja_*
*.ninja
*.pc
test/*.test
wayland-generated-protocols
# for CLion
.idea
@ -61,11 +63,10 @@ cmake-build-*
.DS_Store
xcuserdata
*.xcworkspace
Xcode/build.xcconfig
# for QtCreator
CMakeLists.txt.user
build*/
*.pro.user*
# for Visual Studio Code
.vscode/
# for Visual C++
.vs
@ -75,35 +76,28 @@ Release
*.ncb
*.suo
*.sdf
VisualC/tests/controllermap/axis.bmp
VisualC/tests/controllermap/button.bmp
VisualC/tests/controllermap/controllermap.bmp
VisualC/tests/controllermap/controllermap_back.bmp
VisualC/tests/gamepadmap/axis.bmp
VisualC/tests/gamepadmap/button.bmp
VisualC/tests/gamepadmap/gamepadmap.bmp
VisualC/tests/gamepadmap/gamepadmap_back.bmp
VisualC/tests/loopwave/sample.wav
VisualC/tests/testautomation/CompareSurfaces0001_Reference.bmp
VisualC/tests/testautomation/CompareSurfaces0001_TestOutput.bmp
VisualC/tests/testgamecontroller/axis.bmp
VisualC/tests/testgamecontroller/button.bmp
VisualC/tests/testgamecontroller/controllermap.bmp
VisualC/tests/testgamecontroller/controllermap_back.bmp
VisualC/tests/testoverlay2/moose.dat
VisualC/tests/testautomation/*.bmp
VisualC/tests/testgamepad/axis.bmp
VisualC/tests/testgamepad/button.bmp
VisualC/tests/testgamepad/gamepadmap.bmp
VisualC/tests/testgamepad/gamepadmap_back.bmp
VisualC/tests/testoverlay/moose.dat
VisualC/tests/testrendertarget/icon.bmp
VisualC/tests/testrendertarget/sample.bmp
VisualC/tests/testscale/icon.bmp
VisualC/tests/testscale/sample.bmp
VisualC/tests/testsprite2/icon.bmp
VisualC/tests/testsprite/icon.bmp
VisualC/tests/testyuv/testyuv.bmp
VisualC/visualtest/icon.bmp
VisualC/visualtest/testquit.actions
VisualC/visualtest/testquit.config
VisualC/visualtest/testquit.exe
VisualC/visualtest/testquit.parameters
VisualC/visualtest/testsprite2.exe
VisualC/visualtest/testsprite2_sample.actions
VisualC/visualtest/testsprite2_sample.config
VisualC/visualtest/testsprite2_sample.parameters
VisualC-GDK/**/Layout
VisualC-GDK/shaders/*.h
src/render/direct3d12/D3D12_*_One.h
src/render/direct3d12/D3D12_*_Series.h
src/gpu/d3d12/D3D12_*_One.h
src/gpu/d3d12/D3D12_*_Series.h
# for Android
android-project/local.properties
@ -111,28 +105,28 @@ android-project/.gradle/
test/checkkeys
test/checkkeysthreads
test/controllermap
test/gamepadmap
test/loopwave
test/loopwavequeue
test/testatomic
test/testaudiocapture
test/testaudiorecording
test/testaudiohotplug
test/testaudioinfo
test/testautomation
test/testbounds
test/testcustomcursor
test/testdisplayinfo
test/testdraw2
test/testdraw
test/testdrawchessboard
test/testdropfile
test/testerror
test/testevdev
test/testfile
test/testfilesystem
test/testgamecontroller
test/testgamepad
test/testgeometry
test/testgesture
test/testgl2
test/testgl
test/testgles
test/testgles2
test/testhaptic
@ -150,7 +144,7 @@ test/testmessage
test/testmouse
test/testmultiaudio
test/testnative
test/testoverlay2
test/testoverlay
test/testplatform
test/testpower
test/testqsort
@ -164,7 +158,7 @@ test/testsem
test/testsensor
test/testshader
test/testshape
test/testsprite2
test/testsprite
test/testspriteminimal
test/teststreaming
test/testsurround
@ -174,16 +168,11 @@ test/testurl
test/testver
test/testviewport
test/testvulkan
test/testwm2
test/testwm
test/testyuv
test/torturethread
builddir/
!build-scripts/
debian/*.debhelper.log
debian/*.substvars
debian/*.tar.gz
debian/.debhelper/
debian/files
debian/libsdl*/
debian/tmp/
# for Doxygen
docs/output
SDL.tag
doxygen_warn.txt

35
third-party/SDL/.wikiheaders-options generated vendored
View File

@ -1,17 +1,32 @@
projectfullname = SDL2
projectshortname = SDL2
incsubdir = include
wikisubdir = SDL2
projectfullname = Simple Directmedia Layer
projectshortname = SDL
incsubdir = include/SDL3
wikisubdir =
readmesubdir = docs
apiprefixregex = (SDL_|SDLK_|KMOD_|AUDIO_)
mainincludefname = SDL.h
versionfname = include/SDL_version.h
apiprefixregex = (SDL_|SDLK_|[US]int\d+)
mainincludefname = SDL3/SDL.h
versionfname = include/SDL3/SDL_version.h
versionmajorregex = \A\#define\s+SDL_MAJOR_VERSION\s+(\d+)\Z
versionminorregex = \A\#define\s+SDL_MINOR_VERSION\s+(\d+)\Z
versionpatchregex = \A\#define\s+SDL_PATCHLEVEL\s+(\d+)\Z
versionmicroregex = \A\#define\s+SDL_MICRO_VERSION\s+(\d+)\Z
selectheaderregex = \ASDL.*?\.h\Z
projecturl = https://libsdl.org/
wikiurl = https://wiki.libsdl.org/SDL2
wikiurl = https://wiki.libsdl.org
bugreporturl = https://github.com/libsdl-org/sdlwiki/issues/new
warn_about_missing = 0
wikipreamble = (This is the legacy documentation for stable SDL2, the current stable version; [SDL3](https://wiki.libsdl.org/SDL3/) is the current development version.)
#wikipreamble = (This is the documentation for SDL3, which is the current stable version. [SDL2](https://wiki.libsdl.org/SDL2/) was the previous version!)
wikiheaderfiletext = Defined in [<SDL3/%fname%>](https://github.com/libsdl-org/SDL/blob/main/include/SDL3/%fname%)
manpageheaderfiletext = Defined in SDL3/%fname%
manpagesymbolfilterregex = \A[US]int\d+\Z
# All SDL_test_* headers become undefined categories, everything else just converts like SDL_audio.h -> Audio
# A handful of others we fix up in the header itself with /* WIKI CATEGORY: x */ comments.
headercategoryeval = s/\ASDL_test_?.*?\.h\Z//; s/\ASDL_?(.*?)\.h\Z/$1/; ucfirst();
quickrefenabled = 1
quickrefcategoryorder = Init,Hints,Error,Version,Properties,Log,Video,Events,Keyboard,Mouse,Touch,Gamepad,Joystick,Haptic,Audio,Time,Timer,Render,SharedObject,Thread,Mutex,Atomic,Filesystem,IOStream,AsyncIO,Storage,Pixels,Surface,Blendmode,Rect,Camera,Clipboard,Dialog,GPU,Messagebox,Vulkan,Metal,Platform,Power,Sensor,Process,Bits,Endian,Assert,CPUInfo,Intrinsics,Locale,System,Misc,GUID,Main,Stdinc
quickreftitle = SDL3 API Quick Reference
quickrefurl = https://libsdl.org/
quickrefdesc = The latest version of this document can be found at https://wiki.libsdl.org/SDL3/QuickReference
quickrefmacroregex = \A(SDL_PLATFORM_.*|SDL_.*_INTRINSICS|SDL_Atomic...Ref|SDL_assert.*?|SDL_COMPILE_TIME_ASSERT|SDL_arraysize|SDL_Swap[BL]E\d\d|SDL_[a-z]+_cast)\Z

85
third-party/SDL/Android.mk generated vendored
View File

@ -8,11 +8,11 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := SDL2
LOCAL_MODULE := SDL3
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/include/build_config $(LOCAL_PATH)/src
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := \
$(subst $(LOCAL_PATH)/,, \
@ -24,45 +24,69 @@ LOCAL_SRC_FILES := \
$(wildcard $(LOCAL_PATH)/src/audio/openslES/*.c) \
$(LOCAL_PATH)/src/atomic/SDL_atomic.c.arm \
$(LOCAL_PATH)/src/atomic/SDL_spinlock.c.arm \
$(wildcard $(LOCAL_PATH)/src/camera/*.c) \
$(wildcard $(LOCAL_PATH)/src/camera/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/camera/dummy/*.c) \
$(wildcard $(LOCAL_PATH)/src/core/*.c) \
$(wildcard $(LOCAL_PATH)/src/core/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \
$(LOCAL_PATH)/src/dialog/SDL_dialog.c \
$(LOCAL_PATH)/src/dialog/SDL_dialog_utils.c \
$(LOCAL_PATH)/src/dialog/android/SDL_androiddialog.c \
$(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \
$(wildcard $(LOCAL_PATH)/src/events/*.c) \
$(wildcard $(LOCAL_PATH)/src/file/*.c) \
$(wildcard $(LOCAL_PATH)/src/io/*.c) \
$(wildcard $(LOCAL_PATH)/src/io/generic/*.c) \
$(wildcard $(LOCAL_PATH)/src/gpu/*.c) \
$(wildcard $(LOCAL_PATH)/src/gpu/vulkan/*.c) \
$(wildcard $(LOCAL_PATH)/src/haptic/*.c) \
$(wildcard $(LOCAL_PATH)/src/haptic/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/haptic/dummy/*.c) \
$(wildcard $(LOCAL_PATH)/src/hidapi/*.c) \
$(wildcard $(LOCAL_PATH)/src/hidapi/android/*.cpp) \
$(wildcard $(LOCAL_PATH)/src/joystick/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/dummy/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/hidapi/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/steam/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/virtual/*.c) \
$(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \
$(wildcard $(LOCAL_PATH)/src/locale/*.c) \
$(wildcard $(LOCAL_PATH)/src/locale/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/main/*.c) \
$(wildcard $(LOCAL_PATH)/src/main/generic/*.c) \
$(wildcard $(LOCAL_PATH)/src/misc/*.c) \
$(wildcard $(LOCAL_PATH)/src/misc/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/power/*.c) \
$(wildcard $(LOCAL_PATH)/src/power/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/process/*.c) \
$(wildcard $(LOCAL_PATH)/src/process/dummy/*.c) \
$(wildcard $(LOCAL_PATH)/src/filesystem/*.c) \
$(wildcard $(LOCAL_PATH)/src/filesystem/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/filesystem/posix/*.c) \
$(wildcard $(LOCAL_PATH)/src/sensor/*.c) \
$(wildcard $(LOCAL_PATH)/src/sensor/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/sensor/dummy/*.c) \
$(wildcard $(LOCAL_PATH)/src/render/*.c) \
$(wildcard $(LOCAL_PATH)/src/render/*/*.c) \
$(wildcard $(LOCAL_PATH)/src/stdlib/*.c) \
$(wildcard $(LOCAL_PATH)/src/storage/*.c) \
$(wildcard $(LOCAL_PATH)/src/storage/generic/*.c) \
$(wildcard $(LOCAL_PATH)/src/thread/*.c) \
$(wildcard $(LOCAL_PATH)/src/thread/pthread/*.c) \
$(wildcard $(LOCAL_PATH)/src/time/*.c) \
$(wildcard $(LOCAL_PATH)/src/time/unix/*.c) \
$(wildcard $(LOCAL_PATH)/src/timer/*.c) \
$(wildcard $(LOCAL_PATH)/src/timer/unix/*.c) \
$(wildcard $(LOCAL_PATH)/src/tray/dummy/*.c) \
$(wildcard $(LOCAL_PATH)/src/tray/*.c) \
$(wildcard $(LOCAL_PATH)/src/video/*.c) \
$(wildcard $(LOCAL_PATH)/src/video/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/video/yuv2rgb/*.c) \
$(wildcard $(LOCAL_PATH)/src/test/*.c))
$(wildcard $(LOCAL_PATH)/src/video/yuv2rgb/*.c))
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
LOCAL_CFLAGS += \
-Wall -Wextra \
-Wdocumentation \
-Wmissing-prototypes \
-Wunreachable-code-break \
-Wunneeded-internal-declaration \
@ -81,7 +105,7 @@ LOCAL_CXXFLAGS += -std=gnu++11
LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid
LOCAL_LDFLAGS := -Wl,--no-undefined
LOCAL_LDFLAGS := -Wl,--no-undefined -Wl,--no-undefined-version -Wl,--version-script=$(LOCAL_PATH)/src/dynapi/SDL_dynapi.sym
ifeq ($(NDK_DEBUG),1)
cmd-strip :=
@ -92,15 +116,38 @@ LOCAL_STATIC_LIBRARIES := cpufeatures
include $(BUILD_SHARED_LIBRARY)
###########################
#
# SDL_test static library
#
###########################
LOCAL_MODULE := SDL3_test
LOCAL_MODULE_FILENAME := libSDL3_test
LOCAL_SRC_FILES := \
$(subst $(LOCAL_PATH)/,, \
$(wildcard $(LOCAL_PATH)/src/test/*.c))
LOCAL_LDLIBS :=
LOCAL_LDFLAGS :=
LOCAL_EXPORT_LDLIBS :=
include $(BUILD_STATIC_LIBRARY)
###########################
#
# SDL static library
#
###########################
LOCAL_MODULE := SDL2_static
LOCAL_MODULE := SDL3_static
LOCAL_MODULE_FILENAME := libSDL2
LOCAL_MODULE_FILENAME := libSDL3
LOCAL_LDLIBS :=
@ -110,21 +157,5 @@ LOCAL_EXPORT_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
include $(BUILD_STATIC_LIBRARY)
###########################
#
# SDL main static library
#
###########################
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE := SDL2_main
LOCAL_MODULE_FILENAME := libSDL2main
include $(BUILD_STATIC_LIBRARY)
$(call import-module,android/cpufeatures)

7
third-party/SDL/BUGS.txt generated vendored
View File

@ -11,6 +11,9 @@ You may also find help at the SDL forums/mailing list:
https://discourse.libsdl.org/
Bug reports are welcome here, but we really appreciate if you use the issue
tracker, as bugs discussed on the mailing list may be forgotten or missed.
or on Discord:
https://discord.com/invite/BwpFGBWsv8
Bug reports are welcome here, but we really appreciate if you use the issue tracker, as bugs discussed on the mailing list or Discord may be forgotten or missed.

4560
third-party/SDL/CMakeLists.txt generated vendored

File diff suppressed because it is too large Load Diff

38
third-party/SDL/CREDITS.md generated vendored Normal file
View File

@ -0,0 +1,38 @@
# Simple DirectMedia Layer CREDITS
Thanks to everyone who made this possible, including:
- Cliff Matthews, for giving me a reason to start this project. :) -- Executor rocks! *grin*
- Ryan Gordon for helping everybody out and keeping the dream alive. :)
- Frank Praznik for his Wayland support and general windowing development.
- Ozkan Sezer for sanity checks and make sure the i's are dotted and t's are crossed.
- Anonymous Maarten for CMake support and build system development.
- Evan Hemsley, Caleb Cornett, and Ethan Lee for SDL GPU development.
- Gabriel Jacobo for his work on the Android port and generally helping out all around.
- Philipp Wiesemann for his attention to detail reviewing the entire SDL code base and proposes patches.
- Andreas Schiffler for his dedication to unit tests, Visual Studio projects, and managing the Google Summer of Code.
- Mike Sartain for incorporating SDL into Team Fortress 2 and cheering me on at Valve.
- Alfred Reynolds for the game controller API and general (in)sanity
- Jørgen Tjernø¸ for numerous magical macOS fixes.
- Pierre-Loup Griffais for his deep knowledge of OpenGL drivers.
- Julian Winter for the SDL 2.0 website.
- Sheena Smith for many months of great work on the SDL wiki creating the API documentation and style guides.
- Paul Hunkin for his port of SDL to Android during the Google Summer of Code 2010.
- Eli Gottlieb for his work on shaped windows during the Google Summer of Code 2010.
- Jim Grandpre for his work on multi-touch and gesture recognition during
the Google Summer of Code 2010.
- Edgar "bobbens" Simo for his force feedback API development during the
Google Summer of Code 2008.
- Aaron Wishnick for his work on audio resampling and pitch shifting during
the Google Summer of Code 2008.
- Holmes Futrell for his port of SDL to the iPhone and iPod Touch during the
Google Summer of Code 2008.
- Jon Atkins for SDL_image, SDL_mixer and SDL_net documentation.
- Everybody at Loki Software, Inc. and Valve Corporation for their great contributions!
And a big hand to everyone else who has contributed over the years.
THANKS! :)
-- Sam Lantinga <slouken@libsdl.org>

53
third-party/SDL/CREDITS.txt generated vendored
View File

@ -1,53 +0,0 @@
Simple DirectMedia Layer CREDITS
Thanks to everyone who made this possible, including:
* Cliff Matthews, for giving me a reason to start this project. :)
-- Executor rocks! *grin*
* Ryan Gordon for helping everybody out and keeping the dream alive. :)
* Gabriel Jacobo for his work on the Android port and generally helping out all around.
* Philipp Wiesemann for his attention to detail reviewing the entire SDL code base and proposes patches.
* Andreas Schiffler for his dedication to unit tests, Visual Studio projects, and managing the Google Summer of Code.
* Mike Sartain for incorporating SDL into Team Fortress 2 and cheering me on at Valve.
* Alfred Reynolds for the game controller API and general (in)sanity
* Jørgen Tjernø for numerous magical Mac OS X fixes.
* Pierre-Loup Griffais for his deep knowledge of OpenGL drivers.
* Julian Winter for the SDL 2.0 website.
* Sheena Smith for many months of great work on the SDL wiki creating the API documentation and style guides.
* Paul Hunkin for his port of SDL to Android during the Google Summer of Code 2010.
* Eli Gottlieb for his work on shaped windows during the Google Summer of Code 2010.
* Jim Grandpre for his work on multi-touch and gesture recognition during
the Google Summer of Code 2010.
* Edgar "bobbens" Simo for his force feedback API development during the
Google Summer of Code 2008.
* Aaron Wishnick for his work on audio resampling and pitch shifting during
the Google Summer of Code 2008.
* Holmes Futrell for his port of SDL to the iPhone and iPod Touch during the
Google Summer of Code 2008.
* Jon Atkins for SDL_image, SDL_mixer and SDL_net documentation.
* Everybody at Loki Software, Inc. for their great contributions!
And a big hand to everyone else who has contributed over the years.
THANKS! :)
-- Sam Lantinga <slouken@libsdl.org>

47
third-party/SDL/INSTALL.md generated vendored Normal file
View File

@ -0,0 +1,47 @@
# To build and use SDL:
SDL supports a number of development environments:
- [CMake](docs/INTRO-cmake.md)
- [Visual Studio on Windows](docs/INTRO-visualstudio.md)
- [Xcode on Apple platforms](docs/INTRO-xcode.md)
- [Android Studio](docs/INTRO-androidstudio.md)
- [Emscripten for web](docs/INTRO-emscripten.md)
SDL is also usable in other environments. The basic steps are to use CMake to build the library and then use the headers and library that you built in your project. You can search online to see if anyone has specific steps for your setup.
# Documentation
An API reference, tutorials, and additional documentation is available at:
https://wiki.libsdl.org/SDL3
# Example code
There are simple example programs in the examples directory, and you can view them online at:
https://examples.libsdl.org/SDL3
More in-depth test programs are available in the tests directory and can be built by adding `-DSDL_TESTS=ON` to the CMake command line when building SDL.
# Discussions
## Discord
You can join the official Discord server at:
https://discord.com/invite/BwpFGBWsv8
## Forums/mailing lists
You can join SDL development discussions at:
https://discourse.libsdl.org/
Once you sign up, you can use the forum through the website or as a mailing list from your email client.
## Announcement list
You can sign up for the low traffic announcement list at:
https://www.libsdl.org/mailing-list.php

41
third-party/SDL/INSTALL.txt generated vendored
View File

@ -1,41 +0,0 @@
To compile and install SDL:
1. Windows with Visual Studio:
* Read ./docs/README-visualc.md
Windows with gcc, either native or cross-compiling:
* Read the FAQ at https://wiki.libsdl.org/FAQWindows
* Run './configure; make; make install'
macOS with Xcode:
* Read docs/README-macosx.md
macOS from the command line:
* Run './configure; make; make install'
Linux and other UNIX systems:
* Run './configure; make; make install'
Android:
* Read docs/README-android.md
iOS:
* Read docs/README-ios.md
Using Cmake:
* Read docs/README-cmake.md
2. Look at the example programs in ./test, and check out the online
documentation at https://wiki.libsdl.org/
3. Join the SDL developer discussions, sign up on
https://discourse.libsdl.org/
and go to the development forum
https://discourse.libsdl.org/c/sdl-development/6
4. Sign up for the announcement list through the web interface:
https://www.libsdl.org/mailing-list.php
That's it!
Sam Lantinga <slouken@libsdl.org>

2
third-party/SDL/LICENSE.txt generated vendored
View File

@ -1,4 +1,4 @@
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

263
third-party/SDL/Makefile.in generated vendored
View File

@ -1,263 +0,0 @@
# Makefile to build and install the SDL library
top_builddir = .
srcdir = @srcdir@
objects = build
gen = gen
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
includedir = @includedir@
datarootdir = @datarootdir@
datadir = @datadir@
auxdir = @ac_aux_dir@
distpath = $(srcdir)/..
distdir = SDL2-@SDL_VERSION@
distfile = $(distdir).tar.gz
@SET_MAKE@
SHELL = @SHELL@
CC = @CC@
CXX = @CXX@
INCLUDE = @INCLUDE@
CFLAGS = @BUILD_CFLAGS@
EXTRA_CFLAGS = @EXTRA_CFLAGS@
LDFLAGS = @BUILD_LDFLAGS@
EXTRA_LDFLAGS = @EXTRA_LDFLAGS@
LIBTOOL = @LIBTOOL@
INSTALL = @INSTALL@
FGREP = @FGREP@
AR = @AR@
RANLIB = @RANLIB@
RC = @RC@
LINKER = @LINKER@
LIBTOOLLINKERTAG = @LIBTOOLLINKERTAG@
SDL_VENDOR_INFO = @SDL_VENDOR_INFO@
TARGET = libSDL2.la
OBJECTS = @OBJECTS@
GEN_HEADERS = @GEN_HEADERS@
GEN_OBJECTS = @GEN_OBJECTS@
VERSION_OBJECTS = @VERSION_OBJECTS@
SDLMAIN_TARGET = libSDL2main.la
SDLMAIN_OBJECTS = @SDLMAIN_OBJECTS@
SDLTEST_TARGET = libSDL2_test.la
SDLTEST_OBJECTS = @SDLTEST_OBJECTS@
WAYLAND_SCANNER = @WAYLAND_SCANNER@
WAYLAND_SCANNER_CODE_MODE = @WAYLAND_SCANNER_CODE_MODE@
INSTALL_SDL2_CONFIG = @INSTALL_SDL2_CONFIG@
SRC_DIST = *.md *.txt acinclude Android.mk autogen.sh android-project build-scripts cmake cmake_uninstall.cmake.in configure configure.ac docs include Makefile.* mingw sdl2-config.cmake.in sdl2-config-version.cmake.in sdl2-config.in sdl2.m4 sdl2.pc.in SDL2.spec.in SDL2Config.cmake.in src test VisualC VisualC-WinRT Xcode Xcode-iOS wayland-protocols
GEN_DIST = SDL2.spec
ifneq ($V,1)
RUN_CMD_AR = @echo " AR " $@;
RUN_CMD_CC = @echo " CC " $@;
RUN_CMD_CXX = @echo " CXX " $@;
RUN_CMD_LTLINK = @echo " LTLINK" $@;
RUN_CMD_RANLIB = @echo " RANLIB" $@;
RUN_CMD_RC = @echo " RC " $@;
RUN_CMD_GEN = @echo " GEN " $@;
LIBTOOL += --quiet
endif
HDRS = \
SDL.h \
SDL_assert.h \
SDL_atomic.h \
SDL_audio.h \
SDL_bits.h \
SDL_blendmode.h \
SDL_clipboard.h \
SDL_cpuinfo.h \
SDL_egl.h \
SDL_endian.h \
SDL_error.h \
SDL_events.h \
SDL_filesystem.h \
SDL_gamecontroller.h \
SDL_gesture.h \
SDL_guid.h \
SDL_haptic.h \
SDL_hidapi.h \
SDL_hints.h \
SDL_joystick.h \
SDL_keyboard.h \
SDL_keycode.h \
SDL_loadso.h \
SDL_locale.h \
SDL_log.h \
SDL_main.h \
SDL_messagebox.h \
SDL_metal.h \
SDL_misc.h \
SDL_mouse.h \
SDL_mutex.h \
SDL_name.h \
SDL_opengl.h \
SDL_opengl_glext.h \
SDL_opengles.h \
SDL_opengles2_gl2ext.h \
SDL_opengles2_gl2.h \
SDL_opengles2_gl2platform.h \
SDL_opengles2.h \
SDL_opengles2_khrplatform.h \
SDL_pixels.h \
SDL_platform.h \
SDL_power.h \
SDL_quit.h \
SDL_rect.h \
SDL_render.h \
SDL_rwops.h \
SDL_scancode.h \
SDL_sensor.h \
SDL_shape.h \
SDL_stdinc.h \
SDL_surface.h \
SDL_system.h \
SDL_syswm.h \
SDL_thread.h \
SDL_timer.h \
SDL_touch.h \
SDL_types.h \
SDL_version.h \
SDL_video.h \
SDL_vulkan.h \
begin_code.h \
close_code.h
SDLTEST_HDRS = $(shell ls $(srcdir)/include | $(FGREP) SDL_test)
LT_AGE = @LT_AGE@
LT_CURRENT = @LT_CURRENT@
LT_RELEASE = @LT_RELEASE@
LT_REVISION = @LT_REVISION@
LT_LDFLAGS = -no-undefined -rpath $(libdir) -release $(LT_RELEASE) -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
all: $(srcdir)/configure Makefile $(objects)/$(TARGET) $(objects)/$(SDLMAIN_TARGET) $(objects)/$(SDLTEST_TARGET)
$(srcdir)/configure: $(srcdir)/configure.ac
@echo "Warning, configure is out of date, please re-run autogen.sh"
Makefile: $(srcdir)/Makefile.in
$(SHELL) config.status $@
Makefile.in:;
$(objects)/.created:
$(SHELL) $(auxdir)/mkinstalldirs $(objects)
touch $@
update-revision:
$(SHELL) $(auxdir)/updaterev.sh --vendor "$(SDL_VENDOR_INFO)"
.PHONY: all update-revision install install-bin install-hdrs install-lib install-data uninstall uninstall-bin uninstall-hdrs uninstall-lib uninstall-data clean distclean dist $(OBJECTS:.lo=.d)
$(objects)/$(TARGET): $(GEN_HEADERS) $(GEN_OBJECTS) $(OBJECTS) $(VERSION_OBJECTS)
$(RUN_CMD_LTLINK)$(LIBTOOL) --tag=$(LIBTOOLLINKERTAG) --mode=link $(LINKER) -o $@ $(OBJECTS) $(GEN_OBJECTS) $(VERSION_OBJECTS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LT_LDFLAGS)
$(objects)/$(SDLMAIN_TARGET): $(SDLMAIN_OBJECTS)
$(RUN_CMD_LTLINK)$(LIBTOOL) --tag=$(LIBTOOLLINKERTAG) --mode=link $(LINKER) -static -o $@ $(SDLMAIN_OBJECTS) -rpath $(libdir)
$(objects)/$(SDLTEST_TARGET): $(SDLTEST_OBJECTS)
$(RUN_CMD_LTLINK)$(LIBTOOL) --tag=$(LIBTOOLLINKERTAG) --mode=link $(LINKER) -static -o $@ $(SDLTEST_OBJECTS) -rpath $(libdir)
install: all install-bin install-hdrs install-lib install-data
install-bin:
ifeq ($(INSTALL_SDL2_CONFIG),TRUE)
$(SHELL) $(auxdir)/mkinstalldirs $(DESTDIR)$(bindir)
$(INSTALL) -m 755 sdl2-config $(DESTDIR)$(bindir)/sdl2-config
endif
install-hdrs: update-revision
$(SHELL) $(auxdir)/mkinstalldirs $(DESTDIR)$(includedir)/SDL2
for file in $(HDRS) $(SDLTEST_HDRS); do \
$(INSTALL) -m 644 $(srcdir)/include/$$file $(DESTDIR)$(includedir)/SDL2/$$file; \
done
$(INSTALL) -m 644 include/SDL_config.h $(DESTDIR)$(includedir)/SDL2/SDL_config.h
if test -f include/SDL_revision.h; then \
$(INSTALL) -m 644 include/SDL_revision.h $(DESTDIR)$(includedir)/SDL2/SDL_revision.h; \
else \
$(INSTALL) -m 644 $(srcdir)/include/SDL_revision.h $(DESTDIR)$(includedir)/SDL2/SDL_revision.h; \
fi
install-lib: $(objects)/$(TARGET) $(objects)/$(SDLMAIN_TARGET) $(objects)/$(SDLTEST_TARGET)
$(SHELL) $(auxdir)/mkinstalldirs $(DESTDIR)$(libdir)
$(LIBTOOL) --mode=install $(INSTALL) $(objects)/$(TARGET) $(DESTDIR)$(libdir)/$(TARGET)
$(LIBTOOL) --mode=install $(INSTALL) $(objects)/$(SDLMAIN_TARGET) $(DESTDIR)$(libdir)/$(SDLMAIN_TARGET)
$(LIBTOOL) --mode=install $(INSTALL) $(objects)/$(SDLTEST_TARGET) $(DESTDIR)$(libdir)/$(SDLTEST_TARGET)
install-data:
$(SHELL) $(auxdir)/mkinstalldirs $(DESTDIR)$(datadir)/aclocal
$(INSTALL) -m 644 $(srcdir)/sdl2.m4 $(DESTDIR)$(datadir)/aclocal/sdl2.m4
$(SHELL) $(auxdir)/mkinstalldirs $(DESTDIR)$(libdir)/pkgconfig
$(INSTALL) -m 644 sdl2.pc $(DESTDIR)$(libdir)/pkgconfig
ifeq ($(INSTALL_SDL2_CONFIG),TRUE)
$(SHELL) $(auxdir)/mkinstalldirs $(DESTDIR)$(libdir)/cmake/SDL2
$(INSTALL) -m 644 sdl2-config.cmake $(DESTDIR)$(libdir)/cmake/SDL2
$(INSTALL) -m 644 sdl2-config-version.cmake $(DESTDIR)$(libdir)/cmake/SDL2
endif
uninstall: uninstall-bin uninstall-hdrs uninstall-lib uninstall-data
uninstall-bin:
rm -f $(DESTDIR)$(bindir)/sdl2-config
uninstall-hdrs:
for file in $(HDRS) $(SDLTEST_HDRS); do \
rm -f $(DESTDIR)$(includedir)/SDL2/$$file; \
done
rm -f $(DESTDIR)$(includedir)/SDL2/SDL_config.h
rm -f $(DESTDIR)$(includedir)/SDL2/SDL_revision.h
-rmdir $(DESTDIR)$(includedir)/SDL2
uninstall-lib:
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$(TARGET)
rm -f $(DESTDIR)$(libdir)/$(SDLMAIN_TARGET)
rm -f $(DESTDIR)$(libdir)/$(SDLTEST_TARGET)
uninstall-data:
rm -f $(DESTDIR)$(datadir)/aclocal/sdl2.m4
rm -f $(DESTDIR)$(libdir)/pkgconfig/sdl2.pc
rm -f $(DESTDIR)$(libdir)/cmake/SDL2/sdl2-config.cmake
rm -f $(DESTDIR)$(libdir)/cmake/SDL2/sdl2-config-version.cmake
clean:
rm -rf $(objects)
rm -rf $(gen)
if test -f test/Makefile; then (cd test; $(MAKE) $@); fi
distclean: clean
rm -f Makefile Makefile.rules sdl2-config
rm -f config.status config.cache config.log libtool
rm -rf $(srcdir)/autom4te*
find $(srcdir) \( \
-name '*~' -o \
-name '*.bak' -o \
-name '*.old' -o \
-name '*.rej' -o \
-name '*.orig' -o \
-name '.#*' \) \
-exec rm -f {} \;
if test -f test/Makefile; then (cd test; $(MAKE) $@); fi
dist $(distfile):
$(SHELL) $(auxdir)/mkinstalldirs $(distdir)
(cd $(srcdir); tar cf - $(SRC_DIST)) | (cd $(distdir); tar xf -)
tar cf - $(GEN_DIST) | (cd $(distdir); tar xf -)
find $(distdir) \( \
-name '*~' -o \
-name '*.bak' -o \
-name '*.old' -o \
-name '*.rej' -o \
-name '*.orig' -o \
-name '.#*' \) \
-exec rm -f {} \;
if test -f $(distdir)/test/Makefile; then (cd $(distdir)/test && make distclean); fi
# Intentionally no vendor suffix: that's a property of the build, not the source
(cd $(distdir); $(srcdir)/build-scripts/updaterev.sh --dist)
tar cvf - $(distdir) | gzip --best >$(distfile)
rm -rf $(distdir)
rpm: $(distfile)
rpmbuild -ta $?

61
third-party/SDL/Makefile.minimal generated vendored
View File

@ -1,61 +0,0 @@
# Makefile to build the SDL library
CPPFLAGS = -I./include
CFLAGS = -g -O2
AR = ar
RANLIB = ranlib
TARGET = libSDL2.a
TESTTARGET = libSDL2_test.a
SOURCES = \
src/*.c \
src/atomic/*.c \
src/audio/*.c \
src/audio/dummy/*.c \
src/cpuinfo/*.c \
src/events/*.c \
src/file/*.c \
src/haptic/*.c \
src/haptic/dummy/*.c \
src/hidapi/*.c \
src/joystick/*.c \
src/joystick/dummy/*.c \
src/loadso/dummy/*.c \
src/power/*.c \
src/filesystem/dummy/*.c \
src/locale/*.c \
src/locale/dummy/*.c \
src/misc/*.c \
src/misc/dummy/*.c \
src/render/*.c \
src/render/software/*.c \
src/sensor/*.c \
src/sensor/dummy/*.c \
src/stdlib/*.c \
src/libm/*.c \
src/thread/*.c \
src/thread/generic/*.c \
src/timer/*.c \
src/timer/dummy/*.c \
src/video/*.c \
src/video/yuv2rgb/*.c \
src/video/dummy/*.c \
TSOURCES = src/test/*.c
OBJECTS = $(shell echo $(SOURCES) | sed -e 's,\.c,\.o,g')
TOBJECTS= $(shell echo $(TSOURCES) | sed -e 's,\.c,\.o,g')
all: $(TARGET) $(TESTTARGET)
$(TARGET): $(OBJECTS)
$(AR) crv $@ $^
$(RANLIB) $@
$(TESTTARGET): $(TOBJECTS)
$(AR) crv $@ $^
$(RANLIB) $@
clean:
rm -f $(TARGET) $(TESTTARGET) $(OBJECTS) $(TOBJECTS)

298
third-party/SDL/Makefile.os2 generated vendored
View File

@ -1,298 +0,0 @@
# Open Watcom makefile to build SDL2.dll for OS/2:
# wmake -f Makefile.os2
#
# If you have GNU libiconv installed (iconv2.dll), you
# can compile against it by specifying LIBICONV=1, e.g.:
# wmake -f Makefile.os2 LIBICONV=1
#
# If you have libusb-1.0 installed (usb100.dll, libusb.h), you
# can compile hidapi joystick support against it (experimental)
# by specifying HIDAPI=1, e.g.:
# wmake -f Makefile.os2 HIDAPI=1
#
# To error out upon warnings: wmake -f Makefile.os2 ENABLE_WERROR=1
LIBNAME = SDL2
MAJOR_VERSION = 2
MINOR_VERSION = 30
MICRO_VERSION = 0
VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)
DESCRIPTION = Simple DirectMedia Layer 2
LIBICONV=0
ICONVLIB=$(LIBICONV_LIB)
LIBHOME = .
DLLFILE = $(LIBHOME)/$(LIBNAME).dll
LIBFILE = $(LIBHOME)/$(LIBNAME).lib
LNKFILE = $(LIBNAME).lnk
INCPATH = -I"$(%WATCOM)/h/os2" -I"$(%WATCOM)/h"
INCPATH+= -Iinclude
LIBM = SDL2libm.lib
TLIB = SDL2test.lib
LIBS = mmpm2.lib $(LIBM)
CFLAGS = -bt=os2 -d0 -q -bm -5s -fp5 -fpi87 -sg -oeatxhn -ei
# Debug options:
# - debug messages from OS/2 related code to stdout:
#CFLAGS+= -DOS2DEBUG
# - debug messages from OS/2 code via SDL_LogDebug():
#CFLAGS+= -DOS2DEBUG=2
# max warnings:
CFLAGS+= -wx
!ifeq ENABLE_WERROR 1
CFLAGS+= -we
!endif
# newer OpenWatcom versions enable W303 by default
CFLAGS+= -wcd=303
# the include paths :
CFLAGS+= $(INCPATH)
CFLAGS_STATIC=$(CFLAGS)
# building dll:
CFLAGS_DLL =$(CFLAGS)
CFLAGS_DLL+= -bd
# iconv:
LIBICONV_LIB=iconv2.lib
!ifeq LIBICONV 1
CFLAGS_DLL+= -DHAVE_ICONV=1 -DHAVE_ICONV_H=1 -DSDL_USE_LIBICONV
LIBS+= $(ICONVLIB)
!else
LIBS+= libuls.lib libconv.lib
!endif
# hidapi (libusb):
!ifeq HIDAPI 1
CFLAGS_DLL+= -DHAVE_LIBUSB_H=1
!endif
# building SDL itself (for DECLSPEC):
CFLAGS_DLL+= -DBUILD_SDL
CFLAGS_DLL+= -DSDL_BUILD_MAJOR_VERSION=$(MAJOR_VERSION)
CFLAGS_DLL+= -DSDL_BUILD_MINOR_VERSION=$(MINOR_VERSION)
CFLAGS_DLL+= -DSDL_BUILD_MICRO_VERSION=$(MICRO_VERSION)
SRCS = SDL.c SDL_assert.c SDL_error.c SDL_guid.c SDL_log.c SDL_dataqueue.c SDL_hints.c SDL_list.c SDL_utils.c
SRCS+= SDL_getenv.c SDL_iconv.c SDL_malloc.c SDL_qsort.c SDL_stdlib.c SDL_string.c SDL_strtokr.c SDL_crc16.c SDL_crc32.c
SRCS+= SDL_cpuinfo.c SDL_atomic.c SDL_spinlock.c SDL_thread.c SDL_timer.c
SRCS+= SDL_rwops.c SDL_power.c
SRCS+= SDL_audio.c SDL_audiocvt.c SDL_audiodev.c SDL_audiotypecvt.c SDL_mixer.c SDL_wave.c
SRCS+= SDL_events.c SDL_quit.c SDL_keyboard.c SDL_mouse.c SDL_windowevents.c &
SDL_clipboardevents.c SDL_dropevents.c SDL_displayevents.c SDL_gesture.c &
SDL_sensor.c SDL_touch.c
SRCS+= SDL_haptic.c SDL_hidapi.c SDL_gamecontroller.c SDL_joystick.c controller_type.c
SRCS+= SDL_render.c yuv_rgb_sse.c yuv_rgb_std.c SDL_yuv.c SDL_yuv_sw.c SDL_blendfillrect.c &
SDL_blendline.c SDL_blendpoint.c SDL_drawline.c SDL_drawpoint.c &
SDL_render_sw.c SDL_rotate.c SDL_triangle.c
SRCS+= SDL_blit.c SDL_blit_0.c SDL_blit_1.c SDL_blit_A.c SDL_blit_auto.c &
SDL_blit_copy.c SDL_blit_N.c SDL_blit_slow.c SDL_fillrect.c SDL_bmp.c &
SDL_pixels.c SDL_rect.c SDL_RLEaccel.c SDL_shape.c SDL_stretch.c &
SDL_surface.c SDL_video.c SDL_clipboard.c SDL_vulkan_utils.c SDL_egl.c
SRCS+= SDL_syscond.c SDL_sysmutex.c SDL_syssem.c SDL_systhread.c SDL_systls.c
SRCS+= SDL_systimer.c
SRCS+= SDL_sysloadso.c
SRCS+= SDL_sysfilesystem.c
SRCS+= SDL_os2joystick.c SDL_syshaptic.c SDL_sysjoystick.c SDL_virtualjoystick.c
SRCS+= SDL_hidapijoystick.c SDL_hidapi_rumble.c SDL_hidapi_combined.c SDL_hidapi_gamecube.c SDL_hidapi_luna.c SDL_hidapi_ps3.c SDL_hidapi_ps4.c SDL_hidapi_ps5.c SDL_hidapi_shield.c SDL_hidapi_stadia.c SDL_hidapi_switch.c SDL_hidapi_wii.c SDL_hidapi_xbox360.c SDL_hidapi_xbox360w.c SDL_hidapi_xboxone.c SDL_hidapi_steam.c SDL_hidapi_steamdeck.c SDL_steam_virtual_gamepad.c
SRCS+= SDL_dummyaudio.c SDL_diskaudio.c
SRCS+= SDL_nullvideo.c SDL_nullframebuffer.c SDL_nullevents.c
SRCS+= SDL_dummysensor.c
SRCS+= SDL_locale.c SDL_syslocale.c
SRCS+= SDL_url.c SDL_sysurl.c
SRCS+= SDL_os2.c
!ifeq LIBICONV 0
SRCS+= geniconv.c os2cp.c os2iconv.c sys2utf8.c
!endif
SRCS+= SDL_os2audio.c
SRCS+= SDL_os2video.c SDL_os2util.c SDL_os2dive.c SDL_os2vman.c &
SDL_os2mouse.c SDL_os2messagebox.c
SRCS+= SDL_dynapi.c
OBJS = $(SRCS:.c=.obj)
.extensions:
.extensions: .lib .dll .obj .c .asm
.c: ./src;./src/dynapi;./src/audio;./src/cpuinfo;./src/events;./src/file;./src/haptic;./src/joystick;./src/power;./src/render;./src/render/software;./src/sensor;./src/stdlib;./src/thread;./src/timer;./src/video;./src/video/yuv2rgb;./src/atomic;./src/audio/disk;
.c: ./src/haptic/dummy;./src/joystick/dummy;./src/joystick/virtual;./src/audio/dummy;./src/video/dummy;./src/sensor/dummy;
.c: ./src/core/os2;./src/audio/os2;./src/loadso/os2;./src/filesystem/os2;./src/joystick/os2;./src/thread/os2;./src/timer/os2;./src/video/os2;
.c: ./src/core/os2/geniconv;
.c: ./src/locale/;./src/locale/unix;./src/misc;./src/misc/dummy;./src/joystick/hidapi;./src/hidapi
all: $(DLLFILE) $(LIBFILE) $(TLIB) .symbolic
build_dll: .symbolic
@echo * Compiling dll objects
$(DLLFILE): build_dll $(OBJS) $(LIBM) $(LIBICONV_LIB) $(LNKFILE)
@echo * Linking: $@
wlink @$(LNKFILE)
$(LIBFILE): $(DLLFILE)
@echo * Creating LIB file: $@
wlib -q -b -n -c -pa -s -t -zld -ii -io $* $(DLLFILE)
.c.obj:
wcc386 $(CFLAGS_DLL) -fo=$^@ $<
SDL_syscond.obj: "src/thread/generic/SDL_syscond.c"
wcc386 $(CFLAGS_DLL) -fo=$^@ $<
SDL_cpuinfo.obj: SDL_cpuinfo.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_wave.obj: SDL_wave.c
wcc386 $(CFLAGS_DLL) -wcd=124 -fo=$^@ $<
SDL_blendfillrect.obj: SDL_blendfillrect.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_blendline.obj: SDL_blendline.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_blendpoint.obj: SDL_blendpoint.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_RLEaccel.obj: SDL_RLEaccel.c
wcc386 $(CFLAGS_DLL) -wcd=201 -fo=$^@ $<
yuv_rgb_sse.obj: yuv_rgb_sse.c
wcc386 $(CFLAGS_DLL) -wcd=202 -fo=$^@ $<
!ifeq HIDAPI 1
# c99 mode needed because of structs with flexible array members in libusb.h
SDL_hidapi.obj: SDL_hidapi.c
wcc386 $(CFLAGS_DLL) -za99 -fo=$^@ $<
!endif
$(LIBICONV_LIB): "src/core/os2/iconv2.lbc"
@echo * Creating: $@
wlib -q -b -n -c -pa -s -t -zld -ii -io $@ @$<
# SDL2libm
MSRCS= e_atan2.c e_exp.c e_fmod.c e_log10.c e_log.c e_pow.c e_rem_pio2.c e_sqrt.c &
k_cos.c k_rem_pio2.c k_sin.c k_tan.c &
s_atan.c s_copysign.c s_cos.c s_fabs.c s_floor.c s_scalbn.c s_sin.c s_tan.c
MOBJS= $(MSRCS:.c=.obj)
.c: ./src/libm;
e_atan2.obj: e_atan2.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_exp.obj: e_exp.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_fmod.obj: e_fmod.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_log10.obj: e_log10.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_log.obj: e_log.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_pow.obj: e_pow.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_rem_pio2.obj: e_rem_pio2.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_sqrt.obj: e_sqrt.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
k_cos.obj: k_cos.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
k_rem_pio2.obj: k_rem_pio2.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
k_sin.obj: k_sin.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
k_tan.obj: k_tan.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_atan.obj: s_atan.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_copysign.obj: s_copysign.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_cos.obj: s_cos.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_fabs.obj: s_fabs.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_floor.obj: s_floor.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_scalbn.obj: s_scalbn.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_sin.obj: s_sin.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_tan.obj: s_tan.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
build_libm: .symbolic
@echo * Compiling libm objects
$(LIBM): build_libm $(MOBJS)
@echo * Creating: $@
wlib -q -b -n -c -pa -s -t -zld -ii -io $@ $(MOBJS)
# SDL2test
TSRCS = SDL_test_assert.c SDL_test_common.c SDL_test_compare.c &
SDL_test_crc32.c SDL_test_font.c SDL_test_fuzzer.c SDL_test_harness.c &
SDL_test_imageBlit.c SDL_test_imageBlitBlend.c SDL_test_imageFace.c &
SDL_test_imagePrimitives.c SDL_test_imagePrimitivesBlend.c &
SDL_test_log.c SDL_test_md5.c SDL_test_random.c SDL_test_memory.c
TOBJS= $(TSRCS:.c=.obj)
.c: ./src/test;
SDL_test_assert.obj: SDL_test_assert.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_common.obj: SDL_test_common.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_compare.obj: SDL_test_compare.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_crc32.obj: SDL_test_crc32.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_font.obj: SDL_test_font.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_fuzzer.obj: SDL_test_fuzzer.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_harness.obj: SDL_test_harness.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imageBlit.obj: SDL_test_imageBlit.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imageBlitBlend.obj: SDL_test_imageBlitBlend.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imageFace.obj: SDL_test_imageFace.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imagePrimitives.obj: SDL_test_imagePrimitives.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imagePrimitivesBlend.obj: SDL_test_imagePrimitivesBlend.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_log.obj: SDL_test_log.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_md5.obj: SDL_test_md5.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_random.obj: SDL_test_random.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_memory.obj: SDL_test_memory.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
build_tlib: .symbolic
@echo * Compiling testlib objects
$(TLIB): build_tlib $(TOBJS)
@echo * Creating: $@
wlib -q -b -n -c -pa -s -t -zld -ii -io $@ $(TOBJS)
$(LNKFILE):
@echo * Creating linker file: $@
@%create $@
@%append $@ SYSTEM os2v2_dll INITINSTANCE TERMINSTANCE
@%append $@ NAME $(DLLFILE)
@for %i in ($(OBJS)) do @%append $@ FILE %i
@for %i in ($(LIBS)) do @%append $@ LIB %i
@%append $@ OPTION QUIET
@%append $@ OPTION IMPF=$(LIBHOME)/$^&.exp
@%append $@ OPTION MAP=$(LIBHOME)/$^&.map
@%append $@ OPTION DESCRIPTION '@$#libsdl org:$(VERSION)$#@$(DESCRIPTION)'
@%append $@ OPTION ELIMINATE
@%append $@ OPTION MANYAUTODATA
@%append $@ OPTION OSNAME='OS/2 and eComStation'
@%append $@ OPTION SHOWDEAD
clean: .SYMBOLIC
@echo * Clean: $(LIBNAME)
@if exist *.obj rm *.obj
@if exist *.err rm *.err
@if exist $(LNKFILE) rm $(LNKFILE)
@if exist $(LIBM) rm $(LIBM)
@if exist $(LIBICONV_LIB) rm $(LIBICONV_LIB)
distclean: .SYMBOLIC clean
@if exist $(LIBHOME)/*.exp rm $(LIBHOME)/*.exp
@if exist $(LIBHOME)/*.map rm $(LIBHOME)/*.map
@if exist $(LIBFILE) rm $(LIBFILE)
@if exist $(DLLFILE) rm $(DLLFILE)
@if exist $(TLIB) rm $(TLIB)

64
third-party/SDL/Makefile.pandora generated vendored
View File

@ -1,64 +0,0 @@
# Makefile to build the pandora SDL library
AR = arm-none-linux-gnueabi-ar
RANLIB = arm-none-linux-gnueabi-ranlib
CC = arm-none-linux-gnueabi-gcc
CXX = arm-none-linux-gnueabi-g++
STRIP = arm-none-linux-gnueabi-strip
CFLAGS = -O3 -march=armv7-a -mcpu=cortex-a8 -mtune=cortex-a8 -mfloat-abi=softfp \
-mfpu=neon -ftree-vectorize -ffast-math -fomit-frame-pointer -fno-strict-aliasing -fsingle-precision-constant \
-I./include -I$(PNDSDK)/usr/include
TARGET = libSDL2.a
SOURCES =
./src/*.c \
./src/atomic/*.c \
./src/audio/*.c \
./src/audio/disk/*.c \
./src/audio/dsp/*.c \
./src/audio/dummy/*.c \
./src/cpuinfo/*.c \
./src/events/*.c \
./src/file/*.c \
./src/filesystem/unix/*.c \
./src/haptic/*.c \
./src/haptic/linux/*.c \
./src/hidapi/*.c \
./src/joystick/*.c \
./src/joystick/linux/*.c \
./src/loadso/dlopen/*.c \
./src/locale/*.c \
./src/locale/unix/*.c \
./src/misc/*.c \
./src/misc/unix/*.c \
./src/power/*.c \
./src/sensor/*.c \
./src/sensor/dummy/*.c \
./src/stdlib/*.c \
./src/thread/*.c \
./src/thread/pthread/SDL_syscond.c \
./src/thread/pthread/SDL_sysmutex.c \
./src/thread/pthread/SDL_syssem.c \
./src/thread/pthread/SDL_systhread.c \
./src/timer/*.c \
./src/timer/unix/*.c \
./src/video/*.c \
./src/video/yuv2rgb/*.c \
./src/video/dummy/*.c \
./src/video/x11/*.c \
./src/video/pandora/*.c
OBJECTS = $(shell echo $(SOURCES) | sed -e 's,\.c,\.o,g')
CONFIG_H = $(shell cp include/SDL_config_pandora.h include/SDL_config.h)
all: $(TARGET)
$(TARGET): $(CONFIG_H) $(OBJECTS)
$(AR) crv $@ $^
$(RANLIB) $@
clean:
rm -f $(TARGET) $(OBJECTS)

283
third-party/SDL/Makefile.w32 generated vendored
View File

@ -1,283 +0,0 @@
# Open Watcom makefile to build SDL2.dll for Win32:
# wmake -f Makefile.w32
#
# To error out upon warnings: wmake -f Makefile.w32 ENABLE_WERROR=1
LIBNAME = SDL2
MAJOR_VERSION = 2
MINOR_VERSION = 30
MICRO_VERSION = 0
VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)
LIBHOME = .
DLLFILE = $(LIBHOME)/$(LIBNAME).dll
LIBFILE = $(LIBHOME)/$(LIBNAME).lib
EXPFILE = $(LIBHOME)/$(LIBNAME).exp
LNKFILE = $(LIBNAME).lnk
INCPATH = -I"$(%WATCOM)/h/nt" -I"$(%WATCOM)/h/nt/directx" -I"$(%WATCOM)/h"
INCPATH+= -Iinclude
INCPATH+= -I"src/video/khronos"
LIBM = SDL2libm.lib
TLIB = SDL2test.lib
# user32.lib, gdi32.lib, ole32.lib and oleaut32.lib are actually
# among the default libraries in wlink.lnk for nt_dll linkage...
LIBS = user32.lib gdi32.lib winmm.lib imm32.lib ole32.lib oleaut32.lib shell32.lib setupapi.lib version.lib uuid.lib dxguid.lib $(LIBM)
CFLAGS = -bt=nt -d0 -q -bm -5s -fp5 -fpi87 -sg -oeatxhn -ei
# max warnings:
CFLAGS+= -wx
!ifeq ENABLE_WERROR 1
CFLAGS+= -we
!endif
# newer OpenWatcom versions enable W303 by default
CFLAGS+= -wcd=303
# new vulkan headers result in lots of W202 warnings
CFLAGS+= -wcd=202
# the include paths :
CFLAGS+= $(INCPATH)
CFLAGS_STATIC=$(CFLAGS)
# building dll:
CFLAGS_DLL =$(CFLAGS)
CFLAGS_DLL+= -bd
# we override the DECLSPEC define in begin_code.h, because we are using
# an exports file to remove the _cdecl '_' prefix from the symbol names
CFLAGS_DLL+= -DDECLSPEC=
CFLAGS_DLL+= -DSDL_BUILD_MAJOR_VERSION=$(MAJOR_VERSION)
CFLAGS_DLL+= -DSDL_BUILD_MINOR_VERSION=$(MINOR_VERSION)
CFLAGS_DLL+= -DSDL_BUILD_MICRO_VERSION=$(MICRO_VERSION)
RCFLAGS = -q -r -bt=nt $(INCPATH)
SRCS = SDL.c SDL_assert.c SDL_error.c SDL_guid.c SDL_log.c SDL_dataqueue.c SDL_hints.c SDL_list.c SDL_utils.c
SRCS+= SDL_getenv.c SDL_iconv.c SDL_malloc.c SDL_qsort.c SDL_stdlib.c SDL_string.c SDL_strtokr.c SDL_crc16.c SDL_crc32.c
SRCS+= SDL_cpuinfo.c SDL_atomic.c SDL_spinlock.c SDL_thread.c SDL_timer.c
SRCS+= SDL_rwops.c SDL_power.c
SRCS+= SDL_audio.c SDL_audiocvt.c SDL_audiodev.c SDL_audiotypecvt.c SDL_mixer.c SDL_wave.c
SRCS+= SDL_events.c SDL_quit.c SDL_keyboard.c SDL_mouse.c SDL_windowevents.c &
SDL_clipboardevents.c SDL_dropevents.c SDL_displayevents.c SDL_gesture.c &
SDL_sensor.c SDL_touch.c
SRCS+= SDL_haptic.c SDL_hidapi.c SDL_gamecontroller.c SDL_joystick.c controller_type.c
SRCS+= SDL_render.c yuv_rgb_sse.c yuv_rgb_std.c SDL_yuv.c SDL_yuv_sw.c SDL_blendfillrect.c &
SDL_blendline.c SDL_blendpoint.c SDL_drawline.c SDL_drawpoint.c &
SDL_render_sw.c SDL_rotate.c SDL_triangle.c
SRCS+= SDL_blit.c SDL_blit_0.c SDL_blit_1.c SDL_blit_A.c SDL_blit_auto.c &
SDL_blit_copy.c SDL_blit_N.c SDL_blit_slow.c SDL_fillrect.c SDL_bmp.c &
SDL_pixels.c SDL_rect.c SDL_RLEaccel.c SDL_shape.c SDL_stretch.c &
SDL_surface.c SDL_video.c SDL_clipboard.c SDL_vulkan_utils.c SDL_egl.c
SRCS+= SDL_syscond.c SDL_sysmutex.c SDL_syssem.c SDL_systhread.c SDL_systls.c
SRCS+= SDL_systimer.c
SRCS+= SDL_sysloadso.c
SRCS+= SDL_sysfilesystem.c
SRCS+= SDL_syshaptic.c SDL_sysjoystick.c SDL_virtualjoystick.c
SRCS+= SDL_hidapijoystick.c SDL_hidapi_rumble.c SDL_hidapi_combined.c SDL_hidapi_gamecube.c SDL_hidapi_luna.c SDL_hidapi_ps3.c SDL_hidapi_ps4.c SDL_hidapi_ps5.c SDL_hidapi_shield.c SDL_hidapi_stadia.c SDL_hidapi_switch.c SDL_hidapi_wii.c SDL_hidapi_xbox360.c SDL_hidapi_xbox360w.c SDL_hidapi_xboxone.c SDL_hidapi_steam.c SDL_hidapi_steamdeck.c
SRCS+= SDL_dummyaudio.c SDL_diskaudio.c
SRCS+= SDL_nullvideo.c SDL_nullframebuffer.c SDL_nullevents.c
SRCS+= SDL_dummysensor.c
SRCS+= SDL_locale.c SDL_syslocale.c
SRCS+= SDL_url.c SDL_sysurl.c
SRCS+= SDL_winmm.c SDL_directsound.c SDL_wasapi.c SDL_wasapi_win32.c
SRCS+= SDL_hid.c SDL_immdevice.c SDL_windows.c SDL_xinput.c
SRCS+= SDL_dinputhaptic.c SDL_windowshaptic.c SDL_xinputhaptic.c
SRCS+= SDL_dinputjoystick.c SDL_rawinputjoystick.c SDL_windowsjoystick.c SDL_windows_gaming_input.c SDL_xinputjoystick.c
SRCS+= SDL_syspower.c
SRCS+= SDL_d3dmath.c
SRCS+= SDL_render_d3d.c SDL_shaders_d3d.c
SRCS+= SDL_render_d3d11.c SDL_shaders_d3d11.c
SRCS+= SDL_render_d3d12.c SDL_shaders_d3d12.c
SRCS+= SDL_render_gl.c SDL_shaders_gl.c
SRCS+= SDL_render_gles2.c SDL_shaders_gles2.c
SRCS+= SDL_windowssensor.c
SRCS+= SDL_syscond_cv.c
SRCS+= SDL_windowsclipboard.c SDL_windowsevents.c SDL_windowsframebuffer.c SDL_windowskeyboard.c SDL_windowsmessagebox.c SDL_windowsmodes.c SDL_windowsmouse.c SDL_windowsopengl.c SDL_windowsopengles.c SDL_windowsshape.c SDL_windowsvideo.c SDL_windowsvulkan.c SDL_windowswindow.c SDL_steam_virtual_gamepad.c
SRCS+= SDL_dynapi.c
RCSRCS = version.rc
OBJS = $(SRCS:.c=.obj)
RCOBJS= $(RCSRCS:.rc=.res)
.extensions:
.extensions: .lib .dll .obj .res .c .rc .asm
.c: ./src;./src/dynapi;./src/audio;./src/cpuinfo;./src/events;./src/file;./src/haptic;./src/joystick;./src/power;./src/render;./src/render/software;./src/sensor;./src/stdlib;./src/thread;./src/timer;./src/video;./src/video/yuv2rgb;./src/atomic;./src/audio/disk;
.c: ./src/haptic/dummy;./src/joystick/dummy;./src/joystick/virtual;./src/audio/dummy;./src/video/dummy;./src/sensor/dummy;
.c: ./src/core/windows;./src/audio/winmm;./src/audio/directsound;./src/audio/wasapi;./src/loadso/windows;./src/filesystem/windows;./src/haptic/windows;./src/joystick/windows;./src/sensor/windows;./src/thread/windows;./src/timer/windows;./src/video/windows;
.c: ./src/locale/;./src/locale/windows;./src/misc;./src/misc/windows;./src/power/windows;./src/joystick/hidapi;./src/hidapi;./src/render/direct3d;./src/render/direct3d11;./src/render/direct3d12;./src/render/opengl;./src/render/opengles2
.rc: ./src/main/windows
all: $(DLLFILE) $(LIBFILE) $(TLIB) .symbolic
build_dll: .symbolic
@echo * Compiling dll objects
$(DLLFILE): build_dll $(OBJS) $(LIBM) $(RCOBJS) $(LNKFILE)
@echo * Linking: $@
wlink @$(LNKFILE)
$(LIBFILE): $(DLLFILE)
@echo * Creating LIB file: $@
wlib -q -b -n -c -pa -s -t -zld -ii -io $* @$(EXPFILE)
.c.obj:
wcc386 $(CFLAGS_DLL) -fo=$^@ $<
.rc.res:
wrc $(RCFLAGS) -fo=$^@ $<
SDL_syscond.obj: "src/thread/generic/SDL_syscond.c"
wcc386 $(CFLAGS_DLL) -fo=$^@ $<
SDL_cpuinfo.obj: SDL_cpuinfo.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_wave.obj: SDL_wave.c
wcc386 $(CFLAGS_DLL) -wcd=124 -fo=$^@ $<
SDL_blendfillrect.obj: SDL_blendfillrect.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_blendline.obj: SDL_blendline.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_blendpoint.obj: SDL_blendpoint.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_RLEaccel.obj: SDL_RLEaccel.c
wcc386 $(CFLAGS_DLL) -wcd=201 -fo=$^@ $<
SDL_malloc.obj: SDL_malloc.c
wcc386 $(CFLAGS_DLL) -wcd=201 -fo=$^@ $<
yuv_rgb_sse.obj: yuv_rgb_sse.c
wcc386 $(CFLAGS_DLL) -wcd=202 -fo=$^@ $<
# SDL2libm
MSRCS= e_atan2.c e_exp.c e_fmod.c e_log10.c e_log.c e_pow.c e_rem_pio2.c e_sqrt.c &
k_cos.c k_rem_pio2.c k_sin.c k_tan.c &
s_atan.c s_copysign.c s_cos.c s_fabs.c s_floor.c s_scalbn.c s_sin.c s_tan.c
MOBJS= $(MSRCS:.c=.obj)
.c: ./src/libm;
e_atan2.obj: e_atan2.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_exp.obj: e_exp.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_fmod.obj: e_fmod.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_log10.obj: e_log10.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_log.obj: e_log.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_pow.obj: e_pow.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_rem_pio2.obj: e_rem_pio2.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
e_sqrt.obj: e_sqrt.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
k_cos.obj: k_cos.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
k_rem_pio2.obj: k_rem_pio2.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
k_sin.obj: k_sin.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
k_tan.obj: k_tan.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_atan.obj: s_atan.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_copysign.obj: s_copysign.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_cos.obj: s_cos.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_fabs.obj: s_fabs.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_floor.obj: s_floor.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_scalbn.obj: s_scalbn.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_sin.obj: s_sin.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
s_tan.obj: s_tan.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
build_libm: .symbolic
@echo * Compiling libm objects
$(LIBM): build_libm $(MOBJS)
@echo * Creating: $@
wlib -q -b -n -c -pa -s -t -zld -ii -io $@ $(MOBJS)
# SDL2test
TSRCS = SDL_test_assert.c SDL_test_common.c SDL_test_compare.c &
SDL_test_crc32.c SDL_test_font.c SDL_test_fuzzer.c SDL_test_harness.c &
SDL_test_imageBlit.c SDL_test_imageBlitBlend.c SDL_test_imageFace.c &
SDL_test_imagePrimitives.c SDL_test_imagePrimitivesBlend.c &
SDL_test_log.c SDL_test_md5.c SDL_test_random.c SDL_test_memory.c
TOBJS= $(TSRCS:.c=.obj)
.c: ./src/test;
SDL_test_assert.obj: SDL_test_assert.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_common.obj: SDL_test_common.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_compare.obj: SDL_test_compare.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_crc32.obj: SDL_test_crc32.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_font.obj: SDL_test_font.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_fuzzer.obj: SDL_test_fuzzer.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_harness.obj: SDL_test_harness.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imageBlit.obj: SDL_test_imageBlit.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imageBlitBlend.obj: SDL_test_imageBlitBlend.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imageFace.obj: SDL_test_imageFace.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imagePrimitives.obj: SDL_test_imagePrimitives.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_imagePrimitivesBlend.obj: SDL_test_imagePrimitivesBlend.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_log.obj: SDL_test_log.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_md5.obj: SDL_test_md5.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_random.obj: SDL_test_random.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
SDL_test_memory.obj: SDL_test_memory.c
wcc386 $(CFLAGS_STATIC) -fo=$^@ $<
build_tlib: .symbolic
@echo * Compiling testlib objects
$(TLIB): build_tlib $(TOBJS)
@echo * Creating: $@
wlib -q -b -n -c -pa -s -t -zld -ii -io $@ $(TOBJS)
$(LNKFILE): Makefile.w32
@echo * Creating linker file: $@
@%create $@
@%append $@ SYSTEM nt_dll INITINSTANCE TERMINSTANCE
@%append $@ NAME $(DLLFILE)
@for %i in ($(OBJS)) do @%append $@ FILE %i
@for %i in ($(LIBS)) do @%append $@ LIB %i
@%append $@ OPTION RESOURCE=$(RCOBJS)
@%append $@ EXPORT=src/dynapi/SDL2.exports
@%append $@ OPTION QUIET
@%append $@ OPTION IMPF=$(EXPFILE)
@%append $@ OPTION MAP=$(LIBHOME)/$^&.map
@%append $@ OPTION ELIMINATE
@%append $@ OPTION SHOWDEAD
clean: .SYMBOLIC
@echo * Clean: $(LIBNAME)
@if exist *.obj rm *.obj
@if exist *.res rm *.res
@if exist *.err rm *.err
@if exist $(LNKFILE) rm $(LNKFILE)
@if exist $(LIBM) rm $(LIBM)
distclean: .SYMBOLIC clean
@if exist $(LIBHOME)/*.exp rm $(LIBHOME)/*.exp
@if exist $(LIBHOME)/*.map rm $(LIBHOME)/*.map
@if exist $(LIBFILE) rm $(LIBFILE)
@if exist $(DLLFILE) rm $(DLLFILE)
@if exist $(TLIB) rm $(TLIB)

13
third-party/SDL/README-SDL.txt generated vendored
View File

@ -1,13 +0,0 @@
Please distribute this file with the SDL runtime environment:
The Simple DirectMedia Layer (SDL for short) is a cross-platform library
designed to make it easy to write multi-media software, such as games
and emulators.
The Simple DirectMedia Layer library source code is available from:
https://www.libsdl.org/
This library is distributed under the terms of the zlib license:
http://www.zlib.net/zlib_license.html

16
third-party/SDL/README.md generated vendored
View File

@ -1,16 +1,16 @@
# Simple DirectMedia Layer (SDL) Version 2.0
Simple DirectMedia Layer (SDL for short) is a cross-platform library
designed to make it easy to write multi-media software, such as games
and emulators.
You can find the latest release and additional information at:
https://www.libsdl.org/
Simple DirectMedia Layer is a cross-platform development library designed
to provide low level access to audio, keyboard, mouse, joystick, and graphics
hardware via OpenGL and Direct3D. It is used by video playback software,
emulators, and popular games including Valve's award winning catalog
and many Humble Bundle games.
Installation instructions and a quick introduction is available in
[INSTALL.md](INSTALL.md)
More extensive documentation is available in the docs directory, starting
with README.md
This library is distributed under the terms of the zlib license,
available in [LICENSE.txt](LICENSE.txt).
Enjoy!

119
third-party/SDL/SDL2.spec.in generated vendored
View File

@ -1,119 +0,0 @@
Summary: Simple DirectMedia Layer
Name: SDL2
Version: @SDL_VERSION@
Release: 2
Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz
URL: http://www.libsdl.org/
License: zlib
Group: System Environment/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
Prefix: %{_prefix}
%ifos linux
Provides: libSDL2-2.0.so.0
%endif
%define __defattr %defattr(-,root,root)
%define __soext so
%description
This is the Simple DirectMedia Layer, a generic API that provides low
level access to audio, keyboard, mouse, and display framebuffer across
multiple platforms.
%package devel
Summary: Libraries, includes and more to develop SDL applications.
Group: Development/Libraries
Requires: %{name} = %{version}
%description devel
This is the Simple DirectMedia Layer, a generic API that provides low
level access to audio, keyboard, mouse, and display framebuffer across
multiple platforms.
This is the libraries, include files and other resources you can use
to develop SDL applications.
%prep
%setup -q
%build
%ifos linux
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} --disable-video-directfb
%else
%configure
%endif
make
%install
rm -rf $RPM_BUILD_ROOT
%ifos linux
make install prefix=$RPM_BUILD_ROOT%{prefix} \
bindir=$RPM_BUILD_ROOT%{_bindir} \
libdir=$RPM_BUILD_ROOT%{_libdir} \
includedir=$RPM_BUILD_ROOT%{_includedir} \
datadir=$RPM_BUILD_ROOT%{_datadir} \
mandir=$RPM_BUILD_ROOT%{_mandir}
%else
%makeinstall
%endif
%clean
rm -rf $RPM_BUILD_ROOT
%files
%{__defattr}
%doc README*.txt LICENSE.txt CREDITS.txt BUGS.txt
%{_libdir}/lib*.%{__soext}.*
%files devel
%{__defattr}
%doc docs/README*.md
%{_bindir}/*-config
%{_libdir}/lib*.a
%{_libdir}/lib*.la
%{_libdir}/lib*.%{__soext}
%{_includedir}/*/*.h
%{_libdir}/cmake/*
%{_libdir}/pkgconfig/SDL2/*
%{_datadir}/aclocal/*
%changelog
* Thu Jun 04 2015 Ryan C. Gordon <icculus@icculus.org>
- Fixed README paths.
* Sun Dec 07 2014 Simone Contini <s.contini@oltrelinux.com>
- Fixed changelog date issue and docs filenames
* Sun Jan 22 2012 Sam Lantinga <slouken@libsdl.org>
- Updated for SDL 2.0
* Tue May 16 2006 Sam Lantinga <slouken@libsdl.org>
- Removed support for Darwin, due to build problems on ps2linux
* Sat Jan 03 2004 Anders Bjorklund <afb@algonet.se>
- Added support for Darwin, updated spec file
* Wed Jan 19 2000 Sam Lantinga <slouken@libsdl.org>
- Re-integrated spec file into SDL distribution
- 'name' and 'version' come from configure
- Some of the documentation is devel specific
- Removed SMP support from %build - it doesn't work with libtool anyway
* Tue Jan 18 2000 Hakan Tandogan <hakan@iconsult.com>
- Hacked Mandrake sdl spec to build 1.1
* Sun Dec 19 1999 John Buswell <johnb@mandrakesoft.com>
- Build Release
* Sat Dec 18 1999 John Buswell <johnb@mandrakesoft.com>
- Add symlink for libSDL-1.0.so.0 required by sdlbomber
- Added docs
* Thu Dec 09 1999 Lenny Cartier <lenny@mandrakesoft.com>
- v 1.0.0
* Mon Nov 1 1999 Chmouel Boudjnah <chmouel@mandrakesoft.com>
- First spec file for Mandrake distribution.
# end of file

77
third-party/SDL/SDL2Config.cmake.in generated vendored
View File

@ -1,77 +0,0 @@
# sdl2 cmake project-config input for CMakeLists.txt script
include(FeatureSummary)
set_package_properties(SDL2 PROPERTIES
URL "https://www.libsdl.org/"
DESCRIPTION "low level access to audio, keyboard, mouse, joystick, and graphics hardware"
)
@PACKAGE_INIT@
set(SDL2_FOUND TRUE)
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2Targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/SDL2Targets.cmake")
set(SDL2_SDL2_FOUND TRUE)
endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2staticTargets.cmake")
if(ANDROID)
enable_language(CXX)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/SDL2staticTargets.cmake")
set(SDL2_SDL2-static_FOUND TRUE)
endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2mainTargets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/SDL2mainTargets.cmake")
set(SDL2_SDL2main_FOUND TRUE)
endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2testTargets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/SDL2testTargets.cmake")
set(SDL2_SDL2test_FOUND TRUE)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
set(SDL_ALSA @SDL_ALSA@)
set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
sdlFindALSA()
endif()
unset(SDL_ALSA)
unset(SDL_ALSA_SHARED)
check_required_components(SDL2)
# Create SDL2::SDL2 alias for static-only builds
if(TARGET SDL2::SDL2-static AND NOT TARGET SDL2::SDL2)
if(CMAKE_VERSION VERSION_LESS "3.18")
# FIXME: Aliasing local targets is not supported on CMake < 3.18, so make it global.
add_library(SDL2::SDL2 INTERFACE IMPORTED)
set_target_properties(SDL2::SDL2 PROPERTIES INTERFACE_LINK_LIBRARIES "SDL2::SDL2-static")
else()
add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static)
endif()
endif()
# For compatibility with autotools sdl2-config.cmake, provide SDL2_* variables.
set(SDL2_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@")
set(SDL2_EXEC_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@")
set(SDL2_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@/SDL2")
set(SDL2_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@;@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@/SDL2")
set(SDL2_BINDIR "@PACKAGE_CMAKE_INSTALL_FULL_BINDIR@")
set(SDL2_LIBDIR "@PACKAGE_CMAKE_INSTALL_FULL_LIBDIR@")
set(SDL2_LIBRARIES SDL2::SDL2)
set(SDL2_STATIC_LIBRARIES SDL2::SDL2-static)
set(SDL2_STATIC_PRIVATE_LIBS)
set(SDL2MAIN_LIBRARY)
if(TARGET SDL2::SDL2main)
set(SDL2MAIN_LIBRARY SDL2::SDL2main)
list(INSERT SDL2_LIBRARIES 0 SDL2::SDL2main)
list(INSERT SDL2_STATIC_LIBRARIES 0 SDL2::SDL2main)
endif()
set(SDL2TEST_LIBRARY SDL2::SDL2test)

10
third-party/SDL/TODO.txt generated vendored
View File

@ -1,10 +0,0 @@
Future work roadmap:
* http://wiki.libsdl.org/Roadmap
* Check 1.2 revisions:
3554 - Need to resolve semantics for locking keys on different platforms
4874 - Do we want screen rotation? At what level?
4974 - Windows file code needs to convert UTF-8 to Unicode, but we don't need to tap dance for Windows 95/98
4865 - See if this is still needed (mouse coordinate clamping)
4866 - See if this is still needed (blocking window repositioning)

25
third-party/SDL/VisualC-GDK/SDL.sln generated vendored
View File

@ -4,15 +4,16 @@ VisualStudioVersion = 17.1.32414.318
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D69D5741-611F-4E14-8541-1FEE94F50B5A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2", "SDL\SDL.vcxproj", "{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL3", "SDL\SDL.vcxproj", "{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2main", "SDLmain\SDLmain.vcxproj", "{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsprite", "tests\testsprite\testsprite.vcxproj", "{40FB7794-D3C3-4CFE-BCF4-A80C96635682}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsprite2", "tests\testsprite2\testsprite2.vcxproj", "{40FB7794-D3C3-4CFE-BCF4-A80C96635682}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL3_test", "SDL_test\SDL_test.vcxproj", "{DA956FD3-E143-46F2-9FE5-C77BEBC56B1A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2test", "SDLtest\SDLtest.vcxproj", "{DA956FD3-E143-46F2-9FE5-C77BEBC56B1A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgamecontroller", "tests\testgamecontroller\testgamecontroller.vcxproj", "{55812185-D13C-4022-9C81-32E0F4A08305}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testcontroller", "tests\testcontroller\testcontroller.vcxproj", "{55812185-D13C-4022-9C81-32E0F4A08305}"
ProjectSection(ProjectDependencies) = postProject
{DA956FD3-E143-46F2-9FE5-C77BEBC56B1A} = {DA956FD3-E143-46F2-9FE5-C77BEBC56B1A}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgdk", "tests\testgdk\testgdk.vcxproj", "{1C9A3F71-35A5-4C56-B292-F4375B3C3649}"
EndProject
@ -38,18 +39,6 @@ Global
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.Scarlett.x64.Build.0 = Release|Gaming.Xbox.Scarlett.x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.XboxOne.x64.ActiveCfg = Release|Gaming.Xbox.XboxOne.x64
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.XboxOne.x64.Build.0 = Release|Gaming.Xbox.XboxOne.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|Gaming.Desktop.x64.ActiveCfg = Debug|Gaming.Desktop.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|Gaming.Desktop.x64.Build.0 = Debug|Gaming.Desktop.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|Gaming.Xbox.Scarlett.x64.ActiveCfg = Debug|Gaming.Xbox.Scarlett.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|Gaming.Xbox.Scarlett.x64.Build.0 = Debug|Gaming.Xbox.Scarlett.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|Gaming.Xbox.XboxOne.x64.ActiveCfg = Debug|Gaming.Xbox.XboxOne.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|Gaming.Xbox.XboxOne.x64.Build.0 = Debug|Gaming.Xbox.XboxOne.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|Gaming.Desktop.x64.ActiveCfg = Release|Gaming.Desktop.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|Gaming.Desktop.x64.Build.0 = Release|Gaming.Desktop.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|Gaming.Xbox.Scarlett.x64.ActiveCfg = Release|Gaming.Xbox.Scarlett.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|Gaming.Xbox.Scarlett.x64.Build.0 = Release|Gaming.Xbox.Scarlett.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|Gaming.Xbox.XboxOne.x64.ActiveCfg = Release|Gaming.Xbox.XboxOne.x64
{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|Gaming.Xbox.XboxOne.x64.Build.0 = Release|Gaming.Xbox.XboxOne.x64
{40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Debug|Gaming.Desktop.x64.ActiveCfg = Debug|Gaming.Desktop.x64
{40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Debug|Gaming.Desktop.x64.Build.0 = Debug|Gaming.Desktop.x64
{40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Debug|Gaming.Desktop.x64.Deploy.0 = Debug|Gaming.Desktop.x64

Some files were not shown because too many files have changed in this diff Show More