diff --git a/Source/controls/touch/renderers.cpp b/Source/controls/touch/renderers.cpp index 6bbe710c4..04a3cffe1 100644 --- a/Source/controls/touch/renderers.cpp +++ b/Source/controls/touch/renderers.cpp @@ -90,7 +90,7 @@ VirtualGamepadButtonType GetStandButtonType(bool isPressed) return isPressed ? GAMEPAD_STANDDOWN : GAMEPAD_STAND; } -void LoadButtonArt(ButtonTexture *buttonArt, SDL_Renderer *renderer) +void LoadButtonArt(ButtonTexture *buttonArt) { constexpr unsigned Sprites = 13; constexpr unsigned Frames = 2; @@ -100,14 +100,9 @@ void LoadButtonArt(ButtonTexture *buttonArt, SDL_Renderer *renderer) buttonArt->numSprites = Sprites; buttonArt->numFrames = Frames; - - if (renderer != nullptr) { - buttonArt->texture.reset(SDL_CreateTextureFromSurface(renderer, buttonArt->surface.get())); - buttonArt->surface = nullptr; - } } -void LoadPotionArt(ButtonTexture *potionArt, SDL_Renderer *renderer) +void LoadPotionArt(ButtonTexture *potionArt) { item_cursor_graphic potionGraphics[] { ICURS_POTION_OF_HEALING, @@ -149,12 +144,7 @@ void LoadPotionArt(ButtonTexture *potionArt, SDL_Renderer *renderer) potionArt->numFrames = sizeof(potionGraphics); - if (renderer == nullptr) { - potionArt->surface.reset(SDL_ConvertSurfaceFormat(surface.get(), SDL_PIXELFORMAT_ARGB8888, 0)); - } else { - potionArt->texture.reset(SDL_CreateTextureFromSurface(renderer, surface.get())); - potionArt->surface = nullptr; - } + potionArt->surface.reset(SDL_ConvertSurfaceFormat(surface.get(), SDL_PIXELFORMAT_ARGB8888, 0)); } bool InteractsWithCharButton(Point point) @@ -223,39 +213,24 @@ void RenderVirtualGamepad(SDL_Surface *surface) Renderer.Render(renderFunction); } -void VirtualGamepadRenderer::LoadArt(SDL_Renderer *renderer) +void VirtualGamepadRenderer::LoadArt() { - menuPanelRenderer.LoadArt(renderer); - directionPadRenderer.LoadArt(renderer); - LoadButtonArt(&buttonArt, renderer); - LoadPotionArt(&potionArt, renderer); + menuPanelRenderer.LoadArt(); + directionPadRenderer.LoadArt(); + LoadButtonArt(&buttonArt); + LoadPotionArt(&potionArt); } -void VirtualMenuPanelRenderer::LoadArt(SDL_Renderer *renderer) +void VirtualMenuPanelRenderer::LoadArt() { menuArt.surface.reset(LoadPNG("ui_art\\menu.png")); menuArtLevelUp.surface.reset(LoadPNG("ui_art\\menu-levelup.png")); - - if (renderer != nullptr) { - menuArt.texture.reset(SDL_CreateTextureFromSurface(renderer, menuArt.surface.get())); - menuArt.surface = nullptr; - menuArtLevelUp.texture.reset(SDL_CreateTextureFromSurface(renderer, menuArtLevelUp.surface.get())); - menuArtLevelUp.surface = nullptr; - } } -void VirtualDirectionPadRenderer::LoadArt(SDL_Renderer *renderer) +void VirtualDirectionPadRenderer::LoadArt() { padArt.surface.reset(LoadPNG("ui_art\\directions.png")); knobArt.surface.reset(LoadPNG("ui_art\\directions2.png")); - - if (renderer != nullptr) { - padArt.texture.reset(SDL_CreateTextureFromSurface(renderer, padArt.surface.get())); - padArt.surface = nullptr; - - knobArt.texture.reset(SDL_CreateTextureFromSurface(renderer, knobArt.surface.get())); - knobArt.surface = nullptr; - } } void VirtualGamepadRenderer::Render(RenderFunction renderFunction) @@ -516,25 +491,25 @@ void VirtualGamepadRenderer::UnloadArt() { menuPanelRenderer.UnloadArt(); directionPadRenderer.UnloadArt(); - buttonArt.clear(); - potionArt.clear(); + buttonArt.clearSurface(); + potionArt.clearSurface(); } void VirtualMenuPanelRenderer::UnloadArt() { - menuArt.clear(); - menuArtLevelUp.clear(); + menuArt.clearSurface(); + menuArtLevelUp.clearSurface(); } void VirtualDirectionPadRenderer::UnloadArt() { - padArt.clear(); - knobArt.clear(); + padArt.clearSurface(); + knobArt.clearSurface(); } -void InitVirtualGamepadGFX(SDL_Renderer *renderer) +void InitVirtualGamepadGFX() { - Renderer.LoadArt(renderer); + Renderer.LoadArt(); } void FreeVirtualGamepadGFX() @@ -542,4 +517,72 @@ void FreeVirtualGamepadGFX() Renderer.UnloadArt(); } +void VirtualGamepadRenderer::createTextures(SDL_Renderer &renderer) +{ + menuPanelRenderer.createTextures(renderer); + directionPadRenderer.createTextures(renderer); + if (buttonArt.surface != nullptr) { + buttonArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, buttonArt.surface.get())); + buttonArt.surface = nullptr; + } + if (potionArt.surface != nullptr) { + potionArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, potionArt.surface.get())); + potionArt.surface = nullptr; + } +} + +void VirtualMenuPanelRenderer::createTextures(SDL_Renderer &renderer) +{ + if (menuArt.surface != nullptr) { + menuArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, menuArt.surface.get())); + menuArt.surface = nullptr; + } + if (menuArtLevelUp.surface != nullptr) { + menuArtLevelUp.texture.reset(SDL_CreateTextureFromSurface(&renderer, menuArtLevelUp.surface.get())); + menuArtLevelUp.surface = nullptr; + } +} + +void VirtualDirectionPadRenderer::createTextures(SDL_Renderer &renderer) +{ + if (padArt.surface != nullptr) { + padArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, padArt.surface.get())); + padArt.surface = nullptr; + } + if (knobArt.surface != nullptr) { + knobArt.texture.reset(SDL_CreateTextureFromSurface(&renderer, knobArt.surface.get())); + knobArt.surface = nullptr; + } +} + +void VirtualGamepadRenderer::destroyTextures() +{ + menuPanelRenderer.destroyTextures(); + directionPadRenderer.destroyTextures(); + buttonArt.destroyTexture(); + potionArt.destroyTexture(); +} + +void VirtualMenuPanelRenderer::destroyTextures() +{ + menuArt.destroyTexture(); + menuArtLevelUp.destroyTexture(); +} + +void VirtualDirectionPadRenderer::destroyTextures() +{ + padArt.destroyTexture(); + knobArt.destroyTexture(); +} + +void InitVirtualGamepadTextures(SDL_Renderer &renderer) +{ + Renderer.createTextures(renderer); +} + +void FreeVirtualGamepadTextures() +{ + Renderer.destroyTextures(); +} + } // namespace devilution diff --git a/Source/controls/touch/renderers.h b/Source/controls/touch/renderers.h index 0cfb54aef..7ceab432f 100644 --- a/Source/controls/touch/renderers.h +++ b/Source/controls/touch/renderers.h @@ -61,12 +61,16 @@ struct ButtonTexture { Size size() const; - void clear() + void clearSurface() { surface = nullptr; - texture = nullptr; numFrames = 1; } + + void destroyTexture() + { + texture = nullptr; + } }; typedef std::function RenderFunction; @@ -78,7 +82,23 @@ public: { } - void LoadArt(SDL_Renderer *renderer); + void LoadArt(); + + /** + * @brief Converts surfaces to textures. + * + * Must be called from the main thread. + * + * Per https://wiki.libsdl.org/SDL3/CategoryRender: + * > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986 + */ + void createTextures(SDL_Renderer &renderer); + + /** + * @brief Must be called from the main thread. + */ + void destroyTextures(); + void Render(RenderFunction renderFunction); void UnloadArt(); @@ -95,7 +115,23 @@ public: { } - void LoadArt(SDL_Renderer *renderer); + void LoadArt(); + + /** + * @brief Converts surfaces to textures. + * + * Must be called from the main thread. + * + * Per https://wiki.libsdl.org/SDL3/CategoryRender: + * > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986 + */ + void createTextures(SDL_Renderer &renderer); + + /** + * @brief Must be called from the main thread. + */ + void destroyTextures(); + void Render(RenderFunction renderFunction); void UnloadArt(); @@ -213,7 +249,23 @@ public: { } - void LoadArt(SDL_Renderer *renderer); + void LoadArt(); + + /** + * @brief Converts surfaces to textures. + * + * Must be called from the main thread. + * + * Per https://wiki.libsdl.org/SDL3/CategoryRender: + * > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986 + */ + void createTextures(SDL_Renderer &renderer); + + /** + * @brief Must be called from the main thread. + */ + void destroyTextures(); + void Render(RenderFunction renderFunction); void UnloadArt(); @@ -234,7 +286,22 @@ private: ButtonTexture potionArt; }; -void InitVirtualGamepadGFX(SDL_Renderer *renderer); +void InitVirtualGamepadGFX(); + +/** + * @brief Creates textures for the virtual gamepad. + * + * Must be called after `InitVirtualGamepadGFX`. + * Must be called from the main thread. + * + * Per https://wiki.libsdl.org/SDL3/CategoryRender: + * > These functions must be called from the main thread. See this bug for details: https://github.com/libsdl-org/SDL/issues/986 + */ +void InitVirtualGamepadTextures(SDL_Renderer &renderer); + +/** @brief Must be called from the main thread. */ +void FreeVirtualGamepadTextures(); + void RenderVirtualGamepad(SDL_Renderer *renderer); void RenderVirtualGamepad(SDL_Surface *surface); void FreeVirtualGamepadGFX(); diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 54302f031..65342a561 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1324,7 +1324,7 @@ void LoadAllGFX() { IncProgress(); #if !defined(USE_SDL1) && !defined(__vita__) - InitVirtualGamepadGFX(renderer); + InitVirtualGamepadGFX(); #endif IncProgress(); InitObjectGFX(); @@ -3044,7 +3044,7 @@ void LoadGameLevelSetLevel(bool firstflag, lvl_entry lvldir, const Player &myPla IncProgress(); if (!HeadlessMode) { #if !defined(USE_SDL1) && !defined(__vita__) - InitVirtualGamepadGFX(renderer); + InitVirtualGamepadGFX(); #endif InitMissileGFX(gbIsHellfire); IncProgress(); @@ -3101,7 +3101,7 @@ void LoadGameLevelStandardLevel(bool firstflag, lvl_entry lvldir, const Player & IncProgress(); #if !defined(USE_SDL1) && !defined(__vita__) - InitVirtualGamepadGFX(renderer); + InitVirtualGamepadGFX(); #endif IncProgress(); diff --git a/Source/gamemenu.cpp b/Source/gamemenu.cpp index 691a06f86..0a983288e 100644 --- a/Source/gamemenu.cpp +++ b/Source/gamemenu.cpp @@ -19,6 +19,10 @@ #include "qol/floatingnumbers.h" #include "utils/language.h" +#ifndef USE_SDL1 +#include "controls/touch/renderers.h" +#endif + namespace devilution { bool isGameMenuOpen = false; @@ -302,7 +306,17 @@ void gamemenu_load_game(bool /*bActivate*/) InitDiabloMsg(EMSG_LOADING); RedrawEverything(); DrawAndBlit(); +#ifndef USE_SDL1 + DeactivateVirtualGamepad(); + FreeVirtualGamepadTextures(); +#endif LoadGame(false); +#if !defined(USE_SDL1) && !defined(__vita__) + if (renderer != nullptr) { + InitVirtualGamepadTextures(*renderer); + } +#endif + NewCursor(CURSOR_HAND); ClrDiabloMsg(); CornerStone.activated = false; PaletteFadeOut(8); diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 601473e5d..2dde740af 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -12,12 +12,10 @@ #include "control.h" #include "engine.h" #include "engine/clx_sprite.hpp" -#include "engine/demomode.h" #include "engine/dx.h" #include "engine/events.hpp" #include "engine/load_cel.hpp" #include "engine/load_clx.hpp" -#include "engine/load_pcx.hpp" #include "engine/palette.h" #include "engine/render/clx_render.hpp" #include "hwcursor.hpp" @@ -26,12 +24,18 @@ #include "pfile.h" #include "plrmsg.h" #include "utils/sdl_geometry.h" +#include "utils/sdl_thread.h" + +#ifndef USE_SDL1 +#include "controls/touch/renderers.h" +#endif namespace devilution { namespace { constexpr uint32_t MaxProgress = 534; +constexpr uint32_t ProgressStepSize = 23; OptionalOwnedClxSpriteList sgpBackCel; @@ -225,118 +229,18 @@ void DrawCutsceneForeground() RenderPresent(); } -} // namespace - -void RegisterCustomEvents() -{ -#ifndef USE_SDL1 - CustomEventsBegin = SDL_RegisterEvents(NumCustomEvents); -#endif -} - -bool IsCustomEvent(SdlEventType eventType) -{ - return eventType >= CustomEventsBegin && eventType < CustomEventsBegin + NumCustomEvents; -} - -interface_mode GetCustomEvent(SdlEventType eventType) -{ - return static_cast(eventType - CustomEventsBegin); -} - -SdlEventType CustomEventToSdlEvent(interface_mode eventType) +void DoLoad(interface_mode uMsg) { - return CustomEventsBegin + eventType; -} - -void interface_msg_pump() -{ - SDL_Event event; - uint16_t modState; - while (FetchMessage(&event, &modState)) { - if (event.type != SDL_QUIT) { - HandleMessage(event, modState); - } - } -} - -void IncProgress() -{ - if (!HeadlessMode && !demo::IsRunning()) - interface_msg_pump(); - if (!IsProgress) - return; - sgdwProgress += 23; - if (sgdwProgress > MaxProgress) - sgdwProgress = MaxProgress; - if (!HeadlessMode && !demo::IsRunning()) - DrawCutsceneForeground(); -} - -void CompleteProgress() -{ - if (HeadlessMode) - return; - if (!IsProgress) - return; - while (sgdwProgress < MaxProgress) - IncProgress(); -} - -void ShowProgress(interface_mode uMsg) -{ - IsProgress = true; - - gbSomebodyWonGameKludge = false; - uint32_t delayStart = SDL_GetTicks(); - - EventHandler previousHandler = SetEventHandler(DisableInputEventHandler); - - if (!HeadlessMode) { - assert(ghMainWnd); - - interface_msg_pump(); - ClearScreenBuffer(); - scrollrt_draw_game_screen(); - - if (IsHardwareCursor()) - SetHardwareCursorVisible(false); - - BlackPalette(); - - // Blit the background once and then free it. - LoadCutsceneBackground(uMsg); - DrawCutsceneBackground(); - if (RenderDirectlyToOutputSurface && PalSurface != nullptr) { - // Render into all the backbuffers if there are multiple. - const void *initialPixels = PalSurface->pixels; - if (DiabloUiSurface() == PalSurface) - BltFast(nullptr, nullptr); - RenderPresent(); - while (PalSurface->pixels != initialPixels) { - DrawCutsceneBackground(); - if (DiabloUiSurface() == PalSurface) - BltFast(nullptr, nullptr); - RenderPresent(); - } - } - FreeCutsceneBackground(); - - PaletteFadeIn(8); - IncProgress(); - sound_init(); - IncProgress(); - } + IncProgress(); + sound_init(); + IncProgress(); Player &myPlayer = *MyPlayer; - switch (uMsg) { case WM_DIABLOADGAME: - IncProgress(); - IncProgress(); + IncProgress(2); LoadGame(true); - IncProgress(); - IncProgress(); + IncProgress(2); break; case WM_DIABNEWGAME: myPlayer.pOriginalCathedral = !gbIsHellfire; @@ -477,37 +381,228 @@ void ShowProgress(interface_mode uMsg) LoadGameLevel(false, ENTRY_MAIN); IncProgress(); break; + default: + app_fatal("Unknown progress mode"); } + SDL_Event event; + event.type = CustomEventToSdlEvent(WM_DONE); + SDL_PushEvent(&event); +} + +struct { + uint32_t delayStart; + EventHandler prevHandler; + bool done; + std::array palette; +} ProgressEventHandlerState; + +void ProgressEventHandler(const SDL_Event &event, uint16_t modState) +{ + DisableInputEventHandler(event, modState); + if (!IsCustomEvent(event.type)) return; + + static uint32_t drawnProgress; + drawnProgress = 0; + + const interface_mode customEvent = GetCustomEvent(event.type); + switch (customEvent) { + case WM_PROGRESS: + if (!HeadlessMode && drawnProgress != sgdwProgress) { + DrawCutsceneForeground(); + drawnProgress = sgdwProgress; + } + break; + case WM_DONE: { + // We may have loaded a new palette. + // Temporarily switch back to the load screen palette for fade out. + std::array prevPalette; + if (!HeadlessMode) { + prevPalette = orig_palette; + orig_palette = ProgressEventHandlerState.palette; + ApplyGamma(logical_palette, orig_palette, 256); + } + NewCursor(CURSOR_HAND); + + if (!HeadlessMode) { + assert(ghMainWnd); + + if (RenderDirectlyToOutputSurface && PalSurface != nullptr) { + // Ensure that all back buffers have the full progress bar. + const void *initialPixels = PalSurface->pixels; + do { + DrawCutsceneForeground(); + if (DiabloUiSurface() == PalSurface) + BltFast(nullptr, nullptr); + RenderPresent(); + } while (PalSurface->pixels != initialPixels); + } + + PaletteFadeOut(8); + orig_palette = prevPalette; + ApplyGamma(logical_palette, orig_palette, 256); + } + + [[maybe_unused]] EventHandler prevHandler = SetEventHandler(ProgressEventHandlerState.prevHandler); + assert(prevHandler == ProgressEventHandler); + ProgressEventHandlerState.prevHandler = nullptr; + IsProgress = false; + + Player &myPlayer = *MyPlayer; + NetSendCmdLocParam2(true, CMD_PLAYER_JOINLEVEL, myPlayer.position.tile, myPlayer.plrlevel, myPlayer.plrIsOnSetLevel ? 1 : 0); + DelayPlrMessages(SDL_GetTicks() - ProgressEventHandlerState.delayStart); + + if (gbSomebodyWonGameKludge && myPlayer.isOnLevel(16)) { + PrepDoEnding(); + } + + gbSomebodyWonGameKludge = false; + ProgressEventHandlerState.done = true; + +#if !defined(USE_SDL1) && !defined(__vita__) + if (renderer != nullptr) { + InitVirtualGamepadTextures(*renderer); + } +#endif + } break; + default: + app_fatal("Unknown progress mode"); + break; + } +} + +} // namespace + +void RegisterCustomEvents() +{ +#ifndef USE_SDL1 + CustomEventsBegin = SDL_RegisterEvents(NumCustomEvents); +#endif +} + +bool IsCustomEvent(SdlEventType eventType) +{ + return eventType >= CustomEventsBegin && eventType < CustomEventsBegin + NumCustomEvents; +} + +interface_mode GetCustomEvent(SdlEventType eventType) +{ + return static_cast(eventType - CustomEventsBegin); +} + +SdlEventType CustomEventToSdlEvent(interface_mode eventType) +{ + return CustomEventsBegin + eventType; +} + +void interface_msg_pump() +{ + SDL_Event event; + uint16_t modState; + while (FetchMessage(&event, &modState)) { + if (event.type != SDL_QUIT) { + HandleMessage(event, modState); + } + } +} + +void IncProgress(uint32_t steps) +{ + if (!IsProgress) + return; + const uint32_t prevProgress = sgdwProgress; + sgdwProgress += ProgressStepSize * steps; + if (sgdwProgress > MaxProgress) + sgdwProgress = MaxProgress; + if (!HeadlessMode && sgdwProgress != prevProgress) { + SDL_Event event; + event.type = CustomEventToSdlEvent(WM_PROGRESS); + SDL_PushEvent(&event); + } +} + +void CompleteProgress() +{ + if (HeadlessMode) + return; + if (!IsProgress) + return; + if (sgdwProgress < MaxProgress) { + IncProgress((MaxProgress - sgdwProgress) / ProgressStepSize); + } +} + +void ShowProgress(interface_mode uMsg) +{ + IsProgress = true; + gbSomebodyWonGameKludge = false; + + ProgressEventHandlerState.delayStart = SDL_GetTicks(); + ProgressEventHandlerState.prevHandler = SetEventHandler(ProgressEventHandler); + ProgressEventHandlerState.done = false; + +#ifndef USE_SDL1 + DeactivateVirtualGamepad(); + FreeVirtualGamepadTextures(); +#endif + if (!HeadlessMode) { assert(ghMainWnd); + interface_msg_pump(); + ClearScreenBuffer(); + scrollrt_draw_game_screen(); + + if (IsHardwareCursor()) + SetHardwareCursorVisible(false); + + BlackPalette(); + + // Blit the background once and then free it. + LoadCutsceneBackground(uMsg); + DrawCutsceneBackground(); + ProgressEventHandlerState.palette = orig_palette; if (RenderDirectlyToOutputSurface && PalSurface != nullptr) { - // Ensure that all back buffers have the full progress bar. + // Render into all the backbuffers if there are multiple. const void *initialPixels = PalSurface->pixels; - do { - DrawCutsceneForeground(); + if (DiabloUiSurface() == PalSurface) + BltFast(nullptr, nullptr); + RenderPresent(); + while (PalSurface->pixels != initialPixels) { + DrawCutsceneBackground(); if (DiabloUiSurface() == PalSurface) BltFast(nullptr, nullptr); RenderPresent(); - } while (PalSurface->pixels != initialPixels); + } } - - PaletteFadeOut(8); + FreeCutsceneBackground(); } - previousHandler = SetEventHandler(previousHandler); - assert(previousHandler == DisableInputEventHandler); - IsProgress = false; - - NetSendCmdLocParam2(true, CMD_PLAYER_JOINLEVEL, myPlayer.position.tile, myPlayer.plrlevel, myPlayer.plrIsOnSetLevel ? 1 : 0); - DelayPlrMessages(SDL_GetTicks() - delayStart); + // Begin loading + static interface_mode loadTarget; + loadTarget = uMsg; + SdlThread loadThread = SdlThread([]() { + DoLoad(loadTarget); + }); - if (gbSomebodyWonGameKludge && myPlayer.isOnLevel(16)) { - PrepDoEnding(); + if (!HeadlessMode) { + PaletteFadeIn(8); } - gbSomebodyWonGameKludge = false; + while (true) { + SDL_Event event; + // We use the real `SDL_PollEvent` here instead of `FetchEvent` + // to process real events rather than the recorded ones in demo mode. + while (SDL_PollEvent(&event)) { + if (event.type != SDL_QUIT) { + HandleMessage(event, SDL_GetModState()); + } + if (ProgressEventHandlerState.done) { + loadThread.join(); + return; + } + } + } } } // namespace devilution diff --git a/Source/interfac.h b/Source/interfac.h index eeabe434c..9b445c538 100644 --- a/Source/interfac.h +++ b/Source/interfac.h @@ -26,8 +26,12 @@ enum interface_mode : uint8_t { WM_DIABNEWGAME, WM_DIABLOADGAME, + // Asynchronous loading events. + WM_PROGRESS, + WM_DONE, + WM_FIRST = WM_DIABNEXTLVL, - WM_LAST = WM_DIABLOADGAME, + WM_LAST = WM_DONE, }; void RegisterCustomEvents(); @@ -59,7 +63,7 @@ enum Cutscenes : uint8_t { }; void interface_msg_pump(); -void IncProgress(); +void IncProgress(uint32_t steps = 1); void CompleteProgress(); void ShowProgress(interface_mode uMsg); diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index df2f24539..2e65c9421 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -2552,7 +2552,6 @@ void LoadGame(bool firstflag) SetUpMissileAnimationData(); RedoMissileFlags(); - NewCursor(CURSOR_HAND); gbProcessPlayers = IsDiabloAlive(!firstflag); if (gbIsHellfireSaveGame != gbIsHellfire) { diff --git a/test/timedemo_test.cpp b/test/timedemo_test.cpp index 9a783e234..79eb5d334 100644 --- a/test/timedemo_test.cpp +++ b/test/timedemo_test.cpp @@ -23,6 +23,9 @@ bool Dummy_GetHeroInfo(_uiheroinfo *pInfo) void RunTimedemo(std::string timedemoFolderName) { + if (SDL_Init(SDL_INIT_EVENTS) <= -1) { + ErrSdl(); + } std::string unitTestFolderCompletePath = paths::BasePath() + "/test/fixtures/timedemo/" + timedemoFolderName; paths::SetPrefPath(unitTestFolderCompletePath); paths::SetConfigPath(unitTestFolderCompletePath); @@ -72,6 +75,7 @@ void RunTimedemo(std::string timedemoFolderName) ASSERT_FALSE(gbRunGame); gbRunGame = false; init_cleanup(); + SDL_Quit(); } } // namespace