From 5e778431c3ff0bbbade5de7382699aa4377a455f Mon Sep 17 00:00:00 2001 From: "Stephen C. Wills" Date: Tue, 29 Aug 2023 07:46:49 -0400 Subject: [PATCH] Deterministic timer simulation for shrine messages in demo mode (#6516) --- Source/CMakeLists.txt | 1 + Source/engine/demomode.cpp | 19 ++++++++++++++----- Source/engine/demomode.h | 6 ++++++ Source/error.cpp | 5 +++-- Source/minitext.cpp | 5 +++-- Source/utils/timer.cpp | 10 ++++++++++ Source/utils/timer.hpp | 7 +++++++ 7 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 Source/utils/timer.cpp create mode 100644 Source/utils/timer.hpp diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 40e2e2396..112b45692 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -166,6 +166,7 @@ set(libdevilutionx_SRCS utils/str_cat.cpp utils/str_case.cpp utils/surface_to_clx.cpp + utils/timer.cpp utils/utf8.cpp) if(SUPPORTS_MPQ) diff --git a/Source/engine/demomode.cpp b/Source/engine/demomode.cpp index da025765a..02ad8182f 100644 --- a/Source/engine/demomode.cpp +++ b/Source/engine/demomode.cpp @@ -715,6 +715,9 @@ bool FetchMessage(SDL_Event *event, uint16_t *modState) void RecordGameLoopResult(bool runGameLoop) { WriteDemoMsgHeader(runGameLoop ? DemoMsg::GameTick : DemoMsg::Rendering); + + if (runGameLoop && !IsRunning()) + LogicTick++; } void RecordMessage(const SDL_Event &event, uint16_t modState) @@ -790,6 +793,12 @@ void RecordMessage(const SDL_Event &event, uint16_t modState) void NotifyGameLoopStart() { + LogicTick = 0; + + if (IsRunning()) { + StartTime = SDL_GetTicks(); + } + if (IsRecording()) { const std::string path = StrCat(paths::PrefPath(), "demo_", RecordNumber, ".dmo"); DemoRecording = OpenFile(path.c_str(), "wb"); @@ -803,11 +812,6 @@ void NotifyGameLoopStart() WriteLE32(DemoRecording, gSaveNumber); WriteSettings(DemoRecording); } - - if (IsRunning()) { - StartTime = SDL_GetTicks(); - LogicTick = 0; - } } void NotifyGameLoopEnd() @@ -843,6 +847,11 @@ void NotifyGameLoopEnd() } } +uint32_t SimulateMillisecondsSinceStartup() +{ + return LogicTick * 50; +} + } // namespace demo } // namespace devilution diff --git a/Source/engine/demomode.h b/Source/engine/demomode.h index a18040635..59629c9d1 100644 --- a/Source/engine/demomode.h +++ b/Source/engine/demomode.h @@ -28,6 +28,8 @@ void RecordMessage(const SDL_Event &event, uint16_t modState); void NotifyGameLoopStart(); void NotifyGameLoopEnd(); + +uint32_t SimulateMillisecondsSinceStartup(); #else inline void OverrideOptions() { @@ -60,6 +62,10 @@ inline void NotifyGameLoopStart() inline void NotifyGameLoopEnd() { } +inline uint32_t SimulateMillisecondsSinceStartup() +{ + return 0; +} #endif } // namespace demo diff --git a/Source/error.cpp b/Source/error.cpp index c3ac72abc..5368d7adf 100644 --- a/Source/error.cpp +++ b/Source/error.cpp @@ -16,6 +16,7 @@ #include "stores.h" #include "utils/algorithm/container.hpp" #include "utils/language.h" +#include "utils/timer.hpp" namespace devilution { @@ -30,7 +31,7 @@ const int LineWidth = 418; void InitNextLines() { - msgdelay = SDL_GetTicks(); + msgdelay = GetMillisecondsSinceStartup(); TextLines.clear(); const std::string paragraphs = WordWrapString(DiabloMessages.front(), LineWidth, GameFont12, 1); @@ -172,7 +173,7 @@ void DrawDiabloMsg(const Surface &out) lineNumber += 1; } - if (msgdelay > 0 && msgdelay <= SDL_GetTicks() - 3500) { + if (msgdelay > 0 && msgdelay <= GetMillisecondsSinceStartup() - 3500) { msgdelay = 0; } if (msgdelay == 0) { diff --git a/Source/minitext.cpp b/Source/minitext.cpp index c67032e7e..46cfaba0f 100644 --- a/Source/minitext.cpp +++ b/Source/minitext.cpp @@ -20,6 +20,7 @@ #include "playerdat.hpp" #include "textdat.h" #include "utils/language.h" +#include "utils/timer.hpp" namespace devilution { @@ -81,7 +82,7 @@ uint32_t CalculateTextSpeed(int nSFX) int CalculateTextPosition() { - uint32_t currTime = SDL_GetTicks(); + uint32_t currTime = GetMillisecondsSinceStartup(); int y = (currTime - ScrollStart) / qtextSpd - 260; @@ -165,7 +166,7 @@ void InitQTextMsg(_speech_id m) LoadText(_(Speeches[m].txtstr)); qtextflag = true; qtextSpd = CalculateTextSpeed(sfxnr); - ScrollStart = SDL_GetTicks(); + ScrollStart = GetMillisecondsSinceStartup(); } PlaySFX(sfxnr); } diff --git a/Source/utils/timer.cpp b/Source/utils/timer.cpp new file mode 100644 index 000000000..a9665d9ed --- /dev/null +++ b/Source/utils/timer.cpp @@ -0,0 +1,10 @@ +#include "engine/demomode.h" + +namespace devilution { + +uint32_t GetMillisecondsSinceStartup() +{ + return (demo::IsRunning() || demo::IsRecording()) ? demo::SimulateMillisecondsSinceStartup() : SDL_GetTicks(); +} + +} // namespace devilution diff --git a/Source/utils/timer.hpp b/Source/utils/timer.hpp new file mode 100644 index 000000000..1bc7cde91 --- /dev/null +++ b/Source/utils/timer.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace devilution { + +uint32_t GetMillisecondsSinceStartup(); + +}