diff --git a/MarathonRecomp/CMakeLists.txt b/MarathonRecomp/CMakeLists.txt index fd622cee7..6331c9023 100644 --- a/MarathonRecomp/CMakeLists.txt +++ b/MarathonRecomp/CMakeLists.txt @@ -127,7 +127,7 @@ set(MARATHON_RECOMP_APU_CXX_SOURCES "apu/audio.cpp" "apu/xma_decoder.cpp" "apu/embedded_player.cpp" - "apu/driver/sdl2_driver.cpp" + "apu/driver/sdl3_driver.cpp" ) set(MARATHON_RECOMP_HID_CXX_SOURCES @@ -200,7 +200,7 @@ set(MARATHON_RECOMP_UTILS_CXX_SOURCES ) set(MARATHON_RECOMP_THIRDPARTY_SOURCES - "${MARATHON_RECOMP_THIRDPARTY_ROOT}/imgui/backends/imgui_impl_sdl2.cpp" + "${MARATHON_RECOMP_THIRDPARTY_ROOT}/imgui/backends/imgui_impl_sdl3.cpp" "${MARATHON_RECOMP_THIRDPARTY_ROOT}/imgui/imgui.cpp" "${MARATHON_RECOMP_THIRDPARTY_ROOT}/imgui/imgui_demo.cpp" "${MARATHON_RECOMP_THIRDPARTY_ROOT}/imgui/imgui_draw.cpp" @@ -410,8 +410,8 @@ target_link_libraries(MarathonRecomp PRIVATE nfd::nfd o1heap XenonUtils - SDL2::SDL2-static - SDL2_mixer + SDL3::SDL3-static + SDL3_mixer::SDL3_mixer tomlplusplus::tomlplusplus MarathonRecompLib xxHash::xxhash diff --git a/MarathonRecomp/app.cpp b/MarathonRecomp/app.cpp index 4c08a7efa..344286d7b 100644 --- a/MarathonRecomp/app.cpp +++ b/MarathonRecomp/app.cpp @@ -89,7 +89,7 @@ PPC_FUNC(sub_825EA610) if (std::this_thread::get_id() == g_mainThreadId) { SDL_PumpEvents(); - SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); + SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); GameWindow::Update(); } diff --git a/MarathonRecomp/apu/driver/sdl2_driver.cpp b/MarathonRecomp/apu/driver/sdl3_driver.cpp similarity index 77% rename from MarathonRecomp/apu/driver/sdl2_driver.cpp rename to MarathonRecomp/apu/driver/sdl3_driver.cpp index a2615f44f..4733ddc93 100644 --- a/MarathonRecomp/apu/driver/sdl2_driver.cpp +++ b/MarathonRecomp/apu/driver/sdl3_driver.cpp @@ -7,47 +7,46 @@ static PPCFunc* g_clientCallback{}; static uint32_t g_clientCallbackParam{}; // pointer in guest memory -static SDL_AudioDeviceID g_audioDevice{}; +static SDL_AudioStream* g_audioStream{}; static bool g_downMixToStereo; static void CreateAudioDevice() { - if (g_audioDevice != NULL) - SDL_CloseAudioDevice(g_audioDevice); + if (g_audioStream != nullptr) + { + SDL_DestroyAudioStream(g_audioStream); + g_audioStream = nullptr; + } bool surround = Config::ChannelConfiguration == EChannelConfiguration::Surround; - int allowedChanges = surround ? SDL_AUDIO_ALLOW_CHANNELS_CHANGE : 0; - SDL_AudioSpec desired{}, obtained{}; + SDL_AudioSpec deviceSpec{}; + if (surround && SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &deviceSpec, nullptr)) + surround = deviceSpec.channels >= XAUDIO_NUM_CHANNELS; + + SDL_AudioSpec desired{}; desired.freq = XAUDIO_SAMPLES_HZ; - desired.format = AUDIO_F32SYS; + desired.format = SDL_AUDIO_F32; desired.channels = surround ? XAUDIO_NUM_CHANNELS : 2; - desired.samples = XAUDIO_NUM_SAMPLES; - g_audioDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &obtained, allowedChanges); - - if (obtained.channels != 2 && obtained.channels != XAUDIO_NUM_CHANNELS) // This check may fail only when surround sound is enabled. - { - SDL_CloseAudioDevice(g_audioDevice); - g_audioDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &obtained, 0); - } + g_audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &desired, nullptr, nullptr); - if (!g_audioDevice) + if (!g_audioStream) LOGFN_ERROR("Failed to open audio device: {}", SDL_GetError()); - g_downMixToStereo = (obtained.channels == 2); + g_downMixToStereo = (desired.channels == 2); } void XAudioInitializeSystem() { #ifdef _WIN32 // Force wasapi on Windows. - SDL_setenv("SDL_AUDIODRIVER", "wasapi", true); + SDL_SetHint(SDL_HINT_AUDIO_DRIVER, "wasapi"); #endif SDL_SetHint(SDL_HINT_AUDIO_CATEGORY, "playback"); - SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, "Marathon Recompiled"); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, "Marathon Recompiled"); - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) + if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) { LOGFN_ERROR("Failed to init audio subsystem: {}", SDL_GetError()); return; @@ -69,11 +68,11 @@ static void AudioThread() while (!g_audioThreadShouldExit) { - uint32_t queuedAudioSize = SDL_GetQueuedAudioSize(g_audioDevice); + int queuedAudioSize = SDL_GetAudioStreamQueued(g_audioStream); constexpr size_t MAX_LATENCY = 10; const size_t callbackAudioSize = channels * XAUDIO_NUM_SAMPLES * sizeof(float); - if ((queuedAudioSize / callbackAudioSize) <= MAX_LATENCY) + if (queuedAudioSize >= 0 && (queuedAudioSize / callbackAudioSize) <= MAX_LATENCY) { ctx.ppcContext.r3.u32 = g_clientCallbackParam; g_clientCallback(ctx.ppcContext, g_memory.base); @@ -92,7 +91,7 @@ static void AudioThread() static void CreateAudioThread() { - SDL_PauseAudioDevice(g_audioDevice, 0); + SDL_ResumeAudioStreamDevice(g_audioStream); g_audioThreadShouldExit = false; g_audioThread = std::make_unique(AudioThread); } @@ -143,7 +142,7 @@ void XAudioSubmitFrame(void* samples) audioFrames[i * 2 + 1] = isnan(samp1) ? 0.0f : samp1; } - SDL_QueueAudio(g_audioDevice, &audioFrames, sizeof(audioFrames)); + SDL_PutAudioStreamData(g_audioStream, &audioFrames, sizeof(audioFrames)); } else { @@ -158,7 +157,7 @@ void XAudioSubmitFrame(void* samples) } } - SDL_QueueAudio(g_audioDevice, &audioFrames, sizeof(audioFrames)); + SDL_PutAudioStreamData(g_audioStream, &audioFrames, sizeof(audioFrames)); } } diff --git a/MarathonRecomp/apu/embedded_player.cpp b/MarathonRecomp/apu/embedded_player.cpp index cd1ad0a0e..842b7b262 100644 --- a/MarathonRecomp/apu/embedded_player.cpp +++ b/MarathonRecomp/apu/embedded_player.cpp @@ -25,9 +25,14 @@ enum class EmbeddedSound struct EmbeddedSoundData { - Mix_Chunk* chunk{}; + MIX_Audio* audio{}; }; +static constexpr size_t EMBEDDED_TRACK_COUNT = 8; + +static MIX_Mixer* g_mixer; +static std::array g_tracks = {}; + static std::array g_embeddedSoundData = {}; static const std::unordered_map g_embeddedSoundMap = { @@ -40,12 +45,12 @@ static const std::unordered_map g_embeddedSound { "cannot_deside", EmbeddedSound::CannotDeside }, }; -static size_t g_channelIndex; +static size_t g_trackIndex; static void PlayEmbeddedSound(EmbeddedSound s) { EmbeddedSoundData &data = g_embeddedSoundData[size_t(s)]; - if (data.chunk == nullptr) + if (data.audio == nullptr) { // The sound hasn't been created yet, create it and pick it. const void *soundData = nullptr; @@ -85,25 +90,41 @@ static void PlayEmbeddedSound(EmbeddedSound s) return; } - data.chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(soundData, soundDataSize), 1); + data.audio = MIX_LoadAudio_IO(g_mixer, SDL_IOFromConstMem(soundData, soundDataSize), true, true); } - - Mix_VolumeChunk(data.chunk, (Config::MasterVolume * Config::EffectsVolume * EmbeddedPlayer::EFFECTS_VOLUME) * MIX_MAX_VOLUME); - Mix_PlayChannel(g_channelIndex % MIX_CHANNELS, data.chunk, 0); - ++g_channelIndex; + + MIX_Track *track = g_tracks[g_trackIndex % EMBEDDED_TRACK_COUNT]; + ++g_trackIndex; + + MIX_SetTrackGain(track, Config::MasterVolume * Config::EffectsVolume * EmbeddedPlayer::EFFECTS_VOLUME); + MIX_SetTrackAudio(track, data.audio); + MIX_PlayTrack(track, 0); } -static Mix_Music* g_installerMusic; +static MIX_Audio* g_installerMusic; +static MIX_Track* g_musicTrack; -void EmbeddedPlayer::Init() +void EmbeddedPlayer::Init() { - Mix_OpenAudio(XAUDIO_SAMPLES_HZ, AUDIO_F32SYS, 2, 4096); - g_installerMusic = Mix_LoadMUS_RW(SDL_RWFromConstMem(g_installer_music, sizeof(g_installer_music)), 1); + MIX_Init(); + + SDL_AudioSpec spec{}; + spec.freq = XAUDIO_SAMPLES_HZ; + spec.format = SDL_AUDIO_F32; + spec.channels = 2; + g_mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec); + + for (MIX_Track *&track : g_tracks) + track = MIX_CreateTrack(g_mixer); + + g_installerMusic = MIX_LoadAudio_IO(g_mixer, SDL_IOFromConstMem(g_installer_music, sizeof(g_installer_music)), false, true); + g_musicTrack = MIX_CreateTrack(g_mixer); + MIX_SetTrackAudio(g_musicTrack, g_installerMusic); s_isActive = true; } -void EmbeddedPlayer::Play(const char *name) +void EmbeddedPlayer::Play(const char *name) { assert(s_isActive && "Playback shouldn't be requested if the Embedded Player isn't active."); @@ -118,32 +139,37 @@ void EmbeddedPlayer::Play(const char *name) void EmbeddedPlayer::PlayMusic() { - if (!Mix_PlayingMusic()) + if (!MIX_TrackPlaying(g_musicTrack)) { - Mix_PlayMusic(g_installerMusic, INT_MAX); - Mix_VolumeMusic(Config::MasterVolume * Config::MusicVolume * MUSIC_VOLUME * MIX_MAX_VOLUME); + SDL_PropertiesID options = SDL_CreateProperties(); + SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOPS_NUMBER, -1); + + MIX_SetTrackGain(g_musicTrack, Config::MasterVolume * Config::MusicVolume * MUSIC_VOLUME); + MIX_PlayTrack(g_musicTrack, options); + + SDL_DestroyProperties(options); } } void EmbeddedPlayer::FadeOutMusic() { - if (Mix_PlayingMusic()) - Mix_FadeOutMusic(1000); + if (MIX_TrackPlaying(g_musicTrack)) + MIX_StopTrack(g_musicTrack, MIX_TrackMSToFrames(g_musicTrack, 1000)); } -void EmbeddedPlayer::Shutdown() +void EmbeddedPlayer::Shutdown() { + MIX_DestroyMixer(g_mixer); + for (EmbeddedSoundData &data : g_embeddedSoundData) { - if (data.chunk != nullptr) - Mix_FreeChunk(data.chunk); + if (data.audio != nullptr) + MIX_DestroyAudio(data.audio); } - Mix_HaltMusic(); - Mix_FreeMusic(g_installerMusic); + MIX_DestroyAudio(g_installerMusic); - Mix_CloseAudio(); - Mix_Quit(); + MIX_Quit(); s_isActive = false; } diff --git a/MarathonRecomp/gpu/video.cpp b/MarathonRecomp/gpu/video.cpp index 3a4393d1f..20f2382a7 100644 --- a/MarathonRecomp/gpu/video.cpp +++ b/MarathonRecomp/gpu/video.cpp @@ -1590,7 +1590,7 @@ static void CreateImGuiBackend() OptionsMenu::Init(); InstallerWizard::Init(); - ImGui_ImplSDL2_InitForOther(GameWindow::s_pWindow); + ImGui_ImplSDL3_InitForOther(GameWindow::s_pWindow); #ifdef ENABLE_IM_FONT_ATLAS_SNAPSHOT g_imFontTexture = LoadTexture( @@ -2872,7 +2872,7 @@ static void DrawFPS() static void DrawImGui() { - ImGui_ImplSDL2_NewFrame(); + ImGui_ImplSDL3_NewFrame(); auto& io = ImGui::GetIO(); io.DisplaySize = { float(Video::s_viewportWidth), float(Video::s_viewportHeight) }; diff --git a/MarathonRecomp/hid/driver/sdl_hid.cpp b/MarathonRecomp/hid/driver/sdl_hid.cpp index 2e6b5521a..0a8dd97ba 100644 --- a/MarathonRecomp/hid/driver/sdl_hid.cpp +++ b/MarathonRecomp/hid/driver/sdl_hid.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -7,50 +7,44 @@ #include #include -#define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X) +#define TRANSLATE_INPUT(S, X) SDL_GetGamepadButton(controller, S) << FirstBitLow(X) #define VIBRATION_TIMEOUT_MS 5000 class Controller { public: - SDL_GameController* controller{}; + SDL_Gamepad* controller{}; SDL_Joystick* joystick{}; - SDL_JoystickID id{ -1 }; + SDL_JoystickID id{}; XAMINPUT_GAMEPAD state{}; XAMINPUT_VIBRATION vibration{ 0, 0 }; - int index{}; Controller() = default; - explicit Controller(int index) : Controller(SDL_GameControllerOpen(index)) - { - this->index = index; - } - - Controller(SDL_GameController* controller) : controller(controller) + Controller(SDL_Gamepad* controller) : controller(controller) { if (!controller) return; - joystick = SDL_GameControllerGetJoystick(controller); - id = SDL_JoystickInstanceID(joystick); + joystick = SDL_GetGamepadJoystick(controller); + id = SDL_GetJoystickID(joystick); } - SDL_GameControllerType GetControllerType() const + SDL_GamepadType GetControllerType() const { - return SDL_GameControllerGetType(controller); + return SDL_GetGamepadType(controller); } hid::EInputDevice GetInputDevice() const { switch (GetControllerType()) { - case SDL_CONTROLLER_TYPE_PS3: - case SDL_CONTROLLER_TYPE_PS4: - case SDL_CONTROLLER_TYPE_PS5: + case SDL_GAMEPAD_TYPE_PS3: + case SDL_GAMEPAD_TYPE_PS4: + case SDL_GAMEPAD_TYPE_PS5: return hid::EInputDevice::PlayStation; - case SDL_CONTROLLER_TYPE_XBOX360: - case SDL_CONTROLLER_TYPE_XBOXONE: + case SDL_GAMEPAD_TYPE_XBOX360: + case SDL_GAMEPAD_TYPE_XBOXONE: return hid::EInputDevice::Xbox; default: return hid::EInputDevice::Unknown; @@ -59,7 +53,7 @@ class Controller const char* GetControllerName() const { - auto result = SDL_GameControllerName(controller); + auto result = SDL_GetGamepadName(controller); if (!result) return "Unknown Device"; @@ -72,11 +66,11 @@ class Controller if (!controller) return; - SDL_GameControllerClose(controller); + SDL_CloseGamepad(controller); controller = nullptr; joystick = nullptr; - id = -1; + id = 0; } bool CanPoll() @@ -91,14 +85,14 @@ class Controller auto& pad = state; - pad.sThumbLX = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); - pad.sThumbLY = ~SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); + pad.sThumbLX = SDL_GetGamepadAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); + pad.sThumbLY = ~SDL_GetGamepadAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); - pad.sThumbRX = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); - pad.sThumbRY = ~SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); + pad.sThumbRX = SDL_GetGamepadAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); + pad.sThumbRY = ~SDL_GetGamepadAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); - pad.bLeftTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) >> 7; - pad.bRightTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7; + pad.bLeftTrigger = SDL_GetGamepadAxis(controller, SDL_GAMEPAD_AXIS_LEFT_TRIGGER) >> 7; + pad.bRightTrigger = SDL_GetGamepadAxis(controller, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) >> 7; } void Poll() @@ -110,25 +104,25 @@ class Controller pad.wButtons = 0; - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_UP, XAMINPUT_GAMEPAD_DPAD_UP); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_DOWN, XAMINPUT_GAMEPAD_DPAD_DOWN); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_LEFT, XAMINPUT_GAMEPAD_DPAD_LEFT); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_RIGHT, XAMINPUT_GAMEPAD_DPAD_RIGHT); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_DPAD_UP, XAMINPUT_GAMEPAD_DPAD_UP); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_DPAD_DOWN, XAMINPUT_GAMEPAD_DPAD_DOWN); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_DPAD_LEFT, XAMINPUT_GAMEPAD_DPAD_LEFT); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_DPAD_RIGHT, XAMINPUT_GAMEPAD_DPAD_RIGHT); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_START, XAMINPUT_GAMEPAD_START); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_BACK, XAMINPUT_GAMEPAD_BACK); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_TOUCHPAD, XAMINPUT_GAMEPAD_BACK); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_START, XAMINPUT_GAMEPAD_START); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_BACK, XAMINPUT_GAMEPAD_BACK); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_TOUCHPAD, XAMINPUT_GAMEPAD_BACK); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_LEFTSTICK, XAMINPUT_GAMEPAD_LEFT_THUMB); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_RIGHTSTICK, XAMINPUT_GAMEPAD_RIGHT_THUMB); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_LEFT_STICK, XAMINPUT_GAMEPAD_LEFT_THUMB); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_RIGHT_STICK, XAMINPUT_GAMEPAD_RIGHT_THUMB); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_LEFTSHOULDER, XAMINPUT_GAMEPAD_LEFT_SHOULDER); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, XAMINPUT_GAMEPAD_RIGHT_SHOULDER); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, XAMINPUT_GAMEPAD_LEFT_SHOULDER); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, XAMINPUT_GAMEPAD_RIGHT_SHOULDER); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_A, XAMINPUT_GAMEPAD_A); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_B, XAMINPUT_GAMEPAD_B); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_X, XAMINPUT_GAMEPAD_X); - pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_Y, XAMINPUT_GAMEPAD_Y); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_SOUTH, XAMINPUT_GAMEPAD_A); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_EAST, XAMINPUT_GAMEPAD_B); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_WEST, XAMINPUT_GAMEPAD_X); + pad.wButtons |= TRANSLATE_INPUT(SDL_GAMEPAD_BUTTON_NORTH, XAMINPUT_GAMEPAD_Y); } void SetVibration(const XAMINPUT_VIBRATION& vibration) @@ -138,12 +132,12 @@ class Controller this->vibration = vibration; - SDL_GameControllerRumble(controller, vibration.wLeftMotorSpeed * 256, vibration.wRightMotorSpeed * 256, VIBRATION_TIMEOUT_MS); + SDL_RumbleGamepad(controller, vibration.wLeftMotorSpeed * 256, vibration.wRightMotorSpeed * 256, VIBRATION_TIMEOUT_MS); } void SetLED(const uint8_t r, const uint8_t g, const uint8_t b) const { - SDL_GameControllerSetLED(controller, r, g, b); + SDL_SetGamepadLED(controller, r, g, b); } }; @@ -169,7 +163,7 @@ inline size_t FindFreeController() return -1; } -inline Controller* FindController(int which) +inline Controller* FindController(SDL_JoystickID which) { for (auto& controller : g_controllers) { @@ -241,17 +235,17 @@ static void SetControllerTimeOfDayLED(Controller& controller, EPlayerCharacter p controller.SetLED(r, g, b); } -int HID_OnSDLEvent(void*, SDL_Event* event) +bool HID_OnSDLEvent(void*, SDL_Event* event) { switch (event->type) { - case SDL_CONTROLLERDEVICEADDED: + case SDL_EVENT_GAMEPAD_ADDED: { const auto freeIndex = FindFreeController(); if (freeIndex != -1) { - auto controller = Controller(event->cdevice.which); + auto controller = Controller(SDL_OpenGamepad(event->gdevice.which)); g_controllers[freeIndex] = controller; @@ -261,9 +255,9 @@ int HID_OnSDLEvent(void*, SDL_Event* event) break; } - case SDL_CONTROLLERDEVICEREMOVED: + case SDL_EVENT_GAMEPAD_REMOVED: { - auto* controller = FindController(event->cdevice.which); + auto* controller = FindController(event->gdevice.which); if (controller) controller->Close(); @@ -271,21 +265,21 @@ int HID_OnSDLEvent(void*, SDL_Event* event) break; } - case SDL_CONTROLLERBUTTONDOWN: - case SDL_CONTROLLERBUTTONUP: - case SDL_CONTROLLERAXISMOTION: - case SDL_CONTROLLERTOUCHPADDOWN: + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: { - auto* controller = FindController(event->cdevice.which); + auto* controller = FindController(event->gdevice.which); if (!controller) break; - if (event->type == SDL_CONTROLLERAXISMOTION) + if (event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION) { - if (abs(event->caxis.value) > 8000) + if (abs(event->gaxis.value) > 8000) { - SDL_ShowCursor(SDL_DISABLE); + SDL_HideCursor(); SetControllerInputDevice(controller); } @@ -293,7 +287,7 @@ int HID_OnSDLEvent(void*, SDL_Event* event) } else { - SDL_ShowCursor(SDL_DISABLE); + SDL_HideCursor(); SetControllerInputDevice(controller); controller->Poll(); @@ -302,36 +296,33 @@ int HID_OnSDLEvent(void*, SDL_Event* event) break; } - case SDL_KEYDOWN: - case SDL_KEYUP: + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: hid::g_inputDevice = hid::EInputDevice::Keyboard; break; - case SDL_MOUSEMOTION: - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: + case SDL_EVENT_MOUSE_MOTION: + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: { if (!GameWindow::IsFullscreen() || GameWindow::s_isFullscreenCursorVisible) - SDL_ShowCursor(SDL_ENABLE); + SDL_ShowCursor(); hid::g_inputDevice = hid::EInputDevice::Mouse; break; } - case SDL_WINDOWEVENT: + case SDL_EVENT_WINDOW_FOCUS_LOST: { - if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) - { - // Stop vibrating controllers on focus lost. - for (auto& controller : g_controllers) - controller.SetVibration({ 0, 0 }); - } + // Stop vibrating controllers on focus lost. + for (auto& controller : g_controllers) + controller.SetVibration({ 0, 0 }); break; } - case SDL_USER_PLAYER_CHAR: + case SDL_EVENT_USER_PLAYER_CHAR: { for (auto& controller : g_controllers) SetControllerTimeOfDayLED(controller, static_cast(event->user.code)); @@ -340,7 +331,7 @@ int HID_OnSDLEvent(void*, SDL_Event* event) } } - return 0; + return true; } void hid::Init() @@ -349,24 +340,20 @@ void hid::Init() SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS3, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, "1"); SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1"); - - SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); // Uses Button Labels. This hint is disabled for Nintendo Controllers. SDL_InitSubSystem(SDL_INIT_EVENTS); SDL_AddEventWatch(HID_OnSDLEvent, nullptr); - SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); + SDL_InitSubSystem(SDL_INIT_GAMEPAD); // Load controller mappings from SDL_GameControllerDB - if (int mappings = SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt"); mappings > 0) { + if (int mappings = SDL_AddGamepadMappingsFromFile("gamecontrollerdb.txt"); mappings > 0) { LOGFN("Loaded {} controller mapping(s) from SDL_GameControllerDB ({})", mappings, "gamecontrollerdb.txt"); } } diff --git a/MarathonRecomp/kernel/xam.cpp b/MarathonRecomp/kernel/xam.cpp index 8e13a58ec..a6b0b7117 100644 --- a/MarathonRecomp/kernel/xam.cpp +++ b/MarathonRecomp/kernel/xam.cpp @@ -10,7 +10,7 @@ #include #include "xxHashMap.h" #include -#include +#include struct XamListener : KernelObject { diff --git a/MarathonRecomp/patches/frontend_listener.cpp b/MarathonRecomp/patches/frontend_listener.cpp index 58c22ea70..6a668a4b8 100644 --- a/MarathonRecomp/patches/frontend_listener.cpp +++ b/MarathonRecomp/patches/frontend_listener.cpp @@ -16,9 +16,9 @@ static class FrontendListener : public SDLEventListener switch (event->type) { - case SDL_KEYDOWN: + case SDL_EVENT_KEY_DOWN: { - if (event->key.keysym.sym != SDLK_F8 || m_isF8KeyDown) + if (event->key.key != SDLK_F8 || m_isF8KeyDown) break; // TODO @@ -28,8 +28,8 @@ static class FrontendListener : public SDLEventListener break; } - case SDL_KEYUP: - m_isF8KeyDown = event->key.keysym.sym != SDLK_F8; + case SDL_EVENT_KEY_UP: + m_isF8KeyDown = event->key.key != SDLK_F8; break; } diff --git a/MarathonRecomp/sdl_events.h b/MarathonRecomp/sdl_events.h index 05044bc4d..fd9d9ab2b 100644 --- a/MarathonRecomp/sdl_events.h +++ b/MarathonRecomp/sdl_events.h @@ -1,15 +1,14 @@ #pragma once -#include +#include #include -#define SDL_USER_PLAYER_CHAR (SDL_USEREVENT + 1) +#define SDL_EVENT_USER_PLAYER_CHAR (SDL_EVENT_USER + 1) inline void SDL_ResizeEvent(SDL_Window* pWindow, int width, int height) { SDL_Event event{}; - event.type = SDL_WINDOWEVENT; - event.window.event = SDL_WINDOWEVENT_RESIZED; + event.type = SDL_EVENT_WINDOW_RESIZED; event.window.windowID = SDL_GetWindowID(pWindow); event.window.data1 = width; event.window.data2 = height; @@ -20,8 +19,7 @@ inline void SDL_ResizeEvent(SDL_Window* pWindow, int width, int height) inline void SDL_MoveEvent(SDL_Window* pWindow, int x, int y) { SDL_Event event{}; - event.type = SDL_WINDOWEVENT; - event.window.event = SDL_WINDOWEVENT_MOVED; + event.type = SDL_EVENT_WINDOW_MOVED; event.window.windowID = SDL_GetWindowID(pWindow); event.window.data1 = x; event.window.data2 = y; @@ -32,7 +30,7 @@ inline void SDL_MoveEvent(SDL_Window* pWindow, int x, int y) inline void SDL_User_PlayerChar(EPlayerCharacter character) { SDL_Event event{}; - event.type = SDL_USER_PLAYER_CHAR; + event.type = SDL_EVENT_USER_PLAYER_CHAR; event.user.code = static_cast(character); SDL_PushEvent(&event); diff --git a/MarathonRecomp/stdafx.h b/MarathonRecomp/stdafx.h index 4489026b0..cd57dd5b1 100644 --- a/MarathonRecomp/stdafx.h +++ b/MarathonRecomp/stdafx.h @@ -35,12 +35,12 @@ using Microsoft::WRL::ComPtr; #include #include #include -#include -#include +#include +#include #include #include #include -#include +#include #include #include #include diff --git a/MarathonRecomp/ui/common_menu.h b/MarathonRecomp/ui/common_menu.h index 4663d4844..d02eb1a74 100644 --- a/MarathonRecomp/ui/common_menu.h +++ b/MarathonRecomp/ui/common_menu.h @@ -28,8 +28,8 @@ class CommonMenu bool OnSDLEvent(SDL_Event* event) override { - if (event->type == SDL_CONTROLLERAXISMOTION && event->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX) - RightStickX = event->caxis.value / 32767.0f; + if (event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION && event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTX) + RightStickX = event->gaxis.value / 32767.0f; return false; } diff --git a/MarathonRecomp/ui/game_window.cpp b/MarathonRecomp/ui/game_window.cpp index 6cfb64da5..e370dbc24 100644 --- a/MarathonRecomp/ui/game_window.cpp +++ b/MarathonRecomp/ui/game_window.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #if _WIN32 #include @@ -17,22 +16,39 @@ bool m_isFullscreenKeyReleased = true; bool m_isResizing = false; -int Window_OnSDLEvent(void*, SDL_Event* event) +static SDL_DisplayID GetDisplayID(int displayIndex) +{ + int displayCount = 0; + auto displays = SDL_GetDisplays(&displayCount); + SDL_DisplayID result = 0; + + if (displays) + { + if (displayIndex >= 0 && displayIndex < displayCount) + result = displays[displayIndex]; + + SDL_free(displays); + } + + return result; +} + +bool Window_OnSDLEvent(void*, SDL_Event* event) { if (ImGui::GetIO().BackendPlatformUserData != nullptr) - ImGui_ImplSDL2_ProcessEvent(event); + ImGui_ImplSDL3_ProcessEvent(event); for (auto listener : GetEventListeners()) { if (listener->OnSDLEvent(event)) { - return 0; + return true; } } switch (event->type) { - case SDL_QUIT: + case SDL_EVENT_QUIT: { if (App::s_isSaving) break; @@ -42,14 +58,14 @@ int Window_OnSDLEvent(void*, SDL_Event* event) break; } - case SDL_KEYDOWN: + case SDL_EVENT_KEY_DOWN: { - switch (event->key.keysym.sym) + switch (event->key.key) { // Toggle fullscreen on ALT+ENTER. case SDLK_RETURN: { - if (!(event->key.keysym.mod & KMOD_ALT) || !m_isFullscreenKeyReleased) + if (!(event->key.mod & SDL_KMOD_ALT) || !m_isFullscreenKeyReleased) break; Config::Fullscreen = GameWindow::SetFullscreen(!GameWindow::IsFullscreen()); @@ -90,80 +106,83 @@ int Window_OnSDLEvent(void*, SDL_Event* event) break; } - case SDL_KEYUP: + case SDL_EVENT_KEY_UP: { - switch (event->key.keysym.sym) + switch (event->key.key) { // Allow user to input ALT+ENTER again. case SDLK_RETURN: m_isFullscreenKeyReleased = true; break; } - } - case SDL_WINDOWEVENT: - { - switch (event->window.event) - { - case SDL_WINDOWEVENT_FOCUS_LOST: - GameWindow::s_isFocused = false; - SDL_ShowCursor(SDL_ENABLE); - break; + break; + } - case SDL_WINDOWEVENT_FOCUS_GAINED: - { - GameWindow::s_isFocused = true; + case SDL_EVENT_WINDOW_FOCUS_LOST: + GameWindow::s_isFocused = false; + SDL_ShowCursor(); + break; - if (GameWindow::IsFullscreen()) - SDL_ShowCursor(GameWindow::s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE); + case SDL_EVENT_WINDOW_FOCUS_GAINED: + { + GameWindow::s_isFocused = true; - break; - } + if (GameWindow::IsFullscreen()) + { + if (GameWindow::s_isFullscreenCursorVisible) + SDL_ShowCursor(); + else + SDL_HideCursor(); + } - case SDL_WINDOWEVENT_RESTORED: - Config::WindowState = EWindowState::Normal; - break; + break; + } - case SDL_WINDOWEVENT_MAXIMIZED: - Config::WindowState = EWindowState::Maximised; - break; + case SDL_EVENT_WINDOW_RESTORED: + Config::WindowState = EWindowState::Normal; + break; - case SDL_WINDOWEVENT_RESIZED: - m_isResizing = true; - Config::WindowSize = -1; - GameWindow::s_width = event->window.data1; - GameWindow::s_height = event->window.data2; - GameWindow::SetTitle(fmt::format("{} - [{}x{}]", GameWindow::GetTitle(), GameWindow::s_width, GameWindow::s_height).c_str()); - break; + case SDL_EVENT_WINDOW_MAXIMIZED: + Config::WindowState = EWindowState::Maximised; + break; - case SDL_WINDOWEVENT_MOVED: - GameWindow::s_x = event->window.data1; - GameWindow::s_y = event->window.data2; - break; - } + case SDL_EVENT_WINDOW_RESIZED: + m_isResizing = true; + Config::WindowSize = -1; + GameWindow::s_width = event->window.data1; + GameWindow::s_height = event->window.data2; + GameWindow::SetTitle(fmt::format("{} - [{}x{}]", GameWindow::GetTitle(), GameWindow::s_width, GameWindow::s_height).c_str()); + break; + case SDL_EVENT_WINDOW_MOVED: + GameWindow::s_x = event->window.data1; + GameWindow::s_y = event->window.data2; break; - } - case SDL_USER_PLAYER_CHAR: + case SDL_EVENT_USER_PLAYER_CHAR: GameWindow::s_playerCharacter = static_cast(event->user.code); GameWindow::SetIcon(GameWindow::s_playerCharacter); break; } - return 0; + return false; } void GameWindow::Init(const char* sdlVideoDriver) { #ifdef __linux__ - SDL_SetHint("SDL_APP_ID", "io.github.sonicnext_dev.marathonrecomp"); + SDL_SetHint(SDL_HINT_APP_ID, "io.github.sonicnext_dev.marathonrecomp"); #endif - if (SDL_VideoInit(sdlVideoDriver) != 0 && sdlVideoDriver) + if (sdlVideoDriver) + SDL_SetHint(SDL_HINT_VIDEO_DRIVER, sdlVideoDriver); + + if (!SDL_InitSubSystem(SDL_INIT_VIDEO) && sdlVideoDriver) { LOGFN_ERROR("Failed to initialise the SDL video driver: \"{}\". Falling back to default.", sdlVideoDriver); - SDL_VideoInit(nullptr); + SDL_ResetHint(SDL_HINT_VIDEO_DRIVER); + SDL_InitSubSystem(SDL_INIT_VIDEO); } auto videoDriverName = SDL_GetCurrentVideoDriver(); @@ -171,7 +190,6 @@ void GameWindow::Init(const char* sdlVideoDriver) if (videoDriverName) LOGFN("SDL video driver: \"{}\"", videoDriverName); - SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); SDL_AddEventWatch(Window_OnSDLEvent, s_pWindow); #ifdef _WIN32 @@ -189,10 +207,11 @@ void GameWindow::Init(const char* sdlVideoDriver) if (!IsPositionValid()) GameWindow::ResetDimensions(); - s_pWindow = SDL_CreateWindow("Marathon Recompiled", s_x, s_y, s_width, s_height, GetWindowFlags()); + s_pWindow = SDL_CreateWindow("Marathon Recompiled", s_width, s_height, GetWindowFlags()); + SDL_SetWindowPosition(s_pWindow, s_x, s_y); if (IsFullscreen()) - SDL_ShowCursor(SDL_DISABLE); + SDL_HideCursor(); SetDisplay(Config::Monitor); SetIcon(); @@ -200,12 +219,8 @@ void GameWindow::Init(const char* sdlVideoDriver) SDL_SetWindowMinimumSize(s_pWindow, MIN_WIDTH, MIN_HEIGHT); - SDL_SysWMinfo info; - SDL_VERSION(&info.version); - SDL_GetWindowWMInfo(s_pWindow, &info); - #if defined(_WIN32) - s_renderWindow = info.info.win.window; + s_renderWindow = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(s_pWindow), SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr); if (Config::DisableDWMRoundedCorners) { @@ -215,9 +230,12 @@ void GameWindow::Init(const char* sdlVideoDriver) #elif defined(PLUME_SDL_VULKAN_ENABLED) s_renderWindow = s_pWindow; #elif defined(__linux__) - s_renderWindow = { info.info.x11.display, info.info.x11.window }; + s_renderWindow = { + (Display*)SDL_GetPointerProperty(SDL_GetWindowProperties(s_pWindow), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr), + (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(s_pWindow), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0) + }; #elif defined(__APPLE__) - s_renderWindow.window = info.info.cocoa.window; + s_renderWindow.window = SDL_GetPointerProperty(SDL_GetWindowProperties(s_pWindow), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr); s_renderWindow.view = SDL_Metal_GetLayer(SDL_Metal_CreateView(s_pWindow)); #else static_assert(false, "Unknown platform."); @@ -250,8 +268,8 @@ void GameWindow::Update() SDL_Surface* GameWindow::GetIconSurface(void* pIconBmp, size_t iconSize) { - auto rw = SDL_RWFromMem(pIconBmp, iconSize); - auto surface = SDL_LoadBMP_RW(rw, 1); + auto io = SDL_IOFromMem(pIconBmp, iconSize); + auto surface = SDL_LoadBMP_IO(io, true); if (!surface) LOGF_ERROR("Failed to load icon: {}", SDL_GetError()); @@ -264,7 +282,7 @@ void GameWindow::SetIcon(void* pIconBmp, size_t iconSize) if (auto icon = GetIconSurface(pIconBmp, iconSize)) { SDL_SetWindowIcon(s_pWindow, icon); - SDL_FreeSurface(icon); + SDL_DestroySurface(icon); } } @@ -330,20 +348,25 @@ void GameWindow::SetTitleBarColour() bool GameWindow::IsFullscreen() { - return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP; + return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_FULLSCREEN; } bool GameWindow::SetFullscreen(bool isEnabled) { if (isEnabled) { - SDL_SetWindowFullscreen(s_pWindow, SDL_WINDOW_FULLSCREEN_DESKTOP); - SDL_ShowCursor(s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE); + SDL_SetWindowFullscreenMode(s_pWindow, nullptr); + SDL_SetWindowFullscreen(s_pWindow, true); + + if (s_isFullscreenCursorVisible) + SDL_ShowCursor(); + else + SDL_HideCursor(); } else { - SDL_SetWindowFullscreen(s_pWindow, 0); - SDL_ShowCursor(SDL_ENABLE); + SDL_SetWindowFullscreen(s_pWindow, false); + SDL_ShowCursor(); SetIcon(GameWindow::s_playerCharacter); SetDimensions(Config::WindowWidth, Config::WindowHeight, Config::WindowX, Config::WindowY); @@ -351,18 +374,18 @@ bool GameWindow::SetFullscreen(bool isEnabled) return isEnabled; } - + void GameWindow::SetFullscreenCursorVisibility(bool isVisible) { s_isFullscreenCursorVisible = isVisible; - if (IsFullscreen()) + if (IsFullscreen() && !s_isFullscreenCursorVisible) { - SDL_ShowCursor(s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE); + SDL_HideCursor(); } else { - SDL_ShowCursor(SDL_ENABLE); + SDL_ShowCursor(); } } @@ -429,15 +452,15 @@ void GameWindow::ResetDimensions() Config::WindowHeight = s_height; } -uint32_t GameWindow::GetWindowFlags() +SDL_WindowFlags GameWindow::GetWindowFlags() { - uint32_t flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI; + SDL_WindowFlags flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY; if (Config::WindowState == EWindowState::Maximised) flags |= SDL_WINDOW_MAXIMIZED; if (Config::Fullscreen) - flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + flags |= SDL_WINDOW_FULLSCREEN; #ifdef PLUME_SDL_VULKAN_ENABLED flags |= SDL_WINDOW_VULKAN; @@ -448,20 +471,42 @@ uint32_t GameWindow::GetWindowFlags() int GameWindow::GetDisplayCount() { - auto result = SDL_GetNumVideoDisplays(); + int result = 0; + auto displays = SDL_GetDisplays(&result); - if (result < 0) + if (!displays) { LOGF_ERROR("Failed to get display count: {}", SDL_GetError()); return 1; } + SDL_free(displays); + return result; } int GameWindow::GetDisplay() { - return SDL_GetWindowDisplayIndex(s_pWindow); + auto displayID = SDL_GetDisplayForWindow(s_pWindow); + int displayCount = 0; + auto displays = SDL_GetDisplays(&displayCount); + int result = -1; + + if (displays) + { + for (int i = 0; i < displayCount; i++) + { + if (displays[i] == displayID) + { + result = i; + break; + } + } + + SDL_free(displays); + } + + return result; } void GameWindow::SetDisplay(int displayIndex) @@ -476,7 +521,7 @@ void GameWindow::SetDisplay(int displayIndex) SDL_Rect bounds; - if (SDL_GetDisplayBounds(displayIndex, &bounds) == 0) + if (SDL_GetDisplayBounds(GetDisplayID(displayIndex), &bounds)) { SetFullscreen(false); SetDimensions(bounds.w, bounds.h, bounds.x, bounds.y); @@ -492,49 +537,46 @@ std::vector GameWindow::GetDisplayModes(bool ignoreInvalidModes { auto result = std::vector(); auto uniqueResolutions = std::set>(); - auto displayIndex = GetDisplay(); - auto modeCount = SDL_GetNumDisplayModes(displayIndex); + auto displayID = GetDisplayID(GetDisplay()); + auto modeCount = 0; + auto modes = SDL_GetFullscreenDisplayModes(displayID, &modeCount); - if (modeCount <= 0) + if (!modes) return result; for (int i = modeCount - 1; i >= 0; i--) { - SDL_DisplayMode mode; + const SDL_DisplayMode& mode = *modes[i]; - if (SDL_GetDisplayMode(displayIndex, i, &mode) == 0) + if (ignoreInvalidModes) { - if (ignoreInvalidModes) - { - if (mode.w < MIN_WIDTH || mode.h < MIN_HEIGHT) - continue; + if (mode.w < MIN_WIDTH || mode.h < MIN_HEIGHT) + continue; - SDL_DisplayMode desktopMode; + auto desktopMode = SDL_GetDesktopDisplayMode(displayID); - if (SDL_GetDesktopDisplayMode(displayIndex, &desktopMode) == 0) - { - if (mode.w >= desktopMode.w || mode.h >= desktopMode.h) - continue; - } - } + if (desktopMode && (mode.w >= desktopMode->w || mode.h >= desktopMode->h)) + continue; + } - if (ignoreRefreshRates) - { - auto res = std::make_pair(mode.w, mode.h); + if (ignoreRefreshRates) + { + auto res = std::make_pair(mode.w, mode.h); - if (uniqueResolutions.find(res) == uniqueResolutions.end()) - { - uniqueResolutions.insert(res); - result.push_back(mode); - } - } - else + if (uniqueResolutions.find(res) == uniqueResolutions.end()) { + uniqueResolutions.insert(res); result.push_back(mode); } } + else + { + result.push_back(mode); + } } + SDL_free(modes); + return result; } @@ -564,34 +606,43 @@ int GameWindow::FindNearestDisplayMode() bool GameWindow::IsPositionValid() { - auto displayCount = GetDisplayCount(); + int displayCount = 0; + auto displays = SDL_GetDisplays(&displayCount); + + if (!displays) + return false; + + auto result = false; for (int i = 0; i < displayCount; i++) { SDL_Rect bounds; - if (SDL_GetDisplayBounds(i, &bounds) == 0) - { - auto x = s_x; - auto y = s_y; + if (!SDL_GetDisplayBounds(displays[i], &bounds)) + continue; - // Window spans across the entire display in windowed mode, which is invalid. - if (!Config::Fullscreen && s_width == bounds.w && s_height == bounds.h) - return false; + auto x = s_x; + auto y = s_y; - if (x == SDL_WINDOWPOS_CENTERED_DISPLAY(i)) - x = bounds.w / 2 - s_width / 2; + // Window spans across the entire display in windowed mode, which is invalid. + if (!Config::Fullscreen && s_width == bounds.w && s_height == bounds.h) + break; - if (y == SDL_WINDOWPOS_CENTERED_DISPLAY(i)) - y = bounds.h / 2 - s_height / 2; + if (x == SDL_WINDOWPOS_CENTERED_DISPLAY(displays[i])) + x = bounds.w / 2 - s_width / 2; - if (x >= bounds.x && x < bounds.x + bounds.w && - y >= bounds.y && y < bounds.y + bounds.h) - { - return true; - } + if (y == SDL_WINDOWPOS_CENTERED_DISPLAY(displays[i])) + y = bounds.h / 2 - s_height / 2; + + if (x >= bounds.x && x < bounds.x + bounds.w && + y >= bounds.y && y < bounds.y + bounds.h) + { + result = true; + break; } } - return false; + SDL_free(displays); + + return result; } diff --git a/MarathonRecomp/ui/game_window.h b/MarathonRecomp/ui/game_window.h index 187c6b184..19a74755e 100644 --- a/MarathonRecomp/ui/game_window.h +++ b/MarathonRecomp/ui/game_window.h @@ -41,7 +41,7 @@ class GameWindow static void GetSizeInPixels(int *w, int *h); static void SetDimensions(int w, int h, int x = SDL_WINDOWPOS_CENTERED, int y = SDL_WINDOWPOS_CENTERED); static void ResetDimensions(); - static uint32_t GetWindowFlags(); + static uint64_t GetWindowFlags(); static int GetDisplayCount(); static int GetDisplay(); static void SetDisplay(int displayIndex); diff --git a/MarathonRecomp/ui/installer_wizard.cpp b/MarathonRecomp/ui/installer_wizard.cpp index bcb25a944..eac2e9fd7 100644 --- a/MarathonRecomp/ui/installer_wizard.cpp +++ b/MarathonRecomp/ui/installer_wizard.cpp @@ -183,7 +183,7 @@ class SDLEventListenerForInstaller : public SDLEventListener auto noModals = g_currentMessagePrompt.empty() && !g_currentPickerVisible; - if (event->type == SDL_QUIT && g_currentPage == WizardPage::Installing) + if (event->type == SDL_EVENT_QUIT && g_currentPage == WizardPage::Installing) { // Pretend the back button was pressed if the user tried quitting during installation. // This condition is above the rest of the event processing as we want to block the exit @@ -204,18 +204,18 @@ class SDLEventListenerForInstaller : public SDLEventListener switch (event->type) { - case SDL_KEYDOWN: + case SDL_EVENT_KEY_DOWN: { - switch (event->key.keysym.scancode) + switch (event->key.scancode) { case SDL_SCANCODE_LEFT: case SDL_SCANCODE_RIGHT: - tapDirection.x = (event->key.keysym.scancode == SDL_SCANCODE_RIGHT) ? 1.0f : -1.0f; + tapDirection.x = (event->key.scancode == SDL_SCANCODE_RIGHT) ? 1.0f : -1.0f; break; case SDL_SCANCODE_UP: case SDL_SCANCODE_DOWN: - tapDirection.y = (event->key.keysym.scancode == SDL_SCANCODE_DOWN) ? 1.0f : -1.0f; + tapDirection.y = (event->key.scancode == SDL_SCANCODE_DOWN) ? 1.0f : -1.0f; break; case SDL_SCANCODE_RETURN: @@ -231,31 +231,31 @@ class SDLEventListenerForInstaller : public SDLEventListener break; } - case SDL_CONTROLLERBUTTONDOWN: + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: { - switch (event->cbutton.button) + switch (event->gbutton.button) { - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + case SDL_GAMEPAD_BUTTON_DPAD_LEFT: tapDirection = { -1.0f, 0.0f }; break; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + case SDL_GAMEPAD_BUTTON_DPAD_RIGHT: tapDirection = { 1.0f, 0.0f }; break; - case SDL_CONTROLLER_BUTTON_DPAD_UP: + case SDL_GAMEPAD_BUTTON_DPAD_UP: tapDirection = { 0.0f, -1.0f }; break; - case SDL_CONTROLLER_BUTTON_DPAD_DOWN: + case SDL_GAMEPAD_BUTTON_DPAD_DOWN: tapDirection = { 0.0f, 1.0f }; break; - case SDL_CONTROLLER_BUTTON_A: + case SDL_GAMEPAD_BUTTON_SOUTH: g_currentCursorAccepted = (g_currentCursorIndex >= 0); break; - case SDL_CONTROLLER_BUTTON_B: + case SDL_GAMEPAD_BUTTON_EAST: g_currentCursorBack = true; break; } @@ -263,26 +263,26 @@ class SDLEventListenerForInstaller : public SDLEventListener break; } - case SDL_CONTROLLERAXISMOTION: + case SDL_EVENT_GAMEPAD_AXIS_MOTION: { - if (event->caxis.axis < 2) + if (event->gaxis.axis < 2) { - auto newAxisValue = event->caxis.value / axisValueRange; - auto sameDirection = (newAxisValue * m_joypadAxis[event->caxis.axis]) > 0.0f; - auto wasInRange = abs(m_joypadAxis[event->caxis.axis]) > axisTapRange; + auto newAxisValue = event->gaxis.value / axisValueRange; + auto sameDirection = (newAxisValue * m_joypadAxis[event->gaxis.axis]) > 0.0f; + auto wasInRange = abs(m_joypadAxis[event->gaxis.axis]) > axisTapRange; auto isInRange = abs(newAxisValue) > axisTapRange; if (sameDirection && !wasInRange && isInRange) - tapDirection[event->caxis.axis] = newAxisValue; + tapDirection[event->gaxis.axis] = newAxisValue; - m_joypadAxis[event->caxis.axis] = newAxisValue; + m_joypadAxis[event->gaxis.axis] = newAxisValue; } break; } - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEMOTION: + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_MOTION: { for (size_t i = 0; i < g_currentCursorRects.size(); i++) { @@ -292,7 +292,7 @@ class SDLEventListenerForInstaller : public SDLEventListener { newCursorIndex = int(i); - if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT) + if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN && event->button.button == SDL_BUTTON_LEFT) g_currentCursorAccepted = true; break; @@ -1388,7 +1388,7 @@ bool InstallerWizard::Run(std::filesystem::path installPath, bool skipGame) Video::WaitOnSwapChain(); EmbeddedPlayer::PlayMusic(); SDL_PumpEvents(); - SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); + SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); GameWindow::Update(); Video::Present(); } diff --git a/MarathonRecomp/ui/message_window.cpp b/MarathonRecomp/ui/message_window.cpp index fc22baa63..b1bb4f7cc 100644 --- a/MarathonRecomp/ui/message_window.cpp +++ b/MarathonRecomp/ui/message_window.cpp @@ -47,9 +47,9 @@ class SDLEventListenerForMessageWindow : public SDLEventListener switch (event->type) { - case SDL_KEYDOWN: + case SDL_EVENT_KEY_DOWN: { - switch (event->key.keysym.scancode) + switch (event->key.scancode) { case SDL_SCANCODE_UP: g_joypadAxis.y = 1.0f; @@ -72,7 +72,7 @@ class SDLEventListenerForMessageWindow : public SDLEventListener break; } - case SDL_MOUSEBUTTONDOWN: + case SDL_EVENT_MOUSE_BUTTON_DOWN: { // Only accept left mouse button. if (event->button.button != SDL_BUTTON_LEFT) @@ -87,23 +87,23 @@ class SDLEventListenerForMessageWindow : public SDLEventListener break; } - case SDL_CONTROLLERBUTTONDOWN: + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: { - switch (event->cbutton.button) + switch (event->gbutton.button) { - case SDL_CONTROLLER_BUTTON_DPAD_UP: + case SDL_GAMEPAD_BUTTON_DPAD_UP: g_joypadAxis = { 0.0f, 1.0f }; break; - case SDL_CONTROLLER_BUTTON_DPAD_DOWN: + case SDL_GAMEPAD_BUTTON_DPAD_DOWN: g_joypadAxis = { 0.0f, -1.0f }; break; - case SDL_CONTROLLER_BUTTON_A: + case SDL_GAMEPAD_BUTTON_SOUTH: g_isAccepted = true; break; - case SDL_CONTROLLER_BUTTON_B: + case SDL_GAMEPAD_BUTTON_EAST: g_isDeclined = true; break; } @@ -111,19 +111,19 @@ class SDLEventListenerForMessageWindow : public SDLEventListener break; } - case SDL_CONTROLLERAXISMOTION: + case SDL_EVENT_GAMEPAD_AXIS_MOTION: { - if (event->caxis.axis < 2) + if (event->gaxis.axis < 2) { - float newAxisValue = -(event->caxis.value / axisValueRange); - bool sameDirection = (newAxisValue * g_joypadAxis[event->caxis.axis]) > 0.0f; - bool wasInRange = abs(g_joypadAxis[event->caxis.axis]) > axisTapRange; + float newAxisValue = -(event->gaxis.value / axisValueRange); + bool sameDirection = (newAxisValue * g_joypadAxis[event->gaxis.axis]) > 0.0f; + bool wasInRange = abs(g_joypadAxis[event->gaxis.axis]) > axisTapRange; bool isInRange = abs(newAxisValue) > axisTapRange; if (sameDirection && !wasInRange && isInRange) - tapDirection[event->caxis.axis] = newAxisValue; + tapDirection[event->gaxis.axis] = newAxisValue; - g_joypadAxis[event->caxis.axis] = newAxisValue; + g_joypadAxis[event->gaxis.axis] = newAxisValue; } break; diff --git a/MarathonRecomp/user/config.cpp b/MarathonRecomp/user/config.cpp index 0070de613..0ce0032eb 100644 --- a/MarathonRecomp/user/config.cpp +++ b/MarathonRecomp/user/config.cpp @@ -261,16 +261,12 @@ CONFIG_DEFINE_ENUM_TEMPLATE(SDL_Scancode) { "RIGHT ALT", SDL_SCANCODE_RALT }, { "RIGHT SUPER", SDL_SCANCODE_RGUI }, { "MODE", SDL_SCANCODE_MODE }, - { "AUDIO NEXT", SDL_SCANCODE_AUDIONEXT }, - { "AUDIO PREV", SDL_SCANCODE_AUDIOPREV }, - { "AUDIO STOP", SDL_SCANCODE_AUDIOSTOP }, - { "AUDIO PLAY", SDL_SCANCODE_AUDIOPLAY }, - { "AUDIO MUTE", SDL_SCANCODE_AUDIOMUTE }, - { "MEDIA SELECT", SDL_SCANCODE_MEDIASELECT }, - { "WWW", SDL_SCANCODE_WWW }, - { "MAIL", SDL_SCANCODE_MAIL }, - { "CALCULATOR", SDL_SCANCODE_CALCULATOR }, - { "COMPUTER", SDL_SCANCODE_COMPUTER }, + { "AUDIO NEXT", SDL_SCANCODE_MEDIA_NEXT_TRACK }, + { "AUDIO PREV", SDL_SCANCODE_MEDIA_PREVIOUS_TRACK }, + { "AUDIO STOP", SDL_SCANCODE_MEDIA_STOP }, + { "AUDIO PLAY", SDL_SCANCODE_MEDIA_PLAY }, + { "AUDIO MUTE", SDL_SCANCODE_MUTE }, + { "MEDIA SELECT", SDL_SCANCODE_MEDIA_SELECT }, { "AC SEARCH", SDL_SCANCODE_AC_SEARCH }, { "AC HOME", SDL_SCANCODE_AC_HOME }, { "AC BACK", SDL_SCANCODE_AC_BACK }, @@ -278,18 +274,10 @@ CONFIG_DEFINE_ENUM_TEMPLATE(SDL_Scancode) { "AC STOP", SDL_SCANCODE_AC_STOP }, { "AC REFRESH", SDL_SCANCODE_AC_REFRESH }, { "AC BOOKMARKS", SDL_SCANCODE_AC_BOOKMARKS }, - { "BRIGHTNESS DOWN", SDL_SCANCODE_BRIGHTNESSDOWN }, - { "BRIGHTNESS UP", SDL_SCANCODE_BRIGHTNESSUP }, - { "DISPLAY SWITCH", SDL_SCANCODE_DISPLAYSWITCH }, - { "KBD ILLUM TOGGLE", SDL_SCANCODE_KBDILLUMTOGGLE }, - { "KBD ILLUM DOWN", SDL_SCANCODE_KBDILLUMDOWN }, - { "KBD ILLUM UP", SDL_SCANCODE_KBDILLUMUP }, - { "EJECT", SDL_SCANCODE_EJECT }, + { "EJECT", SDL_SCANCODE_MEDIA_EJECT }, { "SLEEP", SDL_SCANCODE_SLEEP }, - { "APP 1", SDL_SCANCODE_APP1 }, - { "APP 2", SDL_SCANCODE_APP2 }, - { "AUDIO REWIND", SDL_SCANCODE_AUDIOREWIND }, - { "AUDIO FAST FORWARD", SDL_SCANCODE_AUDIOFASTFORWARD }, + { "AUDIO REWIND", SDL_SCANCODE_MEDIA_REWIND }, + { "AUDIO FAST FORWARD", SDL_SCANCODE_MEDIA_FAST_FORWARD }, { "SOFT LEFT", SDL_SCANCODE_SOFTLEFT }, { "SOFT RIGHT", SDL_SCANCODE_SOFTRIGHT }, { "CALL", SDL_SCANCODE_CALL }, diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index eccab8299..9525b29b4 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -5,15 +5,15 @@ set(MSDF_ATLAS_USE_SKIA OFF) set(MSDF_ATLAS_NO_ARTERY_FONT ON) set(MSDFGEN_DISABLE_PNG ON) -set(SDL2MIXER_DEPS_SHARED OFF) -set(SDL2MIXER_VENDORED ON) -set(SDL2MIXER_FLAC OFF) -set(SDL2MIXER_MOD OFF) -set(SDL2MIXER_MP3 OFF) -set(SDL2MIXER_MIDI OFF) -set(SDL2MIXER_OPUS OFF) -set(SDL2MIXER_VORBIS "VORBISFILE") -set(SDL2MIXER_WAVPACK OFF) +set(SDLMIXER_DEPS_SHARED OFF) +set(SDLMIXER_VENDORED ON) +set(SDLMIXER_FLAC OFF) +set(SDLMIXER_MOD OFF) +set(SDLMIXER_MP3 OFF) +set(SDLMIXER_MIDI OFF) +set(SDLMIXER_OPUS OFF) +set(SDLMIXER_VORBIS_STB OFF) +set(SDLMIXER_WAVPACK OFF) if (CMAKE_SYSTEM_NAME MATCHES "Linux") set(PLUME_SDL_VULKAN_ENABLED ON CACHE BOOL "") diff --git a/thirdparty/SDL b/thirdparty/SDL index 98d1f3a45..fa2c02bb6 160000 --- a/thirdparty/SDL +++ b/thirdparty/SDL @@ -1 +1 @@ -Subproject commit 98d1f3a45aae568ccd6ed5fec179330f47d4d356 +Subproject commit fa2c02bb6e21974a89ea9824bc53c9932abe5f9c diff --git a/thirdparty/SDL_mixer b/thirdparty/SDL_mixer index 437992692..72a81869b 160000 --- a/thirdparty/SDL_mixer +++ b/thirdparty/SDL_mixer @@ -1 +1 @@ -Subproject commit 437992692cf9300f2b2f04be35adc7445a9055bf +Subproject commit 72a81869b45e249e8e67102db4e98dd2441f05a1 diff --git a/thirdparty/imgui b/thirdparty/imgui index 8199457a7..cb16568fc 160000 --- a/thirdparty/imgui +++ b/thirdparty/imgui @@ -1 +1 @@ -Subproject commit 8199457a7d9e453f8d3d9cadc14683fb54a858b5 +Subproject commit cb16568fca5297512ff6a8f3b877f461c4323fbe