Browse Source

SDL3: Add some backports / compat helpers

pull/8217/head
Gleb Mazovetskiy 5 months ago
parent
commit
88f706e0d1
  1. 9
      Source/DiabloUI/button.cpp
  2. 10
      Source/DiabloUI/credits.cpp
  3. 161
      Source/DiabloUI/diabloui.cpp
  4. 45
      Source/DiabloUI/dialogs.cpp
  5. 18
      Source/DiabloUI/progress.cpp
  6. 4
      Source/DiabloUI/selyesno.cpp
  7. 28
      Source/DiabloUI/settingsmenu.cpp
  8. 68
      Source/DiabloUI/text_input.cpp
  9. 11
      Source/DiabloUI/title.cpp
  10. 5
      Source/appfat.cpp
  11. 13
      Source/capture.cpp
  12. 37
      Source/control.cpp
  13. 31
      Source/controls/controller.cpp
  14. 21
      Source/controls/controller_motion.cpp
  15. 192
      Source/controls/devices/game_controller.cpp
  16. 30
      Source/controls/devices/joystick.cpp
  17. 34
      Source/controls/menu_controls.cpp
  18. 66
      Source/controls/plrctrls.cpp
  19. 13
      Source/controls/touch/event_handlers.cpp
  20. 13
      Source/cursor.cpp
  21. 83
      Source/diablo.cpp
  22. 6
      Source/dvlnet/base.cpp
  23. 6
      Source/dvlnet/base_protocol.h
  24. 4
      Source/dvlnet/protocol_zt.cpp
  25. 6
      Source/dvlnet/tcp_client.cpp
  26. 11
      Source/dvlnet/zerotier_lwip.cpp
  27. 7
      Source/dvlnet/zerotier_native.cpp
  28. 37
      Source/engine/assets.cpp
  29. 56
      Source/engine/assets.hpp
  30. 4
      Source/engine/dx.cpp
  31. 40
      Source/engine/events.cpp
  32. 1
      Source/engine/palette.cpp
  33. 23
      Source/engine/render/scrollrt.cpp
  34. 5
      Source/gmenu.cpp
  35. 33
      Source/hwcursor.cpp
  36. 13
      Source/hwcursor.hpp
  37. 55
      Source/interfac.cpp
  38. 7
      Source/inv.cpp
  39. 6
      Source/lua/modules/dev/items.cpp
  40. 4
      Source/lua/modules/log.cpp
  41. 4
      Source/main.cpp
  42. 4
      Source/menu.cpp
  43. 27
      Source/movie.cpp
  44. 21
      Source/mpq/mpq_sdl_rwops.cpp
  45. 9
      Source/mpq/mpq_sdl_rwops.hpp
  46. 18
      Source/options.cpp
  47. 54
      Source/panels/console.cpp
  48. 24
      Source/pfile.cpp
  49. 11
      Source/qol/floatingnumbers.cpp
  50. 14
      Source/qol/stash.cpp
  51. 11
      Source/restrict.cpp
  52. 16
      Source/storm/storm_svid.cpp
  53. 77
      Source/utils/display.cpp
  54. 16
      Source/utils/file_util.cpp
  55. 21
      Source/utils/language.cpp
  56. 20
      Source/utils/sdl2_to_1_2_backports.h
  57. 325
      Source/utils/sdl_compat.h
  58. 52
      Source/utils/surface_to_pcx.cpp
  59. 11
      Source/utils/surface_to_pcx.hpp
  60. 11
      Source/utils/surface_to_png.cpp
  61. 6
      Source/utils/timer.cpp
  62. 22
      test/text_render_integration_test.cpp
  63. 19
      test/timedemo_test.cpp
  64. 1
      test/writehero_test.cpp

9
Source/DiabloUI/button.cpp

