core_timing: Allow configuring a fixed or random initial system tick value. (#7309)

* core_timing: Apply random base ticks value on startup.

* core: Maintain consistent base system ticks in TAS movies.

* frontend: Add setting to configure a fixed base system ticks value.
This commit is contained in:
Steveice10
2024-01-07 09:38:02 -08:00
committed by GitHub
parent 96aa1b3a08
commit 0165012ba4
14 changed files with 150 additions and 17 deletions

View File

@ -3,9 +3,11 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <random>
#include <tuple>
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "core/core_timing.h"
namespace Core {
@ -19,15 +21,28 @@ bool Timing::Event::operator<(const Timing::Event& right) const {
return std::tie(time, fifo_order) < std::tie(right.time, right.fifo_order);
}
Timing::Timing(std::size_t num_cores, u32 cpu_clock_percentage) {
Timing::Timing(std::size_t num_cores, u32 cpu_clock_percentage, s64 override_base_ticks) {
// Generate non-zero base tick count to simulate time the system ran before launching the game.
// This accounts for games that rely on the system tick to seed randomness.
const auto base_ticks = override_base_ticks >= 0 ? override_base_ticks : GenerateBaseTicks();
timers.resize(num_cores);
for (std::size_t i = 0; i < num_cores; ++i) {
timers[i] = std::make_shared<Timer>();
timers[i] = std::make_shared<Timer>(base_ticks);
}
UpdateClockSpeed(cpu_clock_percentage);
current_timer = timers[0].get();
}
s64 Timing::GenerateBaseTicks() {
if (Settings::values.init_ticks_type.GetValue() == Settings::InitTicks::Fixed) {
return Settings::values.init_ticks_override.GetValue();
}
// Bounded to 32 bits to make sure we don't generate too high of a counter and risk overflowing.
std::mt19937 random_gen(std::random_device{}());
return random_gen();
}
void Timing::UpdateClockSpeed(u32 cpu_clock_percentage) {
for (auto& timer : timers) {
timer->cpu_clock_scale = 100.0 / cpu_clock_percentage;
@ -146,7 +161,7 @@ std::shared_ptr<Timing::Timer> Timing::GetTimer(std::size_t cpu_id) {
return timers[cpu_id];
}
Timing::Timer::Timer() = default;
Timing::Timer::Timer(s64 base_ticks) : executed_ticks(base_ticks) {}
Timing::Timer::~Timer() {
MoveEvents();