summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2024-01-13 13:14:48 +0100
committerAdmiral H. Curtiss <pikachu025@gmail.com>2024-01-15 08:05:30 +0100
commit95cba6be2beda7fbf4fb597b0aa4cbb8912d8265 (patch)
tree30c854ca14e32320334914d6c48e4f99e0a17233 /Source/Core
parentc76dee7807c331582cfb36376329e760eab3f704 (diff)
Core/Movie: Refactor to class, move to System.
A bit of global state remains (the `header` in `BeginRecordingInput()`) due to unclear lifetime requirements.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/BootManager.cpp7
-rw-r--r--Source/Core/Core/Core.cpp8
-rw-r--r--Source/Core/Core/DolphinAnalytics.cpp3
-rw-r--r--Source/Core/Core/HW/DVD/DVDInterface.cpp4
-rw-r--r--Source/Core/Core/HW/EXI/EXI.cpp6
-rw-r--r--Source/Core/Core/HW/EXI/EXI_Channel.cpp2
-rw-r--r--Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp5
-rw-r--r--Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp18
-rw-r--r--Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h6
-rw-r--r--Source/Core/Core/HW/SI/SI.cpp9
-rw-r--r--Source/Core/Core/HW/SI/SI_DeviceGBAEmu.cpp3
-rw-r--r--Source/Core/Core/HW/SI/SI_DeviceGCAdapter.cpp3
-rw-r--r--Source/Core/Core/HW/SI/SI_DeviceGCController.cpp21
-rw-r--r--Source/Core/Core/HW/SI/SI_DeviceGCController.h8
-rw-r--r--Source/Core/Core/HW/VideoInterface.cpp2
-rw-r--r--Source/Core/Core/HW/Wiimote.cpp6
-rw-r--r--Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp13
-rw-r--r--Source/Core/Core/IOS/FS/HostBackend/FS.cpp10
-rw-r--r--Source/Core/Core/Movie.cpp843
-rw-r--r--Source/Core/Core/Movie.h202
-rw-r--r--Source/Core/Core/NetPlayClient.cpp16
-rw-r--r--Source/Core/Core/State.cpp29
-rw-r--r--Source/Core/Core/System.cpp9
-rw-r--r--Source/Core/Core/System.h5
-rw-r--r--Source/Core/Core/WiiRoot.cpp12
-rw-r--r--Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp7
-rw-r--r--Source/Core/DolphinQt/GBAWidget.cpp2
-rw-r--r--Source/Core/DolphinQt/MainWindow.cpp41
-rw-r--r--Source/Core/DolphinQt/MenuBar.cpp11
-rw-r--r--Source/Core/DolphinQt/TAS/TASCheckBox.cpp6
-rw-r--r--Source/Core/VideoCommon/OnScreenUI.cpp24
-rw-r--r--Source/Core/VideoCommon/VideoConfig.cpp5
32 files changed, 727 insertions, 619 deletions
diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp
index 76d25aa088..72f525027f 100644
--- a/Source/Core/Core/BootManager.cpp
+++ b/Source/Core/Core/BootManager.cpp
@@ -66,11 +66,13 @@ bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
return false;
// Movie settings
- if (Movie::IsPlayingInput() && Movie::IsConfigSaved())
+ auto& system = Core::System::GetInstance();
+ auto& movie = system.GetMovie();
+ if (movie.IsPlayingInput() && movie.IsConfigSaved())
{
for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS)
{
- if (Movie::IsUsingMemcard(slot) && Movie::IsStartingFromClearSave() && !StartUp.bWii)
+ if (movie.IsUsingMemcard(slot) && movie.IsStartingFromClearSave() && !StartUp.bWii)
{
const auto raw_path =
File::GetUserPath(D_GCUSER_IDX) +
@@ -142,7 +144,6 @@ bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
if (!boot->riivolution_patches.empty())
Config::SetCurrent(Config::MAIN_FAST_DISC_SPEED, true);
- auto& system = Core::System::GetInstance();
system.Initialize();
Core::UpdateWantDeterminism(/*initial*/ true);
diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp
index 646fcfec47..e686fca30f 100644
--- a/Source/Core/Core/Core.cpp
+++ b/Source/Core/Core/Core.cpp
@@ -564,8 +564,8 @@ static void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot
system.GetCustomAssetLoader().Init();
Common::ScopeGuard asset_loader_guard([&system] { system.GetCustomAssetLoader().Shutdown(); });
- Movie::Init(*boot);
- Common::ScopeGuard movie_guard{&Movie::Shutdown};
+ system.GetMovie().Init(*boot);
+ Common::ScopeGuard movie_guard([&system] { system.GetMovie().Shutdown(); });
AudioCommon::InitSoundStream(system);
Common::ScopeGuard audio_guard([&system] { AudioCommon::ShutdownSoundStream(system); });
@@ -1019,7 +1019,8 @@ void UpdateWantDeterminism(bool initial)
// For now, this value is not itself configurable. Instead, individual
// settings that depend on it, such as GPU determinism mode. should have
// override options for testing,
- bool new_want_determinism = Movie::IsMovieActive() || NetPlay::IsNetPlayRunning();
+ auto& system = Core::System::GetInstance();
+ bool new_want_determinism = system.GetMovie().IsMovieActive() || NetPlay::IsNetPlayRunning();
if (new_want_determinism != s_wants_determinism || initial)
{
NOTICE_LOG_FMT(COMMON, "Want determinism <- {}", new_want_determinism ? "true" : "false");
@@ -1030,7 +1031,6 @@ void UpdateWantDeterminism(bool initial)
if (ios)
ios->UpdateWantDeterminism(new_want_determinism);
- auto& system = Core::System::GetInstance();
system.GetFifo().UpdateWantDeterminism(new_want_determinism);
// We need to clear the cache because some parts of the JIT depend on want_determinism,
diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp
index a8bc51aa69..5593a66963 100644
--- a/Source/Core/Core/DolphinAnalytics.cpp
+++ b/Source/Core/Core/DolphinAnalytics.cpp
@@ -34,6 +34,7 @@
#include "Core/HW/GCPad.h"
#include "Core/Movie.h"
#include "Core/NetPlayProto.h"
+#include "Core/System.h"
#include "InputCommon/GCAdapter.h"
#include "InputCommon/InputConfig.h"
#include "VideoCommon/VideoBackendBase.h"
@@ -417,7 +418,7 @@ void DolphinAnalytics::MakePerGameBuilder()
// NetPlay / recording.
builder.AddData("netplay", NetPlay::IsNetPlayRunning());
- builder.AddData("movie", Movie::IsMovieActive());
+ builder.AddData("movie", Core::System::GetInstance().GetMovie().IsMovieActive());
// Controller information
// We grab enough to tell what percentage of our users are playing with keyboard/mouse, some kind
diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp
index 2a7765d955..ae2f6e4e61 100644
--- a/Source/Core/Core/HW/DVD/DVDInterface.cpp
+++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp
@@ -476,7 +476,7 @@ void DVDInterface::ChangeDisc(const std::string& new_path)
m_disc_path_to_insert = new_path;
m_system.GetCoreTiming().ScheduleEvent(m_system.GetSystemTimers().GetTicksPerSecond(),
m_insert_disc);
- Movie::SignalDiscChange(new_path);
+ m_system.GetMovie().SignalDiscChange(new_path);
for (size_t i = 0; i < m_auto_disc_change_paths.size(); ++i)
{
@@ -1087,7 +1087,7 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
const bool force_eject = eject && !kill;
- if (Config::Get(Config::MAIN_AUTO_DISC_CHANGE) && !Movie::IsPlayingInput() &&
+ if (Config::Get(Config::MAIN_AUTO_DISC_CHANGE) && !m_system.GetMovie().IsPlayingInput() &&
m_system.GetDVDThread().IsInsertedDiscRunning() && !m_auto_disc_change_paths.empty())
{
m_system.GetCoreTiming().ScheduleEvent(
diff --git a/Source/Core/Core/HW/EXI/EXI.cpp b/Source/Core/Core/HW/EXI/EXI.cpp
index d6c09b36fa..fd371fa076 100644
--- a/Source/Core/Core/HW/EXI/EXI.cpp
+++ b/Source/Core/Core/HW/EXI/EXI.cpp
@@ -36,9 +36,11 @@ ExpansionInterfaceManager::~ExpansionInterfaceManager() = default;
void ExpansionInterfaceManager::AddMemoryCard(Slot slot)
{
EXIDeviceType memorycard_device;
- if (Movie::IsPlayingInput() && Movie::IsConfigSaved())
+
+ auto& movie = m_system.GetMovie();
+ if (movie.IsPlayingInput() && movie.IsConfigSaved())
{
- if (Movie::IsUsingMemcard(slot))
+ if (movie.IsUsingMemcard(slot))
{
memorycard_device = Config::Get(Config::GetInfoForEXIDevice(slot));
if (memorycard_device != EXIDeviceType::MemoryCardFolder &&
diff --git a/Source/Core/Core/HW/EXI/EXI_Channel.cpp b/Source/Core/Core/HW/EXI/EXI_Channel.cpp
index ca2d8f49cd..8d47a816e4 100644
--- a/Source/Core/Core/HW/EXI/EXI_Channel.cpp
+++ b/Source/Core/Core/HW/EXI/EXI_Channel.cpp
@@ -264,7 +264,7 @@ void CEXIChannel::DoState(PointerWrap& p)
}
if (type == EXIDeviceType::MemoryCardFolder && old_header_data != m_memcard_header_data &&
- !Movie::IsMovieActive())
+ !m_system.GetMovie().IsMovieActive())
{
// We have loaded a savestate that has a GCI folder memcard that is different to the virtual
// card that is currently active. In order to prevent the game from recognizing this card as a
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp
index 4667f9f69e..159df02f64 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceIPL.cpp
@@ -406,9 +406,10 @@ u32 CEXIIPL::GetEmulatedTime(Core::System& system, u32 epoch)
{
u64 ltime = 0;
- if (Movie::IsMovieActive())
+ auto& movie = system.GetMovie();
+ if (movie.IsMovieActive())
{
- ltime = Movie::GetRecordingStartTime();
+ ltime = movie.GetRecordingStartTime();
// let's keep time moving forward, regardless of what it starts at
ltime += system.GetCoreTiming().GetTicks() / system.GetSystemTimers().GetTicksPerSecond();
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp
index 03f5610007..cfc76f27db 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp
@@ -149,7 +149,8 @@ CEXIMemoryCard::CEXIMemoryCard(Core::System& system, const Slot slot, bool gci_f
}
std::pair<std::string /* path */, bool /* migrate */>
-CEXIMemoryCard::GetGCIFolderPath(Slot card_slot, AllowMovieFolder allow_movie_folder)
+CEXIMemoryCard::GetGCIFolderPath(Slot card_slot, AllowMovieFolder allow_movie_folder,
+ Movie::MovieManager& movie)
{
std::string path_override = Config::Get(Config::GetInfoForGCIPathOverride(card_slot));
@@ -157,9 +158,8 @@ CEXIMemoryCard::GetGCIFolderPath(Slot card_slot, AllowMovieFolder allow_movie_fo
return {std::move(path_override), false};
const bool use_movie_folder = allow_movie_folder == AllowMovieFolder::Yes &&
- Movie::IsPlayingInput() && Movie::IsConfigSaved() &&
- Movie::IsUsingMemcard(card_slot) &&
- Movie::IsStartingFromClearSave();
+ movie.IsPlayingInput() && movie.IsConfigSaved() &&
+ movie.IsUsingMemcard(card_slot) && movie.IsStartingFromClearSave();
const DiscIO::Region region = Config::ToGameCubeRegion(SConfig::GetInstance().m_region);
if (use_movie_folder)
@@ -182,7 +182,8 @@ void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data)
current_game_id = Common::swap32(reinterpret_cast<const u8*>(game_id.c_str()));
}
- const auto [dir_path, migrate] = GetGCIFolderPath(m_card_slot, AllowMovieFolder::Yes);
+ const auto [dir_path, migrate] =
+ GetGCIFolderPath(m_card_slot, AllowMovieFolder::Yes, m_system.GetMovie());
const File::FileInfo file_info(dir_path);
if (!file_info.Exists())
@@ -219,8 +220,9 @@ void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data)
void CEXIMemoryCard::SetupRawMemcard(u16 size_mb)
{
std::string filename;
- if (Movie::IsPlayingInput() && Movie::IsConfigSaved() && Movie::IsUsingMemcard(m_card_slot) &&
- Movie::IsStartingFromClearSave())
+ auto& movie = m_system.GetMovie();
+ if (movie.IsPlayingInput() && movie.IsConfigSaved() && movie.IsUsingMemcard(m_card_slot) &&
+ movie.IsStartingFromClearSave())
{
filename = File::GetUserPath(D_GCUSER_IDX) +
fmt::format("Movie{}.raw", s_card_short_names[m_card_slot]);
@@ -501,7 +503,7 @@ void CEXIMemoryCard::DoState(PointerWrap& p)
// otherwise, we'll assume the user wants to keep their memcards and saves separate,
// unless we're loading (in which case we let the savestate contents decide, in order to stay
// aligned with them).
- bool storeContents = (Movie::IsMovieActive());
+ bool storeContents = m_system.GetMovie().IsMovieActive();
p.Do(storeContents);
if (storeContents)
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h
index cbb204d06a..2264abb076 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.h
@@ -26,6 +26,10 @@ namespace Memcard
{
struct HeaderData;
}
+namespace Movie
+{
+class MovieManager;
+}
namespace ExpansionInterface
{
@@ -58,7 +62,7 @@ public:
static void Shutdown();
static std::pair<std::string /* path */, bool /* migrate */>
- GetGCIFolderPath(Slot card_slot, AllowMovieFolder allow_movie_folder);
+ GetGCIFolderPath(Slot card_slot, AllowMovieFolder allow_movie_folder, Movie::MovieManager& movie);
private:
void SetupGciFolder(const Memcard::HeaderData& header_data);
diff --git a/Source/Core/Core/HW/SI/SI.cpp b/Source/Core/Core/HW/SI/SI.cpp
index eeebf291d5..423f373337 100644
--- a/Source/Core/Core/HW/SI/SI.cpp
+++ b/Source/Core/Core/HW/SI/SI.cpp
@@ -265,19 +265,20 @@ void SerialInterfaceManager::Init()
m_channel[i].in_lo.hex = 0;
m_channel[i].has_recent_device_change = false;
- if (Movie::IsMovieActive())
+ auto& movie = m_system.GetMovie();
+ if (movie.IsMovieActive())
{
m_desired_device_types[i] = SIDEVICE_NONE;
- if (Movie::IsUsingGBA(i))
+ if (movie.IsUsingGBA(i))
{
m_desired_device_types[i] = SIDEVICE_GC_GBA_EMULATED;
}
- else if (Movie::IsUsingPad(i))
+ else if (movie.IsUsingPad(i))
{
SIDevices current = Config::Get(Config::GetInfoForSIDevice(i));
// GC pad-compatible devices can be used for both playing and recording
- if (Movie::IsUsingBongo(i))
+ if (movie.IsUsingBongo(i))
m_desired_device_types[i] = SIDEVICE_GC_TARUKONGA;
else if (SIDevice_IsGCController(current))
m_desired_device_types[i] = current;
diff --git a/Source/Core/Core/HW/SI/SI_DeviceGBAEmu.cpp b/Source/Core/Core/HW/SI/SI_DeviceGBAEmu.cpp
index 4bb0e69617..10522842de 100644
--- a/Source/Core/Core/HW/SI/SI_DeviceGBAEmu.cpp
+++ b/Source/Core/Core/HW/SI/SI_DeviceGBAEmu.cpp
@@ -125,7 +125,8 @@ bool CSIDevice_GBAEmu::GetData(u32& hi, u32& low)
GCPadStatus pad_status{};
if (!NetPlay::IsNetPlayRunning())
pad_status = Pad::GetGBAStatus(m_device_number);
- SerialInterface::CSIDevice_GCController::HandleMoviePadStatus(m_device_number, &pad_status);
+ SerialInterface::CSIDevice_GCController::HandleMoviePadStatus(m_system.GetMovie(),
+ m_device_number, &pad_status);
static constexpr std::array<PadButton, 10> buttons_map = {
PadButton::PAD_BUTTON_A, // A
diff --git a/Source/Core/Core/HW/SI/SI_DeviceGCAdapter.cpp b/Source/Core/Core/HW/SI/SI_DeviceGCAdapter.cpp
index 8a06fa1ff0..88747062f8 100644
--- a/Source/Core/Core/HW/SI/SI_DeviceGCAdapter.cpp
+++ b/Source/Core/Core/HW/SI/SI_DeviceGCAdapter.cpp
@@ -11,6 +11,7 @@
#include "Core/Core.h"
#include "Core/HW/GCPad.h"
#include "Core/NetPlayProto.h"
+#include "Core/System.h"
#include "InputCommon/GCAdapter.h"
namespace SerialInterface
@@ -38,7 +39,7 @@ GCPadStatus CSIDevice_GCAdapter::GetPadStatus()
pad_status = GCAdapter::Input(m_device_number);
}
- HandleMoviePadStatus(m_device_number, &pad_status);
+ HandleMoviePadStatus(m_system.GetMovie(), m_device_number, &pad_status);
// Our GCAdapter code sets PAD_GET_ORIGIN when a new device has been connected.
// Watch for this to calibrate real controllers on connection.
diff --git a/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp b/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp
index fde127f3f6..f8150a6339 100644
--- a/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp
+++ b/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp
@@ -120,25 +120,26 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int request_length)
return 0;
}
-void CSIDevice_GCController::HandleMoviePadStatus(int device_number, GCPadStatus* pad_status)
+void CSIDevice_GCController::HandleMoviePadStatus(Movie::MovieManager& movie, int device_number,
+ GCPadStatus* pad_status)
{
- Movie::SetPolledDevice();
+ movie.SetPolledDevice();
if (NetPlay_GetInput(device_number, pad_status))
{
}
- else if (Movie::IsPlayingInput())
+ else if (movie.IsPlayingInput())
{
- Movie::PlayController(pad_status, device_number);
- Movie::InputUpdate();
+ movie.PlayController(pad_status, device_number);
+ movie.InputUpdate();
}
- else if (Movie::IsRecordingInput())
+ else if (movie.IsRecordingInput())
{
- Movie::RecordInput(pad_status, device_number);
- Movie::InputUpdate();
+ movie.RecordInput(pad_status, device_number);
+ movie.InputUpdate();
}
else
{
- Movie::CheckPadStatus(pad_status, device_number);
+ movie.CheckPadStatus(pad_status, device_number);
}
}
@@ -153,7 +154,7 @@ GCPadStatus CSIDevice_GCController::GetPadStatus()
pad_status = Pad::GetStatus(m_device_number);
}
- HandleMoviePadStatus(m_device_number, &pad_status);
+ HandleMoviePadStatus(m_system.GetMovie(), m_device_number, &pad_status);
// Our GCAdapter code sets PAD_GET_ORIGIN when a new device has been connected.
// Watch for this to calibrate real controllers on connection.
diff --git a/Source/Core/Core/HW/SI/SI_DeviceGCController.h b/Source/Core/Core/HW/SI/SI_DeviceGCController.h
index 43e3d7aabb..6c8996b53f 100644
--- a/Source/Core/Core/HW/SI/SI_DeviceGCController.h
+++ b/Source/Core/Core/HW/SI/SI_DeviceGCController.h
@@ -9,6 +9,11 @@
#include "Core/HW/SI/SI_Device.h"
#include "InputCommon/GCPadStatus.h"
+namespace Movie
+{
+class MovieManager;
+}
+
namespace SerialInterface
{
class CSIDevice_GCController : public ISIDevice
@@ -78,7 +83,8 @@ public:
// Direct rumble to the right GC Controller
static void Rumble(int pad_num, ControlState strength, SIDevices device);
- static void HandleMoviePadStatus(int device_number, GCPadStatus* pad_status);
+ static void HandleMoviePadStatus(Movie::MovieManager& movie, int device_number,
+ GCPadStatus* pad_status);
protected:
void SetOrigin(const GCPadStatus& pad_status);
diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp
index 1217b789d9..83a30cbbcf 100644
--- a/Source/Core/Core/HW/VideoInterface.cpp
+++ b/Source/Core/Core/HW/VideoInterface.cpp
@@ -852,7 +852,7 @@ void VideoInterfaceManager::Update(u64 ticks)
// in case frame counter display is enabled
if (m_half_line_count == 0 || m_half_line_count == GetHalfLinesPerEvenField())
- Movie::FrameUpdate();
+ m_system.GetMovie().FrameUpdate();
// If this half-line is at some boundary of the "active video lines" in either field, we either
// need to (a) send a request to the GPU thread to actually render the XFB, or (b) increment
diff --git a/Source/Core/Core/HW/Wiimote.cpp b/Source/Core/Core/HW/Wiimote.cpp
index 13ef2139f6..86f9c6a56c 100644
--- a/Source/Core/Core/HW/Wiimote.cpp
+++ b/Source/Core/Core/HW/Wiimote.cpp
@@ -19,6 +19,7 @@
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
#include "Core/Movie.h"
#include "Core/NetPlayClient.h"
+#include "Core/System.h"
#include "Core/WiiUtils.h"
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
@@ -192,8 +193,9 @@ void Initialize(InitializeMode init_mode)
WiimoteReal::Initialize(init_mode);
// Reload Wiimotes with our settings
- if (Movie::IsMovieActive())
- Movie::ChangeWiiPads();
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (movie.IsMovieActive())
+ movie.ChangeWiiPads();
}
void ResetAllWiimotes()
diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
index 1baccc4e81..e74e807898 100644
--- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
+++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
@@ -23,6 +23,7 @@
#include "Core/Core.h"
#include "Core/HW/Wiimote.h"
#include "Core/Movie.h"
+#include "Core/System.h"
#include "Core/HW/WiimoteCommon/WiimoteConstants.h"
#include "Core/HW/WiimoteCommon/WiimoteHid.h"
@@ -552,7 +553,8 @@ void Wiimote::Update(const WiimoteEmu::DesiredWiimoteState& target_state)
void Wiimote::SendDataReport(const DesiredWiimoteState& target_state)
{
- Movie::SetPolledDevice();
+ auto& movie = Core::System::GetInstance().GetMovie();
+ movie.SetPolledDevice();
if (InputReportID::ReportDisabled == m_reporting_mode)
{
@@ -569,9 +571,8 @@ void Wiimote::SendDataReport(const DesiredWiimoteState& target_state)
DataReportBuilder rpt_builder(m_reporting_mode);
- if (Movie::IsPlayingInput() &&
- Movie::PlayWiimote(m_bt_device_index, rpt_builder, m_active_extension,
- GetExtensionEncryptionKey()))
+ if (movie.IsPlayingInput() && movie.PlayWiimote(m_bt_device_index, rpt_builder,
+ m_active_extension, GetExtensionEncryptionKey()))
{
// Update buttons in status struct from movie:
rpt_builder.GetCoreData(&m_status.buttons);
@@ -640,8 +641,8 @@ void Wiimote::SendDataReport(const DesiredWiimoteState& target_state)
}
}
- Movie::CheckWiimoteStatus(m_bt_device_index, rpt_builder, m_active_extension,
- GetExtensionEncryptionKey());
+ movie.CheckWiimoteStatus(m_bt_device_index, rpt_builder, m_active_extension,
+ GetExtensionEncryptionKey());
// Send the report:
InterruptDataInputCallback(rpt_builder.GetDataPtr(), rpt_builder.GetDataSize());
diff --git a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp
index a916ffba81..503a8c4607 100644
--- a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp
+++ b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp
@@ -23,6 +23,7 @@
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
+#include "Core/System.h"
#include "Core/WiiRoot.h"
namespace IOS::HLE::FS
@@ -391,8 +392,9 @@ void HostFileSystem::DoState(PointerWrap& p)
// then a call to p.DoExternal() will be used to skip over reading the contents of the "/"
// directory (it skips over the number of bytes specified by size_of_nand_folder_saved)
+ auto& movie = Core::System::GetInstance().GetMovie();
bool original_save_state_made_during_movie_recording =
- Movie::IsMovieActive() && Core::WiiRootIsTemporary();
+ movie.IsMovieActive() && Core::WiiRootIsTemporary();
p.Do(original_save_state_made_during_movie_recording);
u32 temp_val = 0;
@@ -414,17 +416,17 @@ void HostFileSystem::DoState(PointerWrap& p)
else // case where we're in read mode.
{
DoStateRead(p, "/tmp");
- if (!Movie::IsMovieActive() || !original_save_state_made_during_movie_recording ||
+ if (!movie.IsMovieActive() || !original_save_state_made_during_movie_recording ||
!Core::WiiRootIsTemporary() ||
(original_save_state_made_during_movie_recording !=
- (Movie::IsMovieActive() && Core::WiiRootIsTemporary())))
+ (movie.IsMovieActive() && Core::WiiRootIsTemporary())))
{
(void)p.DoExternal(temp_val);
}
else
{
p.Do(temp_val);
- if (Movie::IsMovieActive() && Core::WiiRootIsTemporary())
+ if (movie.IsMovieActive() && Core::WiiRootIsTemporary())
DoStateRead(p, "/");
}
}
diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp
index fb96379748..84b6ddc9f6 100644
--- a/Source/Core/Core/Movie.cpp
+++ b/Source/Core/Core/Movie.cpp
@@ -82,51 +82,6 @@ namespace Movie
using namespace WiimoteCommon;
using namespace WiimoteEmu;
-enum class PlayMode
-{
- None = 0,
- Recording,
- Playing,
-};
-
-static bool s_bReadOnly = true;
-static u32 s_rerecords = 0;
-static PlayMode s_playMode = PlayMode::None;
-
-static std::array<ControllerType, 4> s_controllers{};
-static std::array<bool, 4> s_wiimotes{};
-static ControllerState s_padState;
-static DTMHeader tmpHeader;
-static std::vector<u8> s_temp_input;
-static u64 s_currentByte = 0;
-static u64 s_currentFrame = 0, s_totalFrames = 0; // VI
-static u64 s_currentLagCount = 0;
-static u64 s_totalLagCount = 0; // just stats
-static u64 s_currentInputCount = 0, s_totalInputCount = 0; // just stats
-static u64 s_totalTickCount = 0, s_tickCountAtLastInput = 0; // just stats
-static u64 s_recordingStartTime; // seconds since 1970 that recording started
-static bool s_bSaveConfig = false, s_bNetPlay = false;
-static bool s_bClearSave = false;
-static bool s_bDiscChange = false;
-static bool s_bReset = false;
-static std::string s_author;
-static std::string s_discChange;
-static std::array<u8, 16> s_MD5;
-static u8 s_bongos, s_memcards;
-static std::array<u8, 20> s_revision;
-static u32 s_DSPiromHash = 0;
-static u32 s_DSPcoefHash = 0;
-
-static bool s_bRecordingFromSaveState = false;
-static bool s_bPolled = false;
-
-// s_InputDisplay is used by both CPU and GPU (is mutable).
-static std::mutex s_input_display_lock;
-static std::string s_InputDisplay[8];
-
-static std::string s_current_file_name;
-
-static void GetSettings();
static bool IsMovieHeader(const std::array<u8, 4>& magic)
{
return magic[0] == 'D' && magic[1] == 'T' && magic[2] == 'M' && magic[3] == 0x1A;
@@ -161,45 +116,51 @@ static std::array<u8, 20> ConvertGitRevisionToBytes(const std::string& revision)
return revision_bytes;
}
+MovieManager::MovieManager(Core::System& system) : m_system(system)
+{
+}
+
+MovieManager::~MovieManager() = default;
+
// NOTE: GPU Thread
-std::string GetInputDisplay()
+std::string MovieManager::GetInputDisplay()
{
if (!IsMovieActive())
{
- s_controllers = {};
- s_wiimotes = {};
+ m_controllers = {};
+ m_wiimotes = {};
for (int i = 0; i < 4; ++i)
{
auto& si = Core::System::GetInstance().GetSerialInterface();
if (si.GetDeviceType(i) == SerialInterface::SIDEVICE_GC_GBA_EMULATED)
- s_controllers[i] = ControllerType::GBA;
+ m_controllers[i] = ControllerType::GBA;
else if (si.GetDeviceType(i) != SerialInterface::SIDEVICE_NONE)
- s_controllers[i] = ControllerType::GC;
+ m_controllers[i] = ControllerType::GC;
else
- s_controllers[i] = ControllerType::None;
- s_wiimotes[i] = Config::Get(Config::GetInfoForWiimoteSource(i)) != WiimoteSource::None;
+ m_controllers[i] = ControllerType::None;
+ m_wiimotes[i] = Config::Get(Config::GetInfoForWiimoteSource(i)) != WiimoteSource::None;
}
}
std::string input_display;
{
- std::lock_guard guard(s_input_display_lock);
+ std::lock_guard guard(m_input_display_lock);
for (int i = 0; i < 4; ++i)
{
if (IsUsingPad(i))
- input_display += s_InputDisplay[i] + '\n';
+ input_display += m_input_display[i] + '\n';
}
for (int i = 0; i < 4; ++i)
{
if (IsUsingWiimote(i))
- input_display += s_InputDisplay[i + 4] + '\n';
+ input_display += m_input_display[i + 4] + '\n';
}
}
return input_display;
}
// NOTE: GPU Thread
-std::string GetRTCDisplay()
+std::string MovieManager::GetRTCDisplay()
{
using ExpansionInterface::CEXIIPL;
@@ -213,53 +174,50 @@ std::string GetRTCDisplay()
}
// NOTE: GPU Thread
-std::string GetRerecords()
+std::string MovieManager::GetRerecords()
{
if (IsMovieActive())
- return fmt::format("Rerecords: {}", s_rerecords);
+ return fmt::format("Rerecords: {}", m_rerecords);
return "Rerecords: N/A";
}
-void FrameUpdate()
+void MovieManager::FrameUpdate()
{
- s_currentFrame++;
- if (!s_bPolled)
- s_currentLagCount++;
+ m_current_frame++;
+ if (!m_polled)
+ m_current_lag_count++;
if (IsRecordingInput())
{
- s_totalFrames = s_currentFrame;
- s_totalLagCount = s_currentLagCount;
+ m_total_frames = m_current_frame;
+ m_total_lag_count = m_current_lag_count;
}
- s_bPolled = false;
+ m_polled = false;
}
-static void CheckMD5();
-static void GetMD5();
-
// called when game is booting up, even if no movie is active,
// but potentially after BeginRecordingInput or PlayInput has been called.
// NOTE: EmuThread
-void Init(const BootParameters& boot)
+void MovieManager::Init(const BootParameters& boot)
{
if (std::holds_alternative<BootParameters::Disc>(boot.parameters))
- s_current_file_name = std::get<BootParameters::Disc>(boot.parameters).path;
+ m_current_file_name = std::get<BootParameters::Disc>(boot.parameters).path;
else
- s_current_file_name.clear();
+ m_current_file_name.clear();
- s_bPolled = false;
- s_bSaveConfig = false;
+ m_polled = false;
+ m_save_config = false;
if (IsPlayingInput())
{
ReadHeader();
- std::thread md5thread(CheckMD5);
+ std::thread md5thread(&MovieManager::CheckMD5, this);
md5thread.detach();
- if (strncmp(tmpHeader.gameID.data(), SConfig::GetInstance().GetGameID().c_str(), 6))
+ if (strncmp(m_temp_header.gameID.data(), SConfig::GetInstance().GetGameID().c_str(), 6))
{
PanicAlertFmtT("The recorded game ({0}) is not the same as the selected game ({1})",
- tmpHeader.GetGameID(), SConfig::GetInstance().GetGameID());
+ m_temp_header.GetGameID(), SConfig::GetInstance().GetGameID());
EndPlayInput(false);
}
}
@@ -267,135 +225,135 @@ void Init(const BootParameters& boot)
if (IsRecordingInput())
{
GetSettings();
- std::thread md5thread(GetMD5);
+ std::thread md5thread(&MovieManager::GetMD5, this);
md5thread.detach();
- s_tickCountAtLastInput = 0;
+ m_tick_count_at_last_input = 0;
}
- memset(&s_padState, 0, sizeof(s_padState));
+ memset(&m_pad_state, 0, sizeof(m_pad_state));
- for (auto& disp : s_InputDisplay)
+ for (auto& disp : m_input_display)
disp.clear();
if (!IsMovieActive())
{
- s_bRecordingFromSaveState = false;
- s_rerecords = 0;
- s_currentByte = 0;
- s_currentFrame = 0;
- s_currentLagCount = 0;
- s_currentInputCount = 0;
+ m_recording_from_save_state = false;
+ m_rerecords = 0;
+ m_current_byte = 0;
+ m_current_frame = 0;
+ m_current_lag_count = 0;
+ m_current_input_count = 0;
}
}
// NOTE: CPU Thread
-void InputUpdate()
+void MovieManager::InputUpdate()
{
- s_currentInputCount++;
+ m_current_input_count++;
if (IsRecordingInput())
{
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
- s_totalInputCount = s_currentInputCount;
- s_totalTickCount += core_timing.GetTicks() - s_tickCountAtLastInput;
- s_tickCountAtLastInput = core_timing.GetTicks();
+ m_total_input_count = m_current_input_count;
+ m_total_tick_count += core_timing.GetTicks() - m_tick_count_at_last_input;
+ m_tick_count_at_last_input = core_timing.GetTicks();
}
}
// NOTE: CPU Thread
-void SetPolledDevice()
+void MovieManager::SetPolledDevice()
{
- s_bPolled = true;
+ m_polled = true;
}
// NOTE: Host Thread
-void SetReadOnly(bool bEnabled)
+void MovieManager::SetReadOnly(bool bEnabled)
{
- if (s_bReadOnly != bEnabled)
+ if (m_read_only != bEnabled)
Core::DisplayMessage(bEnabled ? "Read-only mode." : "Read+Write mode.", 1000);
- s_bReadOnly = bEnabled;
+ m_read_only = bEnabled;
}
-bool IsRecordingInput()
+bool MovieManager::IsRecordingInput() const
{
- return (s_playMode == PlayMode::Recording);
+ return (m_play_mode == PlayMode::Recording);
}
-bool IsRecordingInputFromSaveState()
+bool MovieManager::IsRecordingInputFromSaveState() const
{
- return s_bRecordingFromSaveState;
+ return m_recording_from_save_state;
}
-bool IsJustStartingRecordingInputFromSaveState()
+bool MovieManager::IsJustStartingRecordingInputFromSaveState() const
{
- return IsRecordingInputFromSaveState() && s_currentFrame == 0;
+ return IsRecordingInputFromSaveState() && m_current_frame == 0;
}
-bool IsJustStartingPlayingInputFromSaveState()
+bool MovieManager::IsJustStartingPlayingInputFromSaveState() const
{
- return IsRecordingInputFromSaveState() && s_currentFrame == 1 && IsPlayingInput();
+ return IsRecordingInputFromSaveState() && m_current_frame == 1 && IsPlayingInput();
}
-bool IsPlayingInput()
+bool MovieManager::IsPlayingInput() const
{
- return (s_playMode == PlayMode::Playing);
+ return (m_play_mode == PlayMode::Playing);
}
-bool IsMovieActive()
+bool MovieManager::IsMovieActive() const
{
- return s_playMode != PlayMode::None;
+ return m_play_mode != PlayMode::None;
}
-bool IsReadOnly()
+bool MovieManager::IsReadOnly() const
{
- return s_bReadOnly;
+ return m_read_only;
}
-u64 GetRecordingStartTime()
+u64 MovieManager::GetRecordingStartTime() const
{
- return s_recordingStartTime;
+ return m_recording_start_time;
}
-u64 GetCurrentFrame()
+u64 MovieManager::GetCurrentFrame() const
{
- return s_currentFrame;
+ return m_current_frame;
}
-u64 GetTotalFrames()
+u64 MovieManager::GetTotalFrames() const
{
- return s_totalFrames;
+ return m_total_frames;
}
-u64 GetCurrentInputCount()
+u64 MovieManager::GetCurrentInputCount() const
{
- return s_currentInputCount;
+ return m_current_input_count;
}
-u64 GetTotalInputCount()
+u64 MovieManager::GetTotalInputCount() const
{
- return s_totalInputCount;
+ return m_total_input_count;
}
-u64 GetCurrentLagCount()
+u64 MovieManager::GetCurrentLagCount() const
{
- return s_currentLagCount;
+ return m_current_lag_count;
}
-u64 GetTotalLagCount()
+u64 MovieManager::GetTotalLagCount() const
{
- return s_totalLagCount;
+ return m_total_lag_count;
}
-void SetClearSave(bool enabled)
+void MovieManager::SetClearSave(bool enabled)
{
- s_bClearSave = enabled;
+ m_clear_save = enabled;
}
-void SignalDiscChange(const std::string& new_path)
+void MovieManager::SignalDiscChange(const std::string& new_path)
{
- if (Movie::IsRecordingInput())
+ if (IsRecordingInput())
{
size_t size_of_path_without_filename = new_path.find_last_of("/\\") + 1;
std::string filename = new_path.substr(size_of_path_without_filename);
@@ -406,66 +364,66 @@ void SignalDiscChange(const std::string& new_path)
"The filename of the disc image must not be longer than 40 characters.",
filename);
}
- s_discChange = filename;
- s_bDiscChange = true;
+ m_disc_change_filename = filename;
+ m_has_disc_change = true;
}
}
-void SetReset(bool reset)
+void MovieManager::SetReset(bool reset)
{
- s_bReset = reset;
+ m_reset = reset;
}
-bool IsUsingPad(int controller)
+bool MovieManager::IsUsingPad(int controller) const
{
- return s_controllers[controller] != ControllerType::None;
+ return m_controllers[controller] != ControllerType::None;
}
-bool IsUsingBongo(int controller)
+bool MovieManager::IsUsingBongo(int controller) const
{
- return ((s_bongos & (1 << controller)) != 0);
+ return ((m_bongos & (1 << controller)) != 0);
}
-bool IsUsingGBA(int controller)
+bool MovieManager::IsUsingGBA(int controller) const
{
- return s_controllers[controller] == ControllerType::GBA;
+ return m_controllers[controller] == ControllerType::GBA;
}
-bool IsUsingWiimote(int wiimote)
+bool MovieManager::IsUsingWiimote(int wiimote) const
{
- return s_wiimotes[wiimote];
+ return m_wiimotes[wiimote];
}
-bool IsConfigSaved()
+bool MovieManager::IsConfigSaved() const
{
- return s_bSaveConfig;
+ return m_save_config;
}
-bool IsStartingFromClearSave()
+bool MovieManager::IsStartingFromClearSave() const
{
- return s_bClearSave;
+ return m_clear_save;
}
-bool IsUsingMemcard(ExpansionInterface::Slot slot)
+bool MovieManager::IsUsingMemcard(ExpansionInterface::Slot slot) const
{
switch (slot)
{
case ExpansionInterface::Slot::A:
- return (s_memcards & 1) != 0;
+ return (m_memcards & 1) != 0;
case ExpansionInterface::Slot::B:
- return (s_memcards & 2) != 0;
+ return (m_memcards & 2) != 0;
default:
return false;
}
}
-bool IsNetPlayRecording()
+bool MovieManager::IsNetPlayRecording() const
{
- return s_bNetPlay;
+ return m_net_play;
}
// NOTE: Host Thread
-void ChangePads()
+void MovieManager::ChangePads()
{
if (!Core::IsRunning())
return;
@@ -483,7 +441,7 @@ void ChangePads()
controllers[i] = ControllerType::None;
}
- if (s_controllers == controllers)
+ if (m_controllers == controllers)
return;
auto& si = Core::System::GetInstance().GetSerialInterface();
@@ -513,7 +471,7 @@ void ChangePads()
}
// NOTE: Host / Emu Threads
-void ChangeWiiPads(bool instantly)
+void MovieManager::ChangeWiiPads(bool instantly)
{
WiimoteEnabledArray wiimotes{};
@@ -523,7 +481,7 @@ void ChangeWiiPads(bool instantly)
}
// This is important for Wiimotes, because they can desync easily if they get re-activated
- if (instantly && s_wiimotes == wiimotes)
+ if (instantly && m_wiimotes == wiimotes)
return;
const auto bt = WiiUtils::GetBluetoothEmuDevice();
@@ -539,43 +497,43 @@ void ChangeWiiPads(bool instantly)
}
// NOTE: Host Thread
-bool BeginRecordingInput(const ControllerTypeArray& controllers,
- const WiimoteEnabledArray& wiimotes)
+bool MovieManager::BeginRecordingInput(const ControllerTypeArray& controllers,
+ const WiimoteEnabledArray& wiimotes)
{
- if (s_playMode != PlayMode::None ||
+ if (m_play_mode != PlayMode::None ||
(controllers == ControllerTypeArray{} && wiimotes == WiimoteEnabledArray{}))
return false;
- const auto start_recording = [controllers, wiimotes] {
- s_controllers = controllers;
- s_wiimotes = wiimotes;
- s_currentFrame = s_totalFrames = 0;
- s_currentLagCount = s_totalLagCount = 0;
- s_currentInputCount = s_totalInputCount = 0;
- s_totalTickCount = s_tickCountAtLastInput = 0;
- s_bongos = 0;
- s_memcards = 0;
+ const auto start_recording = [this, controllers, wiimotes] {
+ m_controllers = controllers;
+ m_wiimotes = wiimotes;
+ m_current_frame = m_total_frames = 0;
+ m_current_lag_count = m_total_lag_count = 0;
+ m_current_input_count = m_total_input_count = 0;
+ m_total_tick_count = m_tick_count_at_last_input = 0;
+ m_bongos = 0;
+ m_memcards = 0;
if (NetPlay::IsNetPlayRunning())
{
- s_bNetPlay = true;
- s_recordingStartTime = ExpansionInterface::CEXIIPL::NetPlay_GetEmulatedTime();
+ m_net_play = true;
+ m_recording_start_time = ExpansionInterface::CEXIIPL::NetPlay_GetEmulatedTime();
}
else if (Config::Get(Config::MAIN_CUSTOM_RTC_ENABLE))
{
- s_recordingStartTime = Config::Get(Config::MAIN_CUSTOM_RTC_VALUE);
+ m_recording_start_time = Config::Get(Config::MAIN_CUSTOM_RTC_VALUE);
}
else
{
- s_recordingStartTime = Common::Timer::GetLocalTimeSinceJan1970();
+ m_recording_start_time = Common::Timer::GetLocalTimeSinceJan1970();
}
- s_rerecords = 0;
+ m_rerecords = 0;
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
{
const SerialInterface::SIDevices si_device = Config::Get(Config::GetInfoForSIDevice(i));
if (si_device == SerialInterface::SIDEVICE_GC_TARUKONGA)
- s_bongos |= (1 << i);
+ m_bongos |= (1 << i);
}
if (Core::IsRunningAndStarted())
@@ -585,9 +543,9 @@ bool BeginRecordingInput(const ControllerTypeArray& controllers,
File::Delete(save_path);
State::SaveAs(save_path);
- s_bRecordingFromSaveState = true;
+ m_recording_from_save_state = true;
- std::thread md5thread(GetMD5);
+ std::thread md5thread(&MovieManager::GetMD5, this);
md5thread.detach();
GetSettings();
}
@@ -599,11 +557,11 @@ bool BeginRecordingInput(const ControllerTypeArray& controllers,
Wiimote::ResetAllWiimotes();
}
- s_playMode = PlayMode::Recording;
- s_author = Config::Get(Config::MAIN_MOVIE_MOVIE_AUTHOR);
- s_temp_input.clear();
+ m_play_mode = PlayMode::Recording;
+ m_author = Config::Get(Config::MAIN_MOVIE_MOVIE_AUTHOR);
+ m_temp_input.clear();
- s_currentByte = 0;
+ m_current_byte = 0;
// This is a bit of a hack, SYSCONF movie code expects the movie layer active for both recording
// and playback. That layer is really only designed for playback, not recording. Also, we can't
@@ -663,7 +621,7 @@ static std::string Analog1DToString(u32 v, const std::string& prefix, u32 range
}
// NOTE: CPU Thread
-static void SetInputDisplayString(ControllerState padState, int controllerID)
+static std::string GenerateInputDisplayString(ControllerState padState, int controllerID)
{
std::string display_str = fmt::format("P{}:", controllerID + 1);
@@ -711,16 +669,13 @@ static void SetInputDisplayString(ControllerState padState, int controllerID)
display_str += " DISCONNECTED";
}
- std::lock_guard guard(s_input_display_lock);
- s_InputDisplay[controllerID] = std::move(display_str);
+ return display_str;
}
// NOTE: CPU Thread
-static void SetWiiInputDisplayString(int remoteID, const DataReportBuilder& rpt,
- ExtensionNumber ext, const EncryptionKey& key)
+static std::string GenerateWiiInputDisplayString(int remoteID, const DataReportBuilder& rpt,
+ ExtensionNumber ext, const EncryptionKey& key)
{
- int controllerID = remoteID + 4;
-
std::string display_str = fmt::format("R{}:", remoteID + 1);
if (rpt.HasCore())
@@ -842,133 +797,143 @@ static void SetWiiInputDisplayString(int remoteID, const DataReportBuilder& rpt,
display_str += Analog2DToString(right_stick.x, right_stick.y, " R-ANA", 31);
}
- std::lock_guard guard(s_input_display_lock);
- s_InputDisplay[controllerID] = std::move(display_str);
+ return display_str;
}
// NOTE: CPU Thread
-void CheckPadStatus(const GCPadStatus* PadStatus, int controllerID)
+void MovieManager::CheckPadStatus(const GCPadStatus* PadStatus, int controllerID)
{
- s_padState.A = ((PadStatus->button & PAD_BUTTON_A) != 0);
- s_padState.B = ((PadStatus->button & PAD_BUTTON_B) != 0);
- s_padState.X = ((PadStatus->button & PAD_BUTTON_X) != 0);
- s_padState.Y = ((PadStatus->button & PAD_BUTTON_Y) != 0);
- s_padState.Z = ((PadStatus->button & PAD_TRIGGER_Z) != 0);
- s_padState.Start = ((PadStatus->button & PAD_BUTTON_START) != 0);
+ m_pad_state.A = ((PadStatus->button & PAD_BUTTON_A) != 0);
+ m_pad_state.B = ((PadStatus->button & PAD_BUTTON_B) != 0);
+ m_pad_state.X = ((PadStatus->button & PAD_BUTTON_X) != 0);
+ m_pad_state.Y = ((PadStatus->button & PAD_BUTTON_Y) != 0);
+ m_pad_state.Z = ((PadStatus->button & PAD_TRIGGER_Z) != 0);
+ m_pad_state.Start = ((PadStatus->button & PAD_BUTTON_START) != 0);
- s_padState.DPadUp = ((PadStatus->button & PAD_BUTTON_UP) != 0);
- s_padState.DPadDown = ((PadStatus->button & PAD_BUTTON_DOWN) != 0);
- s_padState.DPadLeft = ((PadStatus->button & PAD_BUTTON_LEFT) != 0);
- s_padState.DPadRight = ((PadStatus->button & PAD_BUTTON_RIGHT) != 0);
+ m_pad_state.DPadUp = ((PadStatus->button & PAD_BUTTON_UP) != 0);
+ m_pad_state.DPadDown = ((PadStatus->button & PAD_BUTTON_DOWN) != 0);
+ m_pad_state.DPadLeft = ((PadStatus->button & PAD_BUTTON_LEFT) != 0);
+ m_pad_state.DPadRight = ((PadStatus->button & PAD_BUTTON_RIGHT) != 0);
- s_padState.L = ((PadStatus->button & PAD_TRIGGER_L) != 0);
- s_padState.R = ((PadStatus->button & PAD_TRIGGER_R) != 0);
- s_padState.TriggerL = PadStatus->triggerLeft;
- s_padState.TriggerR = PadStatus->triggerRight;
+ m_pad_state.L = ((PadStatus->button & PAD_TRIGGER_L) != 0);
+ m_pad_state.R = ((PadStatus->button & PAD_TRIGGER_R) != 0);
+ m_pad_state.TriggerL = PadStatus->triggerLeft;
+ m_pad_state.TriggerR = PadStatus->triggerRight;
- s_padState.AnalogStickX = PadStatus->stickX;
- s_padState.AnalogStickY = PadStatus->stickY;
+ m_pad_state.AnalogStickX = PadStatus->stickX;
+ m_pad_state.AnalogStickY = PadStatus->stickY;
- s_padState.CStickX = PadStatus->substickX;
- s_padState.CStickY = PadStatus->substickY;
+ m_pad_state.CStickX = PadStatus->substickX;
+ m_pad_state.CStickY = PadStatus->substickY;
- s_padState.is_connected = PadStatus->isConnected;
+ m_pad_state.is_connected = PadStatus->isConnected;
- s_padState.get_origin = (PadStatus->button & PAD_GET_ORIGIN) != 0;
+ m_pad_state.get_origin = (PadStatus->button & PAD_GET_ORIGIN) != 0;
- s_padState.disc = s_bDiscChange;
- s_bDiscChange = false;
- s_padState.reset = s_bReset;
- s_bReset = false;
+ m_pad_state.disc = m_has_disc_change;
+ m_has_disc_change = false;
+ m_pad_state.reset = m_reset;
+ m_reset = false;
+
+ {
+ std::string display_str = GenerateInputDisplayString(m_pad_state, controllerID);
- SetInputDisplayString(s_padState, controllerID);
+ std::lock_guard guard(m_input_display_lock);
+ m_input_display[controllerID] = std::move(display_str);
+ }
}
// NOTE: CPU Thread
-void RecordInput(const GCPadStatus* PadStatus, int controllerID)
+void MovieManager::RecordInput(const GCPadStatus* PadStatus, int controllerID)
{
if (!IsRecordingInput() || !IsUsingPad(controllerID))
return;
CheckPadStatus(PadStatus, controllerID);
- s_temp_input.resize(s_currentByte + sizeof(ControllerState));
- memcpy(&s_temp_input[s_currentByte], &s_padState, sizeof(ControllerState));
- s_currentByte += sizeof(ControllerState);
+ m_temp_input.resize(m_current_byte + sizeof(ControllerState));
+ memcpy(&m_temp_input[m_current_byte], &m_pad_state, sizeof(ControllerState));
+ m_current_byte += sizeof(ControllerState);
}
// NOTE: CPU Thread
-void CheckWiimoteStatus(int wiimote, const DataReportBuilder& rpt, ExtensionNumber ext,
- const EncryptionKey& key)
+void MovieManager::CheckWiimoteStatus(int wiimote, const DataReportBuilder& rpt,
+ ExtensionNumber ext, const EncryptionKey& key)
{
- SetWiiInputDisplayString(wiimote, rpt, ext, key);
+ {
+ std::string display_str = GenerateWiiInputDisplayString(wiimote, rpt, ext, key);
+
+ std::lock_guard guard(m_input_display_lock);
+ m_input_display[wiimote + 4] = std::move(display_str);
+ }
if (IsRecordingInput())
RecordWiimote(wiimote, rpt.GetDataPtr(), rpt.GetDataSize());
}
-void RecordWiimote(int wiimote, const u8* data, u8 size)
+void MovieManager::RecordWiimote(int wiimote, const u8* data, u8 size)
{
if (!IsRecordingInput() || !IsUsingWiimote(wiimote))
return;
InputUpdate();
- s_temp_input.resize(s_currentByte + size + 1);
- s_temp_input[s_currentByte++] = size;
- memcpy(&s_temp_input[s_currentByte], data, size);
- s_currentByte += size;
+ m_temp_input.resize(m_current_byte + size + 1);
+ m_temp_input[m_current_byte++] = size;
+ memcpy(&m_temp_input[m_current_byte], data, size);
+ m_current_byte += size;
}
// NOTE: EmuThread / Host Thread
-void ReadHeader()
+void MovieManager::ReadHeader()
{
for (int i = 0; i < 4; ++i)
{
- if (tmpHeader.GBAControllers & (1 << i))
- s_controllers[i] = ControllerType::GBA;
- else if (tmpHeader.controllers & (1 << i))
- s_controllers[i] = ControllerType::GC;
+ if (m_temp_header.GBAControllers & (1 << i))
+ m_controllers[i] = ControllerType::GBA;
+ else if (m_temp_header.controllers & (1 << i))
+ m_controllers[i] = ControllerType::GC;
else
- s_controllers[i] = ControllerType::None;
- s_wiimotes[i] = (tmpHeader.controllers & (1 << (i + 4))) != 0;
+ m_controllers[i] = ControllerType::None;
+ m_wiimotes[i] = (m_temp_header.controllers & (1 << (i + 4))) != 0;
}
- s_recordingStartTime = tmpHeader.recordingStartTime;
- if (s_rerecords < tmpHeader.numRerecords)
- s_rerecords = tmpHeader.numRerecords;
+ m_recording_start_time = m_temp_header.recordingStartTime;
+ if (m_rerecords < m_temp_header.numRerecords)
+ m_rerecords = m_temp_header.numRerecords;
- if (tmpHeader.bSaveConfig)
+ if (m_temp_header.bSaveConfig)
{
- s_bSaveConfig = true;
- Config::AddLayer(ConfigLoaders::GenerateMovieConfigLoader(&tmpHeader));
- s_bClearSave = tmpHeader.bClearSave;
- s_memcards = tmpHeader.memcards;
- s_bongos = tmpHeader.bongos;
- s_bNetPlay = tmpHeader.bNetPlay;
- s_revision = tmpHeader.revision;
+ m_save_config = true;
+ Config::AddLayer(ConfigLoaders::GenerateMovieConfigLoader(&m_temp_header));
+ m_clear_save = m_temp_header.bClearSave;
+ m_memcards = m_temp_header.memcards;
+ m_bongos = m_temp_header.bongos;
+ m_net_play = m_temp_header.bNetPlay;
+ m_revision = m_temp_header.revision;
}
else
{
GetSettings();
}
- s_discChange = {tmpHeader.discChange.begin(), tmpHeader.discChange.end()};
- s_author = {tmpHeader.author.begin(), tmpHeader.author.end()};
- s_MD5 = tmpHeader.md5;
- s_DSPiromHash = tmpHeader.DSPiromHash;
- s_DSPcoefHash = tmpHeader.DSPcoefHash;
+ m_disc_change_filename = {m_temp_header.discChange.begin(), m_temp_header.discChange.end()};
+ m_author = {m_temp_header.author.begin(), m_temp_header.author.end()};
+ m_md5 = m_temp_header.md5;
+ m_dsp_irom_hash = m_temp_header.DSPiromHash;
+ m_dsp_coef_hash = m_temp_header.DSPcoefHash;
}
// NOTE: Host Thread
-bool PlayInput(const std::string& movie_path, std::optional<std::string>* savestate_path)
+bool MovieManager::PlayInput(const std::string& movie_path,
+ std::optional<std::string>* savestate_path)
{
- if (s_playMode != PlayMode::None)
+ if (m_play_mode != PlayMode::None)
return false;
File::IOFile recording_file(movie_path, "rb");
- if (!recording_file.ReadArray(&tmpHeader, 1))
+ if (!recording_file.ReadArray(&m_temp_header, 1))
return false;
- if (!IsMovieHeader(tmpHeader.filetype))
+ if (!IsMovieHeader(m_temp_header.filetype))
{
PanicAlertFmtT("Invalid recording file");
return false;
@@ -981,28 +946,28 @@ bool PlayInput(const std::string& movie_path, std::optional<std::string>* savest
return false;
#endif // USE_RETRO_ACHIEVEMENTS
- s_totalFrames = tmpHeader.frameCount;
- s_totalLagCount = tmpHeader.lagCount;
- s_totalInputCount = tmpHeader.inputCount;
- s_totalTickCount = tmpHeader.tickCount;
- s_currentFrame = 0;
- s_currentLagCount = 0;
- s_currentInputCount = 0;
+ m_total_frames = m_temp_header.frameCount;
+ m_total_lag_count = m_temp_header.lagCount;
+ m_total_input_count = m_temp_header.inputCount;
+ m_total_tick_count = m_temp_header.tickCount;
+ m_current_frame = 0;
+ m_current_lag_count = 0;
+ m_current_input_count = 0;
- s_playMode = PlayMode::Playing;
+ m_play_mode = PlayMode::Playing;
// Wiimotes cause desync issues if they're not reset before launching the game
Wiimote::ResetAllWiimotes();
Core::UpdateWantDeterminism();
- s_temp_input.resize(recording_file.GetSize() - 256);
- recording_file.ReadBytes(s_temp_input.data(), s_temp_input.size());
- s_currentByte = 0;
+ m_temp_input.resize(recording_file.GetSize() - 256);
+ recording_file.ReadBytes(m_temp_input.data(), m_temp_input.size());
+ m_current_byte = 0;
recording_file.Close();
// Load savestate (and skip to frame data)
- if (tmpHeader.bFromSaveState && savestate_path)
+ if (m_temp_header.bFromSaveState && savestate_path)
{
const std::string savestate_path_temp = movie_path + ".sav";
if (File::Exists(savestate_path_temp))
@@ -1016,34 +981,34 @@ bool PlayInput(const std::string& movie_path, std::optional<std::string>* savest
movie_path, savestate_path_temp);
}
- s_bRecordingFromSaveState = true;
+ m_recording_from_save_state = true;
#ifdef USE_RETRO_ACHIEVEMENTS
// On the chance someone tries to re-enable before the TAS can start
Config::SetBase(Config::RA_HARDCORE_ENABLED, false);
#endif // USE_RETRO_ACHIEVEMENTS
- Movie::LoadInput(movie_path);
+ LoadInput(movie_path);
}
return true;
}
-void DoState(PointerWrap& p)
+void MovieManager::DoState(PointerWrap& p)
{
// many of these could be useful to save even when no movie is active,
// and the data is tiny, so let's just save it regardless of movie state.
- p.Do(s_currentFrame);
- p.Do(s_currentByte);
- p.Do(s_currentLagCount);
- p.Do(s_currentInputCount);
- p.Do(s_bPolled);
- p.Do(s_tickCountAtLastInput);
- // other variables (such as s_totalBytes and s_totalFrames) are set in LoadInput
+ p.Do(m_current_frame);
+ p.Do(m_current_byte);
+ p.Do(m_current_lag_count);
+ p.Do(m_current_input_count);
+ p.Do(m_polled);
+ p.Do(m_tick_count_at_last_input);
+ // other variables (such as s_totalBytes and m_total_frames) are set in LoadInput
}
// NOTE: Host Thread
-void LoadInput(const std::string& movie_path)
+void MovieManager::LoadInput(const std::string& movie_path)
{
File::IOFile t_record;
if (!t_record.Open(movie_path, "r+b"))
@@ -1053,21 +1018,21 @@ void LoadInput(const std::string& movie_path)
return;
}
- t_record.ReadArray(&tmpHeader, 1);
+ t_record.ReadArray(&m_temp_header, 1);
- if (!IsMovieHeader(tmpHeader.filetype))
+ if (!IsMovieHeader(m_temp_header.filetype))
{
PanicAlertFmtT("Savestate movie {0} is corrupted, movie recording stopping...", movie_path);
EndPlayInput(false);
return;
}
ReadHeader();
- if (!s_bReadOnly)
+ if (!m_read_only)
{
- s_rerecords++;
- tmpHeader.numRerecords = s_rerecords;
+ m_rerecords++;
+ m_temp_header.numRerecords = m_rerecords;
t_record.Seek(0, File::SeekOrigin::Begin);
- t_record.WriteArray(&tmpHeader, 1);
+ t_record.WriteArray(&m_temp_header, 1);
}
ChangePads();
@@ -1078,46 +1043,47 @@ void LoadInput(const std::string& movie_path)
bool afterEnd = false;
// This can only happen if the user manually deletes data from the dtm.
- if (s_currentByte > totalSavedBytes)
+ if (m_current_byte > totalSavedBytes)
{
PanicAlertFmtT(
"Warning: You loaded a save whose movie ends before the current frame in the save "
"(byte {0} < {1}) (frame {2} < {3}). You should load another save before continuing.",
- totalSavedBytes + 256, s_currentByte + 256, tmpHeader.frameCount, s_currentFrame);
+ totalSavedBytes + 256, m_current_byte + 256, m_temp_header.frameCount, m_current_frame);
afterEnd = true;
}
- if (!s_bReadOnly || s_temp_input.empty())
+ if (!m_read_only || m_temp_input.empty())
{
- s_totalFrames = tmpHeader.frameCount;
- s_totalLagCount = tmpHeader.lagCount;
- s_totalInputCount = tmpHeader.inputCount;
- s_totalTickCount = s_tickCountAtLastInput = tmpHeader.tickCount;
+ m_total_frames = m_temp_header.frameCount;
+ m_total_lag_count = m_temp_header.lagCount;
+ m_total_input_count = m_temp_header.inputCount;
+ m_total_tick_count = m_tick_count_at_last_input = m_temp_header.tickCount;
- s_temp_input.resize(static_cast<size_t>(totalSavedBytes));
- t_record.ReadBytes(s_temp_input.data(), s_temp_input.size());
+ m_temp_input.resize(static_cast<size_t>(totalSavedBytes));
+ t_record.ReadBytes(m_temp_input.data(), m_temp_input.size());
}
- else if (s_currentByte > 0)
+ else if (m_current_byte > 0)
{
- if (s_currentByte > totalSavedBytes)
+ if (m_current_byte > totalSavedBytes)
{
}
- else if (s_currentByte > s_temp_input.size())
+ else if (m_current_byte > m_temp_input.size())
{
afterEnd = true;
PanicAlertFmtT(
"Warning: You loaded a save that's after the end of the current movie. (byte {0} "
"> {1}) (input {2} > {3}). You should load another save before continuing, or load "
"this state with read-only mode off.",
- s_currentByte + 256, s_temp_input.size() + 256, s_currentInputCount, s_totalInputCount);
+ m_current_byte + 256, m_temp_input.size() + 256, m_current_input_count,
+ m_total_input_count);
}
- else if (s_currentByte > 0 && !s_temp_input.empty())
+ else if (m_current_byte > 0 && !m_temp_input.empty())
{
// verify identical from movie start to the save's current frame
- std::vector<u8> movInput(s_currentByte);
+ std::vector<u8> movInput(m_current_byte);
t_record.ReadArray(movInput.data(), movInput.size());
- const auto result = std::mismatch(movInput.begin(), movInput.end(), s_temp_input.begin());
+ const auto result = std::mismatch(movInput.begin(), movInput.end(), m_temp_input.begin());
if (result.first != movInput.end())
{
@@ -1136,13 +1102,13 @@ void LoadInput(const std::string& movie_path)
"read-only mode off. Otherwise you'll probably get a desync.",
byte_offset, byte_offset);
- std::copy(movInput.begin(), movInput.end(), s_temp_input.begin());
+ std::copy(movInput.begin(), movInput.end(), m_temp_input.begin());
}
else
{
const ptrdiff_t frame = mismatch_index / sizeof(ControllerState);
ControllerState curPadState;
- memcpy(&curPadState, &s_temp_input[frame * sizeof(ControllerState)],
+ memcpy(&curPadState, &m_temp_input[frame * sizeof(ControllerState)],
sizeof(ControllerState));
ControllerState movPadState;
memcpy(&movPadState, &movInput[frame * sizeof(ControllerState)], sizeof(ControllerState));
@@ -1161,41 +1127,41 @@ void LoadInput(const std::string& movie_path)
"Start={24}, A={25}, B={26}, X={27}, Y={28}, Z={29}, DUp={30}, DDown={31}, "
"DLeft={32}, DRight={33}, L={34}, R={35}, LT={36}, RT={37}, AnalogX={38}, "
"AnalogY={39}, CX={40}, CY={41}, Connected={42}",
- frame, s_totalFrames, tmpHeader.frameCount, frame, curPadState.Start, curPadState.A,
- curPadState.B, curPadState.X, curPadState.Y, curPadState.Z, curPadState.DPadUp,
- curPadState.DPadDown, curPadState.DPadLeft, curPadState.DPadRight, curPadState.L,
- curPadState.R, curPadState.TriggerL, curPadState.TriggerR, curPadState.AnalogStickX,
- curPadState.AnalogStickY, curPadState.CStickX, curPadState.CStickY,
- curPadState.is_connected, frame, movPadState.Start, movPadState.A, movPadState.B,
- movPadState.X, movPadState.Y, movPadState.Z, movPadState.DPadUp, movPadState.DPadDown,
- movPadState.DPadLeft, movPadState.DPadRight, movPadState.L, movPadState.R,
- movPadState.TriggerL, movPadState.TriggerR, movPadState.AnalogStickX,
- movPadState.AnalogStickY, movPadState.CStickX, movPadState.CStickY,
- curPadState.is_connected);
+ frame, m_total_frames, m_temp_header.frameCount, frame, curPadState.Start,
+ curPadState.A, curPadState.B, curPadState.X, curPadState.Y, curPadState.Z,
+ curPadState.DPadUp, curPadState.DPadDown, curPadState.DPadLeft, curPadState.DPadRight,
+ curPadState.L, curPadState.R, curPadState.TriggerL, curPadState.TriggerR,
+ curPadState.AnalogStickX, curPadState.AnalogStickY, curPadState.CStickX,
+ curPadState.CStickY, curPadState.is_connected, frame, movPadState.Start,
+ movPadState.A, movPadState.B, movPadState.X, movPadState.Y, movPadState.Z,
+ movPadState.DPadUp, movPadState.DPadDown, movPadState.DPadLeft, movPadState.DPadRight,
+ movPadState.L, movPadState.R, movPadState.TriggerL, movPadState.TriggerR,
+ movPadState.AnalogStickX, movPadState.AnalogStickY, movPadState.CStickX,
+ movPadState.CStickY, curPadState.is_connected);
}
}
}
}
t_record.Close();
- s_bSaveConfig = tmpHeader.bSaveConfig;
+ m_save_config = m_temp_header.bSaveConfig;
if (!afterEnd)
{
- if (s_bReadOnly)
+ if (m_read_only)
{
- if (s_playMode != PlayMode::Playing)
+ if (m_play_mode != PlayMode::Playing)
{
- s_playMode = PlayMode::Playing;
+ m_play_mode = PlayMode::Playing;
Core::UpdateWantDeterminism();
Core::DisplayMessage("Switched to playback", 2000);
}
}
else
{
- if (s_playMode != PlayMode::Recording)
+ if (m_play_mode != PlayMode::Recording)
{
- s_playMode = PlayMode::Recording;
+ m_play_mode = PlayMode::Recording;
Core::UpdateWantDeterminism();
Core::DisplayMessage("Switched to recording", 2000);
}
@@ -1208,169 +1174,174 @@ void LoadInput(const std::string& movie_path)
}
// NOTE: CPU Thread
-static void CheckInputEnd()
+void MovieManager::CheckInputEnd()
{
- if (s_currentByte >= s_temp_input.size() ||
- (Core::System::GetInstance().GetCoreTiming().GetTicks() > s_totalTickCount &&
+ if (m_current_byte >= m_temp_input.size() ||
+ (Core::System::GetInstance().GetCoreTiming().GetTicks() > m_total_tick_count &&
!IsRecordingInputFromSaveState()))
{
- EndPlayInput(!s_bReadOnly);
+ EndPlayInput(!m_read_only);
}
}
// NOTE: CPU Thread
-void PlayController(GCPadStatus* PadStatus, int controllerID)
+void MovieManager::PlayController(GCPadStatus* PadStatus, int controllerID)
{
// Correct playback is entirely dependent on the emulator polling the controllers
// in the same order done during recording
- if (!IsPlayingInput() || !IsUsingPad(controllerID) || s_temp_input.empty())
+ if (!IsPlayingInput() || !IsUsingPad(controllerID) || m_temp_input.empty())
return;
- if (s_currentByte + sizeof(ControllerState) > s_temp_input.size())
+ if (m_current_byte + sizeof(ControllerState) > m_temp_input.size())
{
- PanicAlertFmtT("Premature movie end in PlayController. {0} + {1} > {2}", s_currentByte,
- sizeof(ControllerState), s_temp_input.size());
- EndPlayInput(!s_bReadOnly);
+ PanicAlertFmtT("Premature movie end in PlayController. {0} + {1} > {2}", m_current_byte,
+ sizeof(ControllerState), m_temp_input.size());
+ EndPlayInput(!m_read_only);
return;
}
- memcpy(&s_padState, &s_temp_input[s_currentByte], sizeof(ControllerState));
- s_currentByte += sizeof(ControllerState);
+ memcpy(&m_pad_state, &m_temp_input[m_current_byte], sizeof(ControllerState));
+ m_current_byte += sizeof(ControllerState);
- PadStatus->isConnected = s_padState.is_connected;
+ PadStatus->isConnected = m_pad_state.is_connected;
- PadStatus->triggerLeft = s_padState.TriggerL;
- PadStatus->triggerRight = s_padState.TriggerR;
+ PadStatus->triggerLeft = m_pad_state.TriggerL;
+ PadStatus->triggerRight = m_pad_state.TriggerR;
- PadStatus->stickX = s_padState.AnalogStickX;
- PadStatus->stickY = s_padState.AnalogStickY;
+ PadStatus->stickX = m_pad_state.AnalogStickX;
+ PadStatus->stickY = m_pad_state.AnalogStickY;
- PadStatus->substickX = s_padState.CStickX;
- PadStatus->substickY = s_padState.CStickY;
+ PadStatus->substickX = m_pad_state.CStickX;
+ PadStatus->substickY = m_pad_state.CStickY;
PadStatus->button = 0;
PadStatus->button |= PAD_USE_ORIGIN;
- if (s_padState.A)
+ if (m_pad_state.A)
{
PadStatus->button |= PAD_BUTTON_A;
PadStatus->analogA = 0xFF;
}
- if (s_padState.B)
+ if (m_pad_state.B)
{
PadStatus->button |= PAD_BUTTON_B;
PadStatus->analogB = 0xFF;
}
- if (s_padState.X)
+ if (m_pad_state.X)
PadStatus->button |= PAD_BUTTON_X;
- if (s_padState.Y)
+ if (m_pad_state.Y)
PadStatus->button |= PAD_BUTTON_Y;
- if (s_padState.Z)
+ if (m_pad_state.Z)
PadStatus->button |= PAD_TRIGGER_Z;
- if (s_padState.Start)
+ if (m_pad_state.Start)
PadStatus->button |= PAD_BUTTON_START;
- if (s_padState.DPadUp)
+ if (m_pad_state.DPadUp)
PadStatus->button |= PAD_BUTTON_UP;
- if (s_padState.DPadDown)
+ if (m_pad_state.DPadDown)
PadStatus->button |= PAD_BUTTON_DOWN;
- if (s_padState.DPadLeft)
+ if (m_pad_state.DPadLeft)
PadStatus->button |= PAD_BUTTON_LEFT;
- if (s_padState.DPadRight)
+ if (m_pad_state.DPadRight)
PadStatus->button |= PAD_BUTTON_RIGHT;
- if (s_padState.L)
+ if (m_pad_state.L)
PadStatus->button |= PAD_TRIGGER_L;
- if (s_padState.R)
+ if (m_pad_state.R)
PadStatus->button |= PAD_TRIGGER_R;
- if (s_padState.get_origin)
+ if (m_pad_state.get_origin)
PadStatus->button |= PAD_GET_ORIGIN;
- if (s_padState.disc)
+ if (m_pad_state.disc)
{
- Core::RunAsCPUThread([] {
- auto& system = Core::System::GetInstance();
- if (!system.GetDVDInterface().AutoChangeDisc())
+ Core::RunAsCPUThread([this] {
+ if (!m_system.GetDVDInterface().AutoChangeDisc())
{
- system.GetCPU().Break();
- PanicAlertFmtT("Change the disc to {0}", s_discChange);
+ m_system.GetCPU().Break();
+ PanicAlertFmtT("Change the disc to {0}", m_disc_change_filename);
}
});
}
- if (s_padState.reset)
+ if (m_pad_state.reset)
{
auto& system = Core::System::GetInstance();
system.GetProcessorInterface().ResetButton_Tap();
}
- SetInputDisplayString(s_padState, controllerID);
+ {
+ std::string display_str = GenerateInputDisplayString(m_pad_state, controllerID);
+
+ std::lock_guard guard(m_input_display_lock);
+ m_input_display[controllerID] = std::move(display_str);
+ }
+
CheckInputEnd();
}
// NOTE: CPU Thread
-bool PlayWiimote(int wiimote, WiimoteCommon::DataReportBuilder& rpt, ExtensionNumber ext,
- const EncryptionKey& key)
+bool MovieManager::PlayWiimote(int wiimote, WiimoteCommon::DataReportBuilder& rpt,
+ ExtensionNumber ext, const EncryptionKey& key)
{
- if (!IsPlayingInput() || !IsUsingWiimote(wiimote) || s_temp_input.empty())
+ if (!IsPlayingInput() || !IsUsingWiimote(wiimote) || m_temp_input.empty())
return false;
- if (s_currentByte > s_temp_input.size())
+ if (m_current_byte > m_temp_input.size())
{
- PanicAlertFmtT("Premature movie end in PlayWiimote. {0} > {1}", s_currentByte,
- s_temp_input.size());
- EndPlayInput(!s_bReadOnly);
+ PanicAlertFmtT("Premature movie end in PlayWiimote. {0} > {1}", m_current_byte,
+ m_temp_input.size());
+ EndPlayInput(!m_read_only);
return false;
}
const u8 size = rpt.GetDataSize();
- const u8 sizeInMovie = s_temp_input[s_currentByte];
+ const u8 sizeInMovie = m_temp_input[m_current_byte];
if (size != sizeInMovie)
{
PanicAlertFmtT(
"Fatal desync. Aborting playback. (Error in PlayWiimote: {0} != {1}, byte {2}.){3}",
- sizeInMovie, size, s_currentByte,
- (s_controllers == ControllerTypeArray{}) ?
+ sizeInMovie, size, m_current_byte,
+ (m_controllers == ControllerTypeArray{}) ?
" Try re-creating the recording with all GameCube controllers "
"disabled (in Configure > GameCube > Device Settings)." :
"");
- EndPlayInput(!s_bReadOnly);
+ EndPlayInput(!m_read_only);
return false;
}
- s_currentByte++;
+ m_current_byte++;
- if (s_currentByte + size > s_temp_input.size())
+ if (m_current_byte + size > m_temp_input.size())
{
- PanicAlertFmtT("Premature movie end in PlayWiimote. {0} + {1} > {2}", s_currentByte, size,
- s_temp_input.size());
- EndPlayInput(!s_bReadOnly);
+ PanicAlertFmtT("Premature movie end in PlayWiimote. {0} + {1} > {2}", m_current_byte, size,
+ m_temp_input.size());
+ EndPlayInput(!m_read_only);
return false;
}
- memcpy(rpt.GetDataPtr(), &s_temp_input[s_currentByte], size);
- s_currentByte += size;
+ memcpy(rpt.GetDataPtr(), &m_temp_input[m_current_byte], size);
+ m_current_byte += size;
- s_currentInputCount++;
+ m_current_input_count++;
CheckInputEnd();
return true;
}
// NOTE: Host / EmuThread / CPU Thread
-void EndPlayInput(bool cont)
+void MovieManager::EndPlayInput(bool cont)
{
if (cont)
{
- // If !IsMovieActive(), changing s_playMode requires calling UpdateWantDeterminism
+ // If !IsMovieActive(), changing m_play_mode requires calling UpdateWantDeterminism
ASSERT(IsMovieActive());
- s_playMode = PlayMode::Recording;
+ m_play_mode = PlayMode::Recording;
Core::DisplayMessage("Reached movie end. Resuming recording.", 2000);
}
- else if (s_playMode != PlayMode::None)
+ else if (m_play_mode != PlayMode::None)
{
// We can be called by EmuThread during boot (CPU::State::PowerDown)
auto& system = Core::System::GetInstance();
@@ -1378,15 +1349,15 @@ void EndPlayInput(bool cont)
bool was_running = Core::IsRunningAndStarted() && !cpu.IsStepping();
if (was_running && Config::Get(Config::MAIN_MOVIE_PAUSE_MOVIE))
cpu.Break();
- s_rerecords = 0;
- s_currentByte = 0;
- s_playMode = PlayMode::None;
+ m_rerecords = 0;
+ m_current_byte = 0;
+ m_play_mode = PlayMode::None;
Core::DisplayMessage("Movie End.", 2000);
- s_bRecordingFromSaveState = false;
+ m_recording_from_save_state = false;
Config::RemoveLayer(Config::LayerType::Movie);
// we don't clear these things because otherwise we can't resume playback if we load a movie
// state later
- // s_totalFrames = s_totalBytes = 0;
+ // m_total_frames = s_totalBytes = 0;
// delete tmpInput;
// tmpInput = nullptr;
@@ -1395,7 +1366,7 @@ void EndPlayInput(bool cont)
}
// NOTE: Save State + Host Thread
-void SaveRecording(const std::string& filename)
+void MovieManager::SaveRecording(const std::string& filename)
{
File::IOFile save_record(filename, "wb");
// Create the real header now and write it
@@ -1420,26 +1391,26 @@ void SaveRecording(const std::string& filename)
header.controllers |= 1 << (i + 4);
}
- header.bFromSaveState = s_bRecordingFromSaveState;
- header.frameCount = s_totalFrames;
- header.lagCount = s_totalLagCount;
- header.inputCount = s_totalInputCount;
- header.numRerecords = s_rerecords;
- header.recordingStartTime = s_recordingStartTime;
+ header.bFromSaveState = m_recording_from_save_state;
+ header.frameCount = m_total_frames;
+ header.lagCount = m_total_lag_count;
+ header.inputCount = m_total_input_count;
+ header.numRerecords = m_rerecords;
+ header.recordingStartTime = m_recording_start_time;
header.bSaveConfig = true;
ConfigLoaders::SaveToDTM(&header);
- header.memcards = s_memcards;
- header.bClearSave = s_bClearSave;
- header.bNetPlay = s_bNetPlay;
- strncpy(header.discChange.data(), s_discChange.c_str(), header.discChange.size());
- strncpy(header.author.data(), s_author.c_str(), header.author.size());
- header.md5 = s_MD5;
- header.bongos = s_bongos;
- header.revision = s_revision;
- header.DSPiromHash = s_DSPiromHash;
- header.DSPcoefHash = s_DSPcoefHash;
- header.tickCount = s_totalTickCount;
+ header.memcards = m_memcards;
+ header.bClearSave = m_clear_save;
+ header.bNetPlay = m_net_play;
+ strncpy(header.discChange.data(), m_disc_change_filename.c_str(), header.discChange.size());
+ strncpy(header.author.data(), m_author.c_str(), header.author.size());
+ header.md5 = m_md5;
+ header.bongos = m_bongos;
+ header.revision = m_revision;
+ header.DSPiromHash = m_dsp_irom_hash;
+ header.DSPcoefHash = m_dsp_coef_hash;
+ header.tickCount = m_total_tick_count;
// TODO
header.uniqueID = 0;
@@ -1447,9 +1418,9 @@ void SaveRecording(const std::string& filename)
save_record.WriteArray(&header, 1);
- bool success = save_record.WriteBytes(s_temp_input.data(), s_temp_input.size());
+ bool success = save_record.WriteBytes(m_temp_input.data(), m_temp_input.size());
- if (success && s_bRecordingFromSaveState)
+ if (success && m_recording_from_save_state)
{
std::string stateFilename = filename + ".sav";
success = File::CopyRegularFile(File::GetUserPath(D_STATESAVES_IDX) + "dtm.sav", stateFilename);
@@ -1462,17 +1433,17 @@ void SaveRecording(const std::string& filename)
}
// NOTE: GPU Thread
-void SetGraphicsConfig()
+void MovieManager::SetGraphicsConfig()
{
- g_Config.bEFBAccessEnable = tmpHeader.bEFBAccessEnable;
- g_Config.bSkipEFBCopyToRam = tmpHeader.bSkipEFBCopyToRam;
- g_Config.bEFBEmulateFormatChanges = tmpHeader.bEFBEmulateFormatChanges;
- g_Config.bImmediateXFB = tmpHeader.bImmediateXFB;
- g_Config.bSkipXFBCopyToRam = tmpHeader.bSkipXFBCopyToRam;
+ g_Config.bEFBAccessEnable = m_temp_header.bEFBAccessEnable;
+ g_Config.bSkipEFBCopyToRam = m_temp_header.bSkipEFBCopyToRam;
+ g_Config.bEFBEmulateFormatChanges = m_temp_header.bEFBEmulateFormatChanges;
+ g_Config.bImmediateXFB = m_temp_header.bImmediateXFB;
+ g_Config.bSkipXFBCopyToRam = m_temp_header.bSkipXFBCopyToRam;
}
// NOTE: EmuThread / Host Thread
-void GetSettings()
+void MovieManager::GetSettings()
{
using ExpansionInterface::EXIDeviceType;
const EXIDeviceType slot_a_type = Config::Get(Config::MAIN_SLOT_A);
@@ -1482,12 +1453,12 @@ void GetSettings()
const bool slot_b_has_raw_memcard = slot_b_type == EXIDeviceType::MemoryCard;
const bool slot_b_has_gci_folder = slot_b_type == EXIDeviceType::MemoryCardFolder;
- s_bSaveConfig = true;
- s_bNetPlay = NetPlay::IsNetPlayRunning();
+ m_save_config = true;
+ m_net_play = NetPlay::IsNetPlayRunning();
if (SConfig::GetInstance().bWii)
{
u64 title_id = SConfig::GetInstance().GetTitleID();
- s_bClearSave = !File::Exists(
+ m_clear_save = !File::Exists(
Common::GetTitleDataPath(title_id, Common::FromWhichRoot::Session) + "/banner.bin");
}
else
@@ -1495,22 +1466,22 @@ void GetSettings()
const auto raw_memcard_exists = [](ExpansionInterface::Slot card_slot) {
return File::Exists(Config::GetMemcardPath(card_slot, SConfig::GetInstance().m_region));
};
- const auto gci_folder_has_saves = [](ExpansionInterface::Slot card_slot) {
+ const auto gci_folder_has_saves = [this](ExpansionInterface::Slot card_slot) {
const auto [path, migrate] = ExpansionInterface::CEXIMemoryCard::GetGCIFolderPath(
- card_slot, ExpansionInterface::AllowMovieFolder::No);
+ card_slot, ExpansionInterface::AllowMovieFolder::No, *this);
const u64 number_of_saves = File::ScanDirectoryTree(path, false).size;
return number_of_saves > 0;
};
- s_bClearSave = !(slot_a_has_raw_memcard && raw_memcard_exists(ExpansionInterface::Slot::A)) &&
+ m_clear_save = !(slot_a_has_raw_memcard && raw_memcard_exists(ExpansionInterface::Slot::A)) &&
!(slot_b_has_raw_memcard && raw_memcard_exists(ExpansionInterface::Slot::B)) &&
!(slot_a_has_gci_folder && gci_folder_has_saves(ExpansionInterface::Slot::A)) &&
!(slot_b_has_gci_folder && gci_folder_has_saves(ExpansionInterface::Slot::B));
}
- s_memcards |= (slot_a_has_raw_memcard || slot_a_has_gci_folder) << 0;
- s_memcards |= (slot_b_has_raw_memcard || slot_b_has_gci_folder) << 1;
+ m_memcards |= (slot_a_has_raw_memcard || slot_a_has_gci_folder) << 0;
+ m_memcards |= (slot_b_has_raw_memcard || slot_b_has_gci_folder) << 1;
- s_revision = ConvertGitRevisionToBytes(Common::GetScmRevGitStr());
+ m_revision = ConvertGitRevisionToBytes(Common::GetScmRevGitStr());
if (!Config::Get(Config::MAIN_DSP_HLE))
{
@@ -1536,29 +1507,27 @@ void GetSettings()
file_coef.Close();
for (u16& entry : coef)
entry = Common::swap16(entry);
- s_DSPiromHash =
+ m_dsp_irom_hash =
Common::HashAdler32(reinterpret_cast<u8*>(irom.data()), DSP::DSP_IROM_BYTE_SIZE);
- s_DSPcoefHash =
+ m_dsp_coef_hash =
Common::HashAdler32(reinterpret_cast<u8*>(coef.data()), DSP::DSP_COEF_BYTE_SIZE);
}
else
{
- s_DSPiromHash = 0;
- s_DSPcoefHash = 0;
+ m_dsp_irom_hash = 0;
+ m_dsp_coef_hash = 0;
}
}
-static const mbedtls_md_info_t* s_md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
-
// NOTE: Entrypoint for own thread
-static void CheckMD5()
+void MovieManager::CheckMD5()
{
- if (s_current_file_name.empty())
+ if (m_current_file_name.empty())
return;
for (int i = 0, n = 0; i < 16; ++i)
{
- if (tmpHeader.md5[i] != 0)
+ if (m_temp_header.md5[i] != 0)
continue;
n++;
if (n == 16)
@@ -1567,29 +1536,31 @@ static void CheckMD5()
Core::DisplayMessage("Verifying checksum...", 2000);
std::array<u8, 16> game_md5;
- mbedtls_md_file(s_md5_info, s_current_file_name.c_str(), game_md5.data());
+ mbedtls_md_file(mbedtls_md_info_from_type(MBEDTLS_MD_MD5), m_current_file_name.c_str(),
+ game_md5.data());
- if (game_md5 == s_MD5)
+ if (game_md5 == m_md5)
Core::DisplayMessage("Checksum of current game matches the recorded game.", 2000);
else
Core::DisplayMessage("Checksum of current game does not match the recorded game!", 3000);
}
// NOTE: Entrypoint for own thread
-static void GetMD5()
+void MovieManager::GetMD5()
{
- if (s_current_file_name.empty())
+ if (m_current_file_name.empty())
return;
Core::DisplayMessage("Calculating checksum of game file...", 2000);
- mbedtls_md_file(s_md5_info, s_current_file_name.c_str(), s_MD5.data());
+ mbedtls_md_file(mbedtls_md_info_from_type(MBEDTLS_MD_MD5), m_current_file_name.c_str(),
+ m_md5.data());
Core::DisplayMessage("Finished calculating checksum.", 2000);
}
// NOTE: EmuThread
-void Shutdown()
+void MovieManager::Shutdown()
{
- s_currentInputCount = s_totalInputCount = s_totalFrames = s_tickCountAtLastInput = 0;
- s_temp_input.clear();
+ m_current_input_count = m_total_input_count = m_total_frames = m_tick_count_at_last_input = 0;
+ m_temp_input.clear();
}
} // namespace Movie
diff --git a/Source/Core/Core/Movie.h b/Source/Core/Core/Movie.h
index e0264d42ab..74b541cc2f 100644
--- a/Source/Core/Core/Movie.h
+++ b/Source/Core/Core/Movie.h
@@ -5,9 +5,11 @@
#include <array>
#include <cstring>
+#include <mutex>
#include <optional>
#include <string>
#include <string_view>
+#include <vector>
#include "Common/CommonTypes.h"
@@ -16,6 +18,11 @@ struct BootParameters;
struct GCPadStatus;
class PointerWrap;
+namespace Core
+{
+class System;
+}
+
namespace ExpansionInterface
{
enum class Slot : int;
@@ -137,68 +144,137 @@ static_assert(sizeof(DTMHeader) == 256, "DTMHeader should be 256 bytes");
#pragma pack(pop)
-void FrameUpdate();
-void InputUpdate();
-void Init(const BootParameters& boot);
-
-void SetPolledDevice();
-
-bool IsRecordingInput();
-bool IsRecordingInputFromSaveState();
-bool IsJustStartingRecordingInputFromSaveState();
-bool IsJustStartingPlayingInputFromSaveState();
-bool IsPlayingInput();
-bool IsMovieActive();
-bool IsReadOnly();
-u64 GetRecordingStartTime();
-
-u64 GetCurrentFrame();
-u64 GetTotalFrames();
-u64 GetCurrentInputCount();
-u64 GetTotalInputCount();
-u64 GetCurrentLagCount();
-u64 GetTotalLagCount();
-
-void SetClearSave(bool enabled);
-void SignalDiscChange(const std::string& new_path);
-void SetReset(bool reset);
-
-bool IsConfigSaved();
-bool IsStartingFromClearSave();
-bool IsUsingMemcard(ExpansionInterface::Slot slot);
-void SetGraphicsConfig();
-bool IsNetPlayRecording();
-
-bool IsUsingPad(int controller);
-bool IsUsingWiimote(int wiimote);
-bool IsUsingBongo(int controller);
-bool IsUsingGBA(int controller);
-void ChangePads();
-void ChangeWiiPads(bool instantly = false);
-
-void SetReadOnly(bool bEnabled);
-
-bool BeginRecordingInput(const ControllerTypeArray& controllers,
- const WiimoteEnabledArray& wiimotes);
-void RecordInput(const GCPadStatus* PadStatus, int controllerID);
-void RecordWiimote(int wiimote, const u8* data, u8 size);
-
-bool PlayInput(const std::string& movie_path, std::optional<std::string>* savestate_path);
-void LoadInput(const std::string& movie_path);
-void ReadHeader();
-void PlayController(GCPadStatus* PadStatus, int controllerID);
-bool PlayWiimote(int wiimote, WiimoteCommon::DataReportBuilder& rpt,
- WiimoteEmu::ExtensionNumber ext, const WiimoteEmu::EncryptionKey& key);
-void EndPlayInput(bool cont);
-void SaveRecording(const std::string& filename);
-void DoState(PointerWrap& p);
-void Shutdown();
-void CheckPadStatus(const GCPadStatus* PadStatus, int controllerID);
-void CheckWiimoteStatus(int wiimote, const WiimoteCommon::DataReportBuilder& rpt,
- WiimoteEmu::ExtensionNumber ext, const WiimoteEmu::EncryptionKey& key);
-
-std::string GetInputDisplay();
-std::string GetRTCDisplay();
-std::string GetRerecords();
+enum class PlayMode
+{
+ None = 0,
+ Recording,
+ Playing,
+};
+
+class MovieManager
+{
+public:
+ explicit MovieManager(Core::System& system);
+ MovieManager(const MovieManager& other) = delete;
+ MovieManager(MovieManager&& other) = delete;
+ MovieManager& operator=(const MovieManager& other) = delete;
+ MovieManager& operator=(MovieManager&& other) = delete;
+ ~MovieManager();
+
+ void FrameUpdate();
+ void InputUpdate();
+ void Init(const BootParameters& boot);
+
+ void SetPolledDevice();
+
+ bool IsRecordingInput() const;
+ bool IsRecordingInputFromSaveState() const;
+ bool IsJustStartingRecordingInputFromSaveState() const;
+ bool IsJustStartingPlayingInputFromSaveState() const;
+ bool IsPlayingInput() const;
+ bool IsMovieActive() const;
+ bool IsReadOnly() const;
+ u64 GetRecordingStartTime() const;
+
+ u64 GetCurrentFrame() const;
+ u64 GetTotalFrames() const;
+ u64 GetCurrentInputCount() const;
+ u64 GetTotalInputCount() const;
+ u64 GetCurrentLagCount() const;
+ u64 GetTotalLagCount() const;
+
+ void SetClearSave(bool enabled);
+ void SignalDiscChange(const std::string& new_path);
+ void SetReset(bool reset);
+
+ bool IsConfigSaved() const;
+ bool IsStartingFromClearSave() const;
+ bool IsUsingMemcard(ExpansionInterface::Slot slot) const;
+ void SetGraphicsConfig();
+ bool IsNetPlayRecording() const;
+
+ bool IsUsingPad(int controller) const;
+ bool IsUsingWiimote(int wiimote) const;
+ bool IsUsingBongo(int controller) const;
+ bool IsUsingGBA(int controller) const;
+ void ChangePads();
+ void ChangeWiiPads(bool instantly = false);
+
+ void SetReadOnly(bool bEnabled);
+
+ bool BeginRecordingInput(const ControllerTypeArray& controllers,
+ const WiimoteEnabledArray& wiimotes);
+ void RecordInput(const GCPadStatus* PadStatus, int controllerID);
+ void RecordWiimote(int wiimote, const u8* data, u8 size);
+
+ bool PlayInput(const std::string& movie_path, std::optional<std::string>* savestate_path);
+ void LoadInput(const std::string& movie_path);
+ void ReadHeader();
+ void PlayController(GCPadStatus* PadStatus, int controllerID);
+ bool PlayWiimote(int wiimote, WiimoteCommon::DataReportBuilder& rpt,
+ WiimoteEmu::ExtensionNumber ext, const WiimoteEmu::EncryptionKey& key);
+ void EndPlayInput(bool cont);
+ void SaveRecording(const std::string& filename);
+ void DoState(PointerWrap& p);
+ void Shutdown();
+ void CheckPadStatus(const GCPadStatus* PadStatus, int controllerID);
+ void CheckWiimoteStatus(int wiimote, const WiimoteCommon::DataReportBuilder& rpt,
+ WiimoteEmu::ExtensionNumber ext, const WiimoteEmu::EncryptionKey& key);
+
+ std::string GetInputDisplay();
+ std::string GetRTCDisplay();
+ std::string GetRerecords();
+
+private:
+ void GetSettings();
+ void CheckInputEnd();
+
+ void CheckMD5();
+ void GetMD5();
+
+ bool m_read_only = true;
+ u32 m_rerecords = 0;
+ PlayMode m_play_mode = PlayMode::None;
+
+ std::array<ControllerType, 4> m_controllers{};
+ std::array<bool, 4> m_wiimotes{};
+ ControllerState m_pad_state{};
+ DTMHeader m_temp_header{};
+ std::vector<u8> m_temp_input;
+ u64 m_current_byte = 0;
+ u64 m_current_frame = 0;
+ u64 m_total_frames = 0; // VI
+ u64 m_current_lag_count = 0;
+ u64 m_total_lag_count = 0;
+ u64 m_current_input_count = 0;
+ u64 m_total_input_count = 0;
+ u64 m_total_tick_count = 0;
+ u64 m_tick_count_at_last_input = 0;
+ u64 m_recording_start_time = 0; // seconds since 1970 that recording started
+ bool m_save_config = false;
+ bool m_net_play = false;
+ bool m_clear_save = false;
+ bool m_has_disc_change = false;
+ bool m_reset = false;
+ std::string m_author;
+ std::string m_disc_change_filename;
+ std::array<u8, 16> m_md5{};
+ u8 m_bongos = 0;
+ u8 m_memcards = 0;
+ std::array<u8, 20> m_revision{};
+ u32 m_dsp_irom_hash = 0;
+ u32 m_dsp_coef_hash = 0;
+
+ bool m_recording_from_save_state = false;
+ bool m_polled = false;
+
+ std::string m_current_file_name;
+
+ // m_input_display is used by both CPU and GPU (is mutable).
+ std::mutex m_input_display_lock;
+ std::array<std::string, 8> m_input_display;
+
+ Core::System& m_system;
+};
} // namespace Movie
diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp
index 0f6d3a38ba..c40b122a70 100644
--- a/Source/Core/Core/NetPlayClient.cpp
+++ b/Source/Core/Core/NetPlayClient.cpp
@@ -1763,8 +1763,9 @@ bool NetPlayClient::StartGame(const std::string& path)
if (m_dialog->IsRecording())
{
- if (Movie::IsReadOnly())
- Movie::SetReadOnly(false);
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (movie.IsReadOnly())
+ movie.SetReadOnly(false);
Movie::ControllerTypeArray controllers{};
Movie::WiimoteEnabledArray wiimotes{};
@@ -1778,7 +1779,7 @@ bool NetPlayClient::StartGame(const std::string& path)
controllers[i] = Movie::ControllerType::None;
wiimotes[i] = m_wiimote_map[i] > 0;
}
- Movie::BeginRecordingInput(controllers, wiimotes);
+ movie.BeginRecordingInput(controllers, wiimotes);
}
for (unsigned int i = 0; i < 4; ++i)
@@ -2114,14 +2115,15 @@ bool NetPlayClient::GetNetPads(const int pad_nb, const bool batching, GCPadStatu
m_pad_buffer[pad_nb].Pop(*pad_status);
- if (Movie::IsRecordingInput())
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (movie.IsRecordingInput())
{
- Movie::RecordInput(pad_status, pad_nb);
- Movie::InputUpdate();
+ movie.RecordInput(pad_status, pad_nb);
+ movie.InputUpdate();
}
else
{
- Movie::CheckPadStatus(pad_status, pad_nb);
+ movie.CheckPadStatus(pad_status, pad_nb);
}
return true;
diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp
index 4147136588..09334242e8 100644
--- a/Source/Core/Core/State.cpp
+++ b/Source/Core/Core/State.cpp
@@ -171,7 +171,7 @@ static void DoState(PointerWrap& p)
// Movie must be done before the video backend, because the window is redrawn in the video backend
// state load, and the frame number must be up-to-date.
- Movie::DoState(p);
+ system.GetMovie().DoState(p);
p.DoMarker("Movie");
// Begin with video backend, so that it gets a chance to clear its caches and writeback modified
@@ -443,9 +443,10 @@ static void CompressAndDumpState(CompressAndDumpState_args& save_args)
}
}
- if ((Movie::IsMovieActive()) && !Movie::IsJustStartingRecordingInputFromSaveState())
- Movie::SaveRecording(dtmname);
- else if (!Movie::IsMovieActive())
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if ((movie.IsMovieActive()) && !movie.IsJustStartingRecordingInputFromSaveState())
+ movie.SaveRecording(dtmname);
+ else if (!movie.IsMovieActive())
File::Delete(dtmname);
// Move written state to final location.
@@ -867,13 +868,14 @@ void LoadAs(const std::string& filename)
Core::RunOnCPUThread(
[&] {
// Save temp buffer for undo load state
- if (!Movie::IsJustStartingRecordingInputFromSaveState())
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (!movie.IsJustStartingRecordingInputFromSaveState())
{
std::lock_guard lk2(s_undo_load_buffer_mutex);
SaveToBuffer(s_undo_load_buffer);
const std::string dtmpath = File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm";
- if (Movie::IsMovieActive())
- Movie::SaveRecording(dtmpath);
+ if (movie.IsMovieActive())
+ movie.SaveRecording(dtmpath);
else if (File::Exists(dtmpath))
File::Delete(dtmpath);
}
@@ -904,10 +906,10 @@ void LoadAs(const std::string& filename)
Core::DisplayMessage(
fmt::format("Loaded State from {}", tempfilename.filename().string()), 2000);
if (File::Exists(filename + ".dtm"))
- Movie::LoadInput(filename + ".dtm");
- else if (!Movie::IsJustStartingRecordingInputFromSaveState() &&
- !Movie::IsJustStartingPlayingInputFromSaveState())
- Movie::EndPlayInput(false);
+ movie.LoadInput(filename + ".dtm");
+ else if (!movie.IsJustStartingRecordingInputFromSaveState() &&
+ !movie.IsJustStartingPlayingInputFromSaveState())
+ movie.EndPlayInput(false);
}
else
{
@@ -1015,13 +1017,14 @@ void UndoLoadState()
std::lock_guard lk(s_undo_load_buffer_mutex);
if (!s_undo_load_buffer.empty())
{
- if (Movie::IsMovieActive())
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (movie.IsMovieActive())
{
const std::string dtmpath = File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm";
if (File::Exists(dtmpath))
{
LoadFromBuffer(s_undo_load_buffer);
- Movie::LoadInput(dtmpath);
+ movie.LoadInput(dtmpath);
}
else
{
diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp
index fa325d909b..8dbffa3abb 100644
--- a/Source/Core/Core/System.cpp
+++ b/Source/Core/Core/System.cpp
@@ -26,6 +26,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/WII_IPC.h"
+#include "Core/Movie.h"
#include "Core/PowerPC/Interpreter/Interpreter.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
@@ -52,7 +53,7 @@ struct System::Impl
m_mmu(system, m_memory, m_power_pc), m_processor_interface(system),
m_serial_interface(system), m_system_timers(system), m_video_interface(system),
m_interpreter(system, m_power_pc.GetPPCState(), m_mmu), m_jit_interface(system),
- m_fifo_player(system), m_fifo_recorder(system)
+ m_fifo_player(system), m_fifo_recorder(system), m_movie(system)
{
}
@@ -93,6 +94,7 @@ struct System::Impl
VideoCommon::CustomAssetLoader m_custom_asset_loader;
FifoPlayer m_fifo_player;
FifoRecorder m_fifo_recorder;
+ Movie::MovieManager m_movie;
};
System::System() : m_impl{std::make_unique<Impl>(*this)}
@@ -248,6 +250,11 @@ PowerPC::MMU& System::GetMMU() const
return m_impl->m_mmu;
}
+Movie::MovieManager& System::GetMovie() const
+{
+ return m_impl->m_movie;
+}
+
PixelEngine::PixelEngineManager& System::GetPixelEngine() const
{
return m_impl->m_pixel_engine;
diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h
index c835464987..742c63bc23 100644
--- a/Source/Core/Core/System.h
+++ b/Source/Core/Core/System.h
@@ -74,6 +74,10 @@ namespace MemoryInterface
{
class MemoryInterfaceManager;
};
+namespace Movie
+{
+class MovieManager;
+}
namespace PixelEngine
{
class PixelEngineManager;
@@ -161,6 +165,7 @@ public:
Memory::MemoryManager& GetMemory() const;
MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const;
PowerPC::MMU& GetMMU() const;
+ Movie::MovieManager& GetMovie() const;
PixelEngine::PixelEngineManager& GetPixelEngine() const;
PixelShaderManager& GetPixelShaderManager() const;
PowerPC::PowerPCManager& GetPowerPC() const;
diff --git a/Source/Core/Core/WiiRoot.cpp b/Source/Core/Core/WiiRoot.cpp
index 94024d63ea..a6486d3fa5 100644
--- a/Source/Core/Core/WiiRoot.cpp
+++ b/Source/Core/Core/WiiRoot.cpp
@@ -28,6 +28,7 @@
#include "Core/Movie.h"
#include "Core/NetPlayClient.h"
#include "Core/SysConf.h"
+#include "Core/System.h"
namespace Core
{
@@ -127,24 +128,25 @@ static bool CopyNandFile(FS::FileSystem* source_fs, const std::string& source_fi
static void InitializeDeterministicWiiSaves(FS::FileSystem* session_fs,
const BootSessionData& boot_session_data)
{
+ auto& movie = Core::System::GetInstance().GetMovie();
const u64 title_id = SConfig::GetInstance().GetTitleID();
const auto configured_fs = FS::MakeFileSystem(FS::Location::Configured);
- if (Movie::IsRecordingInput())
+ if (movie.IsRecordingInput())
{
if (NetPlay::IsNetPlayRunning() && !SConfig::GetInstance().bCopyWiiSaveNetplay)
{
- Movie::SetClearSave(true);
+ movie.SetClearSave(true);
}
else
{
// TODO: Check for the actual save data
const std::string path = Common::GetTitleDataPath(title_id) + "/banner.bin";
- Movie::SetClearSave(!configured_fs->GetMetadata(IOS::PID_KERNEL, IOS::PID_KERNEL, path));
+ movie.SetClearSave(!configured_fs->GetMetadata(IOS::PID_KERNEL, IOS::PID_KERNEL, path));
}
}
if ((NetPlay::IsNetPlayRunning() && SConfig::GetInstance().bCopyWiiSaveNetplay) ||
- (Movie::IsMovieActive() && !Movie::IsStartingFromClearSave()))
+ (movie.IsMovieActive() && !movie.IsStartingFromClearSave()))
{
auto* sync_fs = boot_session_data.GetWiiSyncFS();
auto& sync_titles = boot_session_data.GetWiiSyncTitles();
@@ -154,7 +156,7 @@ static void InitializeDeterministicWiiSaves(FS::FileSystem* session_fs,
sync_fs ? "sync_fs" : "configured_fs");
// Copy the current user's save to the Blank NAND
- if (Movie::IsMovieActive() && !NetPlay::IsNetPlayRunning())
+ if (movie.IsMovieActive() && !NetPlay::IsNetPlayRunning())
{
INFO_LOG_FMT(CORE, "Wii Save Init: Copying {0:016x}.", title_id);
CopySave(source_fs, session_fs, title_id);
diff --git a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp
index 216273c23a..dfd415e912 100644
--- a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp
+++ b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp
@@ -15,6 +15,7 @@
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "Core/Movie.h"
+#include "Core/System.h"
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
@@ -197,9 +198,9 @@ void AchievementSettingsWidget::LoadSettings()
SignalBlocking(m_common_hardcore_enabled_input)
->setChecked(Config::Get(Config::RA_HARDCORE_ENABLED));
SignalBlocking(m_common_hardcore_enabled_input)
- ->setEnabled(enabled &&
- (hardcore_enabled ||
- (Core::GetState() == Core::State::Uninitialized && !Movie::IsPlayingInput())));
+ ->setEnabled(enabled && (hardcore_enabled ||
+ (Core::GetState() == Core::State::Uninitialized &&
+ !Core::System::GetInstance().GetMovie().IsPlayingInput())));
SignalBlocking(m_common_progress_enabled_input)
->setChecked(Config::Get(Config::RA_PROGRESS_ENABLED));
diff --git a/Source/Core/DolphinQt/GBAWidget.cpp b/Source/Core/DolphinQt/GBAWidget.cpp
index b355efddd3..15aef84a15 100644
--- a/Source/Core/DolphinQt/GBAWidget.cpp
+++ b/Source/Core/DolphinQt/GBAWidget.cpp
@@ -365,7 +365,7 @@ void GBAWidget::SaveSettings()
bool GBAWidget::CanControlCore()
{
- return !Movie::IsMovieActive() && !NetPlay::IsNetPlayRunning();
+ return !Core::System::GetInstance().GetMovie().IsMovieActive() && !NetPlay::IsNetPlayRunning();
}
bool GBAWidget::CanResetCore()
diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp
index 74e6198c84..b644c9df07 100644
--- a/Source/Core/DolphinQt/MainWindow.cpp
+++ b/Source/Core/DolphinQt/MainWindow.cpp
@@ -277,7 +277,7 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
if (!movie_path.empty())
{
std::optional<std::string> savestate_path;
- if (Movie::PlayInput(movie_path, &savestate_path))
+ if (Core::System::GetInstance().GetMovie().PlayInput(movie_path, &savestate_path))
{
m_pending_boot->boot_session_data.SetSavestateData(std::move(savestate_path),
DeleteSavestateAfterBoot::No);
@@ -646,8 +646,9 @@ void MainWindow::ConnectHotkeys()
connect(m_hotkey_scheduler, &HotkeyScheduler::ConnectWiiRemote, this,
&MainWindow::OnConnectWiiRemote);
connect(m_hotkey_scheduler, &HotkeyScheduler::ToggleReadOnlyMode, [this] {
- bool read_only = !Movie::IsReadOnly();
- Movie::SetReadOnly(read_only);
+ auto& movie = Core::System::GetInstance().GetMovie();
+ bool read_only = !movie.IsReadOnly();
+ movie.SetReadOnly(read_only);
emit ReadOnlyModeChanged(read_only);
});
@@ -1011,9 +1012,10 @@ void MainWindow::ForceStop()
void MainWindow::Reset()
{
- if (Movie::IsRecordingInput())
- Movie::SetReset(true);
auto& system = Core::System::GetInstance();
+ auto& movie = system.GetMovie();
+ if (movie.IsRecordingInput())
+ movie.SetReset(true);
system.GetProcessorInterface().ResetButton_Tap();
}
@@ -1853,15 +1855,16 @@ void MainWindow::OnPlayRecording()
if (dtm_file.isEmpty())
return;
- if (!Movie::IsReadOnly())
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (!movie.IsReadOnly())
{
// let's make the read-only flag consistent at the start of a movie.
- Movie::SetReadOnly(true);
+ movie.SetReadOnly(true);
emit ReadOnlyModeChanged(true);
}
std::optional<std::string> savestate_path;
- if (Movie::PlayInput(dtm_file.toStdString(), &savestate_path))
+ if (movie.PlayInput(dtm_file.toStdString(), &savestate_path))
{
emit RecordingStatusChanged(true);
@@ -1871,14 +1874,17 @@ void MainWindow::OnPlayRecording()
void MainWindow::OnStartRecording()
{
- if ((!Core::IsRunningAndStarted() && Core::IsRunning()) || Movie::IsRecordingInput() ||
- Movie::IsPlayingInput())
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if ((!Core::IsRunningAndStarted() && Core::IsRunning()) || movie.IsRecordingInput() ||
+ movie.IsPlayingInput())
+ {
return;
+ }
- if (Movie::IsReadOnly())
+ if (movie.IsReadOnly())
{
// The user just chose to record a movie, so that should take precedence
- Movie::SetReadOnly(false);
+ movie.SetReadOnly(false);
emit ReadOnlyModeChanged(true);
}
@@ -1897,7 +1903,7 @@ void MainWindow::OnStartRecording()
wiimotes[i] = Config::Get(Config::GetInfoForWiimoteSource(i)) != WiimoteSource::None;
}
- if (Movie::BeginRecordingInput(controllers, wiimotes))
+ if (movie.BeginRecordingInput(controllers, wiimotes))
{
emit RecordingStatusChanged(true);
@@ -1908,10 +1914,11 @@ void MainWindow::OnStartRecording()
void MainWindow::OnStopRecording()
{
- if (Movie::IsRecordingInput())
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (movie.IsRecordingInput())
OnExportRecording();
- if (Movie::IsMovieActive())
- Movie::EndPlayInput(false);
+ if (movie.IsMovieActive())
+ movie.EndPlayInput(false);
emit RecordingStatusChanged(false);
}
@@ -1921,7 +1928,7 @@ void MainWindow::OnExportRecording()
QString dtm_file = DolphinFileDialog::getSaveFileName(
this, tr("Save Recording File As"), QString(), tr("Dolphin TAS Movies (*.dtm)"));
if (!dtm_file.isEmpty())
- Movie::SaveRecording(dtm_file.toStdString());
+ Core::System::GetInstance().GetMovie().SaveRecording(dtm_file.toStdString());
});
}
diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp
index 1fa1a7d562..fbfc83ef46 100644
--- a/Source/Core/DolphinQt/MenuBar.cpp
+++ b/Source/Core/DolphinQt/MenuBar.cpp
@@ -146,7 +146,8 @@ void MenuBar::OnEmulationStateChanged(Core::State state)
#else // USE_RETRO_ACHIEVEMENTS
m_recording_play->setEnabled(m_game_selected && !running);
#endif // USE_RETRO_ACHIEVEMENTS
- m_recording_start->setEnabled((m_game_selected || running) && !Movie::IsPlayingInput());
+ m_recording_start->setEnabled((m_game_selected || running) &&
+ !Core::System::GetInstance().GetMovie().IsPlayingInput());
// JIT
m_jit_interpreter_core->setEnabled(running);
@@ -775,8 +776,9 @@ void MenuBar::AddMovieMenu()
m_recording_read_only = movie_menu->addAction(tr("&Read-Only Mode"));
m_recording_read_only->setCheckable(true);
- m_recording_read_only->setChecked(Movie::IsReadOnly());
- connect(m_recording_read_only, &QAction::toggled, [](bool value) { Movie::SetReadOnly(value); });
+ m_recording_read_only->setChecked(Core::System::GetInstance().GetMovie().IsReadOnly());
+ connect(m_recording_read_only, &QAction::toggled,
+ [](bool value) { Core::System::GetInstance().GetMovie().SetReadOnly(value); });
movie_menu->addAction(tr("TAS Input"), this, [this] { emit ShowTASInput(); });
@@ -1231,7 +1233,8 @@ void MenuBar::OnSelectionChanged(std::shared_ptr<const UICommon::GameFile> game_
m_game_selected = !!game_file;
m_recording_play->setEnabled(m_game_selected && !Core::IsRunning());
- m_recording_start->setEnabled((m_game_selected || Core::IsRunning()) && !Movie::IsPlayingInput());
+ m_recording_start->setEnabled((m_game_selected || Core::IsRunning()) &&
+ !Core::System::GetInstance().GetMovie().IsPlayingInput());
}
void MenuBar::OnRecordingStatusChanged(bool recording)
diff --git a/Source/Core/DolphinQt/TAS/TASCheckBox.cpp b/Source/Core/DolphinQt/TAS/TASCheckBox.cpp
index bd3865e689..3e7f998339 100644
--- a/Source/Core/DolphinQt/TAS/TASCheckBox.cpp
+++ b/Source/Core/DolphinQt/TAS/TASCheckBox.cpp
@@ -6,6 +6,7 @@
#include <QMouseEvent>
#include "Core/Movie.h"
+#include "Core/System.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/TAS/TASInputWindow.h"
@@ -23,7 +24,8 @@ bool TASCheckBox::GetValue() const
if (check_state == Qt::PartiallyChecked)
{
- const u64 frames_elapsed = Movie::GetCurrentFrame() - m_frame_turbo_started;
+ const u64 frames_elapsed =
+ Core::System::GetInstance().GetMovie().GetCurrentFrame() - m_frame_turbo_started;
return static_cast<int>(frames_elapsed % m_turbo_total_frames) < m_turbo_press_frames;
}
@@ -50,7 +52,7 @@ void TASCheckBox::mousePressEvent(QMouseEvent* event)
return;
}
- m_frame_turbo_started = Movie::GetCurrentFrame();
+ m_frame_turbo_started = Core::System::GetInstance().GetMovie().GetCurrentFrame();
m_turbo_press_frames = m_parent->GetTurboPressFrames();
m_turbo_total_frames = m_turbo_press_frames + m_parent->GetTurboReleaseFrames();
setCheckState(Qt::PartiallyChecked);
diff --git a/Source/Core/VideoCommon/OnScreenUI.cpp b/Source/Core/VideoCommon/OnScreenUI.cpp
index fdb5d49af7..dce1c2146f 100644
--- a/Source/Core/VideoCommon/OnScreenUI.cpp
+++ b/Source/Core/VideoCommon/OnScreenUI.cpp
@@ -11,6 +11,7 @@
#include "Core/Config/MainSettings.h"
#include "Core/Config/NetplaySettings.h"
#include "Core/Movie.h"
+#include "Core/System.h"
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/AbstractPipeline.h"
@@ -284,26 +285,27 @@ void OnScreenUI::DrawDebugText()
ImGui::GetIO().DisplaySize);
if (ImGui::Begin("Movie", nullptr, ImGuiWindowFlags_NoFocusOnAppearing))
{
- if (Movie::IsPlayingInput())
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (movie.IsPlayingInput())
{
- ImGui::Text("Frame: %" PRIu64 " / %" PRIu64, Movie::GetCurrentFrame(),
- Movie::GetTotalFrames());
- ImGui::Text("Input: %" PRIu64 " / %" PRIu64, Movie::GetCurrentInputCount(),
- Movie::GetTotalInputCount());
+ ImGui::Text("Frame: %" PRIu64 " / %" PRIu64, movie.GetCurrentFrame(),
+ movie.GetTotalFrames());
+ ImGui::Text("Input: %" PRIu64 " / %" PRIu64, movie.GetCurrentInputCount(),
+ movie.GetTotalInputCount());
}
else if (Config::Get(Config::MAIN_SHOW_FRAME_COUNT))
{
- ImGui::Text("Frame: %" PRIu64, Movie::GetCurrentFrame());
- ImGui::Text("Input: %" PRIu64, Movie::GetCurrentInputCount());
+ ImGui::Text("Frame: %" PRIu64, movie.GetCurrentFrame());
+ ImGui::Text("Input: %" PRIu64, movie.GetCurrentInputCount());
}
if (Config::Get(Config::MAIN_SHOW_LAG))
- ImGui::Text("Lag: %" PRIu64 "\n", Movie::GetCurrentLagCount());
+ ImGui::Text("Lag: %" PRIu64 "\n", movie.GetCurrentLagCount());
if (Config::Get(Config::MAIN_MOVIE_SHOW_INPUT_DISPLAY))
- ImGui::TextUnformatted(Movie::GetInputDisplay().c_str());
+ ImGui::TextUnformatted(movie.GetInputDisplay().c_str());
if (Config::Get(Config::MAIN_MOVIE_SHOW_RTC))
- ImGui::TextUnformatted(Movie::GetRTCDisplay().c_str());
+ ImGui::TextUnformatted(movie.GetRTCDisplay().c_str());
if (Config::Get(Config::MAIN_MOVIE_SHOW_RERECORD))
- ImGui::TextUnformatted(Movie::GetRerecords().c_str());
+ ImGui::TextUnformatted(movie.GetRerecords().c_str());
}
ImGui::End();
}
diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp
index daba4be9e1..51ab90fb7e 100644
--- a/Source/Core/VideoCommon/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/VideoConfig.cpp
@@ -47,8 +47,9 @@ static bool IsVSyncActive(bool enabled)
void UpdateActiveConfig()
{
- if (Movie::IsPlayingInput() && Movie::IsConfigSaved())
- Movie::SetGraphicsConfig();
+ auto& movie = Core::System::GetInstance().GetMovie();
+ if (movie.IsPlayingInput() && movie.IsConfigSaved())
+ movie.SetGraphicsConfig();
g_ActiveConfig = g_Config;
g_ActiveConfig.bVSyncActive = IsVSyncActive(g_ActiveConfig.bVSync);
}