@ -19,6 +19,7 @@
#include "engine/render/clx_render.hpp"
#include "engine/render/text_render.hpp"
#include "engine/surface.hpp"
#include "utils/sdl_compat.h"
namespace devilution {
@ -65,21 +66,13 @@ bool HandleMouseEventButton(const SDL_Event &event, UiButton *button)
if (event.button.button != SDL_BUTTON_LEFT)
return false;
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_MOUSE_BUTTON_UP:
#else
case SDL_MOUSEBUTTONUP:
#endif
if (button->IsPressed()) {
button->Activate();
return true;
}
return false;
#ifdef USE_SDL3
case SDL_EVENT_MOUSE_BUTTON_DOWN:
#else
case SDL_MOUSEBUTTONDOWN:
#endif
button->Press();
return true;
default:

10
Source/DiabloUI/credits.cpp

@ -30,6 +30,7 @@
#include "utils/display.h"
#include "utils/is_of.hpp"
#include "utils/language.h"
#include "utils/sdl_compat.h"
#include "utils/sdl_geometry.h"
#include "utils/ui_fwd.h"
@ -109,11 +110,7 @@ void CreditsRenderer::Render()
return;
prev_offset_y_ = offsetY;
#ifdef USE_SDL3
SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);
#else
SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000);
#endif
const Point uiPosition = GetUIRectangle().position;
if (ArtBackgroundWidescreen)
RenderClxSprite(Surface(DiabloUiSurface()), (*ArtBackgroundWidescreen)[0], uiPosition - Displacement { 320, 0 });
@ -165,13 +162,8 @@ bool TextDialog(const char *const *text, std::size_t textLines)
UiFadeIn();
while (PollEvent(&event)) {
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
#else
case SDL_KEYDOWN:
case SDL_MOUSEBUTTONUP:
#endif
endMenu = true;
break;
default:

161
Source/DiabloUI/diabloui.cpp

@ -198,13 +198,13 @@ void UiInitList(void (*fnFocus)(size_t value), void (*fnSelect)(size_t value), v
fnFocus(selectedItem);
#ifndef __SWITCH__
SDL_StopTextInput(); // input is enabled by default
SDLC_StopTextInput(ghMainWnd); // input is enabled by default
#endif
UiScrollbar *uiScrollbar = nullptr;
for (const auto &item : items) {
if (item->IsType(UiType::Edit)) {
auto *pItemUIEdit = static_cast<UiEdit *>(item.get());
SDL_SetTextInputRect(&item->m_rect);
SDL_SetTextInputArea(ghMainWnd, &item->m_rect, 0);
allowEmptyTextInput = pItemUIEdit->m_allowEmpty;
#ifdef __SWITCH__
switch_start_text_input(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_max_length);
@ -213,7 +213,7 @@ void UiInitList(void (*fnFocus)(size_t value), void (*fnSelect)(size_t value), v
#elif defined(__3DS__)
ctr_vkbdInput(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_value, pItemUIEdit->m_max_length);
#else
SDL_StartTextInput();
SDLC_StartTextInput(ghMainWnd);
#endif
UiTextInputState.emplace(TextInputState::Options {
.value = pItemUIEdit->m_value,
@ -410,11 +410,7 @@ void UiOnBackgroundChange()
// of single-player characters.
//
// Black out the screen immediately to make it appear more smooth.
#ifdef USE_SDL3
SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);
#else
SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000);
#endif
if (DiabloUiSurface() == PalSurface)
BltFast(nullptr, nullptr);
RenderPresent();
@ -423,36 +419,24 @@ void UiOnBackgroundChange()
void UiFocusNavigation(SDL_Event *event)
{
switch (event->type) {
#ifdef USE_SDL3
case SDL_EVENT_KEY_UP:
case SDL_EVENT_MOUSE_BUTTON_UP:
case SDL_EVENT_MOUSE_MOTION:
case SDL_EVENT_MOUSE_WHEEL:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
case SDL_EVENT_JOYSTICK_BALL_MOTION:
case SDL_EVENT_JOYSTICK_HAT_MOTION:
#ifndef USE_SDL1
case SDL_EVENT_MOUSE_WHEEL:
case SDL_EVENT_FINGER_UP:
case SDL_EVENT_FINGER_MOTION:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
#endif
#ifdef USE_SDL3
case SDL_EVENT_WINDOW_EXPOSED:
#else
case SDL_KEYUP:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEMOTION:
#ifndef USE_SDL1
case SDL_MOUSEWHEEL:
#endif
case SDL_JOYBUTTONUP:
case SDL_JOYAXISMOTION:
case SDL_JOYBALLMOTION:
case SDL_JOYHATMOTION:
#ifndef USE_SDL1
case SDL_FINGERUP:
case SDL_FINGERMOTION:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERAXISMOTION:
case SDL_WINDOWEVENT:
#endif
case SDL_SYSWMEVENT:
@ -469,20 +453,11 @@ void UiFocusNavigation(SDL_Event *event)
if (menuActionHandled)
return;
#ifdef USE_SDL3
#ifndef USE_SDL1
if (event->type == SDL_EVENT_MOUSE_WHEEL) {
if (event->wheel.integer_y > 0) {
if (SDLC_EventWheelIntY(*event) > 0) {
UiFocusUp();
} else if (event->wheel.integer_y < 0) {
UiFocusDown();
}
return;
}
#elif SDL_VERSION_ATLEAST(2, 0, 0)
if (event->type == SDL_MOUSEWHEEL) {
if (event->wheel.y > 0) {
UiFocusUp();
} else if (event->wheel.y < 0) {
} else if (SDLC_EventWheelIntY(*event) < 0) {
UiFocusDown();
}
return;
@ -504,13 +479,7 @@ void UiFocusNavigation(SDL_Event *event)
return;
}
if (IsAnyOf(event->type,
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP
#else
SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP
#endif
)
if (IsAnyOf(event->type, SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP)
&& UiItemMouseEvents(event, gUiItems)) {
return;
}
@ -520,26 +489,15 @@ void UiFocusNavigation(SDL_Event *event)
void UiHandleEvents(SDL_Event *event)
{
if (event->type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_MOTION
#else
SDL_MOUSEMOTION
#endif
) {
if (event->type == SDL_EVENT_MOUSE_MOTION) {
#ifdef USE_SDL1
OutputToLogical(&event->motion.x, &event->motion.y);
#endif
MousePosition = { event->motion.x, event->motion.y };
MousePosition = { SDLC_EventMotionIntX(*event), SDLC_EventMotionIntY(*event) };
return;
}
#ifdef USE_SDL3
if (event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_RETURN)
#else
if (event->type == SDL_KEYDOWN && event->key.keysym.sym == SDLK_RETURN)
#endif
{
if (event->type == SDL_EVENT_KEY_DOWN && SDLC_EventKey(*event) == SDLK_RETURN) {
const auto *state = SDLC_GetKeyState();
if (state[SDLC_KEYSTATE_LALT] != 0 || state[SDLC_KEYSTATE_RALT] != 0) {
GetOptions().Graphics.fullscreen.SetValue(!IsFullScreen());
@ -550,13 +508,7 @@ void UiHandleEvents(SDL_Event *event)
}
}
if (event->type ==
#ifdef USE_SDL3
SDL_EVENT_QUIT
#else
SDL_QUIT
#endif
) {
if (event->type == SDL_EVENT_QUIT) {
diablo_quit(0);
}
@ -583,6 +535,8 @@ void UiHandleEvents(SDL_Event *event)
case SDL_EVENT_WINDOW_FOCUS_GAINED:
if (*GetOptions().Gameplay.pauseOnFocusLoss) diablo_focus_unpause();
break;
default:
break;
}
#else
if (event->type == SDL_WINDOWEVENT) {
@ -622,7 +576,7 @@ void UiFocusNavigationSelect()
return;
}
#ifndef __SWITCH__
SDL_StopTextInput();
SDLC_StopTextInput(ghMainWnd);
#endif
UiTextInputState = std::nullopt;
}
@ -635,7 +589,7 @@ void UiFocusNavigationEsc()
UiPlaySelectSound();
if (UiTextInputState.has_value()) {
#ifndef __SWITCH__
SDL_StopTextInput();
SDLC_StopTextInput(ghMainWnd);
#endif
UiTextInputState = std::nullopt;
}
@ -656,8 +610,8 @@ namespace {
bool IsInsideRect(const SDL_Event &event, const SDL_Rect &rect)
{
const SDL_Point point = { event.button.x, event.button.y };
return SDL_PointInRect(&point, &rect) == SDL_TRUE;
const SDL_Point point = { SDLC_EventButtonIntX(event), SDLC_EventButtonIntY(event) };
return SDLC_PointInRect(&point, &rect);
}
void LoadHeros()
@ -728,9 +682,7 @@ void UiInitialize()
LoadUiGFX();
if (ArtCursor) {
if (SDL_ShowCursor(SDL_DISABLE) <= -1) {
ErrSdl();
}
if (!SDLC_HideCursor()) ErrSdl();
}
}
@ -874,11 +826,7 @@ void DrawSelector(const SDL_Rect &rect)
void UiClearScreen()
{
if (!ArtBackground || gnScreenWidth > (*ArtBackground)[0].width() || gnScreenHeight > (*ArtBackground)[0].height()) {
#ifdef USE_SDL3
SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);
#else
SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000);
#endif
}
}
@ -1034,13 +982,7 @@ void Render(const UiEdit &uiEdit)
bool HandleMouseEventArtTextButton(const SDL_Event &event, const UiArtTextButton *uiButton)
{
if (event.type !=
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_UP
#else
SDL_MOUSEBUTTONUP
#endif
|| event.button.button != SDL_BUTTON_LEFT) {
if (event.type != SDL_EVENT_MOUSE_BUTTON_UP || event.button.button != SDL_BUTTON_LEFT) {
return false;
}
@ -1057,35 +999,17 @@ bool HandleMouseEventList(const SDL_Event &event, UiList *uiList)
if (event.button.button != SDL_BUTTON_LEFT)
return false;
if (!IsAnyOf(event.type,
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_UP, SDL_EVENT_MOUSE_BUTTON_DOWN
#else
SDL_MOUSEBUTTONUP, SDL_MOUSEBUTTONDOWN
#endif
)) {
if (!IsAnyOf(event.type, SDL_EVENT_MOUSE_BUTTON_UP, SDL_EVENT_MOUSE_BUTTON_DOWN)) {
return false;
}
std::size_t index = uiList->indexAt(event.button.y);
if (event.type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_DOWN
#else
SDL_MOUSEBUTTONDOWN
#endif
) {
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
uiList->Press(index);
return true;
}
if (event.type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_UP
#else
SDL_MOUSEBUTTONUP
#endif
&& !uiList->IsPressed(index)) {
if (event.type == SDL_EVENT_MOUSE_BUTTON_UP && !uiList->IsPressed(index)) {
return false;
}
@ -1116,13 +1040,7 @@ bool HandleMouseEventScrollBar(const SDL_Event &event, const UiScrollbar *uiSb)
{
if (event.button.button != SDL_BUTTON_LEFT)
return false;
if (event.type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_UP
#else
SDL_MOUSEBUTTONUP
#endif
) {
if (event.type == SDL_EVENT_MOUSE_BUTTON_UP) {
if (scrollBarState.upArrowPressed && IsInsideRect(event, UpArrowRect(*uiSb))) {
UiFocusUp();
return true;
@ -1131,14 +1049,7 @@ bool HandleMouseEventScrollBar(const SDL_Event &event, const UiScrollbar *uiSb)
UiFocusDown();
return true;
}
} else if (event.type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_DOWN
#else
SDL_MOUSEBUTTONDOWN
#endif
) {
} else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (IsInsideRect(event, BarRect(*uiSb))) {
// Scroll up or down based on thumb position.
const SDL_Rect thumbRect = ThumbRect(*uiSb, SelectedItem, SelectedItemMax + 1);
@ -1247,13 +1158,7 @@ bool UiItemMouseEvents(SDL_Event *event, const std::vector<UiItemBase *> &items)
}
}
if (event->type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_UP
#else
SDL_MOUSEBUTTONUP
#endif
&& event->button.button == SDL_BUTTON_LEFT) {
if (event->type == SDL_EVENT_MOUSE_BUTTON_UP && event->button.button == SDL_BUTTON_LEFT) {
scrollBarState.downArrowPressed = scrollBarState.upArrowPressed = false;
for (const auto &item : items) {
if (item->IsType(UiType::Button)) {
@ -1286,13 +1191,7 @@ bool UiItemMouseEvents(SDL_Event *event, const std::vector<std::unique_ptr<UiIte
}
}
if (event->type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_UP
#else
SDL_MOUSEBUTTONUP
#endif
&& event->button.button == SDL_BUTTON_LEFT) {
if (event->type == SDL_EVENT_MOUSE_BUTTON_UP && event->button.button == SDL_BUTTON_LEFT) {
scrollBarState.downArrowPressed = scrollBarState.upArrowPressed = false;
for (const auto &item : items) {
if (item->IsType(UiType::Button)) {

45
Source/DiabloUI/dialogs.cpp

@ -35,6 +35,7 @@
#include "utils/is_of.hpp"
#include "utils/language.h"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
#include "utils/sdl_geometry.h"
#include "utils/ui_fwd.h"
@ -77,14 +78,9 @@ bool Init(std::string_view caption, std::string_view text, bool error, bool rend
{
if (!renderBehind) {
if (!UiLoadBlackBackground()) {
if (
#ifdef USE_SDL3
SDL_ShowCursor()
#else
SDL_ShowCursor(SDL_ENABLE) <= -1
#endif
)
if (!SDLC_ShowCursor()) {
LogError("{}", SDL_GetError());
}
}
}
if (!IsHardwareCursor() && !ArtCursor) {
@ -140,13 +136,8 @@ void DialogLoop(const std::vector<std::unique_ptr<UiItemBase>> &items, const std
do {
while (PollEvent(&event)) {
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
#else
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
#endif
UiItemMouseEvents(&event, items);
break;
default:
@ -182,18 +173,12 @@ void UiOkDialog(std::string_view caption, std::string_view text, bool error, con
if (!gbActive || inDialog) {
if (!HeadlessMode) {
if (
#ifdef USE_SDL3
SDL_ShowCursor()
#else
SDL_ShowCursor(SDL_ENABLE) <= -1
#endif
) {
if (!SDLC_ShowCursor()) {
LogError("{}", SDL_GetError());
}
const std::string captionStr = std::string(caption);
const std::string textStr = std::string(text);
if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr) <= -1) {
if (!SDLC_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr)) {
LogError("{}", SDL_GetError());
}
}
@ -201,13 +186,7 @@ void UiOkDialog(std::string_view caption, std::string_view text, bool error, con
}
if (IsHardwareCursor()) {
if (
#ifdef USE_SDL3
SDL_ShowCursor()
#else
SDL_ShowCursor(SDL_ENABLE) <= -1
#endif
) {
if (!SDLC_ShowCursor()) {
LogError("{}", SDL_GetError());
}
}
@ -216,23 +195,13 @@ void UiOkDialog(std::string_view caption, std::string_view text, bool error, con
LogError("{}\n{}", caption, text);
const std::string captionStr = std::string(caption);
const std::string textStr = std::string(text);
if (
#ifdef USE_SDL3
!SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr)
#else
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr) <= -1
#endif
) {
if (!SDLC_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, captionStr.c_str(), textStr.c_str(), nullptr)) {
LogError("{}", SDL_GetError());
}
}
inDialog = true;
#ifdef USE_SDL3
SDL_SetSurfaceClipRect(DiabloUiSurface(), nullptr);
#else
SDL_SetClipRect(DiabloUiSurface(), nullptr);
#endif
DialogLoop(vecOkDialog, renderBehind);
Deinit();
inDialog = false;

18
Source/DiabloUI/progress.cpp

@ -24,6 +24,7 @@
#include "utils/display.h"
#include "utils/is_of.hpp"
#include "utils/language.h"
#include "utils/sdl_compat.h"
#include "utils/ui_fwd.h"
namespace devilution {
@ -77,11 +78,7 @@ Point GetPosition()
void ProgressRenderBackground()
{
#ifdef USE_SDL3
SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);
#else
SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000);
#endif
const Surface &out = Surface(DiabloUiSurface());
const Point position = GetPosition();
@ -140,23 +137,12 @@ bool UiProgressDialog(int (*fnfunc)())
while (PollEvent(&event)) {
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
#else
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
#endif
UiItemMouseEvents(&event, vecProgress);
break;
#ifdef USE_SDL3
case SDL_EVENT_KEY_DOWN:
switch (event.key.key)
#else
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
#endif
{
switch (SDLC_EventKey(event)) {
#ifndef USE_SDL1
case SDLK_KP_ENTER:
#endif

4
Source/DiabloUI/selyesno.cpp

@ -5,7 +5,11 @@
#include <optional>
#include <vector>
#ifdef USE_SDL3
#include <SDL3/SDL_rect.h>
#else
#include <SDL.h>
#endif
#include "DiabloUI/diabloui.h"
#include "DiabloUI/ui_flags.hpp"

28
Source/DiabloUI/settingsmenu.cpp

@ -7,7 +7,14 @@
#include <string>
#include <vector>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_rect.h>
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif
#include <function_ref.hpp>
#include "DiabloUI/diabloui.h"
@ -29,6 +36,7 @@
#include "utils/enum_traits.h"
#include "utils/is_of.hpp"
#include "utils/language.h"
#include "utils/sdl_compat.h"
#include "utils/sdl_geometry.h"
#include "utils/static_vector.hpp"
#include "utils/str_cat.hpp"
@ -445,15 +453,15 @@ void UiSettingsMenu()
return false;
uint32_t key = SDLK_UNKNOWN;
switch (event.type) {
case SDL_KEYDOWN: {
SDL_Keycode keycode = event.key.keysym.sym;
case SDL_EVENT_KEY_DOWN: {
SDL_Keycode keycode = SDLC_EventKey(event);
remap_keyboard_key(&keycode);
key = static_cast<uint32_t>(keycode);
if (key >= SDLK_a && key <= SDLK_z) {
if (key >= SDLK_A && key <= SDLK_Z) {
key -= 'a' - 'A';
}
} break;
case SDL_MOUSEBUTTONDOWN:
case SDL_EVENT_MOUSE_BUTTON_DOWN:
switch (event.button.button) {
case SDL_BUTTON_MIDDLE:
case SDL_BUTTON_X1:
@ -463,14 +471,14 @@ void UiSettingsMenu()
}
break;
#if SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0) {
case SDL_EVENT_MOUSE_WHEEL:
if (SDLC_EventWheelIntY(event) > 0) {
key = MouseScrollUpButton;
} else if (event.wheel.y < 0) {
} else if (SDLC_EventWheelIntY(event) < 0) {
key = MouseScrollDownButton;
} else if (event.wheel.x > 0) {
} else if (SDLC_EventWheelIntX(event) > 0) {
key = MouseScrollLeftButton;
} else if (event.wheel.x < 0) {
} else if (SDLC_EventWheelIntX(event) < 0) {
key = MouseScrollRightButton;
}
break;
@ -511,7 +519,7 @@ void UiSettingsMenu()
for (const ControllerButtonEvent ctrlEvent : ctrlEvents) {
const bool isGamepadMotion = IsControllerMotion(event);
DetectInputMethod(event, ctrlEvent);
if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) {
if (event.type == SDL_EVENT_KEY_UP && SDLC_EventKey(event) == SDLK_ESCAPE) {
StopPadEntryTimer();
return true;
}

68
Source/DiabloUI/text_input.cpp

@ -21,6 +21,7 @@
#include "utils/log.hpp"
#include "utils/parse_int.hpp"
#include "utils/sdl_compat.h"
#include "utils/sdl_ptrs.h"
#include "utils/str_cat.hpp"
@ -33,70 +34,32 @@ bool HandleInputEvent(const SDL_Event &event, TextInputState &state,
[[maybe_unused]] tl::function_ref<bool(std::string_view)> assignFn)
{
const auto modState = SDL_GetModState();
#ifdef USE_SDL3
const bool isCtrl = (modState & SDL_KMOD_CTRL) != 0;
const bool isAlt = (modState & SDL_KMOD_ALT) != 0;
const bool isShift = (modState & SDL_KMOD_SHIFT) != 0;
#else
const bool isCtrl = (modState & KMOD_CTRL) != 0;
const bool isAlt = (modState & KMOD_ALT) != 0;
const bool isShift = (modState & KMOD_SHIFT) != 0;
#endif
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_KEY_DOWN:
#else
case SDL_KEYDOWN:
#endif
{
#ifdef USE_SDL3
switch (event.key.key)
#else
switch (event.key.keysym.sym)
#endif
{
case SDL_EVENT_KEY_DOWN: {
switch (SDLC_EventKey(event)) {
#ifndef USE_SDL1
#ifdef USE_SDL3
case SDLK_A:
#else
case SDLK_a:
#endif
if (isCtrl) {
state.setCursorToStart();
state.setSelectCursorToEnd();
}
return true;
#ifdef USE_SDL3
case SDLK_C:
#else
case SDLK_c:
#endif
if (isCtrl) {
const std::string selectedText { state.selectedText() };
#ifdef USE_SDL3
if (SDL_SetClipboardText(selectedText.c_str()))
#else
if (SDL_SetClipboardText(selectedText.c_str()) < 0)
#endif
{
if (SDLC_SetClipboardText(selectedText.c_str())) {
LogError("Failed to set clipboard text: {}", SDL_GetError());
SDL_ClearError();
}
}
return true;
#ifdef USE_SDL3
case SDLK_X:
#else
case SDLK_x:
#endif
if (isCtrl) {
const std::string selectedText { state.selectedText() };
#ifdef USE_SDL3
if (SDL_SetClipboardText(selectedText.c_str()))
#else
if (SDL_SetClipboardText(selectedText.c_str()) < 0)
#endif
{
if (SDLC_SetClipboardText(selectedText.c_str())) {
LogError("Failed to set clipboard text: {}", SDL_GetError());
SDL_ClearError();
} else {
@ -104,18 +67,9 @@ bool HandleInputEvent(const SDL_Event &event, TextInputState &state,
}
}
return true;
#ifdef USE_SDL3
case SDLK_V:
#else
case SDLK_v:
#endif
if (isCtrl) {
#if USE_SDL3
if (SDL_HasClipboardText())
#else
if (SDL_HasClipboardText() == SDL_TRUE)
#endif
{
if (SDLC_HasClipboardText()) {
const std::unique_ptr<char, SDLFreeDeleter<char>> clipboard { SDL_GetClipboardText() };
if (clipboard == nullptr) {
LogError("Failed to get clipboard text: {}", SDL_GetError());
@ -158,19 +112,11 @@ bool HandleInputEvent(const SDL_Event &event, TextInputState &state,
#else
// Mark events that will also trigger SDL_TEXTINPUT as handled.
return !isCtrl && !isAlt
#ifdef USE_SDL3
&& event.key.key >= SDLK_SPACE && event.key.key <= SDLK_Z;
#else
&& event.key.keysym.sym >= SDLK_SPACE && event.key.keysym.sym <= SDLK_z;
#endif
&& SDLC_EventKey(event) >= SDLK_SPACE && SDLC_EventKey(event) <= SDLK_Z;
#endif
} break;
#ifndef USE_SDL1
#ifdef USE_SDL3
case SDL_EVENT_TEXT_INPUT:
#else
case SDL_TEXTINPUT:
#endif
#ifdef __vita__
assignFn(event.text.text);
#else

11
Source/DiabloUI/title.cpp

@ -2,7 +2,13 @@
#include <optional>
#include <vector>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_rect.h>
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif
#include "DiabloUI/diabloui.h"
#include "DiabloUI/ui_flags.hpp"
@ -16,6 +22,7 @@
#include "engine/point.hpp"
#include "utils/algorithm/container.hpp"
#include "utils/language.h"
#include "utils/sdl_compat.h"
#include "utils/sdl_geometry.h"
#include "utils/ui_fwd.h"
@ -83,8 +90,8 @@ void UiTitleDialog()
break;
}
switch (event.type) {
case SDL_KEYDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
endMenu = true;
break;
}

5
Source/appfat.cpp

@ -15,6 +15,7 @@
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
#include "utils/sdl_compat.h"
#endif
#include <fmt/format.h>
@ -35,11 +36,7 @@ namespace {
bool Terminating = false;
/** Thread id of the last callee to FreeDlg(). */
#ifdef USE_SDL3
SDL_ThreadID CleanupThreadId;
#else
SDL_threadID CleanupThreadId;
#endif
/**
* @brief Cleans up after a fatal application error.

13
Source/capture.cpp

@ -15,6 +15,8 @@
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#include "utils/sdl_compat.h"
#endif
#include <expected.hpp>
@ -41,12 +43,7 @@
namespace devilution {
namespace {
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
CaptureFile(std::string *dstPath)
SDL_IOStream *CaptureFile(std::string *dstPath)
{
const char *ext =
#if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PCX
@ -67,11 +64,7 @@ CaptureFile(std::string *dstPath)
i++;
*dstPath = StrCat(paths::PrefPath(), filename, "-", i, ext);
}
#ifdef USE_SDL3
return SDL_IOFromFile(dstPath->c_str(), "wb");
#else
return SDL_RWFromFile(dstPath->c_str(), "wb");
#endif
}
/**

37
Source/control.cpp

@ -72,6 +72,7 @@
#include "utils/log.hpp"
#include "utils/parse_int.hpp"
#include "utils/screen_reader.hpp"
#include "utils/sdl_compat.h"
#include "utils/sdl_geometry.h"
#include "utils/sdl_ptrs.h"
#include "utils/status_macros.hpp"
@ -1249,14 +1250,7 @@ void CheckMainPanelButton()
SetPanelObjectPosition(UiPanels::Main, spellSelectButton);
if (!SpellSelectFlag && spellSelectButton.contains(MousePosition)) {
if ((SDL_GetModState() &
#ifdef USE_SDL3
SDL_KMOD_SHIFT
#else
KMOD_SHIFT
#endif
)
!= 0) {
if ((SDL_GetModState() & SDL_KMOD_SHIFT) != 0) {
Player &myPlayer = *MyPlayer;
myPlayer._pRSpell = SpellID::Invalid;
myPlayer._pRSplType = SpellType::Invalid;
@ -1938,23 +1932,14 @@ void TypeChatMessage()
TalkSaveIndex = NextTalkSave;
SDL_Rect rect = MakeSdlRect(GetMainPanel().position.x + 200, GetMainPanel().position.y + 22, 0, 27);
#ifdef USE_SDL3
SDL_SetTextInputArea(ghMainWnd, &rect, /*cursor=*/0);
SDL_StartTextInput(ghMainWnd);
#else
SDL_SetTextInputRect(&rect);
SDL_StartTextInput();
#endif
SDLC_StartTextInput(ghMainWnd);
}
void ResetChat()
{
ChatFlag = false;
#ifdef USE_SDL3
SDL_StopTextInput(ghMainWnd);
#else
SDL_StopTextInput();
#endif
SDLC_StopTextInput(ghMainWnd);
ChatCursor = {};
ChatInputState = std::nullopt;
sgbPlrTalkTbl = 0;
@ -2015,7 +2000,7 @@ bool CheckKeypress(SDL_Keycode vkey)
ControlUpDown(-1);
return true;
default:
return vkey >= SDLK_SPACE && vkey <= SDLK_z;
return vkey >= SDLK_SPACE && vkey <= SDLK_Z;
}
}
@ -2060,22 +2045,14 @@ void OpenGoldDrop(int8_t invIndex, int max)
.min = 0,
.max = max,
});
#ifdef USE_SDL3
SDL_StartTextInput(ghMainWnd);
#else
SDL_StartTextInput();
#endif
SDLC_StartTextInput(ghMainWnd);
}
void CloseGoldDrop()
{
if (!DropGoldFlag)
return;
#ifdef USE_SDL3
SDL_StopTextInput(ghMainWnd);
#else
SDL_StopTextInput();
#endif
SDLC_StopTextInput(ghMainWnd);
DropGoldFlag = false;
GoldDropInputState = std::nullopt;
GoldDropInvIndex = 0;

31
Source/controls/controller.cpp

@ -13,8 +13,8 @@
#endif
#include "controls/devices/joystick.h"
#include "controls/devices/kbcontroller.h"
#include "engine/demomode.h"
#include "utils/sdl_compat.h"
namespace devilution {
@ -36,16 +36,10 @@ StaticVector<ControllerButtonEvent, 4> ToControllerButtonEvents(const SDL_Event
{
ControllerButtonEvent result { ControllerButton_NONE, false };
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_BUTTON_UP:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
case SDL_EVENT_KEY_UP:
#else
#ifndef USE_SDL1
case SDL_CONTROLLERBUTTONUP:
#endif
case SDL_JOYBUTTONUP:
case SDL_KEYUP:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
#endif
result.up = true;
break;
@ -103,33 +97,16 @@ bool HandleControllerAddedOrRemovedEvent(const SDL_Event &event)
{
#ifndef USE_SDL1
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_ADDED:
GameController::Add(event.gdevice.which);
GameController::Add(SDLC_EventGamepadDevice(event).which);
break;
case SDL_EVENT_GAMEPAD_REMOVED:
GameController::Remove(event.gdevice.which);
break;
#else
case SDL_CONTROLLERDEVICEADDED:
GameController::Add(event.cdevice.which);
GameController::Remove(SDLC_EventGamepadDevice(event).which);
break;
case SDL_CONTROLLERDEVICEREMOVED:
GameController::Remove(event.cdevice.which);
break;
#endif
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_ADDED:
#else
case SDL_JOYDEVICEADDED:
#endif
Joystick::Add(event.jdevice.which);
break;
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_REMOVED:
#else
case SDL_JOYDEVICEREMOVED:
#endif
Joystick::Remove(event.jdevice.which);
break;
default:

21
Source/controls/controller_motion.cpp

@ -4,6 +4,7 @@
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_gamepad.h>
#else
#include <SDL.h>
#endif
@ -23,6 +24,7 @@
#include "options.h"
#include "utils/is_of.hpp"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
namespace devilution {
@ -150,32 +152,17 @@ void ScaleJoysticks()
bool IsControllerMotion(const SDL_Event &event)
{
#ifndef USE_SDL1
#ifdef USE_SDL3
if (event.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
return IsAnyOf(event.gaxis.axis,
return IsAnyOf(SDLC_EventGamepadAxis(event).axis,
SDL_GAMEPAD_AXIS_LEFTX,
SDL_GAMEPAD_AXIS_LEFTY,
SDL_GAMEPAD_AXIS_RIGHTX,
SDL_GAMEPAD_AXIS_RIGHTY);
}
#else
if (event.type == SDL_CONTROLLERAXISMOTION) {
return IsAnyOf(event.caxis.axis,
SDL_CONTROLLER_AXIS_LEFTX,
SDL_CONTROLLER_AXIS_LEFTY,
SDL_CONTROLLER_AXIS_RIGHTX,
SDL_CONTROLLER_AXIS_RIGHTY);
}
#endif
#endif
#if defined(JOY_AXIS_LEFTX) || defined(JOY_AXIS_LEFTY) || defined(JOY_AXIS_RIGHTX) || defined(JOY_AXIS_RIGHTY)
#ifdef USE_SDL3
if (event.type == SDL_EVENT_JOYSTICK_AXIS_MOTION)
#else
if (event.type == SDL_JOYAXISMOTION)
#endif
{
if (event.type == SDL_EVENT_JOYSTICK_AXIS_MOTION) {
switch (event.jaxis.axis) {
#ifdef JOY_AXIS_LEFTX
case JOY_AXIS_LEFTX:

192
Source/controls/devices/game_controller.cpp

@ -16,6 +16,7 @@
#include "controls/controller_motion.h"
#include "controls/devices/joystick.h"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
#include "utils/sdl_ptrs.h"
#include "utils/stubs.h"
@ -32,24 +33,10 @@ void GameController::UnlockTriggerState()
ControllerButton GameController::ToControllerButton(const SDL_Event &event)
{
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
#else
case SDL_CONTROLLERAXISMOTION:
#endif
{
const auto &axis =
#ifdef USE_SDL3
event.gaxis;
#else
event.caxis;
#endif
case SDL_EVENT_GAMEPAD_AXIS_MOTION: {
const SDL_GamepadAxisEvent &axis = SDLC_EventGamepadAxis(event);
switch (axis.axis) {
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER:
#else
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
#endif
if (axis.value < 8192 && trigger_left_is_down_) { // 25% pressed
trigger_left_is_down_ = false;
trigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT;
@ -59,11 +46,7 @@ ControllerButton GameController::ToControllerButton(const SDL_Event &event)
trigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT;
}
return trigger_left_state_;
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:
#else
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
#endif
if (axis.value < 8192 && trigger_right_is_down_) { // 25% pressed
trigger_right_is_down_ = false;
trigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT;
@ -75,99 +58,36 @@ ControllerButton GameController::ToControllerButton(const SDL_Event &event)
return trigger_right_state_;
}
} break;
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
switch (event.gbutton.button)
#else
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
switch (event.cbutton.button)
#endif
{
#ifdef USE_SDL3
switch (SDLC_EventGamepadButton(event).button) {
case SDL_GAMEPAD_BUTTON_SOUTH:
#else
case SDL_CONTROLLER_BUTTON_A:
#endif
return ControllerButton_BUTTON_A;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_EAST:
#else
case SDL_CONTROLLER_BUTTON_B:
#endif
return ControllerButton_BUTTON_B;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_WEST:
#else
case SDL_CONTROLLER_BUTTON_X:
#endif
return ControllerButton_BUTTON_X;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_NORTH:
#else
case SDL_CONTROLLER_BUTTON_Y:
#endif
return ControllerButton_BUTTON_Y;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_LEFT_STICK:
#else
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
#endif
return ControllerButton_BUTTON_LEFTSTICK;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_RIGHT_STICK:
#else
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
#endif
return ControllerButton_BUTTON_RIGHTSTICK;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:
#else
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
#endif
return ControllerButton_BUTTON_LEFTSHOULDER;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:
#else
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
#endif
return ControllerButton_BUTTON_RIGHTSHOULDER;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_START:
#else
case SDL_CONTROLLER_BUTTON_START:
#endif
return ControllerButton_BUTTON_START;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_BACK:
#else
case SDL_CONTROLLER_BUTTON_BACK:
#endif
return ControllerButton_BUTTON_BACK;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_DPAD_UP:
#else
case SDL_CONTROLLER_BUTTON_DPAD_UP:
#endif
return ControllerButton_BUTTON_DPAD_UP;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
#else
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
#endif
return ControllerButton_BUTTON_DPAD_DOWN;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
#else
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
#endif
return ControllerButton_BUTTON_DPAD_LEFT;
#ifdef USE_SDL3
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
#else
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
#endif
return ControllerButton_BUTTON_DPAD_RIGHT;
default:
break;
@ -178,105 +98,41 @@ ControllerButton GameController::ToControllerButton(const SDL_Event &event)
return ControllerButton_NONE;
}
#ifdef USE_SDL3
SDL_GamepadButton GameController::ToSdlGameControllerButton(ControllerButton button)
#else
SDL_GameControllerButton GameController::ToSdlGameControllerButton(ControllerButton button)
#endif
{
if (button == ControllerButton_AXIS_TRIGGERLEFT || button == ControllerButton_AXIS_TRIGGERRIGHT)
UNIMPLEMENTED();
switch (button) {
case ControllerButton_BUTTON_A:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_SOUTH;
#else
return SDL_CONTROLLER_BUTTON_A;
#endif
case ControllerButton_BUTTON_B:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_EAST;
#else
return SDL_CONTROLLER_BUTTON_B;
#endif
case ControllerButton_BUTTON_X:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_WEST;
#else
return SDL_CONTROLLER_BUTTON_X;
#endif
case ControllerButton_BUTTON_Y:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_NORTH;
#else
return SDL_CONTROLLER_BUTTON_Y;
#endif
case ControllerButton_BUTTON_BACK:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_BACK;
#else
return SDL_CONTROLLER_BUTTON_BACK;
#endif
case ControllerButton_BUTTON_START:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_START;
#else
return SDL_CONTROLLER_BUTTON_START;
#endif
case ControllerButton_BUTTON_LEFTSTICK:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_LEFT_STICK;
#else
return SDL_CONTROLLER_BUTTON_LEFTSTICK;
#endif
case ControllerButton_BUTTON_RIGHTSTICK:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_RIGHT_STICK;
#else
return SDL_CONTROLLER_BUTTON_RIGHTSTICK;
#endif
case ControllerButton_BUTTON_LEFTSHOULDER:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_LEFT_SHOULDER;
#else
return SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
#endif
case ControllerButton_BUTTON_RIGHTSHOULDER:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER;
#else
return SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
#endif
case ControllerButton_BUTTON_DPAD_UP:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_DPAD_UP;
#else
return SDL_CONTROLLER_BUTTON_DPAD_UP;
#endif
case ControllerButton_BUTTON_DPAD_DOWN:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_DPAD_DOWN;
#else
return SDL_CONTROLLER_BUTTON_DPAD_DOWN;
#endif
case ControllerButton_BUTTON_DPAD_LEFT:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_DPAD_LEFT;
#else
return SDL_CONTROLLER_BUTTON_DPAD_LEFT;
#endif
case ControllerButton_BUTTON_DPAD_RIGHT:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_DPAD_RIGHT;
#else
return SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
#endif
default:
#ifdef USE_SDL3
return SDL_GAMEPAD_BUTTON_INVALID;
#else
return SDL_CONTROLLER_BUTTON_INVALID;
#endif
}
}
@ -287,54 +143,28 @@ bool GameController::IsPressed(ControllerButton button) const
if (button == ControllerButton_AXIS_TRIGGERRIGHT)
return trigger_right_is_down_;
#ifdef USE_SDL3
const SDL_GamepadButton gcButton = ToSdlGameControllerButton(button);
return SDL_GamepadHasButton(sdl_game_controller_, gcButton) && SDL_GetGamepadButton(sdl_game_controller_, gcButton);
#else
const SDL_GameControllerButton gcButton = ToSdlGameControllerButton(button);
return SDL_GameControllerHasButton(sdl_game_controller_, gcButton) && SDL_GameControllerGetButton(sdl_game_controller_, gcButton) != 0;
#endif
}
bool GameController::ProcessAxisMotion(const SDL_Event &event)
{
#ifdef USE_SDL3
if (event.type != SDL_EVENT_GAMEPAD_AXIS_MOTION) return false;
const auto &axis = event.gaxis;
#else
if (event.type != SDL_CONTROLLERAXISMOTION) return false;
const auto &axis = event.caxis;
#endif
const SDL_GamepadAxisEvent &axis = SDLC_EventGamepadAxis(event);
switch (axis.axis) {
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_LEFTX:
#else
case SDL_CONTROLLER_AXIS_LEFTX:
#endif
leftStickXUnscaled = static_cast<float>(axis.value);
leftStickNeedsScaling = true;
break;
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_LEFTY:
#else
case SDL_CONTROLLER_AXIS_LEFTY:
#endif
leftStickYUnscaled = static_cast<float>(-axis.value);
leftStickNeedsScaling = true;
break;
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_RIGHTX:
#else
case SDL_CONTROLLER_AXIS_RIGHTX:
#endif
rightStickXUnscaled = static_cast<float>(axis.value);
rightStickNeedsScaling = true;
break;
#ifdef USE_SDL3
case SDL_GAMEPAD_AXIS_RIGHTY:
#else
case SDL_CONTROLLER_AXIS_RIGHTY:
#endif
rightStickYUnscaled = static_cast<float>(-axis.value);
rightStickNeedsScaling = true;
break;
@ -405,19 +235,11 @@ GameController *GameController::Get(SDL_JoystickID instanceId)
GameController *GameController::Get(const SDL_Event &event)
{
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
return Get(event.gaxis.which);
return Get(SDLC_EventGamepadAxis(event).which);
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
return Get(event.gbutton.which);
#else
case SDL_CONTROLLERAXISMOTION:
return Get(event.caxis.which);
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
return Get(event.cbutton.which);
#endif
return Get(SDLC_EventGamepadButton(event).which);
default:
return nullptr;
}

30
Source/controls/devices/joystick.cpp

@ -16,6 +16,7 @@
#include "controls/controller_motion.h"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
#include "utils/stubs.h"
namespace devilution {
@ -25,14 +26,8 @@ std::vector<Joystick> Joystick::joysticks_;
StaticVector<ControllerButtonEvent, 4> Joystick::ToControllerButtonEvents(const SDL_Event &event)
{
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
#else
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
#endif
{
case SDL_EVENT_JOYSTICK_BUTTON_UP: {
#ifdef USE_SDL3
const bool up = !event.jbutton.down;
#else
@ -331,11 +326,7 @@ bool Joystick::IsPressed(ControllerButton button) const
bool Joystick::ProcessAxisMotion(const SDL_Event &event)
{
#ifdef USE_SDL3
if (event.type != SDL_EVENT_JOYSTICK_AXIS_MOTION) return false;
#else
if (event.type != SDL_JOYAXISMOTION) return false;
#endif
#if defined(JOY_AXIS_LEFTX) || defined(JOY_AXIS_LEFTY) || defined(JOY_AXIS_RIGHTX) || defined(JOY_AXIS_RIGHTY)
switch (event.jaxis.axis) {
@ -445,31 +436,14 @@ Joystick *Joystick::Get(const SDL_Event &event)
{
switch (event.type) {
#ifndef USE_SDL1
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
#else
case SDL_JOYAXISMOTION:
#endif
return Get(event.jaxis.which);
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_BALL_MOTION:
#else
case SDL_JOYBALLMOTION:
#endif
return Get(event.jball.which);
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_HAT_MOTION:
#else
case SDL_JOYHATMOTION:
#endif
return Get(event.jhat.which);
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
#else
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
#endif
return Get(event.jbutton.which);
default:
return nullptr;

34
Source/controls/menu_controls.cpp

@ -103,20 +103,8 @@ std::vector<MenuAction> GetMenuActions(const SDL_Event &event)
}
#if HAS_KBCTRL == 0
if (
event.type ==
#ifdef USE_SDL3
SDL_EVENT_KEY_DOWN
#else
SDL_KEYDOWN
#endif
) {
SDL_Keycode sym =
#ifdef USE_SDL3
event.key.key;
#else
event.key.keysym.sym;
#endif
if (event.type == SDL_EVENT_KEY_DOWN) {
SDL_Keycode sym = SDLC_EventKey(event);
remap_keyboard_key(&sym);
switch (sym) {
case SDLK_UP:
@ -124,14 +112,7 @@ std::vector<MenuAction> GetMenuActions(const SDL_Event &event)
case SDLK_DOWN:
return { MenuAction_DOWN };
case SDLK_TAB:
if ((SDL_GetModState() &
#ifdef USE_SDL3
SDL_KMOD_SHIFT
#else
KMOD_SHIFT
#endif
)
!= 0) {
if ((SDL_GetModState() & SDL_KMOD_SHIFT) != 0) {
return { MenuAction_UP };
}
return { MenuAction_DOWN };
@ -140,14 +121,7 @@ std::vector<MenuAction> GetMenuActions(const SDL_Event &event)
case SDLK_PAGEDOWN:
return { MenuAction_PAGE_DOWN };
case SDLK_RETURN:
if ((SDL_GetModState() &
#ifdef USE_SDL3
SDL_KMOD_ALT
#else
KMOD_ALT
#endif
)
== 0) {
if ((SDL_GetModState() & SDL_KMOD_ALT) == 0) {
return { MenuAction_SELECT };
}
break;

66
Source/controls/plrctrls.cpp

@ -51,6 +51,7 @@
#include "track.h"
#include "utils/is_of.hpp"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
#include "utils/str_cat.hpp"
namespace devilution {
@ -1601,13 +1602,8 @@ bool IsStickMovementSignificant()
ControlTypes GetInputTypeFromEvent(const SDL_Event &event)
{
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_KEY_UP:
#else
case SDL_KEYDOWN:
case SDL_KEYUP:
#endif
return ControlTypes::KeyboardAndMouse;
#ifdef USE_SDL1
case SDL_MOUSEBUTTONDOWN:
@ -1615,81 +1611,38 @@ ControlTypes GetInputTypeFromEvent(const SDL_Event &event)
case SDL_MOUSEMOTION:
return ControlTypes::KeyboardAndMouse;
#else
// SDL 2/3-only events (touch / gamepad):
#ifdef USE_SDL3
// SDL 2/3-only events (touch / gamepad):
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
#else
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
#endif
return event.button.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse;
#ifdef USE_SDL3
case SDL_EVENT_MOUSE_MOTION:
#else
case SDL_MOUSEMOTION:
#endif
return event.motion.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse;
#ifdef USE_SDL3
case SDL_EVENT_MOUSE_WHEEL:
#else
case SDL_MOUSEWHEEL:
#endif
return event.wheel.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse;
#ifdef USE_SDL3
case SDL_EVENT_FINGER_DOWN:
case SDL_EVENT_FINGER_UP:
case SDL_EVENT_FINGER_MOTION:
#else
case SDL_FINGERDOWN:
case SDL_FINGERUP:
case SDL_FINGERMOTION:
#endif
return ControlTypes::VirtualGamepad;
#ifdef USE_SDL3
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
#else
case SDL_CONTROLLERAXISMOTION:
#endif
if (
#ifdef USE_SDL3
IsAnyOf(event.gaxis.axis, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)
#else
IsAnyOf(event.caxis.axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT, SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
#endif
if (IsAnyOf(SDLC_EventGamepadAxis(event).axis, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)
|| IsStickMovementSignificant()) {
return ControlTypes::Gamepad;
}
break;
#endif // !USE_SDL1
#ifdef USE_SDL3
#ifndef USE_SDL1
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
case SDL_EVENT_GAMEPAD_ADDED:
#endif
case SDL_EVENT_JOYSTICK_BALL_MOTION:
case SDL_EVENT_JOYSTICK_HAT_MOTION:
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
#else
#ifndef USE_SDL1
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED:
#endif
case SDL_JOYBALLMOTION:
case SDL_JOYHATMOTION:
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
#endif
return ControlTypes::Gamepad;
#ifdef USE_SDL3
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
case SDL_EVENT_JOYSTICK_ADDED:
#else
case SDL_JOYAXISMOTION:
#ifndef USE_SDL1
case SDL_JOYDEVICEADDED:
#endif
case SDL_EVENT_JOYSTICK_ADDED:
#endif
if (IsStickMovementSignificant()) return ControlTypes::Gamepad;
break;
@ -1708,13 +1661,8 @@ bool ContinueSimulatedMouseEvent(const SDL_Event &event, const ControllerButtonE
#if !defined(USE_SDL1) && !defined(JOY_AXIS_RIGHTX) && !defined(JOY_AXIS_RIGHTY)
if (IsAnyOf(event.type,
#ifdef USE_SDL3
SDL_EVENT_JOYSTICK_AXIS_MOTION, SDL_EVENT_JOYSTICK_HAT_MOTION,
SDL_EVENT_JOYSTICK_BUTTON_DOWN, SDL_EVENT_JOYSTICK_BUTTON_UP
#else
SDL_JOYAXISMOTION, SDL_JOYHATMOTION, SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP
#endif
)
SDL_EVENT_JOYSTICK_BUTTON_DOWN, SDL_EVENT_JOYSTICK_BUTTON_UP)
&& !GameController::All().empty()) {
return true;
}

13
Source/controls/touch/event_handlers.cpp

@ -21,6 +21,7 @@
#include "qol/stash.h"
#include "stores.h"
#include "utils/is_of.hpp"
#include "utils/sdl_compat.h"
#include "utils/ui_fwd.h"
namespace devilution {
@ -45,29 +46,17 @@ Point ScaleToScreenCoordinates(float x, float y)
constexpr bool IsFingerDown(const SDL_Event &event)
{
#ifdef USE_SDL3
return event.type == SDL_EVENT_FINGER_DOWN;
#else
return event.type == SDL_FINGERDOWN;
#endif
}
constexpr bool IsFingerUp(const SDL_Event &event)
{
#ifdef USE_SDL3
return event.type == SDL_EVENT_FINGER_UP;
#else
return event.type == SDL_FINGERUP;
#endif
}
constexpr bool IsFingerMotion(const SDL_Event &event)
{
#ifdef USE_SDL3
return event.type == SDL_EVENT_FINGER_MOTION;
#else
return event.type == SDL_FINGERMOTION;
#endif
}
constexpr SDL_FingerID FingerId(const SDL_TouchFingerEvent &event)

13
Source/cursor.cpp

@ -509,30 +509,17 @@ void CreateHalfSizeItemSprites()
const Surface itemSurface = ownedItemSurface.subregion(0, 0, itemSprite.width(), itemSprite.height());
const SDL_Rect itemSurfaceRect = MakeSdlRect(0, 0, itemSurface.w(), itemSurface.h());
#ifdef USE_SDL3
SDL_SetSurfaceClipRect(itemSurface.surface, &itemSurfaceRect);
SDL_FillSurfaceRect(itemSurface.surface, nullptr, 1);
#else
SDL_SetClipRect(itemSurface.surface, &itemSurfaceRect);
SDL_FillRect(itemSurface.surface, nullptr, 1);
#endif
ClxDraw(itemSurface, { 0, itemSurface.h() }, itemSprite);
const Surface halfSurface = ownedHalfSurface.subregion(0, 0, itemSurface.w() / 2, itemSurface.h() / 2);
const SDL_Rect halfSurfaceRect = MakeSdlRect(0, 0, halfSurface.w(), halfSurface.h());
#ifdef USE_SDL3
SDL_SetSurfaceClipRect(halfSurface.surface, &halfSurfaceRect);
#else
SDL_SetClipRect(halfSurface.surface, &halfSurfaceRect);
#endif
BilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1);
HalfSizeItemSprites[outputIndex].emplace(SurfaceToClx(halfSurface, 1, 1));
#ifdef USE_SDL3
SDL_FillSurfaceRect(itemSurface.surface, nullptr, 1);
#else
SDL_FillRect(itemSurface.surface, nullptr, 1);
#endif
ClxDrawTRN(itemSurface, { 0, itemSurface.h() }, itemSprite, redTrn);
BilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1);
HalfSizeItemSpritesRed[outputIndex].emplace(SurfaceToClx(halfSurface, 1, 1));

83
Source/diablo.cpp

@ -109,6 +109,7 @@
#include "utils/parse_int.hpp"
#include "utils/paths.h"
#include "utils/screen_reader.hpp"
#include "utils/sdl_compat.h"
#include "utils/sdl_thread.h"
#include "utils/status_macros.hpp"
#include "utils/str_cat.hpp"
@ -363,8 +364,8 @@ void LeftMouseDown(uint16_t modState)
return;
}
const bool isShiftHeld = (modState & KMOD_SHIFT) != 0;
const bool isCtrlHeld = (modState & KMOD_CTRL) != 0;
const bool isShiftHeld = (modState & SDL_KMOD_SHIFT) != 0;
const bool isCtrlHeld = (modState & SDL_KMOD_CTRL) != 0;
if (!GetMainPanel().contains(MousePosition)) {
if (!gmenu_is_active() && !TryIconCurs()) {
@ -417,7 +418,7 @@ void LeftMouseUp(uint16_t modState)
CheckMainPanelButtonUp();
CheckStashButtonRelease(MousePosition);
if (CharPanelButtonActive) {
const bool isShiftHeld = (modState & KMOD_SHIFT) != 0;
const bool isShiftHeld = (modState & SDL_KMOD_SHIFT) != 0;
ReleaseChrBtns(isShiftHeld);
}
if (LevelButtonDown)
@ -519,7 +520,7 @@ void PressKey(SDL_Keycode vkey, uint16_t modState)
}
KeymapperPress(vkey);
if (vkey == SDLK_RETURN || vkey == SDLK_KP_ENTER) {
if ((modState & KMOD_ALT) != 0) {
if ((modState & SDL_KMOD_ALT) != 0) {
options.Graphics.fullscreen.SetValue(!IsFullScreen());
if (!demo::IsRunning()) SaveOptions();
} else {
@ -555,7 +556,7 @@ void PressKey(SDL_Keycode vkey, uint16_t modState)
KeymapperPress(vkey);
if (PauseMode == 2) {
if ((vkey == SDLK_RETURN || vkey == SDLK_KP_ENTER) && (modState & KMOD_ALT) != 0) {
if ((vkey == SDLK_RETURN || vkey == SDLK_KP_ENTER) && (modState & SDL_KMOD_ALT) != 0) {
options.Graphics.fullscreen.SetValue(!IsFullScreen());
if (!demo::IsRunning()) SaveOptions();
}
@ -584,8 +585,8 @@ void PressKey(SDL_Keycode vkey, uint16_t modState)
}
return;
#ifdef _DEBUG
case SDLK_v:
if ((modState & KMOD_SHIFT) != 0)
case SDLK_V:
if ((modState & SDL_KMOD_SHIFT) != 0)
NextDebugMonster();
else
GetDebugMonster();
@ -593,7 +594,7 @@ void PressKey(SDL_Keycode vkey, uint16_t modState)
#endif
case SDLK_RETURN:
case SDLK_KP_ENTER:
if ((modState & KMOD_ALT) != 0) {
if ((modState & SDL_KMOD_ALT) != 0) {
options.Graphics.fullscreen.SetValue(!IsFullScreen());
if (!demo::IsRunning()) SaveOptions();
} else if (IsPlayerInStore()) {
@ -682,7 +683,7 @@ void HandleMouseButtonDown(Uint8 button, uint16_t modState)
case SDL_BUTTON_RIGHT:
if (sgbMouseDown == CLICK_NONE) {
sgbMouseDown = CLICK_RIGHT;
RightMouseDown((modState & KMOD_SHIFT) != 0);
RightMouseDown((modState & SDL_KMOD_SHIFT) != 0);
}
break;
default:
@ -765,29 +766,29 @@ void GameEventHandler(const SDL_Event &event, uint16_t modState)
}
switch (event.type) {
case SDL_KEYDOWN:
PressKey(event.key.keysym.sym, modState);
case SDL_EVENT_KEY_DOWN:
PressKey(SDLC_EventKey(event), modState);
return;
case SDL_KEYUP:
ReleaseKey(event.key.keysym.sym);
case SDL_EVENT_KEY_UP:
ReleaseKey(SDLC_EventKey(event));
return;
case SDL_MOUSEMOTION:
case SDL_EVENT_MOUSE_MOTION:
if (ControlMode == ControlTypes::KeyboardAndMouse && invflag)
InvalidateInventorySlot();
MousePosition = { event.motion.x, event.motion.y };
MousePosition = { SDLC_EventMotionIntX(event), SDLC_EventMotionIntY(event) };
gmenu_on_mouse_move();
return;
case SDL_MOUSEBUTTONDOWN:
MousePosition = { event.button.x, event.button.y };
case SDL_EVENT_MOUSE_BUTTON_DOWN:
MousePosition = { SDLC_EventButtonIntX(event), SDLC_EventButtonIntY(event) };
HandleMouseButtonDown(event.button.button, modState);
return;
case SDL_MOUSEBUTTONUP:
MousePosition = { event.button.x, event.button.y };
case SDL_EVENT_MOUSE_BUTTON_UP:
MousePosition = { SDLC_EventButtonIntX(event), SDLC_EventButtonIntY(event) };
HandleMouseButtonUp(event.button.button, modState);
return;
#if SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0) { // Up
case SDL_EVENT_MOUSE_WHEEL:
if (SDLC_EventWheelIntY(event)) { // Up
if (IsPlayerInStore()) {
StoreUp();
} else if (QuestLogIsOpen) {
@ -798,14 +799,14 @@ void GameEventHandler(const SDL_Event &event, uint16_t modState)
ChatLogScrollUp();
} else if (IsStashOpen) {
Stash.PreviousPage();
} else if (SDL_GetModState() & KMOD_CTRL) {
} else if (SDL_GetModState() & SDL_KMOD_CTRL) {
if (AutomapActive) {
AutomapZoomIn();
}
} else {
KeymapperPress(MouseScrollUpButton);
}
} else if (event.wheel.y < 0) { // down
} else if (SDLC_EventWheelIntY(event)) { // down
if (IsPlayerInStore()) {
StoreDown();
} else if (QuestLogIsOpen) {
@ -816,16 +817,16 @@ void GameEventHandler(const SDL_Event &event, uint16_t modState)
ChatLogScrollDown();
} else if (IsStashOpen) {
Stash.NextPage();
} else if (SDL_GetModState() & KMOD_CTRL) {
} else if (SDL_GetModState() & SDL_KMOD_CTRL) {
if (AutomapActive) {
AutomapZoomOut();
}
} else {
KeymapperPress(MouseScrollDownButton);
}
} else if (event.wheel.x > 0) { // left
} else if (SDLC_EventWheelIntX(event) > 0) { // left
KeymapperPress(MouseScrollLeftButton);
} else if (event.wheel.x < 0) { // right
} else if (SDLC_EventWheelIntX(event) < 0) { // right
KeymapperPress(MouseScrollRightButton);
}
break;
@ -894,7 +895,7 @@ void RunGameLoop(interface_mode uMsg)
SDL_Event event;
uint16_t modState;
while (FetchMessage(&event, &modState)) {
if (event.type == SDL_QUIT) {
if (event.type == SDL_EVENT_QUIT) {
gbRunGameResult = false;
gbRunGame = false;
break;
@ -979,7 +980,7 @@ FILE *SdlLogFile = nullptr;
extern "C" void SdlLogToFile(void *userdata, int category, SDL_LogPriority priority, const char *message)
{
FILE *file = reinterpret_cast<FILE *>(userdata);
static const char *const LogPriorityPrefixes[SDL_NUM_LOG_PRIORITIES] = {
static const char *const LogPriorityPrefixes[SDL_LOG_PRIORITY_COUNT] = {
"",
"VERBOSE",
"DEBUG",
@ -1140,7 +1141,7 @@ void DiabloParseFlags(int argc, char **argv)
} else if (arg == "--vanilla") {
gbVanilla = true;
} else if (arg == "--verbose") {
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
#if SDL_VERSION_ATLEAST(2, 0, 0)
} else if (arg == "--log-to-file") {
if (i + 1 == argc) {
@ -1152,7 +1153,7 @@ void DiabloParseFlags(int argc, char **argv)
printInConsole("Failed to open log file for writing");
diablo_quit(64);
}
SDL_LogSetOutputFunction(&SdlLogToFile, /*userdata=*/SdlLogFile);
SDL_SetLogOutputFunction(&SdlLogToFile, /*userdata=*/SdlLogFile);
#endif
#ifdef _DEBUG
} else if (arg == "-i") {
@ -1337,7 +1338,7 @@ void DiabloDeinit()
if (was_window_init)
dx_cleanup(); // Cleanup SDL surfaces stuff, so we have to do it before SDL_Quit().
UnloadFonts();
if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_HAPTIC) != 0)
if (SDL_WasInit((~0U) & ~SDL_INIT_HAPTIC) != 0)
SDL_Quit();
}
@ -1538,7 +1539,7 @@ void GameLogic()
gGameLogicStep = GameLogicStep::None;
#ifdef _DEBUG
if (DebugScrollViewEnabled && (SDL_GetModState() & KMOD_SHIFT) != 0) {
if (DebugScrollViewEnabled && (SDL_GetModState() & SDL_KMOD_SHIFT) != 0) {
ScrollView();
}
#endif
@ -1913,7 +1914,7 @@ void InitKeymapActions()
"CycleAutomapType",
N_("Cycle map type"),
N_("Opaque -> Transparent -> Minimap -> None"),
SDLK_m,
SDLK_M,
CycleAutomapType,
nullptr,
IsGameRunning);
@ -2082,7 +2083,7 @@ void InitKeymapActions()
"OpenConsole",
N_("Console"),
N_("Opens Lua console."),
SDLK_BACKQUOTE,
SDLK_GRAVE,
OpenConsole);
options.Keymapper.AddAction(
"DebugToggle",
@ -2368,14 +2369,14 @@ void InitPadmapActions()
const ControllerButtonCombo standGroundCombo = GetOptions().Padmapper.ButtonComboForAction("StandGround");
const bool standGround = StandToggle || IsControllerButtonComboPressed(standGroundCombo);
sgbMouseDown = CLICK_LEFT;
LeftMouseDown(standGround ? KMOD_SHIFT : KMOD_NONE);
LeftMouseDown(standGround ? SDL_KMOD_SHIFT : SDL_KMOD_NONE);
};
auto leftMouseUp = [] {
const ControllerButtonCombo standGroundCombo = GetOptions().Padmapper.ButtonComboForAction("StandGround");
const bool standGround = StandToggle || IsControllerButtonComboPressed(standGroundCombo);
LastPlayerAction = PlayerActionType::None;
sgbMouseDown = CLICK_NONE;
LeftMouseUp(standGround ? KMOD_SHIFT : KMOD_NONE);
LeftMouseUp(standGround ? SDL_KMOD_SHIFT : SDL_KMOD_NONE);
};
options.Padmapper.AddAction(
"LeftMouseClick1",
@ -2693,7 +2694,7 @@ void setOnInitialized(void (*callback)())
int DiabloMain(int argc, char **argv)
{
#ifdef _DEBUG
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
SDL_SetLogPriorities(SDL_LOG_PRIORITY_DEBUG);
#endif
DiabloParseFlags(argc, argv);
@ -2972,10 +2973,10 @@ bool PressEscKey()
void DisableInputEventHandler(const SDL_Event &event, uint16_t modState)
{
switch (event.type) {
case SDL_MOUSEMOTION:
MousePosition = { event.motion.x, event.motion.y };
case SDL_EVENT_MOUSE_MOTION:
MousePosition = { SDLC_EventMotionIntX(event), SDLC_EventMotionIntY(event) };
return;
case SDL_MOUSEBUTTONDOWN:
case SDL_EVENT_MOUSE_BUTTON_DOWN:
if (sgbMouseDown != CLICK_NONE)
return;
switch (event.button.button) {
@ -2988,7 +2989,7 @@ void DisableInputEventHandler(const SDL_Event &event, uint16_t modState)
default:
return;
}
case SDL_MOUSEBUTTONUP:
case SDL_EVENT_MOUSE_BUTTON_UP:
sgbMouseDown = CLICK_NONE;
return;
}

6
Source/dvlnet/base.cpp

@ -5,6 +5,12 @@
#include <cstring>
#include <memory>
#ifdef USE_SDL3
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif
#include <expected.hpp>
#include "player.h"

6
Source/dvlnet/base_protocol.h

@ -5,6 +5,12 @@
#include <string>
#include <string_view>
#ifdef USE_SDL3
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif
#include <ankerl/unordered_dense.h>
#include "dvlnet/base.h"

4
Source/dvlnet/protocol_zt.cpp

@ -2,6 +2,9 @@
#include <random>
#ifdef USE_SDL3
#include <SDL3/SDL_error.h>
#else
#include <SDL.h>
#ifdef USE_SDL1
@ -9,6 +12,7 @@
#else
#include "utils/sdl2_backports.h"
#endif
#endif
#include <lwip/igmp.h>
#include <lwip/mld6.h>

6
Source/dvlnet/tcp_client.cpp

@ -6,7 +6,13 @@
#include <stdexcept>
#include <system_error>
#ifdef USE_SDL3
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif
#include <asio/connect.hpp>
#include <expected.hpp>

11
Source/dvlnet/zerotier_lwip.cpp

@ -5,17 +5,8 @@
#include <lwip/sockets.h>
#include <lwip/tcpip.h>
#include <SDL.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#else
#include "utils/sdl2_backports.h"
#endif
#include "utils/log.hpp"
#include "dvlnet/zerotier_native.h"
#include "utils/log.hpp"
namespace devilution {
namespace net {

7
Source/dvlnet/zerotier_native.cpp

@ -2,14 +2,19 @@
#include <atomic>
#ifdef USE_SDL3
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#include <ankerl/unordered_dense.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#else
#include "utils/sdl2_backports.h"
#endif
#endif
#include <ankerl/unordered_dense.h>
#if defined(_WIN32) && !defined(DEVILUTIONX_WINDOWS_NO_WCHAR)
#include "utils/stdcompat/filesystem.hpp"

37
Source/engine/assets.cpp

@ -18,6 +18,7 @@
#include "utils/file_util.h"
#include "utils/log.hpp"
#include "utils/paths.h"
#include "utils/sdl_compat.h"
#include "utils/str_cat.hpp"
#include "utils/str_split.hpp"
@ -55,22 +56,13 @@ bool IsDebugLogging()
return IsLogLevel(LogCategory::Application, SDL_LOG_PRIORITY_DEBUG);
}
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
OpenOptionalRWops(const std::string &path)
SDL_IOStream *OpenOptionalRWops(const std::string &path)
{
// SDL always logs an error in Debug mode.
// We check the file presence in Debug mode to avoid this.
if (IsDebugLogging() && !FileExists(path.c_str()))
return nullptr;
#ifdef USE_SDL3
return SDL_IOFromFile(path.c_str(), "rb");
#else
return SDL_RWFromFile(path.c_str(), "rb");
#endif
};
bool FindMpqFile(std::string_view filename, MpqArchive **archive, uint32_t *fileNumber)
@ -144,12 +136,7 @@ AssetRef FindAsset(std::string_view filename)
#endif
if (relativePath[0] == '/') {
result.directHandle =
#ifdef USE_SDL3
SDL_IOFromFile(relativePath.c_str(), "rb");
#else
SDL_RWFromFile(relativePath.c_str(), "rb");
#endif
result.directHandle = SDL_IOFromFile(relativePath.c_str(), "rb");
if (result.directHandle != nullptr) {
return result;
}
@ -182,12 +169,7 @@ AssetRef FindAsset(std::string_view filename)
// Fall back to the bundled assets on supported systems.
// This is handled by SDL when we pass a relative path.
if (!paths::AssetsPath().empty()) {
result.directHandle =
#ifdef USE_SDL3
SDL_IOFromFile(relativePath.c_str(), "rb");
#else
SDL_RWFromFile(relativePath.c_str(), "rb");
#endif
result.directHandle = SDL_IOFromFile(relativePath.c_str(), "rb");
if (result.directHandle != nullptr)
return result;
}
@ -231,22 +213,13 @@ AssetHandle OpenAsset(std::string_view filename, size_t &fileSize, bool threadsa
return OpenAsset(std::move(ref), threadsafe);
}
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
OpenAssetAsSdlRwOps(std::string_view filename, bool threadsafe)
SDL_IOStream *OpenAssetAsSdlRwOps(std::string_view filename, bool threadsafe)
{
#ifdef UNPACKED_MPQS
AssetRef ref = FindAsset(filename);
if (!ref.ok())
return nullptr;
#ifdef USE_SDL3
return SDL_IOFromFile(ref.path, "rb");
#else
return SDL_RWFromFile(ref.path, "rb");
#endif
#else
return OpenAsset(filename, threadsafe).release();
#endif

56
Source/engine/assets.hpp

@ -25,6 +25,7 @@
#include "headless_mode.hpp"
#include "utils/file_util.h"
#include "utils/language.h"
#include "utils/sdl_compat.h"
#include "utils/str_cat.hpp"
#include "utils/string_or_view.hpp"
@ -120,13 +121,8 @@ struct AssetRef {
uint32_t fileNumber;
std::string_view filename;
#ifdef USE_SDL3
// Alternatively, a direct SDL_IOStream handle:
SDL_IOStream *directHandle = nullptr;
#else
// Alternatively, a direct SDL_RWops handle:
SDL_RWops *directHandle = nullptr;
#endif
AssetRef() = default;
@ -172,42 +168,24 @@ struct AssetRef {
int32_t error;
return archive->GetUnpackedFileSize(fileNumber, error);
}
#ifdef USE_SDL3
return static_cast<size_t>(SDL_GetIOSize(directHandle));
#else
return static_cast<size_t>(SDL_RWsize(directHandle));
#endif
}
private:
void closeDirectHandle()
{
if (directHandle != nullptr) {
#ifdef USE_SDL3
SDL_CloseIO(directHandle);
#else
SDL_RWclose(directHandle);
#endif
}
}
};
struct AssetHandle {
#ifdef USE_SDL3
SDL_IOStream *handle = nullptr;
#else
SDL_RWops *handle = nullptr;
#endif
AssetHandle() = default;
explicit AssetHandle(
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
handle)
explicit AssetHandle(SDL_IOStream *handle)
: handle(handle)
{
}
@ -238,22 +216,12 @@ struct AssetHandle {
bool read(void *buffer, size_t len)
{
#ifdef USE_SDL3
return SDL_ReadIO(handle, buffer, len) == len;
#elif SDL_VERSION_ATLEAST(2, 0, 0)
return handle->read(handle, buffer, len, 1) == 1;
#else
return handle->read(handle, buffer, static_cast<int>(len), 1) == 1;
#endif
}
bool seek(long pos)
{
#ifdef USE_SDL3
return SDL_SeekIO(handle, pos, SDL_IO_SEEK_SET) != -1;
#else
return handle->seek(handle, pos, RW_SEEK_SET) != -1;
#endif
}
[[nodiscard]] const char *error() const
@ -261,31 +229,18 @@ struct AssetHandle {
return SDL_GetError();
}
#ifdef USE_SDL3
SDL_IOStream *release() &&
{
SDL_IOStream *result = handle;
handle = nullptr;
return result;
}
#else
SDL_RWops *release() &&
{
SDL_RWops *result = handle;
handle = nullptr;
return result;
}
#endif
private:
void closeHandle()
{
if (handle != nullptr) {
#ifdef USE_SDL3
SDL_CloseIO(handle);
#else
SDL_RWclose(handle);
#endif
}
}
};
@ -324,12 +279,7 @@ AssetHandle OpenAsset(AssetRef &&ref, bool threadsafe = false);
AssetHandle OpenAsset(std::string_view filename, bool threadsafe = false);
AssetHandle OpenAsset(std::string_view filename, size_t &fileSize, bool threadsafe = false);
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
OpenAssetAsSdlRwOps(std::string_view filename, bool threadsafe = false);
SDL_IOStream *OpenAssetAsSdlRwOps(std::string_view filename, bool threadsafe = false);
struct AssetData {
std::unique_ptr<char[]> data;

4
Source/engine/dx.cpp

@ -76,7 +76,7 @@ bool CanRenderDirectlyToOutputSurface()
// Assumes double-buffering is available.
return outputSurface->w == static_cast<int>(gnScreenWidth)
&& outputSurface->h == static_cast<int>(gnScreenHeight)
&& outputSurface->format->BitsPerPixel == 8;
&& SDLC_SURFACE_BITSPERPIXEL(outputSurface) == 8;
#endif
}
@ -262,7 +262,7 @@ void RenderPresent()
#endif
#ifdef USE_SDL3
if (!SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr)) ErrSdl();
if (!SDL_RenderTexture(renderer, texture.get(), nullptr, nullptr)) ErrSdl();
#else
if (SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr) <= -1) ErrSdl();
#endif

40
Source/engine/events.cpp

@ -22,6 +22,7 @@
#include "panels/console.hpp"
#include "utils/is_of.hpp"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
#ifdef USE_SDL1
#include "utils/display.h"
@ -67,55 +68,28 @@ bool FetchMessage_Real(SDL_Event *event, uint16_t *modState)
HandleTouchEvent(e);
#endif
if (e.type ==
#ifdef USE_SDL3
SDL_EVENT_QUIT
#else
SDL_QUIT
#endif
|| IsCustomEvent(e.type)) {
if (e.type == SDL_EVENT_QUIT || IsCustomEvent(e.type)) {
*event = e;
return true;
}
// Erroneous events generated by RG350 kernel.
#ifdef USE_SDL3
if (IsAnyOf(e.type, SDL_EVENT_KEY_DOWN, SDL_EVENT_KEY_UP) && e.key.key == SDLK_UNKNOWN) return true;
#else
if (IsAnyOf(e.type, SDL_KEYUP, SDL_KEYDOWN) && e.key.keysym.sym == SDLK_UNKNOWN) return true;
#endif
if (IsAnyOf(e.type, SDL_EVENT_KEY_DOWN, SDL_EVENT_KEY_UP) && SDLC_EventKey(e) == SDLK_UNKNOWN) return true;
#if !defined(USE_SDL1) && !defined(__vita__)
if (!movie_playing) {
// SDL generates mouse events from touch-based inputs to provide basic
// touchscreeen support for apps that don't explicitly handle touch events
if (IsAnyOf(e.type,
#ifdef USE_SDL3
SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP
#else
SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP
#endif
)
if (IsAnyOf(e.type, SDL_EVENT_MOUSE_BUTTON_DOWN, SDL_EVENT_MOUSE_BUTTON_UP)
&& e.button.which == SDL_TOUCH_MOUSEID) {
return true;
}
if (e.type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_MOTION
#else
SDL_MOUSEMOTION
#endif
&& e.motion.which == SDL_TOUCH_MOUSEID) {
if (e.type == SDL_EVENT_MOUSE_MOTION && e.motion.which == SDL_TOUCH_MOUSEID) {
return true;
}
if (e.type ==
#ifdef USE_SDL3
SDL_EVENT_MOUSE_WHEEL
#else
SDL_MOUSEWHEEL
#endif
&& e.wheel.which == SDL_TOUCH_MOUSEID)
if (e.type == SDL_EVENT_MOUSE_WHEEL && e.wheel.which == SDL_TOUCH_MOUSEID) {
return true;
}
}
#endif

1
Source/engine/palette.cpp

@ -13,6 +13,7 @@
#ifdef USE_SDL3
#include <SDL3/SDL_pixels.h>
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif

23
Source/engine/render/scrollrt.cpp

@ -70,6 +70,7 @@
#include "utils/display.h"
#include "utils/is_of.hpp"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
#include "utils/str_cat.hpp"
#ifndef USE_SDL1
@ -538,14 +539,7 @@ void DrawCell(const Surface &out, const Lightmap lightmap, Point tilePosition, P
bool transparency = TileHasAny(tilePosition, TileProperties::Transparent) && TransList[dTransVal[tilePosition.x][tilePosition.y]];
#ifdef _DEBUG
if ((SDL_GetModState() &
#ifdef USE_SDL3
SDL_KMOD_ALT
#else
KMOD_ALT
#endif
)
!= 0) {
if ((SDL_GetModState() & SDL_KMOD_ALT) != 0) {
transparency = false;
}
#endif
@ -892,14 +886,7 @@ void DrawDungeon(const Surface &out, const Lightmap &lightmap, Point tilePositio
bool transparency = TransList[bMap];
#ifdef _DEBUG
// Turn transparency off here for debugging
transparency = transparency && (SDL_GetModState() &
#ifdef USE_SDL3
SDL_KMOD_ALT
#else
KMOD_ALT
#endif
)
== 0;
transparency = transparency && (SDL_GetModState() & SDL_KMOD_ALT) == 0;
#endif
if (perPixelLighting) {
// Create a special lightmap buffer to bleed light up walls
@ -1652,11 +1639,7 @@ void ClearScreenBuffer()
return;
assert(PalSurface != nullptr);
#ifdef USE_SDL3
SDL_FillSurfaceRect(PalSurface, nullptr, 0);
#else
SDL_FillRect(PalSurface, nullptr, 0);
#endif
}
#ifdef _DEBUG

5
Source/gmenu.cpp

@ -33,6 +33,7 @@
#include "options.h"
#include "stores.h"
#include "utils/language.h"
#include "utils/sdl_compat.h"
#include "utils/ui_fwd.h"
namespace devilution {
@ -135,11 +136,7 @@ void GmenuDrawMenuItem(const Surface &out, TMenuItem *pItem, int y)
const uint16_t steps = std::max<uint16_t>(pItem->sliderSteps(), 2);
const uint16_t pos = SliderFillMin + step * (SliderFillMax - SliderFillMin) / steps;
SDL_Rect rect = MakeSdlRect(SliderValueLeft + uiPositionX, y + SliderValuePaddingTop, pos, SliderValueHeight);
#ifdef USE_SDL3
SDL_FillSurfaceRect(out.surface, &rect, 205);
#else
SDL_FillRect(out.surface, &rect, 205);
#endif
ClxDraw(out, { SliderValueLeft + pos - SliderMarkerWidth / 2 + uiPositionX, y + SliderValuePaddingTop + SliderValueHeight - 1 }, (*option_cel)[0]);
}

33
Source/hwcursor.cpp

@ -28,6 +28,7 @@
#include "engine/surface.hpp"
#include "utils/display.h"
#include "utils/sdl_bilinear_scale.hpp"
#include "utils/sdl_compat.h"
#include "utils/sdl_wrap.h"
namespace devilution {
@ -47,14 +48,10 @@ Size ScaledSize(Size size)
if (renderer != nullptr) {
float scaleX = 1.0F;
float scaleY = 1.0F;
#ifdef USE_SDL3
if (!SDL_GetRenderScale(renderer, &scaleX, &scaleY)) {
LogError("SDL_GetRenderScale: {}", SDL_GetError());
SDL_ClearError();
}
#else
SDL_RenderGetScale(renderer, &scaleX, &scaleY);
#endif
size.width = static_cast<int>(size.width * scaleX);
size.height = static_cast<int>(size.height * scaleY);
}
@ -150,8 +147,7 @@ bool SetHardwareCursorFromSurface(SDL_Surface *surface, HotpointPosition hotpoin
bool SetHardwareCursorFromClxSprite(ClxSprite sprite, HotpointPosition hotpointPosition)
{
const OwnedSurface surface { sprite.width(), sprite.height() };
#ifdef USE_SDL3
if (!SDL_SetSurfacePalette(surface.surface, Palette.get())) {
if (!SDLC_SetSurfacePalette(surface.surface, Palette.get())) {
LogError("SDL_SetSurfacePalette: {}", SDL_GetError());
SDL_ClearError();
return false;
@ -161,18 +157,6 @@ bool SetHardwareCursorFromClxSprite(ClxSprite sprite, HotpointPosition hotpointP
SDL_ClearError();
return false;
}
#else
if (SDL_SetSurfacePalette(surface.surface, Palette.get()) != 0) {
LogError("SDL_SetSurfacePalette: {}", SDL_GetError());
SDL_ClearError();
return false;
}
if (SDL_SetColorKey(surface.surface, SDL_TRUE, 0) != 0) {
LogError("SDL_SetColorKey: {}", SDL_GetError());
SDL_ClearError();
return false;
}
#endif
RenderClxSprite(surface, sprite, { 0, 0 });
return SetHardwareCursorFromSurface(surface.surface, hotpointPosition);
}
@ -198,7 +182,6 @@ bool SetHardwareCursorFromSprite(int pcurs)
// Transparent color must not be used in the sprite itself.
// Colors 1-127 are outside of the UI palette so are safe to use.
constexpr std::uint8_t TransparentColor = 1;
#ifdef USE_SDL3
if (!SDL_FillSurfaceRect(out.surface, nullptr, TransparentColor)) {
LogError("SDL_FillSurfaceRect: {}", SDL_GetError());
SDL_ClearError();
@ -209,18 +192,6 @@ bool SetHardwareCursorFromSprite(int pcurs)
SDL_ClearError();
return false;
}
#else
if (SDL_FillRect(out.surface, nullptr, TransparentColor) != 0) {
LogError("SDL_FillRect: {}", SDL_GetError());
SDL_ClearError();
return false;
}
if (SDL_SetColorKey(out.surface, 1, TransparentColor) != 0) {
LogError("SDL_SetColorKey: {}", SDL_GetError());
SDL_ClearError();
return false;
}
#endif
DrawSoftwareCursor(out, { outlineWidth, size.height - outlineWidth - 1 }, pcurs);
const bool result = SetHardwareCursorFromSurface(

13
Source/hwcursor.hpp

@ -16,6 +16,7 @@
#include "options.h"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
// Set this to 1 to log the hardware cursor state changes.
#define LOG_HWCURSOR 0
@ -144,10 +145,8 @@ inline void DoReinitializeHardwareCursor()
inline bool IsHardwareCursorVisible()
{
#ifdef USE_SDL3
#ifndef USE_SDL1
return SDL_CursorVisible();
#elif SDL_VERSION_ATLEAST(2, 0, 0)
return SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE;
#else
return false;
#endif
@ -164,13 +163,7 @@ inline void SetHardwareCursorVisible(bool visible)
#if LOG_HWCURSOR
Log("hwcursor: SetHardwareCursorVisible {}", visible);
#endif
if (
#ifdef USE_SDL3
visible ? SDL_ShowCursor() : SDL_HideCursor()
#else
SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE) < 0
#endif
) {
if (visible ? SDLC_ShowCursor() : SDLC_HideCursor()) {
LogError("{}", SDL_GetError());
SDL_ClearError();
}

55
Source/interfac.cpp

@ -7,6 +7,7 @@
#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#ifdef USE_SDL3
#include <SDL3/SDL_error.h>
@ -15,7 +16,6 @@
#include <SDL3/SDL_rect.h>
#include <SDL3/SDL_surface.h>
#include <SDL3/SDL_timer.h>
#include <SDL3/SDL_version.h>
#else
#include <SDL.h>
#endif
@ -40,6 +40,7 @@
#include "pfile.h"
#include "plrmsg.h"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
#include "utils/sdl_geometry.h"
#include "utils/sdl_thread.h"
@ -71,11 +72,7 @@ const int BarPos[3][2] = { { 53, 37 }, { 53, 421 }, { 53, 37 } };
OptionalOwnedClxSpriteList ArtCutsceneWidescreen;
#ifdef USE_SDL3
SdlEventType CustomEventType = SDL_EVENT_USER;
#else
SdlEventType CustomEventType = SDL_USEREVENT;
#endif
Cutscenes GetCutSceneFromLevelType(dungeon_type type)
{
@ -229,11 +226,7 @@ void DrawCutsceneBackground()
{
const Rectangle &uiRectangle = GetUIRectangle();
const Surface &out = GlobalBackBuffer();
#ifdef USE_SDL3
SDL_FillSurfaceRect(out.surface, nullptr, 0);
#else
SDL_FillRect(out.surface, nullptr, 0x000000);
#endif
if (ArtCutsceneWidescreen) {
const ClxSprite sprite = (*ArtCutsceneWidescreen)[0];
RenderClxSprite(out, sprite, { uiRectangle.position.x - (sprite.width() - uiRectangle.size.width) / 2, uiRectangle.position.y });
@ -251,11 +244,7 @@ void DrawCutsceneForeground()
out.region.y + BarPos[progress_id][1] + uiRectangle.position.y,
sgdwProgress,
ProgressHeight);
#ifdef USE_SDL3
SDL_FillSurfaceRect(out.surface, &rect, BarColor[progress_id]);
#else
SDL_FillRect(out.surface, &rect, BarColor[progress_id]);
#endif
if (DiabloUiSurface() == PalSurface)
BltFast(&rect, &rect);
@ -312,13 +301,7 @@ bool HandleProgressBarUpdate()
// to process real events rather than the recorded ones in demo mode.
while (PollEvent(&event)) {
CheckShouldSkipRendering();
if (event.type !=
#ifdef USE_SDL3
SDL_EVENT_QUIT
#else
SDL_QUIT
#endif
) {
if (event.type != SDL_EVENT_QUIT) {
HandleMessage(event, SDL_GetModState());
}
if (ProgressEventHandlerState.done) return false;
@ -488,13 +471,7 @@ void DoLoad(interface_mode uMsg)
SDL_Event event;
CustomEventToSdlEvent(event, WM_ERROR);
event.user.data1 = new std::string(std::move(loadResult).error());
if (
#ifdef USE_SDL3
!SDL_PushEvent(&event)
#else
SDL_PushEvent(&event) < 0
#endif
) {
if (!SDLC_PushEvent(&event)) {
LogError("Failed to send WM_ERROR {}", SDL_GetError());
SDL_ClearError();
}
@ -506,13 +483,7 @@ void DoLoad(interface_mode uMsg)
SDL_Event event;
CustomEventToSdlEvent(event, WM_DONE);
if (
#ifdef USE_SDL3
!SDL_PushEvent(&event)
#else
SDL_PushEvent(&event) < 0
#endif
) {
if (!SDLC_PushEvent(&event)) {
LogError("Failed to send WM_DONE {}", SDL_GetError());
SDL_ClearError();
}
@ -627,13 +598,7 @@ void interface_msg_pump()
SDL_Event event;
uint16_t modState;
while (FetchMessage(&event, &modState)) {
if (event.type !=
#ifdef USE_SDL3
SDL_EVENT_QUIT
#else
SDL_QUIT
#endif
) {
if (event.type != SDL_EVENT_QUIT) {
HandleMessage(event, modState);
}
}
@ -650,13 +615,7 @@ void IncProgress(uint32_t steps)
if (!HeadlessMode && sgdwProgress != prevProgress) {
SDL_Event event;
CustomEventToSdlEvent(event, WM_PROGRESS);
if (
#ifdef USE_SDL3
!SDL_PushEvent(&event)
#else
SDL_PushEvent(&event) < 0
#endif
) {
if (!SDLC_PushEvent(&event)) {
LogError("Failed to send WM_PROGRESS {}", SDL_GetError());
SDL_ClearError();
}

7
Source/inv.cpp

@ -1096,12 +1096,7 @@ void StartGoldDrop()
const Point start = GetPanelPosition(UiPanels::Inventory, { 67, 128 });
SDL_Rect rect = MakeSdlRect(start.x, start.y, 180, 20);
#ifdef USE_SDL3
SDL_SetTextInputArea(ghMainWnd, &rect, 0);
#else
SDL_SetTextInputRect(&rect);
#endif
SDL_SetTextInputArea(ghMainWnd, &rect, /*cursor=*/0);
OpenGoldDrop(invIndex, max);
}

6
Source/lua/modules/dev/items.cpp

@ -4,6 +4,12 @@
#include <random>
#include <string>
#ifdef USE_SDL3
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif
#include <sol/sol.hpp>
#include "cursor.h"

4
Source/lua/modules/log.cpp

@ -1,6 +1,10 @@
#include "lua/modules/log.hpp"
#ifdef USE_SDL3
#include <SDL3/SDL_log.h>
#else
#include <SDL.h>
#endif
#include <fmt/args.h>
#include <fmt/format.h>

4
Source/main.cpp

@ -1,5 +1,9 @@
#ifdef USE_SDL3
#include <SDL3/SDL.h>
#else
#include <SDL.h>
#include <SDL_main.h>
#endif
#ifdef __SWITCH__
#include "platform/switch/network.h"

4
Source/menu.cpp

@ -144,11 +144,7 @@ bool mainmenu_select_hero_dialog(GameData *gameData)
void mainmenu_wait_for_button_sound()
{
#ifdef USE_SDL3
SDL_FillSurfaceRect(DiabloUiSurface(), nullptr, 0);
#else
SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000);
#endif
UiFadeIn();
SDL_Delay(350); // delay to let button pressed sound finish playing
}

27
Source/movie.cpp

@ -24,6 +24,7 @@
#include "hwcursor.hpp"
#include "storm/storm_svid.h"
#include "utils/display.h"
#include "utils/sdl_compat.h"
namespace devilution {
@ -60,20 +61,9 @@ void play_movie(const char *pszMovie, bool userCanClose)
}
}
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_KEY_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
#else
case SDL_KEYDOWN:
case SDL_MOUSEBUTTONUP:
#endif
if (userCanClose || (
#ifdef USE_SDL3
event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE
#else
event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE
#endif
))
if (userCanClose || (event.type == SDL_EVENT_KEY_DOWN && SDLC_EventKey(event) == SDLK_ESCAPE))
movie_playing = false;
break;
#ifdef USE_SDL3
@ -102,13 +92,11 @@ void play_movie(const char *pszMovie, bool userCanClose)
}
break;
#endif
#ifdef USE_SDL3
case SDL_EVENT_QUIT:
#else
case SDL_QUIT:
#endif
SVidPlayEnd();
diablo_quit(0);
default:
break;
}
}
if (!SVidPlayContinue())
@ -121,7 +109,14 @@ void play_movie(const char *pszMovie, bool userCanClose)
movie_playing = false;
#ifdef USE_SDL3
float x, y;
SDL_GetMouseState(&x, &y);
MousePosition.x = static_cast<int>(x);
MousePosition.y = static_cast<int>(y);
#else
SDL_GetMouseState(&MousePosition.x, &MousePosition.y);
#endif
OutputToLogical(&MousePosition.x, &MousePosition.y);
InitBackbufferState();
}

21
Source/mpq/mpq_sdl_rwops.cpp

@ -10,6 +10,8 @@
#include <SDL3/SDL_iostream.h>
#else
#include <SDL.h>
#include "utils/sdl_compat.h"
#endif
namespace devilution {
@ -78,25 +80,13 @@ static OffsetType MpqFileRwSeek(struct SDL_RWops *context, OffsetType offset, in
Data &data = *GetData(context);
OffsetType newPosition;
switch (whence) {
#ifdef USE_SDL3
case SDL_IO_SEEK_SET:
#else
case RW_SEEK_SET:
#endif
newPosition = offset;
break;
#ifdef USE_SDL3
case SDL_IO_SEEK_CUR:
#else
case RW_SEEK_CUR:
#endif
newPosition = static_cast<OffsetType>(data.position + offset);
break;
#ifdef USE_SDL3
case SDL_IO_SEEK_END:
#else
case RW_SEEK_END:
#endif
newPosition = static_cast<OffsetType>(data.size + offset);
break;
default:
@ -212,12 +202,7 @@ static int MpqFileRwClose(struct SDL_RWops *context)
} // namespace
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe)
SDL_IOStream *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe)
{
#ifdef USE_SDL3
SDL_IOStreamInterface interface;

9
Source/mpq/mpq_sdl_rwops.hpp

@ -7,17 +7,14 @@
#include <SDL3/SDL_iostream.h>
#else
#include <SDL.h>
#include "utils/sdl_compat.h"
#endif
#include "mpq/mpq_reader.hpp"
namespace devilution {
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe);
SDL_IOStream *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe);
} // namespace devilution

18
Source/options.cpp

@ -1110,26 +1110,12 @@ KeymapperOptions::KeymapperOptions()
keyIDToKeyName.emplace(MouseScrollLeftButton, "SCROLLLEFTMOUSE");
keyIDToKeyName.emplace(MouseScrollRightButton, "SCROLLRIGHTMOUSE");
keyIDToKeyName.emplace(
#ifdef USE_SDL3
SDLK_GRAVE
#else
SDLK_BACKQUOTE
#endif
,
"`");
keyIDToKeyName.emplace(SDLK_GRAVE, "`");
keyIDToKeyName.emplace(SDLK_LEFTBRACKET, "[");
keyIDToKeyName.emplace(SDLK_RIGHTBRACKET, "]");
keyIDToKeyName.emplace(SDLK_BACKSLASH, "\\");
keyIDToKeyName.emplace(SDLK_SEMICOLON, ";");
keyIDToKeyName.emplace(
#ifdef USE_SDL3
SDLK_APOSTROPHE
#else
SDLK_QUOTE
#endif
,
"'");
keyIDToKeyName.emplace(SDLK_APOSTROPHE, "'");
keyIDToKeyName.emplace(SDLK_COMMA, ",");
keyIDToKeyName.emplace(SDLK_PERIOD, ".");
keyIDToKeyName.emplace(SDLK_SLASH, "/");

54
Source/panels/console.cpp

@ -10,6 +10,7 @@
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_keyboard.h>
#include <SDL3/SDL_keycode.h>
#include <SDL3/SDL_rect.h>
#include <SDL3/SDL_scancode.h>
#else
@ -35,6 +36,7 @@
#include "lua/repl.hpp"
#include "utils/algorithm/container.hpp"
#include "utils/display.h"
#include "utils/sdl_compat.h"
#include "utils/sdl_geometry.h"
#include "utils/str_cat.hpp"
#include "utils/str_split.hpp"
@ -142,7 +144,7 @@ constexpr int ScrollStep = LineHeight * 3;
void CloseConsole()
{
IsConsoleVisible = false;
SDL_StopTextInput();
SDLC_StopTextInput(ghMainWnd);
}
int GetConsoleLinesInnerWidth()
@ -456,13 +458,7 @@ bool ConsoleHandleEvent(const SDL_Event &event)
{
if (!IsConsoleVisible) {
// Make console open on the top-left keyboard key even if it is not a backtick.
if (
#ifdef USE_SDL3
event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_GRAVE
#else
event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_GRAVE
#endif
) {
if (event.type == SDL_EVENT_KEY_DOWN && SDLC_EventScancode(event) == SDL_SCANCODE_GRAVE) {
OpenConsole();
return true;
}
@ -473,23 +469,10 @@ bool ConsoleHandleEvent(const SDL_Event &event)
return true;
}
const auto modState = SDL_GetModState();
const bool isShift = (modState &
#ifdef USE_SDL3
SDL_KMOD_SHIFT
#else
KMOD_SHIFT
#endif
)
!= 0;
const bool isShift = (modState & SDL_KMOD_SHIFT) != 0;
switch (event.type) {
#ifdef USE_SDL3
case SDL_EVENT_KEY_DOWN:
switch (event.key.key)
#else
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
#endif
{
switch (SDLC_EventKey(event)) {
case SDLK_ESCAPE:
if (!AutocompleteSuggestions.empty()) {
AutocompleteSuggestions.clear();
@ -540,30 +523,18 @@ bool ConsoleHandleEvent(const SDL_Event &event)
case SDLK_PAGEDOWN:
--PendingScrollPages;
return true;
#ifdef USE_SDL3
case SDLK_L:
#else
case SDLK_l:
#endif
ClearConsole();
return true;
default:
return false;
}
break;
#ifdef USE_SDL3
#ifndef USE_SDL1
case SDL_EVENT_MOUSE_WHEEL:
if (event.wheel.integer_y > 0) {
ScrollOffset += ScrollStep;
} else if (event.wheel.integer_y < 0) {
ScrollOffset -= ScrollStep;
}
return true;
#elif SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0) {
if (SDLC_EventWheelIntY(event) > 0) {
ScrollOffset += ScrollStep;
} else if (event.wheel.y < 0) {
} else if (SDLC_EventWheelIntY(event) < 0) {
ScrollOffset -= ScrollStep;
}
return true;
@ -620,13 +591,8 @@ void DrawConsole(const Surface &out)
if (FirstRender) {
SDL_Rect sdlInputRect = MakeSdlRect(InputRect);
#ifdef USE_SDL3
SDL_SetTextInputArea(ghMainWnd, &sdlInputRect, ConsoleInputState.cursorPosition());
SDL_StartTextInput(ghMainWnd);
#else
SDL_SetTextInputRect(&sdlInputRect);
SDL_StartTextInput();
#endif
SDLC_StartTextInput(ghMainWnd);
FirstRender = false;
if (ConsoleLines.empty()) {
InitConsole();

24
Source/pfile.cpp

@ -35,6 +35,7 @@
#include "utils/language.h"
#include "utils/parse_int.hpp"
#include "utils/paths.h"
#include "utils/sdl_compat.h"
#include "utils/stdcompat/filesystem.hpp"
#include "utils/str_cat.hpp"
#include "utils/str_split.hpp"
@ -288,37 +289,16 @@ void CreateDetailDiffs(std::string_view prefix, std::string_view memoryMapFile,
// Note: Detail diffs are currently only supported in unit tests
const std::string memoryMapFileAssetName = StrCat(paths::BasePath(), "/test/fixtures/memory_map/", memoryMapFile, ".txt");
#ifdef USE_SDL3
SDL_IOStream *handle = SDL_IOFromFile(memoryMapFileAssetName.c_str(), "r");
#else
SDL_RWops *handle = SDL_RWFromFile(memoryMapFileAssetName.c_str(), "r");
#endif
if (handle == nullptr) {
app_fatal(StrCat("MemoryMapFile ", memoryMapFile, " is missing"));
return;
}
const size_t readBytes = static_cast<size_t>(
#ifdef USE_SDL3
SDL_GetIOSize(handle)
#else
SDL_RWsize(handle)
#endif
);
const size_t readBytes = static_cast<size_t>(SDL_GetIOSize(handle));
const std::unique_ptr<std::byte[]> memoryMapFileData { new std::byte[readBytes] };
#ifdef USE_SDL3
SDL_ReadIO(handle, memoryMapFileData.get(), readBytes);
#elif SDL_VERSION_ATLEAST(2, 0, 0)
SDL_RWread(handle, memoryMapFileData.get(), readBytes, 1);
#else
SDL_RWread(handle, memoryMapFileData.get(), static_cast<int>(readBytes), 1);
#endif
#ifdef USE_SDL3
SDL_CloseIO(handle);
#else
SDL_RWclose(handle);
#endif
const std::string_view buffer(reinterpret_cast<const char *>(memoryMapFileData.get()), readBytes);

11
Source/qol/floatingnumbers.cpp

@ -6,6 +6,12 @@
#include <fmt/format.h>
#include <string>
#ifdef USE_SDL3
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif
#include "engine/render/text_render.hpp"
#include "options.h"
#include "utils/str_cat.hpp"
@ -119,7 +125,10 @@ void AddFloatingNumber(Point pos, Displacement offset, DamageType type, int valu
}
}
FloatingNumber num {
pos, offset, endOffset, "", SDL_GetTicks() + 2500, SDL_GetTicks(), UiFlags::Outlined, type, value, index, damageToPlayer
pos, offset, endOffset, "",
static_cast<uint32_t>(SDL_GetTicks() + 2500),
static_cast<uint32_t>(SDL_GetTicks()),
UiFlags::Outlined, type, value, index, damageToPlayer
};
UpdateFloatingData(num);
FloatingQueue.push_back(num);

14
Source/qol/stash.cpp

@ -4,6 +4,12 @@
#include <cstdint>
#include <utility>
#ifdef USE_SDL3
#include <SDL3/SDL_keyboard.h>
#else
#include <SDL.h>
#endif
#include <fmt/format.h>
#include "DiabloUI/text_input.hpp"
@ -21,8 +27,10 @@
#include "inv.h"
#include "minitext.h"
#include "stores.h"
#include "utils/display.h"
#include "utils/format_int.hpp"
#include "utils/language.h"
#include "utils/sdl_compat.h"
#include "utils/str_cat.hpp"
#include "utils/utf8.hpp"
@ -589,7 +597,7 @@ void StartGoldWithdraw()
const Point start = GetPanelPosition(UiPanels::Stash, { 67, 128 });
SDL_Rect rect = MakeSdlRect(start.x, start.y, 180, 20);
SDL_SetTextInputRect(&rect);
SDL_SetTextInputArea(ghMainWnd, &rect, /*cursor=*/0);
IsWithdrawGoldOpen = true;
GoldWithdrawText[0] = '\0';
@ -602,7 +610,7 @@ void StartGoldWithdraw()
.min = 0,
.max = std::min(RoomForGold(), Stash.gold),
});
SDL_StartTextInput();
SDLC_StartTextInput(ghMainWnd);
}
void WithdrawGoldKeyPress(SDL_Keycode vkey)
@ -667,7 +675,7 @@ void CloseGoldWithdraw()
{
if (!IsWithdrawGoldOpen)
return;
SDL_StopTextInput();
SDLC_StopTextInput(ghMainWnd);
IsWithdrawGoldOpen = false;
GoldWithdrawInputState = std::nullopt;
}

11
Source/restrict.cpp

@ -16,25 +16,18 @@
#include <SDL.h>
#endif
#include "utils/sdl_compat.h"
namespace devilution {
void ReadOnlyTest()
{
const std::string path = paths::PrefPath() + "Diablo1ReadOnlyTest.foo";
#ifdef USE_SDL3
SDL_IOStream *file = SDL_IOFromFile(path.c_str(), "w");
#else
SDL_RWops *file = SDL_RWFromFile(path.c_str(), "w");
#endif
if (file == nullptr) {
DirErrorDlg(paths::PrefPath());
}
#ifdef USE_SDL3
SDL_CloseIO(file);
#else
SDL_RWclose(file);
#endif
RemoveFile(path.c_str());
}

16
Source/storm/storm_svid.cpp

@ -187,19 +187,13 @@ void UpdatePalette()
ErrSdl();
}
#else
if (SDL_SetSurfacePalette(SVidSurface.get(), SVidPalette.get()) <= -1) {
if (!SDLC_SetSurfacePalette(SVidSurface.get(), SVidPalette.get())) {
ErrSdl();
}
const SDL_Surface *surface = GetOutputSurface();
if (
#ifdef USE_SDL3
SDL_BITSPERPIXEL(surface->format)
#else
surface->format->BitsPerPixel
#endif
== 8) {
if (SDL_SetSurfacePalette(GetOutputSurface(), SVidPalette.get()) <= -1) {
if (SDLC_SURFACE_BITSPERPIXEL(surface) == 8) {
if (!SDLC_SetSurfacePalette(GetOutputSurface(), SVidPalette.get())) {
ErrSdl();
}
}
@ -378,11 +372,7 @@ bool SVidPlayBegin(const char *filename, int flags)
#endif
// Set the background to black.
#ifdef USE_SDL3
SDL_FillSurfaceRect(GetOutputSurface(), nullptr, 0x000000);
#else
SDL_FillRect(GetOutputSurface(), nullptr, 0x000000);
#endif
// The buffer for the frame. It is not the same as the SDL surface because the SDL surface also has pitch padding.
SVidFrameBuffer = std::unique_ptr<uint8_t[]> { new uint8_t[static_cast<size_t>(SVidWidth * SVidHeight)] };

77
Source/utils/display.cpp

@ -48,6 +48,7 @@
#include "headless_mode.hpp"
#include "options.h"
#include "utils/log.hpp"
#include "utils/sdl_compat.h"
#include "utils/sdl_geometry.h"
#include "utils/sdl_wrap.h"
#include "utils/str_cat.hpp"
@ -99,9 +100,13 @@ namespace {
void CalculatePreferredWindowSize(int &width, int &height)
{
SDL_DisplayMode mode;
if (SDL_GetDesktopDisplayMode(0, &mode) != 0) {
ErrSdl();
}
#ifdef USE_SDL3
const SDL_DisplayMode *modePtr = SDL_GetDesktopDisplayMode(0);
if (modePtr == nullptr) ErrSdl();
mode = *modePtr;
#else
if (SDL_GetDesktopDisplayMode(0, &mode) != 0) ErrSdl();
#endif
if (mode.w < mode.h) {
std::swap(mode.w, mode.h);
@ -175,22 +180,25 @@ void UpdateAvailableResolutions()
// Add resolutions
bool supportsAnyResolution = false;
#ifdef USE_SDL1
auto *modes = SDL_ListModes(nullptr, SDL_FULLSCREEN | SDL_HWPALETTE);
// SDL_ListModes returns -1 if any resolution is allowed (for example returned on 3DS)
if (modes == (SDL_Rect **)-1) {
supportsAnyResolution = true;
} else if (modes != nullptr) {
for (size_t i = 0; modes[i] != nullptr; i++) {
if (modes[i]->w < modes[i]->h) {
std::swap(modes[i]->w, modes[i]->h);
}
sizes.emplace_back(Size {
static_cast<int>(modes[i]->w * scaleFactor),
static_cast<int>(modes[i]->h * scaleFactor) });
}
#ifdef USE_SDL3
const SDL_DisplayMode *fullscreenMode = SDL_GetWindowFullscreenMode(ghMainWnd);
if (fullscreenMode == nullptr) return;
const SDL_DisplayID displayId = SDL_GetDisplayForWindow(ghMainWnd);
if (displayId == 0) return;
int modeCount;
SDLUniquePtr<SDL_DisplayMode *> modes { SDL_GetFullscreenDisplayModes(displayId, &modeCount) };
if (modes == nullptr) return;
for (SDL_DisplayMode **it = modes.get(), **end = modes.get() + modeCount; it != end; ++it) {
const SDL_DisplayMode &mode = **it;
int w = mode.w;
int h = mode.h;
if (w < h) std::swap(w, h);
sizes.emplace_back(Size {
static_cast<int>(w * scaleFactor),
static_cast<int>(h * scaleFactor) });
}
#else
supportsAnyResolution = *GetOptions().Graphics.upscale;
#elif !defined(USE_SDL1)
int displayModeCount = SDL_GetNumDisplayModes(0);
for (int i = 0; i < displayModeCount; i++) {
SDL_DisplayMode mode;
@ -205,6 +213,21 @@ void UpdateAvailableResolutions()
static_cast<int>(mode.h * scaleFactor) });
}
supportsAnyResolution = *GetOptions().Graphics.upscale;
#else
auto *modes = SDL_ListModes(nullptr, SDL_FULLSCREEN | SDL_HWPALETTE);
// SDL_ListModes returns -1 if any resolution is allowed (for example returned on 3DS)
if (modes == (SDL_Rect **)-1) {
supportsAnyResolution = true;
} else if (modes != nullptr) {
for (size_t i = 0; modes[i] != nullptr; i++) {
if (modes[i]->w < modes[i]->h) {
std::swap(modes[i]->w, modes[i]->h);
}
sizes.emplace_back(Size {
static_cast<int>(modes[i]->w * scaleFactor),
static_cast<int>(modes[i]->h * scaleFactor) });
}
}
#endif
if (supportsAnyResolution && sizes.size() == 1) {
@ -233,10 +256,14 @@ void UpdateAvailableResolutions()
#ifndef USE_SDL1
if (*graphicsOptions.fitToScreen) {
#ifdef USE_SDL3
const SDL_DisplayMode *modePtr = SDL_GetDesktopDisplayMode(0);
if (modePtr == nullptr) ErrSdl();
const SDL_DisplayMode &mode = *modePtr;
#else
SDL_DisplayMode mode;
if (SDL_GetDesktopDisplayMode(0, &mode) != 0) {
ErrSdl();
}
if (SDL_GetDesktopDisplayMode(0, &mode) != 0) ErrSdl();
#endif
for (auto &size : sizes) {
if (mode.h == 0) continue;
// Ensure that the ini specified resolution remains present in the resolution list
@ -516,7 +543,13 @@ bool SpawnWindow(const char *lpWindowName)
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight");
#endif
if (SDL_Init(initFlags) <= -1) {
if (
#ifdef USE_SDL3
!SDL_Init(initFlags)
#else
SDL_Init(initFlags) <= -1
#endif
) {
ErrSdl();
}
RegisterCustomEvents();

16
Source/utils/file_util.cpp

@ -10,6 +10,8 @@
#include <SDL3/SDL_iostream.h>
#else
#include <SDL.h>
#include "utils/sdl_compat.h"
#endif
#include "utils/log.hpp"
@ -116,16 +118,11 @@ bool FileExists(const char *path)
#elif defined(DVL_HAS_FILESYSTEM)
std::error_code ec;
return std::filesystem::exists(reinterpret_cast<const char8_t *>(path), ec);
#elif USE_SDL3
#else
SDL_IOStream *file = SDL_IOFromFile(path, "rb");
if (file == nullptr) return false;
SDL_CloseIO(file);
return true;
#else
SDL_RWops *file = SDL_RWFromFile(path, "rb");
if (file == nullptr) return false;
SDL_RWclose(file);
return true;
#endif
}
@ -184,17 +181,10 @@ bool FileExistsAndIsWriteable(const char *path)
#else
if (!FileExists(path))
return false;
#ifdef USE_SDL3
SDL_IOStream *file = SDL_IOFromFile(path, "ab");
if (file == nullptr) return false;
SDL_CloseIO(file);
return true;
#else
SDL_RWops *file = SDL_RWFromFile(path, "ab");
if (file == nullptr) return false;
SDL_RWclose(file);
return true;
#endif
#endif
}

21
Source/utils/language.cpp

@ -5,6 +5,17 @@
#include <string_view>
#include <vector>
#ifdef USE_SDL3
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
#endif
#include <ankerl/unordered_dense.h>
#include <function_ref.hpp>
@ -17,10 +28,6 @@
#include "utils/paths.h"
#include "utils/string_view_hash.hpp"
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
#define MO_MAGIC 0x950412de
std::string forceLocale;
@ -386,10 +393,16 @@ void LanguageInitialize()
#ifdef UNPACKED_MPQS
const bool readWholeFile = false;
#else
#ifdef USE_SDL3
// In SDL3, we don't have a way to check if the handle is to an MPQ file.
// Assume that it is.
const bool readWholeFile = true;
#else
// If reading from an MPQ, it is much faster to
// load the whole file instead of seeking.
const bool readWholeFile = handle.handle->type == SDL_RWOPS_UNKNOWN;
#endif
#endif
std::unique_ptr<std::byte[]> data;

20
Source/utils/sdl2_to_1_2_backports.h

@ -17,6 +17,7 @@
#endif
#define WINDOW_ICON_NAME 0
#define SDL_Window SDL_Surface
//== Utility
@ -112,6 +113,21 @@ inline void SDL_SetTextInputRect(const SDL_Rect *r)
{
}
inline bool SDLC_StartTextInput(SDL_Window *)
{
SDL_StartTextInput();
return true;
}
inline bool SDLC_StopTextInput(SDL_Window *)
{
SDL_StopTextInput();
return true;
}
inline bool SDL_SetTextInputArea(SDL_Window *, const SDL_Rect *, int)
{
return true;
}
//== Graphics helpers
typedef struct SDL_Point {
@ -124,6 +140,8 @@ inline SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r)
return ((p->x >= r->x) && (p->x < (r->x + r->w)) && (p->y >= r->y) && (p->y < (r->y + r->h))) ? SDL_TRUE : SDL_FALSE;
}
inline bool SDLC_PointInRect(const SDL_Point *p, const SDL_Rect *r) { return SDL_PointInRect(p, r) == SDL_TRUE; }
//= Messagebox (simply logged to stderr for now)
enum {
@ -153,8 +171,6 @@ inline int SDL_ShowSimpleMessageBox(Uint32 flags,
//= Window handling
#define SDL_Window SDL_Surface
inline void SDL_GetWindowPosition(SDL_Window *window, int *x, int *y)
{
*x = window->clip_rect.x;

325
Source/utils/sdl_compat.h

@ -2,11 +2,336 @@
#pragma once
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_keyboard.h>
#include <SDL3/SDL_keycode.h>
#include <SDL3/SDL_pixels.h>
#include <SDL3/SDL_scancode.h>
#include <SDL3/SDL_surface.h>
#else
#include <SDL.h>
#ifndef USE_SDL1
#include "utils/sdl2_backports.h"
#endif
#endif
#ifdef USE_SDL1
#define SDL_Scancode Uint8
#endif
#ifdef USE_SDL3
#define SDLC_PushEvent SDL_PushEvent
#define SDLC_SetClipboardText SDL_SetClipboardText
#define SDLC_HasClipboardText SDL_HasClipboardText
inline SDL_Keycode SDLC_EventKey(const SDL_Event &event) { return event.key.key; }
inline SDL_Scancode SDLC_EventScancode(const SDL_Event &event) { return event.key.scancode; }
inline int SDLC_EventMotionIntX(const SDL_Event &event) { return static_cast<int>(event.motion.x); }
inline int SDLC_EventMotionIntY(const SDL_Event &event) { return static_cast<int>(event.motion.y); }
inline int SDLC_EventButtonIntX(const SDL_Event &event) { return static_cast<int>(event.button.x); }
inline int SDLC_EventButtonIntY(const SDL_Event &event) { return static_cast<int>(event.button.y); }
inline int SDLC_EventWheelIntX(const SDL_Event &event) { return event.wheel.integer_x; }
inline int SDLC_EventWheelIntY(const SDL_Event &event) { return event.wheel.integer_y; }
inline const SDL_GamepadAxisEvent &SDLC_EventGamepadAxis(const SDL_Event &event) { return event.gaxis; }
inline const SDL_GamepadButtonEvent &SDLC_EventGamepadButton(const SDL_Event &event) { return event.gbutton; }
inline const SDL_GamepadDeviceEvent &SDLC_EventGamepadDevice(const SDL_Event &event) { return event.gdevice; }
#define SDLC_SURFACE_BITSPERPIXEL(surface) SDL_BITSPERPIXEL(surface->format)
#define SDLC_StartTextInput SDL_StartTextInput
#define SDLC_StopTextInput SDL_StopTextInput
#define SDLC_SetSurfacePalette SDL_SetSurfacePalette
#define SDLC_PointInRect SDL_PointInRect
#define SDLC_ShowCursor SDL_ShowCursor
#define SDLC_HideCursor SDL_HideCursor
#define SDLC_ShowSimpleMessageBox SDL_ShowSimpleMessageBox
#else
#define SDL_EVENT_AUDIO_DEVICE_ADDED SDL_AUDIODEVICEADDED
#define SDL_EVENT_AUDIO_DEVICE_REMOVED SDL_AUDIODEVICEREMOVED
#define SDL_EVENT_CLIPBOARD_UPDATE SDL_CLIPBOARDUPDATE
#define SDL_EVENT_GAMEPAD_AXIS_MOTION SDL_CONTROLLERAXISMOTION
#define SDL_EVENT_GAMEPAD_BUTTON_DOWN SDL_CONTROLLERBUTTONDOWN
#define SDL_EVENT_GAMEPAD_BUTTON_UP SDL_CONTROLLERBUTTONUP
#define SDL_EVENT_GAMEPAD_ADDED SDL_CONTROLLERDEVICEADDED
#define SDL_EVENT_GAMEPAD_REMAPPED SDL_CONTROLLERDEVICEREMAPPED
#define SDL_EVENT_GAMEPAD_REMOVED SDL_CONTROLLERDEVICEREMOVED
#define SDL_EVENT_GAMEPAD_SENSOR_UPDATE SDL_CONTROLLERSENSORUPDATE
#define SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED SDL_CONTROLLERSTEAMHANDLEUPDATED
#define SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN SDL_CONTROLLERTOUCHPADDOWN
#define SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION SDL_CONTROLLERTOUCHPADMOTION
#define SDL_EVENT_GAMEPAD_TOUCHPAD_UP SDL_CONTROLLERTOUCHPADUP
#define SDL_GAMEPAD_AXIS_INVALID SDL_CONTROLLER_AXIS_INVALID
#define SDL_GAMEPAD_AXIS_LEFTX SDL_CONTROLLER_AXIS_LEFTX
#define SDL_GAMEPAD_AXIS_LEFTY SDL_CONTROLLER_AXIS_LEFTY
#define SDL_GAMEPAD_AXIS_COUNT SDL_CONTROLLER_AXIS_MAX
#define SDL_GAMEPAD_AXIS_RIGHTX SDL_CONTROLLER_AXIS_RIGHTX
#define SDL_GAMEPAD_AXIS_RIGHTY SDL_CONTROLLER_AXIS_RIGHTY
#define SDL_GAMEPAD_AXIS_LEFT_TRIGGER SDL_CONTROLLER_AXIS_TRIGGERLEFT
#define SDL_GAMEPAD_AXIS_RIGHT_TRIGGER SDL_CONTROLLER_AXIS_TRIGGERRIGHT
#define SDL_EVENT_FINGER_DOWN SDL_FINGERDOWN
#define SDL_EVENT_FINGER_MOTION SDL_FINGERMOTION
#define SDL_EVENT_FINGER_UP SDL_FINGERUP
#define SDL_EVENT_JOYSTICK_AXIS_MOTION SDL_JOYAXISMOTION
#define SDL_EVENT_JOYSTICK_BATTERY_UPDATED SDL_JOYBATTERYUPDATED
#define SDL_EVENT_JOYSTICK_BUTTON_DOWN SDL_JOYBUTTONDOWN
#define SDL_EVENT_JOYSTICK_BUTTON_UP SDL_JOYBUTTONUP
#define SDL_EVENT_JOYSTICK_ADDED SDL_JOYDEVICEADDED
#define SDL_EVENT_JOYSTICK_REMOVED SDL_JOYDEVICEREMOVED
#define SDL_EVENT_JOYSTICK_BALL_MOTION SDL_JOYBALLMOTION
#define SDL_EVENT_JOYSTICK_HAT_MOTION SDL_JOYHATMOTION
#define SDL_EVENT_KEY_DOWN SDL_KEYDOWN
#define SDL_EVENT_KEYMAP_CHANGED SDL_KEYMAPCHANGED
#define SDL_EVENT_KEY_UP SDL_KEYUP
#define SDL_EVENT_LAST SDL_LASTEVENT
#define SDL_EVENT_LOCALE_CHANGED SDL_LOCALECHANGED
#define SDL_EVENT_MOUSE_BUTTON_DOWN SDL_MOUSEBUTTONDOWN
#define SDL_EVENT_MOUSE_BUTTON_UP SDL_MOUSEBUTTONUP
#define SDL_EVENT_MOUSE_MOTION SDL_MOUSEMOTION
#define SDL_EVENT_MOUSE_WHEEL SDL_MOUSEWHEEL
#define SDL_EVENT_POLL_SENTINEL SDL_POLLSENTINEL
#define SDL_EVENT_QUIT SDL_QUIT
#define SDL_EVENT_TEXT_INPUT SDL_TEXTINPUT
#define SDL_EVENT_USER SDL_USEREVENT
#define SDL_Gamepad SDL_GameController
#define SDL_GamepadButton SDL_GameControllerButton
#define SDL_GamepadAxisEvent SDL_ControllerAxisEvent
#define SDL_GamepadButtonEvent SDL_ControllerButtonEvent
#define SDL_GamepadDeviceEvent SDL_ControllerDeviceEvent
#define SDL_GAMEPAD_BUTTON_SOUTH SDL_CONTROLLER_BUTTON_A
#define SDL_GAMEPAD_BUTTON_EAST SDL_CONTROLLER_BUTTON_B
#define SDL_GAMEPAD_BUTTON_BACK SDL_CONTROLLER_BUTTON_BACK
#define SDL_GAMEPAD_BUTTON_DPAD_DOWN SDL_CONTROLLER_BUTTON_DPAD_DOWN
#define SDL_GAMEPAD_BUTTON_DPAD_LEFT SDL_CONTROLLER_BUTTON_DPAD_LEFT
#define SDL_GAMEPAD_BUTTON_DPAD_RIGHT SDL_CONTROLLER_BUTTON_DPAD_RIGHT
#define SDL_GAMEPAD_BUTTON_DPAD_UP SDL_CONTROLLER_BUTTON_DPAD_UP
#define SDL_GAMEPAD_BUTTON_GUIDE SDL_CONTROLLER_BUTTON_GUIDE
#define SDL_GAMEPAD_BUTTON_INVALID SDL_CONTROLLER_BUTTON_INVALID
#define SDL_GAMEPAD_BUTTON_LEFT_SHOULDER SDL_CONTROLLER_BUTTON_LEFTSHOULDER
#define SDL_GAMEPAD_BUTTON_LEFT_STICK SDL_CONTROLLER_BUTTON_LEFTSTICK
#define SDL_GAMEPAD_BUTTON_COUNT SDL_CONTROLLER_BUTTON_MAX
#define SDL_GAMEPAD_BUTTON_MISC1 SDL_CONTROLLER_BUTTON_MISC1
#define SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 SDL_CONTROLLER_BUTTON_PADDLE1
#define SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 SDL_CONTROLLER_BUTTON_PADDLE2
#define SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 SDL_CONTROLLER_BUTTON_PADDLE3
#define SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 SDL_CONTROLLER_BUTTON_PADDLE4
#define SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
#define SDL_GAMEPAD_BUTTON_RIGHT_STICK SDL_CONTROLLER_BUTTON_RIGHTSTICK
#define SDL_GAMEPAD_BUTTON_START SDL_CONTROLLER_BUTTON_START
#define SDL_GAMEPAD_BUTTON_TOUCHPAD SDL_CONTROLLER_BUTTON_TOUCHPAD
#define SDL_GAMEPAD_BUTTON_WEST SDL_CONTROLLER_BUTTON_X
#define SDL_GAMEPAD_BUTTON_NORTH SDL_CONTROLLER_BUTTON_Y
#define SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT
#define SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
#define SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT
#define SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO
#define SDL_GAMEPAD_TYPE_PS3 SDL_CONTROLLER_TYPE_PS3
#define SDL_GAMEPAD_TYPE_PS4 SDL_CONTROLLER_TYPE_PS4
#define SDL_GAMEPAD_TYPE_PS5 SDL_CONTROLLER_TYPE_PS5
#define SDL_GAMEPAD_TYPE_STANDARD SDL_CONTROLLER_TYPE_UNKNOWN
#define SDL_GAMEPAD_TYPE_VIRTUAL SDL_CONTROLLER_TYPE_VIRTUAL
#define SDL_GAMEPAD_TYPE_XBOX360 SDL_CONTROLLER_TYPE_XBOX360
#define SDL_GAMEPAD_TYPE_XBOXONE SDL_CONTROLLER_TYPE_XBOXONE
#define SDL_KMOD_ALT KMOD_ALT
#define SDL_KMOD_CAPS KMOD_CAPS
#define SDL_KMOD_CTRL KMOD_CTRL
#define SDL_KMOD_GUI KMOD_GUI
#define SDL_KMOD_LALT KMOD_LALT
#define SDL_KMOD_LCTRL KMOD_LCTRL
#define SDL_KMOD_LGUI KMOD_LGUI
#define SDL_KMOD_LSHIFT KMOD_LSHIFT
#define SDL_KMOD_MODE KMOD_MODE
#define SDL_KMOD_NONE KMOD_NONE
#define SDL_KMOD_NUM KMOD_NUM
#define SDL_KMOD_RALT KMOD_RALT
#define SDL_KMOD_RCTRL KMOD_RCTRL
#define SDL_KMOD_RGUI KMOD_RGUI
#define SDL_KMOD_RSHIFT KMOD_RSHIFT
#define SDL_KMOD_SCROLL KMOD_SCROLL
#define SDL_KMOD_SHIFT KMOD_SHIFT
#define SDLK_GRAVE SDLK_BACKQUOTE
#define SDLK_APOSTROPHE SDLK_QUOTE
#define SDLK_A SDLK_a
#define SDLK_B SDLK_b
#define SDLK_C SDLK_c
#define SDLK_D SDLK_d
#define SDLK_E SDLK_e
#define SDLK_F SDLK_f
#define SDLK_G SDLK_g
#define SDLK_H SDLK_h
#define SDLK_I SDLK_i
#define SDLK_J SDLK_j
#define SDLK_K SDLK_k
#define SDLK_L SDLK_l
#define SDLK_M SDLK_m
#define SDLK_N SDLK_n
#define SDLK_O SDLK_o
#define SDLK_P SDLK_p
#define SDLK_Q SDLK_q
#define SDLK_R SDLK_r
#define SDLK_S SDLK_s
#define SDLK_T SDLK_t
#define SDLK_U SDLK_u
#define SDLK_V SDLK_v
#define SDLK_W SDLK_w
#define SDLK_X SDLK_x
#define SDLK_Y SDLK_y
#define SDLK_Z SDLK_z
#define SDL_PIXELFORMAT_XBGR4444 SDL_PIXELFORMAT_BGR444
#define SDL_PIXELFORMAT_XBGR1555 SDL_PIXELFORMAT_BGR555
#define SDL_PIXELFORMAT_XBGR8888 SDL_PIXELFORMAT_BGR888
#define SDL_PIXELFORMAT_XRGB4444 SDL_PIXELFORMAT_RGB444
#define SDL_PIXELFORMAT_XRGB1555 SDL_PIXELFORMAT_RGB555
#define SDL_PIXELFORMAT_XRGB8888 SDL_PIXELFORMAT_RGB888
#define SDL_IO_SEEK_CUR RW_SEEK_CUR
#define SDL_IO_SEEK_END RW_SEEK_END
#define SDL_IO_SEEK_SET RW_SEEK_SET
#define SDL_IOFromConstMem SDL_RWFromConstMem
#define SDL_IOFromFile SDL_RWFromFile
#define SDL_IOFromMem SDL_RWFromMem
#define SDL_IOStream SDL_RWops
#define SDL_SeekIO SDL_RWseek
#define SDL_GetIOSize SDL_RWsize
#define SDL_TellIO SDL_RWtell
#define SDL_GetLogOutputFunction SDL_LogGetOutputFunction
#define SDL_GetLogPriority SDL_LogGetPriority
#define SDL_ResetLogPriorities SDL_LogResetPriorities
#define SDL_SetLogPriorities SDL_LogSetAllPriority
#define SDL_SetLogOutputFunction SDL_LogSetOutputFunction
#define SDL_SetLogPriority SDL_LogSetPriority
#define SDL_LOG_PRIORITY_COUNT SDL_NUM_LOG_PRIORITIES
#define SDL_ThreadID SDL_threadID
#define SDLC_SURFACE_BITSPERPIXEL(surface) surface->format->BitsPerPixel
inline bool SDLC_PushEvent(SDL_Event *event) { return SDL_PushEvent(event) == 0; }
inline
#ifdef USE_SDL1
SDLKey
#else
SDL_Keycode
#endif
SDLC_EventKey(const SDL_Event &event)
{
return event.key.keysym.sym;
}
inline SDL_Scancode SDLC_EventScancode(const SDL_Event &event) { return event.key.keysym.scancode; }
inline int SDLC_EventMotionIntX(const SDL_Event &event) { return event.motion.x; }
inline int SDLC_EventMotionIntY(const SDL_Event &event) { return event.motion.y; }
inline int SDLC_EventButtonIntX(const SDL_Event &event) { return event.button.x; }
inline int SDLC_EventButtonIntY(const SDL_Event &event) { return event.button.y; }
inline bool SDL_FillSurfaceRect(SDL_Surface *dst,
#ifdef USE_SDL1
SDL_Rect *rect,
#else
const SDL_Rect *rect,
#endif
Uint32 color)
{
return SDL_FillRect(dst, rect, color) == 0;
}
inline bool SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect) { return SDL_SetClipRect(surface, rect) == SDL_TRUE; }
inline bool SDL_SetSurfaceColorKey(SDL_Surface *surface, bool enabled, Uint32 key)
{
return SDL_SetColorKey(surface, enabled ? 1 : 0, key) == 0;
}
#ifndef USE_SDL1
inline bool SDLC_SetClipboardText(const char *text) { return SDL_SetClipboardText(text) == 0; }
inline bool SDLC_HasClipboardText() { return SDL_HasClipboardText() == SDL_TRUE; }
inline int SDLC_EventWheelIntX(const SDL_Event &event) { return event.wheel.x; }
inline int SDLC_EventWheelIntY(const SDL_Event &event) { return event.wheel.y; }
inline const SDL_GamepadAxisEvent &SDLC_EventGamepadAxis(const SDL_Event &event) { return event.caxis; }
inline const SDL_GamepadButtonEvent &SDLC_EventGamepadButton(const SDL_Event &event) { return event.cbutton; }
inline const SDL_GamepadDeviceEvent &SDLC_EventGamepadDevice(const SDL_Event &event) { return event.cdevice; }
inline bool SDL_GamepadHasButton(SDL_Gamepad *gamepad, SDL_GamepadButton button)
{
return SDL_GameControllerHasButton(gamepad, button) == SDL_TRUE;
}
inline bool SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button)
{
return SDL_GameControllerGetButton(gamepad, button) != 0;
}
inline bool SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY)
{
SDL_RenderGetScale(renderer, scaleX, scaleY);
return true;
}
// For SDL1.2, these are defined in sdl2_to_1_2_backports.h
inline bool SDLC_StartTextInput([[maybe_unused]] SDL_Window *window)
{
SDL_StartTextInput();
return true;
}
inline bool SDLC_StopTextInput([[maybe_unused]] SDL_Window *window)
{
SDL_StopTextInput();
return true;
}
inline bool SDL_SetTextInputArea([[maybe_unused]] SDL_Window *window, SDL_Rect *rect, [[maybe_unused]] int cursor)
{
SDL_SetTextInputRect(rect);
return true;
}
inline bool SDLC_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)
{
return SDL_SetSurfacePalette(surface, palette) == 0;
}
inline bool SDL_CursorVisible() { return SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE; }
// For SDL1.2, this is defined in sdl2_to_1_2_backports.h
inline bool SDLC_PointInRect(const SDL_Point *p, const SDL_Rect *r) { return SDL_PointInRect(p, r) == SDL_TRUE; }
#endif
inline bool SDLC_ShowCursor() { return SDL_ShowCursor(SDL_ENABLE) == 0; }
inline bool SDLC_HideCursor() { return SDL_ShowCursor(SDL_DISABLE) == 0; }
inline size_t SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
return SDL_RWread(context, ptr, 1, size);
#else
return SDL_RWread(context, ptr, 1, static_cast<int>(size));
#endif
}
inline size_t SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
return SDL_RWwrite(context, ptr, 1, size);
#else
return SDL_RWwrite(context, ptr, 1, static_cast<int>(size));
#endif
}
inline bool SDL_CloseIO(SDL_IOStream *iostr)
{
return SDL_RWclose(iostr) == 0;
}
#define SDLC_ShowSimpleMessageBox(flags, title, message, window) SDL_ShowSimpleMessageBox(flags, title, message, window) == 0
#endif
#ifndef USE_SDL1

52
Source/utils/surface_to_pcx.cpp

@ -18,24 +18,14 @@
#include "engine/surface.hpp"
#include "utils/endian_swap.hpp"
#include "utils/pcx.hpp"
#include "utils/sdl_compat.h"
namespace devilution {
namespace {
tl::expected<void, std::string> CheckedFWrite(const void *ptr, size_t size,
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
out)
tl::expected<void, std::string> CheckedFWrite(const void *ptr, size_t size, SDL_IOStream *out)
{
#ifdef USE_SDL3
if (SDL_WriteIO(out, ptr, size) != size)
#else
if (SDL_RWwrite(out, ptr, size, 1) != 1)
#endif
{
if (SDL_WriteIO(out, ptr, size) != size) {
const char *errorMessage = SDL_GetError();
if (errorMessage == nullptr)
errorMessage = "";
@ -53,13 +43,7 @@ tl::expected<void, std::string> CheckedFWrite(const void *ptr, size_t size,
* @param out File stream to write to
* @return True on success
*/
tl::expected<void, std::string> WritePcxHeader(int16_t width, int16_t height,
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
out)
tl::expected<void, std::string> WritePcxHeader(int16_t width, int16_t height, SDL_IOStream *out)
{
PCXHeader buffer;
@ -84,13 +68,7 @@ tl::expected<void, std::string> WritePcxHeader(int16_t width, int16_t height,
* @param out File stream for the PCX file.
* @return True if successful, else false
*/
tl::expected<void, std::string> WritePcxPalette(SDL_Color *palette,
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
out)
tl::expected<void, std::string> WritePcxPalette(SDL_Color *palette, SDL_IOStream *out)
{
uint8_t pcxPalette[1 + 256 * 3];
@ -153,13 +131,7 @@ uint8_t *WritePcxLine(uint8_t *src, uint8_t *dst, int width)
* @param out File stream for the PCX file.
* @return True if successful, else false
*/
tl::expected<void, std::string> WritePcxPixels(const Surface &buf,
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
out)
tl::expected<void, std::string> WritePcxPixels(const Surface &buf, SDL_IOStream *out)
{
const int width = buf.w();
const std::unique_ptr<uint8_t[]> pBuffer { new uint8_t[static_cast<size_t>(2 * width)] };
@ -176,13 +148,7 @@ tl::expected<void, std::string> WritePcxPixels(const Surface &buf,
} // namespace
tl::expected<void, std::string>
WriteSurfaceToFilePcx(const Surface &buf,
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
outStream)
WriteSurfaceToFilePcx(const Surface &buf, SDL_IOStream *outStream)
{
tl::expected<void, std::string> result = WritePcxHeader(buf.w(), buf.h(), outStream);
if (!result.has_value()) return result;
@ -190,11 +156,7 @@ WriteSurfaceToFilePcx(const Surface &buf,
if (!result.has_value()) return result;
result = WritePcxPalette(buf.surface->format->palette->colors, outStream);
if (!result.has_value()) return result;
#ifdef USE_SDL3
SDL_CloseIO(outStream);
#else
SDL_RWclose(outStream);
#endif
return {};
}

11
Source/utils/surface_to_pcx.hpp

@ -1,10 +1,11 @@
#include <string>
#ifdef USE_SDL3
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_iostream.h>
#else
#include <SDL.h>
#include "utils/sdl_compat.h"
#endif
#include <expected.hpp>
@ -14,12 +15,6 @@
namespace devilution {
tl::expected<void, std::string>
WriteSurfaceToFilePcx(const Surface &buf,
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
outStream);
WriteSurfaceToFilePcx(const Surface &buf, SDL_IOStream *outStream);
} // namespace devilution

11
Source/utils/surface_to_png.cpp

@ -3,10 +3,13 @@
#include <string>
#ifdef USE_SDL3
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_iostream.h>
#include <SDL3_image/SDL_image.h>
#else
#include <SDL.h>
#include "utils/sdl_compat.h"
#endif
#include <expected.hpp>
@ -20,13 +23,7 @@ extern "C" int IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
#endif
tl::expected<void, std::string>
WriteSurfaceToFilePng(const Surface &buf,
#ifdef USE_SDL3
SDL_IOStream *
#else
SDL_RWops *
#endif
dst)
WriteSurfaceToFilePng(const Surface &buf, SDL_IOStream *dst)
{
#ifdef USE_SDL3
const bool ok = IMG_SavePNG_IO(buf.surface, dst, /*closeio=*/true);

6
Source/utils/timer.cpp

@ -1,5 +1,11 @@
#include "engine/demomode.h"
#ifdef USE_SDL3
#include <SDL3/SDL_timer.h>
#else
#include <SDL.h>
#endif
namespace devilution {
uint32_t GetMillisecondsSinceStartup()

22
test/text_render_integration_test.cpp

@ -27,6 +27,7 @@
#include "engine/size.hpp"
#include "engine/surface.hpp"
#include "utils/paths.h"
#include "utils/sdl_compat.h"
#include "utils/sdl_wrap.h"
#include "utils/str_cat.hpp"
#include "utils/surface_to_png.hpp"
@ -229,28 +230,13 @@ SDLPaletteUniquePtr LoadPalette()
std::vector<std::byte> ReadFile(const std::string &path)
{
#ifdef USE_SDL3
SDL_IOStream *rwops = SDL_IOFromFile(path.c_str(), "rb");
#else
SDL_RWops *rwops = SDL_RWFromFile(path.c_str(), "rb");
#endif
std::vector<std::byte> result;
if (rwops == nullptr) return result;
const size_t size = static_cast<size_t>(
#ifdef USE_SDL3
SDL_GetIOSize(rwops)
#else
SDL_RWsize(rwops)
#endif
);
const size_t size = static_cast<size_t>(SDL_GetIOSize(rwops));
result.resize(size);
#ifdef USE_SDL3
SDL_ReadIO(rwops, result.data(), size);
SDL_CloseIO(rwops);
#else
SDL_RWread(rwops, result.data(), size, 1);
SDL_RWclose(rwops);
#endif
return result;
}
@ -315,11 +301,7 @@ TEST_P(TextRenderIntegrationTest, RenderAndCompareTest)
const std::string actualPath = StrCat(paths::BasePath(), FixturesPath, GetParam().name, "-Actual.png");
const std::string expectedPath = StrCat(paths::BasePath(), FixturesPath, GetParam().name, ".png");
#ifdef USE_SDL3
SDL_IOStream *actual = SDL_IOFromFile(actualPath.c_str(), "wb");
#else
SDL_RWops *actual = SDL_RWFromFile(actualPath.c_str(), "wb");
#endif
ASSERT_NE(actual, nullptr) << SDL_GetError();
const tl::expected<void, std::string> result = WriteSurfaceToFilePng(out, actual);

19
test/timedemo_test.cpp

@ -2,6 +2,12 @@
#include <gtest/gtest.h>
#include <iostream>
#ifdef USE_SDL3
#include <SDL3/SDL.h>
#else
#include <SDL.h>
#endif
#include "engine/assets.hpp"
#include "engine/demomode.h"
#include "game_mode.hpp"
@ -26,14 +32,15 @@ bool Dummy_GetHeroInfo(_uiheroinfo *pInfo)
void RunTimedemo(std::string timedemoFolderName)
{
if (SDL_Init(
#ifdef USE_SDL1
0
if (
#ifdef USE_SDL3
!SDL_Init(SDL_INIT_EVENTS)
#elif !defined(USE_SDL1)
SDL_Init(SDL_INIT_EVENTS) < 0
#else
SDL_INIT_EVENTS
SDL_Init(0) < 0
#endif
)
<= -1) {
) {
ErrSdl();
}

1
test/writehero_test.cpp

@ -4,7 +4,6 @@
#include <cstdio>
#include <vector>
#include <SDL_endian.h>
#include <gtest/gtest.h>
#include <picosha2.h>

Loading…
Cancel
Save