Merge pull request #12502 from AdmiralCurtiss/globals-movie

Core/Movie: Refactor to class, move to System.
This commit is contained in:
Mai 2024-01-15 15:12:00 -05:00 committed by GitHub
commit e3d39fcc0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 717 additions and 609 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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(

View File

@ -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 &&

View File

@ -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

View File

@ -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();

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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()

View File

@ -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());

View File

@ -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, "/");
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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);
enum class PlayMode
{
None = 0,
Recording,
Playing,
};
void SetPolledDevice();
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();
bool IsRecordingInput();
bool IsRecordingInputFromSaveState();
bool IsJustStartingRecordingInputFromSaveState();
bool IsJustStartingPlayingInputFromSaveState();
bool IsPlayingInput();
bool IsMovieActive();
bool IsReadOnly();
u64 GetRecordingStartTime();
void FrameUpdate();
void InputUpdate();
void Init(const BootParameters& boot);
u64 GetCurrentFrame();
u64 GetTotalFrames();
u64 GetCurrentInputCount();
u64 GetTotalInputCount();
u64 GetCurrentLagCount();
u64 GetTotalLagCount();
void SetPolledDevice();
void SetClearSave(bool enabled);
void SignalDiscChange(const std::string& new_path);
void SetReset(bool reset);
bool IsRecordingInput() const;
bool IsRecordingInputFromSaveState() const;
bool IsJustStartingRecordingInputFromSaveState() const;
bool IsJustStartingPlayingInputFromSaveState() const;
bool IsPlayingInput() const;
bool IsMovieActive() const;
bool IsReadOnly() const;
u64 GetRecordingStartTime() const;
bool IsConfigSaved();
bool IsStartingFromClearSave();
bool IsUsingMemcard(ExpansionInterface::Slot slot);
void SetGraphicsConfig();
bool IsNetPlayRecording();
u64 GetCurrentFrame() const;
u64 GetTotalFrames() const;
u64 GetCurrentInputCount() const;
u64 GetTotalInputCount() const;
u64 GetCurrentLagCount() const;
u64 GetTotalLagCount() const;
bool IsUsingPad(int controller);
bool IsUsingWiimote(int wiimote);
bool IsUsingBongo(int controller);
bool IsUsingGBA(int controller);
void ChangePads();
void ChangeWiiPads(bool instantly = false);
void SetClearSave(bool enabled);
void SignalDiscChange(const std::string& new_path);
void SetReset(bool reset);
void SetReadOnly(bool bEnabled);
bool IsConfigSaved() const;
bool IsStartingFromClearSave() const;
bool IsUsingMemcard(ExpansionInterface::Slot slot) const;
void SetGraphicsConfig();
bool IsNetPlayRecording() const;
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 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);
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);
void SetReadOnly(bool bEnabled);
std::string GetInputDisplay();
std::string GetRTCDisplay();
std::string GetRerecords();
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

View File

@ -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;

View File

@ -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
{

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -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()

View File

@ -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());
});
}

View File

@ -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)

View File

@ -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);

View File

@ -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();
}

View File

@ -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);
}