From c8d88ad0c838b5f42ca54a2f3e8f20291d501660 Mon Sep 17 00:00:00 2001 From: staphen Date: Sat, 26 Aug 2023 16:59:44 -0400 Subject: [PATCH 1/3] Deterministic timer simulation for shrine messages in demo mode --- Source/CMakeLists.txt | 1 + Source/engine/demomode.cpp | 19 ++++++++++++++----- Source/engine/demomode.h | 6 ++++++ Source/error.cpp | 5 +++-- Source/utils/timer.cpp | 10 ++++++++++ Source/utils/timer.hpp | 7 +++++++ 6 files changed, 41 insertions(+), 7 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 40e2e23961d..112b4569227 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 da025765aac..0bad920239a 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 GetTicks() +{ + return LogicTick * 50; +} + } // namespace demo } // namespace devilution diff --git a/Source/engine/demomode.h b/Source/engine/demomode.h index a18040635a8..f6f860eab0b 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 GetTicks(); #else inline void OverrideOptions() { @@ -60,6 +62,10 @@ inline void NotifyGameLoopStart() inline void NotifyGameLoopEnd() { } +inline uint32_t GetTicks() +{ + return 0; +} #endif } // namespace demo diff --git a/Source/error.cpp b/Source/error.cpp index c3ac72abc8a..914ae010c55 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 = GetTicks(); 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 <= GetTicks() - 3500) { msgdelay = 0; } if (msgdelay == 0) { diff --git a/Source/utils/timer.cpp b/Source/utils/timer.cpp new file mode 100644 index 00000000000..9ef053bf42f --- /dev/null +++ b/Source/utils/timer.cpp @@ -0,0 +1,10 @@ +#include "engine/demomode.h" + +namespace devilution { + +uint32_t GetTicks() +{ + return (demo::IsRunning() || demo::IsRecording()) ? demo::GetTicks() : SDL_GetTicks(); +} + +} // namespace devilution diff --git a/Source/utils/timer.hpp b/Source/utils/timer.hpp new file mode 100644 index 00000000000..4154517332b --- /dev/null +++ b/Source/utils/timer.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace devilution { + +uint32_t GetTicks(); + +} From 769d24a0bd0b5064192b9ea33344be90f0c459d0 Mon Sep 17 00:00:00 2001 From: staphen Date: Sun, 27 Aug 2023 23:44:59 -0400 Subject: [PATCH 2/3] Deterministic timer simulation for dialog in demo mode --- Source/minitext.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/minitext.cpp b/Source/minitext.cpp index c67032e7e27..b7aa3d0e564 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 = GetTicks(); 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 = GetTicks(); } PlaySFX(sfxnr); } From 0ffd65845aa3e5c36285190223f0aea8f0dd3289 Mon Sep 17 00:00:00 2001 From: staphen Date: Mon, 28 Aug 2023 00:00:04 -0400 Subject: [PATCH 3/3] Rename GetTicks() functions --- Source/engine/demomode.cpp | 2 +- Source/engine/demomode.h | 4 ++-- Source/error.cpp | 4 ++-- Source/minitext.cpp | 4 ++-- Source/utils/timer.cpp | 4 ++-- Source/utils/timer.hpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/engine/demomode.cpp b/Source/engine/demomode.cpp index 0bad920239a..02ad8182f1c 100644 --- a/Source/engine/demomode.cpp +++ b/Source/engine/demomode.cpp @@ -847,7 +847,7 @@ void NotifyGameLoopEnd() } } -uint32_t GetTicks() +uint32_t SimulateMillisecondsSinceStartup() { return LogicTick * 50; } diff --git a/Source/engine/demomode.h b/Source/engine/demomode.h index f6f860eab0b..59629c9d1ec 100644 --- a/Source/engine/demomode.h +++ b/Source/engine/demomode.h @@ -29,7 +29,7 @@ void RecordMessage(const SDL_Event &event, uint16_t modState); void NotifyGameLoopStart(); void NotifyGameLoopEnd(); -uint32_t GetTicks(); +uint32_t SimulateMillisecondsSinceStartup(); #else inline void OverrideOptions() { @@ -62,7 +62,7 @@ inline void NotifyGameLoopStart() inline void NotifyGameLoopEnd() { } -inline uint32_t GetTicks() +inline uint32_t SimulateMillisecondsSinceStartup() { return 0; } diff --git a/Source/error.cpp b/Source/error.cpp index 914ae010c55..5368d7adfb0 100644 --- a/Source/error.cpp +++ b/Source/error.cpp @@ -31,7 +31,7 @@ const int LineWidth = 418; void InitNextLines() { - msgdelay = GetTicks(); + msgdelay = GetMillisecondsSinceStartup(); TextLines.clear(); const std::string paragraphs = WordWrapString(DiabloMessages.front(), LineWidth, GameFont12, 1); @@ -173,7 +173,7 @@ void DrawDiabloMsg(const Surface &out) lineNumber += 1; } - if (msgdelay > 0 && msgdelay <= GetTicks() - 3500) { + if (msgdelay > 0 && msgdelay <= GetMillisecondsSinceStartup() - 3500) { msgdelay = 0; } if (msgdelay == 0) { diff --git a/Source/minitext.cpp b/Source/minitext.cpp index b7aa3d0e564..46cfaba0f97 100644 --- a/Source/minitext.cpp +++ b/Source/minitext.cpp @@ -82,7 +82,7 @@ uint32_t CalculateTextSpeed(int nSFX) int CalculateTextPosition() { - uint32_t currTime = GetTicks(); + uint32_t currTime = GetMillisecondsSinceStartup(); int y = (currTime - ScrollStart) / qtextSpd - 260; @@ -166,7 +166,7 @@ void InitQTextMsg(_speech_id m) LoadText(_(Speeches[m].txtstr)); qtextflag = true; qtextSpd = CalculateTextSpeed(sfxnr); - ScrollStart = GetTicks(); + ScrollStart = GetMillisecondsSinceStartup(); } PlaySFX(sfxnr); } diff --git a/Source/utils/timer.cpp b/Source/utils/timer.cpp index 9ef053bf42f..a9665d9ede6 100644 --- a/Source/utils/timer.cpp +++ b/Source/utils/timer.cpp @@ -2,9 +2,9 @@ namespace devilution { -uint32_t GetTicks() +uint32_t GetMillisecondsSinceStartup() { - return (demo::IsRunning() || demo::IsRecording()) ? demo::GetTicks() : SDL_GetTicks(); + return (demo::IsRunning() || demo::IsRecording()) ? demo::SimulateMillisecondsSinceStartup() : SDL_GetTicks(); } } // namespace devilution diff --git a/Source/utils/timer.hpp b/Source/utils/timer.hpp index 4154517332b..1bc7cde9146 100644 --- a/Source/utils/timer.hpp +++ b/Source/utils/timer.hpp @@ -2,6 +2,6 @@ namespace devilution { -uint32_t GetTicks(); +uint32_t GetMillisecondsSinceStartup(); }