Remove Movie (TAS input recording/playback)

Nothing in the core starts a recording or a playback, so a movie is
never active. Each call site keeps its no-movie path: no determinism
toggle, the real clock for the RTC, the configured memory cards, no
pad/Wiimote input mirroring into display strings on every poll. The
state keeps the movie counters' bytes, written as zeroes, so existing
savestates still load.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-11-07 15:12:31 +01:00
1 parent 5e7772c97e
commit 73c3c0baee
29 files changed
+31 -2257

No files matched your search

-2
View File
@@ -1299,7 +1299,6 @@ DOLPHIN_SOURCES_CXX += \
$(CORE_DIR)/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp \
$(CORE_DIR)/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp \
$(CORE_DIR)/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp \
$(CORE_DIR)/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp \
$(CORE_DIR)/Source/Core/Core/ConfigManager.cpp \
$(CORE_DIR)/Source/Core/Core/Core.cpp \
$(CORE_DIR)/Source/Core/Core/CoreTiming.cpp \
@@ -1522,7 +1521,6 @@ DOLPHIN_SOURCES_CXX += \
$(CORE_DIR)/Source/Core/Core/IOS/WFS/WFSSRV.cpp \
$(CORE_DIR)/Source/Core/Core/LibusbUtils.cpp \
$(CORE_DIR)/Source/Core/Core/MemTools.cpp \
$(CORE_DIR)/Source/Core/Core/Movie.cpp \
$(CORE_DIR)/Source/Core/Core/NetworkCaptureLogger.cpp \
$(CORE_DIR)/Source/Core/Core/PatchEngine.cpp \
$(CORE_DIR)/Source/Core/Core/PowerPC/BreakPoints.cpp \
-22
View File
@@ -38,7 +38,6 @@
#include "Core/HW/SI/SI.h"
#include "Core/HW/SI/SI_Device.h"
#include "Core/HW/Sram.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "Core/WiiRoot.h"
@@ -58,27 +57,6 @@ bool BootCore(Core::System& system, std::unique_ptr<BootParameters> boot,
if (!StartUp.SetPathsAndGameMetadata(system, *boot))
return false;
// Movie settings
auto& movie = system.GetMovie();
if (movie.IsPlayingInput() && movie.IsConfigSaved())
{
for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS)
{
if (movie.IsUsingMemcard(slot) && movie.IsStartingFromClearSave() && !system.IsWii())
{
const auto raw_path =
File::GetUserPath(D_GCUSER_IDX) +
fmt::format("Movie{}.raw", slot == ExpansionInterface::Slot::A ? 'A' : 'B');
if (File::Exists(raw_path))
File::Delete(raw_path);
const auto movie_path = File::GetUserPath(D_GCUSER_IDX) + "Movie";
if (File::Exists(movie_path))
File::DeleteDirRecursively(movie_path);
}
}
}
// Override out-of-region languages/countries to prevent games from crashing or behaving oddly
if (!Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS))
{
@@ -1,166 +0,0 @@
// Copyright 2016 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Core/ConfigLoaders/MovieConfigLoader.h"
#include <cstring>
#include <memory>
#include <string>
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/SYSCONFSettings.h"
#include "Core/Config/SessionSettings.h"
#include "Core/Config/WiimoteSettings.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/SI/SI_Device.h"
#include "Core/HW/Wiimote.h"
#include "Core/Movie.h"
namespace PowerPC
{
enum class CPUCore;
}
namespace ConfigLoaders
{
static void LoadFromDTM(Config::Layer* config_layer, Movie::DTMHeader* dtm)
{
config_layer->Set(Config::MAIN_CPU_THREAD, dtm->bDualCore);
config_layer->Set(Config::MAIN_DSP_HLE, dtm->bDSPHLE);
config_layer->Set(Config::MAIN_FAST_DISC_SPEED, dtm->bFastDiscSpeed);
config_layer->Set(Config::MAIN_CPU_CORE, static_cast<PowerPC::CPUCore>(dtm->CPUCore));
config_layer->Set(Config::MAIN_SYNC_GPU, dtm->bSyncGPU);
config_layer->Set(Config::MAIN_GFX_BACKEND, dtm->videoBackend.data());
config_layer->Set(Config::SYSCONF_PROGRESSIVE_SCAN, dtm->bProgressive);
config_layer->Set(Config::SYSCONF_PAL60, dtm->bPAL60);
if (dtm->bWii)
config_layer->Set(Config::SYSCONF_LANGUAGE, static_cast<u32>(dtm->language));
else
config_layer->Set(Config::MAIN_GC_LANGUAGE, static_cast<int>(dtm->language));
config_layer->Set(Config::SYSCONF_WIDESCREEN, dtm->bWidescreen);
config_layer->Set(Config::SYSCONF_COUNTRY, dtm->countryCode);
config_layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, dtm->bEFBAccessEnable);
config_layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, dtm->bSkipEFBCopyToRam);
config_layer->Set(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, dtm->bEFBEmulateFormatChanges);
config_layer->Set(Config::GFX_HACK_IMMEDIATE_XFB, dtm->bImmediateXFB);
config_layer->Set(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, dtm->bSkipXFBCopyToRam);
config_layer->Set(Config::SESSION_USE_FMA, dtm->bUseFMA);
config_layer->Set(Config::MAIN_JIT_FOLLOW_BRANCH, dtm->bFollowBranch);
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
{
SerialInterface::SIDevices device = SerialInterface::SIDEVICE_NONE;
const auto config_info = Config::GetInfoForSIDevice(i);
if (dtm->GBAControllers & (1 << i))
{
device = SerialInterface::SIDEVICE_GC_GBA_EMULATED;
}
else if (dtm->controllers & (1 << i))
{
const SerialInterface::SIDevices si_device = Config::Get(config_info);
if (SerialInterface::SIDevice_IsGCController(si_device))
{
device = si_device;
}
else
{
device = (dtm->bongos & (1 << i)) != 0 ? SerialInterface::SIDEVICE_GC_TARUKONGA :
SerialInterface::SIDEVICE_GC_CONTROLLER;
}
}
config_layer->Set(config_info, device);
}
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
const bool is_using_wiimote = (dtm->controllers & (1 << (i + 4))) != 0;
config_layer->Set(Config::GetInfoForWiimoteSource(i),
is_using_wiimote ? WiimoteSource::Emulated : WiimoteSource::None);
}
}
void SaveToDTM(Movie::DTMHeader* dtm)
{
dtm->bDualCore = Config::Get(Config::MAIN_CPU_THREAD);
dtm->bDSPHLE = Config::Get(Config::MAIN_DSP_HLE);
dtm->bFastDiscSpeed = Config::Get(Config::MAIN_FAST_DISC_SPEED);
dtm->CPUCore = static_cast<u8>(Config::Get(Config::MAIN_CPU_CORE));
dtm->bSyncGPU = Config::Get(Config::MAIN_SYNC_GPU);
const std::string video_backend = Config::Get(Config::MAIN_GFX_BACKEND);
dtm->bProgressive = Config::Get(Config::SYSCONF_PROGRESSIVE_SCAN);
dtm->bPAL60 = Config::Get(Config::SYSCONF_PAL60);
if (dtm->bWii)
dtm->language = Config::Get(Config::SYSCONF_LANGUAGE);
else
dtm->language = Config::Get(Config::MAIN_GC_LANGUAGE);
dtm->bWidescreen = Config::Get(Config::SYSCONF_WIDESCREEN);
dtm->countryCode = Config::Get(Config::SYSCONF_COUNTRY);
dtm->bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
dtm->bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
dtm->bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
dtm->bImmediateXFB = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB);
dtm->bSkipXFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
dtm->bUseFMA = Config::Get(Config::SESSION_USE_FMA);
dtm->bFollowBranch = Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH);
dtm->controllers = 0;
dtm->bongos = 0;
dtm->GBAControllers = 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_NONE)
dtm->controllers |= 1 << i;
if (si_device == SerialInterface::SIDEVICE_GC_GBA_EMULATED)
dtm->GBAControllers |= 1 << i;
else if (si_device == SerialInterface::SIDEVICE_GC_TARUKONGA)
dtm->bongos |= 1 << i;
}
if (dtm->bWii)
{
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
if (Config::Get(Config::GetInfoForWiimoteSource(i)) != WiimoteSource::None)
dtm->controllers |= 1 << (i + 4);
}
}
// Settings which only existed in old Dolphin versions
dtm->bSkipIdle = true;
dtm->bEFBCopyEnable = true;
dtm->bEFBCopyCacheEnable = false;
strncpy(dtm->videoBackend.data(), video_backend.c_str(), dtm->videoBackend.size());
}
// TODO: Future project, let this support all the configuration options.
// This will require a large break to the DTM format
void MovieConfigLayerLoader::Load(Config::Layer* config_layer)
{
LoadFromDTM(config_layer, m_header);
}
void MovieConfigLayerLoader::Save(Config::Layer* config_layer)
{
}
// Loader generation
std::unique_ptr<Config::ConfigLayerLoader> GenerateMovieConfigLoader(Movie::DTMHeader* header)
{
return std::make_unique<MovieConfigLayerLoader>(header);
}
} // namespace ConfigLoaders
@@ -1,34 +0,0 @@
// Copyright 2016 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "Common/Config/Config.h"
namespace Movie
{
struct DTMHeader;
}
namespace ConfigLoaders
{
class MovieConfigLayerLoader final : public Config::ConfigLayerLoader
{
public:
explicit MovieConfigLayerLoader(Movie::DTMHeader* header)
: ConfigLayerLoader(Config::LayerType::Movie), m_header(header)
{
}
void Load(Config::Layer* config_layer) override;
void Save(Config::Layer* config_layer) override;
private:
Movie::DTMHeader* m_header;
};
void SaveToDTM(Movie::DTMHeader* header);
std::unique_ptr<Config::ConfigLayerLoader> GenerateMovieConfigLoader(Movie::DTMHeader* header);
} // namespace ConfigLoaders
+2 -8
View File
@@ -61,7 +61,6 @@
#include "Core/Host.h"
#include "Core/IOS/IOS.h"
#include "Core/MemTools.h"
#include "Core/Movie.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/GDBStub.h"
#include "Core/PowerPC/JitInterface.h"
@@ -510,9 +509,6 @@ void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot,
FreeLook::LoadInputConfig();
system.GetMovie().Init(*boot);
Common::ScopeGuard movie_guard([&system] { system.GetMovie().Shutdown(); });
HW::Init(system, nullptr);
Common::ScopeGuard hw_guard{[&system] {
@@ -611,9 +607,6 @@ void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot,
s_emu_thread_scope_guards.emplace_back(Common::MoveOnlyFunction<void()>(
[g = std::move(flag_guard)]() mutable { g.Exit(); }));
s_emu_thread_scope_guards.emplace_back(Common::MoveOnlyFunction<void()>(
[g = std::move(movie_guard)]() mutable { g.Exit(); }));
s_emu_thread_scope_guards.emplace_back(Common::MoveOnlyFunction<void()>(
[g = std::move(hw_guard)]() mutable { g.Exit(); }));
@@ -921,7 +914,8 @@ void UpdateWantDeterminism(Core::System& system, 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 = system.GetMovie().IsMovieActive();
// Only a movie wanted determinism, and none is ever recorded or played.
const bool new_want_determinism = false;
if (new_want_determinism != s_wants_determinism || initial)
{
NOTICE_LOG_FMT(COMMON, "Want determinism <- {}", new_want_determinism ? "true" : "false");
-1
View File
@@ -27,7 +27,6 @@
#include "Core/HW/EXI/EXI_DeviceBaseboard.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "DiscIO/CachedBlob.h"
+1 -3
View File
@@ -36,7 +36,6 @@
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/DI/DI.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "DiscIO/Blob.h"
@@ -499,7 +498,6 @@ void DVDInterface::ChangeDisc(const Core::CPUThreadGuard& guard, const std::stri
m_disc_path_to_insert = new_path;
m_system.GetCoreTiming().ScheduleEvent(m_system.GetSystemTimers().GetTicksPerSecond(),
m_insert_disc);
m_system.GetMovie().SignalDiscChange(new_path);
for (size_t i = 0; i < m_auto_disc_change_paths.size(); ++i)
{
@@ -1125,7 +1123,7 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
const bool force_eject = eject && !kill;
if (Config::Get(Config::MAIN_AUTO_DISC_CHANGE) && !m_system.GetMovie().IsPlayingInput() &&
if (Config::Get(Config::MAIN_AUTO_DISC_CHANGE) &&
m_system.GetDVDThread().IsInsertedDiscRunning() && !m_auto_disc_change_paths.empty())
{
m_system.GetCoreTiming().ScheduleEvent(
+1 -28
View File
@@ -20,7 +20,6 @@
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/Sram.h"
#include "Core/HW/SystemTimers.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "DiscIO/Enums.h"
@@ -35,33 +34,7 @@ ExpansionInterfaceManager::~ExpansionInterfaceManager() = default;
void ExpansionInterfaceManager::AddMemoryCard(Slot slot)
{
EXIDeviceType memorycard_device;
auto& movie = m_system.GetMovie();
if (movie.IsPlayingInput() && movie.IsConfigSaved())
{
if (movie.IsUsingMemcard(slot))
{
memorycard_device = Config::Get(Config::GetInfoForEXIDevice(slot));
if (memorycard_device != EXIDeviceType::MemoryCardFolder &&
memorycard_device != EXIDeviceType::MemoryCard)
{
PanicAlertFmtT(
"The movie indicates that a memory card should be inserted into {0:n}, but one is not "
"currently inserted (instead, {1} is inserted). For the movie to sync properly, "
"please change the selected device to Memory Card or GCI Folder.",
slot, Common::GetStringT(fmt::format("{:n}", memorycard_device).c_str()));
}
}
else
{
memorycard_device = EXIDeviceType::None;
}
}
else
{
memorycard_device = Config::Get(Config::GetInfoForEXIDevice(slot));
}
const EXIDeviceType memorycard_device = Config::Get(Config::GetInfoForEXIDevice(slot));
m_channels[SlotToEXIChannel(slot)]->AddDevice(memorycard_device, SlotToEXIDevice(slot));
}
+1 -3
View File
@@ -14,7 +14,6 @@
#include "Core/HW/EXI/EXI.h"
#include "Core/HW/EXI/EXI_Device.h"
#include "Core/HW/MMIO.h"
#include "Core/Movie.h"
#include "Core/System.h"
namespace ExpansionInterface
@@ -263,8 +262,7 @@ void CEXIChannel::DoState(PointerWrap& p)
AddDevice(std::move(save_device), device_index, false);
}
if (type == EXIDeviceType::MemoryCardFolder && old_header_data != m_memcard_header_data &&
!m_system.GetMovie().IsMovieActive())
if (type == EXIDeviceType::MemoryCardFolder && old_header_data != m_memcard_header_data)
{
// 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
+2 -17
View File
@@ -25,7 +25,6 @@
#include "Core/CoreTiming.h"
#include "Core/HW/Sram.h"
#include "Core/HW/SystemTimers.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "DiscIO/Enums.h"
@@ -399,22 +398,8 @@ void CEXIIPL::TransferByte(u8& data)
u32 CEXIIPL::GetEmulatedTime(Core::System& system, u32 epoch)
{
u64 ltime = 0;
auto& movie = system.GetMovie();
if (movie.IsMovieActive())
{
ltime = movie.GetRecordingStartTime();
// let's keep time moving forward, regardless of what it starts at
ltime += system.GetCoreTiming().GetTicks() / system.GetSystemTimers().GetTicksPerSecond();
}
else
{
ASSERT(!Core::WantsDeterminism());
ltime = Common::Timer::GetLocalTimeSinceJan1970() -
system.GetSystemTimers().GetLocalTimeRTCOffset();
}
const u64 ltime = Common::Timer::GetLocalTimeSinceJan1970() -
system.GetSystemTimers().GetLocalTimeRTCOffset();
return static_cast<u32>(ltime) - epoch;
}
@@ -32,7 +32,6 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/Sram.h"
#include "Core/HW/SystemTimers.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "DiscIO/Enums.h"
@@ -148,26 +147,14 @@ 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,
Movie::MovieManager& movie)
CEXIMemoryCard::GetGCIFolderPath(Slot card_slot)
{
std::string path_override = Config::Get(Config::GetInfoForGCIPathOverride(card_slot));
if (!path_override.empty())
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();
const DiscIO::Region region = Config::ToGameCubeRegion(SConfig::GetInstance().m_region);
if (use_movie_folder)
{
return {fmt::format("{}{}/Movie/Card {}", File::GetUserPath(D_GCUSER_IDX),
Config::GetDirectoryForRegion(region), s_card_short_names[card_slot]),
false};
}
return {Config::GetGCIFolderPath(card_slot, region), true};
}
@@ -182,7 +169,7 @@ void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data)
}
const auto [dir_path, migrate] =
GetGCIFolderPath(m_card_slot, AllowMovieFolder::Yes, m_system.GetMovie());
GetGCIFolderPath(m_card_slot);
const File::FileInfo file_info(dir_path);
if (!file_info.Exists())
@@ -218,18 +205,8 @@ void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data)
void CEXIMemoryCard::SetupRawMemcard(u16 size_mb)
{
std::string filename;
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]);
}
else
{
filename = Config::GetMemcardPath(m_card_slot, SConfig::GetInstance().m_region, size_mb);
}
const std::string filename =
Config::GetMemcardPath(m_card_slot, SConfig::GetInstance().m_region, size_mb);
m_memory_card = std::make_unique<MemoryCard>(filename, m_card_slot, size_mb);
}
@@ -501,11 +478,9 @@ void CEXIMemoryCard::TransferByte(u8& byte)
void CEXIMemoryCard::DoState(PointerWrap& p)
{
// for movie sync, we need to save/load memory card contents (and other data) in savestates.
// 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 = m_system.GetMovie().IsMovieActive();
// Card contents are kept out of states (only movie sync stored them); a loaded state that
// has them still decides, to stay aligned with it.
bool storeContents = false;
p.Do(storeContents);
if (storeContents)
+1 -12
View File
@@ -26,21 +26,11 @@ namespace Memcard
{
struct HeaderData;
}
namespace Movie
{
class MovieManager;
}
namespace ExpansionInterface
{
enum class Slot : int;
enum class AllowMovieFolder
{
Yes,
No,
};
class CEXIMemoryCard : public IEXIDevice
{
public:
@@ -61,8 +51,7 @@ public:
static void Init(CoreTiming::CoreTimingManager& core_timing);
static void Shutdown();
static std::pair<std::string /* path */, bool /* migrate */>
GetGCIFolderPath(Slot card_slot, AllowMovieFolder allow_movie_folder, Movie::MovieManager& movie);
static std::pair<std::string /* path */, bool /* migrate */> GetGCIFolderPath(Slot card_slot);
private:
void SetupGciFolder(const Memcard::HeaderData& header_data);
-1
View File
@@ -25,7 +25,6 @@
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SI/SI_DeviceGBA.h"
#include "Core/HW/SystemTimers.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
@@ -30,7 +30,6 @@
#include "Core/HW/Triforce/JVSIO.h"
#include "Core/HW/Triforce/MarioKartGP.h"
#include "Core/HW/Triforce/Touchscreen.h"
#include "Core/Movie.h"
#include "Core/System.h"
namespace
@@ -122,8 +122,6 @@ int CSIDevice_GBAEmu::TransferInterval()
DataResponse CSIDevice_GBAEmu::GetData(u32& hi, u32& low)
{
GCPadStatus pad_status = Pad::GetGBAStatus(m_device_number);
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
@@ -29,8 +29,6 @@ GCPadStatus CSIDevice_GCAdapter::GetPadStatus()
{
GCPadStatus pad_status = GCAdapter::Input(m_device_number);
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.
if (pad_status.button & PAD_GET_ORIGIN)
@@ -14,7 +14,6 @@
#include "Core/HW/SI/SI.h"
#include "Core/HW/SI/SI_Device.h"
#include "Core/HW/SystemTimers.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "InputCommon/GCPadStatus.h"
@@ -114,32 +113,10 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int request_length)
return 0;
}
void CSIDevice_GCController::HandleMoviePadStatus(Movie::MovieManager& movie, int device_number,
GCPadStatus* pad_status)
{
movie.SetPolledDevice();
if (movie.IsPlayingInput())
{
movie.PlayController(pad_status, device_number);
movie.InputUpdate();
}
else if (movie.IsRecordingInput())
{
movie.RecordInput(pad_status, device_number);
movie.InputUpdate();
}
else
{
movie.CheckPadStatus(pad_status, device_number);
}
}
GCPadStatus CSIDevice_GCController::GetPadStatus()
{
GCPadStatus pad_status = Pad::GetStatus(m_device_number);
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.
if (pad_status.button & PAD_GET_ORIGIN)
@@ -9,10 +9,6 @@
#include "Core/HW/SI/SI_Device.h"
#include "InputCommon/GCPadStatus.h"
namespace Movie
{
class MovieManager;
}
namespace SerialInterface
{
@@ -80,9 +76,6 @@ public:
// Direct rumble to the right GC Controller
static void Rumble(int pad_num, ControlState strength, SIDevices device);
static void HandleMoviePadStatus(Movie::MovieManager& movie, int device_number,
GCPadStatus* pad_status);
protected:
void SetOrigin(const GCPadStatus& pad_status);
};
-7
View File
@@ -26,7 +26,6 @@
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/SystemTimers.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "DiscIO/Enums.h"
@@ -898,12 +897,6 @@ void VideoInterfaceManager::Update(u64 ticks)
const bool is_at_field_boundary =
m_half_line_count == odd_field_begin || m_half_line_count == even_field_begin;
// Movie's frame counter should be updated before actually rendering the frame,
// in case frame counter display is enabled
if (is_at_field_boundary)
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
// the number of frames we've actually drawn
-6
View File
@@ -19,7 +19,6 @@
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "Core/WiiUtils.h"
@@ -194,11 +193,6 @@ void Initialize(InitializeMode init_mode)
WiimoteCommon::RefreshConfig();
WiimoteReal::Initialize(init_mode);
// Reload Wiimotes with our settings
auto& movie = Core::System::GetInstance().GetMovie();
if (movie.IsMovieActive())
movie.ChangeWiiPads();
}
void ResetAllWiimotes()
+2 -4
View File
@@ -23,7 +23,6 @@
#include "Common/Swap.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "Core/WiiRoot.h"
@@ -322,9 +321,8 @@ 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)
auto& movie = Core::System::GetInstance().GetMovie();
const bool is_full_nand_wanted = movie.IsMovieActive() && Core::WiiRootIsTemporary();
// No movie is ever recorded, so the full NAND is never wanted.
const bool is_full_nand_wanted = false;
bool is_full_nand_in_state = is_full_nand_wanted;
p.Do(is_full_nand_in_state);
@@ -20,7 +20,6 @@
#include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/SysConf.h"
#include "Core/System.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
@@ -349,16 +348,6 @@ void BluetoothEmuDevice::Update()
for (size_t i = 0; i < m_wiimotes.size(); ++i)
next_call[i] = m_wiimotes[i]->PrepareInput(&wiimote_states[i]);
auto& movie = Core::System::GetInstance().GetMovie();
for (int i = 0; i != MAX_WIIMOTES; ++i)
{
if (next_call[i] == WiimoteDevice::NextUpdateInputCall::None)
continue;
movie.PlayWiimote(i, &wiimote_states[i]);
movie.CheckWiimoteStatus(i, wiimote_states[i]);
}
for (size_t i = 0; i < m_wiimotes.size(); ++i)
m_wiimotes[i]->UpdateInput(next_call[i], wiimote_states[i]);
File diff suppressed because it is too large. Load diff
-289
View File
@@ -1,289 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include <retro_atomic.h>
#include "Common/Quiesce.h"
#include "Common/CommonTypes.h"
#include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
struct BootParameters;
struct GCPadStatus;
class PointerWrap;
namespace Core
{
class System;
}
namespace ExpansionInterface
{
enum class Slot : int;
}
namespace WiimoteCommon
{
class DataReportBuilder;
}
namespace WiimoteEmu
{
class EncryptionKey;
enum ExtensionNumber : u8;
} // namespace WiimoteEmu
// Per-(video )Movie actions
namespace Movie
{
// Enumerations and structs
enum class ControllerType
{
None = 0,
GC,
GBA,
};
using ControllerTypeArray = std::array<ControllerType, 4>;
using WiimoteEnabledArray = std::array<bool, 4>;
// GameCube Controller State
#pragma pack(push, 1)
struct ControllerState
{
bool Start : 1, A : 1, B : 1, X : 1, Y : 1, Z : 1; // Binary buttons, 6 bits
bool DPadUp : 1, DPadDown : 1, // Binary D-Pad buttons, 4 bits
DPadLeft : 1, DPadRight : 1;
bool L : 1, R : 1; // Binary triggers, 2 bits
bool disc : 1; // Checks for disc being changed
bool reset : 1; // Console reset button
bool is_connected : 1; // Should controller be treated as connected
bool get_origin : 1; // Special bit to indicate analog origin reset
u8 TriggerL, TriggerR; // Triggers, 16 bits
u8 AnalogStickX, AnalogStickY; // Main Stick, 16 bits
u8 CStickX, CStickY; // Sub-Stick, 16 bits
};
static_assert(sizeof(ControllerState) == 8, "ControllerState should be 8 bytes");
#pragma pack(pop)
// When making changes to the DTM format, keep in mind that there are programs other
// than Dolphin that parse DTM files. The format is expected to be relatively stable.
#pragma pack(push, 1)
struct DTMHeader
{
std::string_view GetGameID() const
{
return {gameID.data(), strnlen(gameID.data(), gameID.size())};
}
std::array<u8, 4> filetype; // Unique Identifier (always "DTM"0x1A)
std::array<char, 6> gameID; // The Game ID
bool bWii; // Wii game
u8 controllers; // Controllers plugged in (from least to most significant,
// the bits are GC controllers 1-4 and Wiimotes 1-4)
bool
bFromSaveState; // false indicates that the recording started from bootup, true for savestate
u64 frameCount; // Number of frames in the recording
u64 inputCount; // Number of input frames in recording
u64 lagCount; // Number of lag frames in the recording
u64 uniqueID; // (not implemented) A Unique ID comprised of: md5(time + Game ID)
u32 numRerecords; // Number of rerecords/'cuts' of this TAS
std::array<char, 32> author; // Author's name (encoded in UTF-8)
std::array<char, 16> videoBackend; // UTF-8 representation of the video backend
std::array<char, 16> audioEmulator; // UTF-8 representation of the audio emulator
std::array<u8, 16> md5; // MD5 of game iso
u64 recordingStartTime; // seconds since 1970 that recording started (used for RTC)
bool bSaveConfig; // Loads the settings below on startup if true
bool bSkipIdle;
bool bDualCore;
bool bProgressive;
bool bDSPHLE;
bool bFastDiscSpeed;
u8 CPUCore; // Uses the values of PowerPC::CPUCore
bool bEFBAccessEnable;
bool bEFBCopyEnable;
bool bSkipEFBCopyToRam;
bool bEFBCopyCacheEnable;
bool bEFBEmulateFormatChanges;
bool bImmediateXFB;
bool bSkipXFBCopyToRam;
u8 memcards; // Memcards inserted (from least to most significant, the bits are slot A and B)
bool bClearSave; // Create a new memory card when playing back a movie if true
u8 bongos; // Bongos plugged in (from least to most significant, the bits are ports 1-4)
bool bSyncGPU;
bool bNetPlay;
bool bPAL60;
u8 language;
u8 reserved3;
bool bFollowBranch;
bool bUseFMA;
u8 GBAControllers; // GBA Controllers plugged in (the bits are ports 1-4)
bool bWidescreen; // true indicates SYSCONF aspect ratio is 16:9, false for 4:3
u8 countryCode; // SYSCONF country code
std::array<u8, 5> reserved; // Padding for any new config options
std::array<char, 40> discChange; // Name of iso file to switch to, for two disc games.
std::array<u8, 20> revision; // Git hash
u32 DSPiromHash;
u32 DSPcoefHash;
u64 tickCount; // Number of ticks in the recording
std::array<u8, 11> reserved2; // Make heading 256 bytes, just because we can
};
static_assert(sizeof(DTMHeader) == 256, "DTMHeader should be 256 bytes");
#pragma pack(pop)
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;
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();
void SetReadOnly(bool bEnabled);
bool BeginRecordingInput(const ControllerTypeArray& controllers,
const WiimoteEnabledArray& wiimotes);
void RecordInput(const GCPadStatus* PadStatus, int controllerID);
void RecordWiimote(int wiimote, const WiimoteEmu::SerializedWiimoteState& serialized_state);
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, WiimoteEmu::DesiredWiimoteState* desired_state);
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 WiimoteEmu::DesiredWiimoteState& desired_state);
std::string GetInputDisplay();
std::string GetRTCDisplay() const;
std::string GetRerecords() const;
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).
// One string per pad and Wii remote, written by the CPU thread and shown by the GPU thread:
// each is published whole and freed through m_input_display_quiesce.
struct DisplayString
{
quiesce_node_t node; // first: the free callback casts it back
std::string text;
};
static void FreeDisplayString(quiesce_node_t* node);
void SetInputDisplay(int index, std::string text);
std::array<retro_atomic_ptr_t, 8> m_input_display{};
mutable quiesce_t m_input_display_quiesce{};
Core::System& m_system;
};
} // namespace Movie
+13 -42
View File
@@ -40,7 +40,6 @@
#include "Core/HW/HW.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/Wiimote.h"
#include "Core/Movie.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
@@ -210,9 +209,16 @@ void DoState(Core::System& system, PointerWrap& p)
return;
}
// 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.
system.GetMovie().DoState(p);
// The movie counters, kept for the state layout: no movie is ever recorded or played.
{
u64 movie_counters[4] = {};
bool movie_polled = false;
u64 movie_tick_count_at_last_input = 0;
for (u64& counter : movie_counters)
p.Do(counter);
p.Do(movie_polled);
p.Do(movie_tick_count_at_last_input);
}
p.DoMarker("Movie");
// Begin with video backend, so that it gets a chance to clear its caches and writeback modified
@@ -482,11 +488,7 @@ static void CompressAndDumpState(Core::System& system, const CompressAndDumpStat
}
}
auto& movie = system.GetMovie();
if ((movie.IsMovieActive()) && !movie.IsJustStartingRecordingInputFromSaveState())
movie.SaveRecording(dtmname);
else if (!movie.IsMovieActive())
File::Delete(dtmname);
File::Delete(dtmname);
// Move written state to final location.
// TODO: This should also be atomic. This is possible on all systems, but needs a special
@@ -847,14 +849,10 @@ static void LoadAsFromCore(Core::System& system, std::string filename)
s_compress_and_dump_thread.WaitForCompletion();
// Save temp buffer for undo load state
auto& movie = system.GetMovie();
if (!movie.IsJustStartingRecordingInputFromSaveState())
{
SaveToBuffer(system, s_undo_load_buffer);
const std::string dtmpath = File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm";
if (movie.IsMovieActive())
movie.SaveRecording(dtmpath);
else if (File::Exists(dtmpath))
if (File::Exists(dtmpath))
File::Delete(dtmpath);
}
@@ -878,15 +876,6 @@ static void LoadAsFromCore(Core::System& system, std::string filename)
if (loaded_successfully)
{
Core::DisplayMessage(fmt::format("Loaded State from {}", filename), 2000);
if (File::Exists(filename + ".dtm"))
{
movie.LoadInput(filename + ".dtm");
}
else if (!movie.IsJustStartingRecordingInputFromSaveState() &&
!movie.IsJustStartingPlayingInputFromSaveState())
{
movie.EndPlayInput(false);
}
}
else
{
@@ -998,25 +987,7 @@ void UndoLoadState(Core::System& system)
return;
}
auto& movie = system.GetMovie();
if (movie.IsMovieActive())
{
// Note: Only the CPU thread writes to "undo.dtm".
const std::string dtmpath = File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm";
if (File::Exists(dtmpath))
{
LoadFromBuffer(system, s_undo_load_buffer);
movie.LoadInput(dtmpath);
}
else
{
PanicAlertFmtT("No undo.dtm found, aborting undo load state to prevent movie desyncs");
}
}
else
{
LoadFromBuffer(system, s_undo_load_buffer);
}
LoadFromBuffer(system, s_undo_load_buffer);
});
}
+1 -7
View File
@@ -24,7 +24,6 @@
#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"
@@ -54,7 +53,7 @@ struct System::Impl
m_serial_interface(system), m_system_timers(system), m_video_interface(system),
m_interpreter(system, m_power_pc.GetPPCState(), m_mmu, m_power_pc.GetBranchWatch(),
m_power_pc.GetSymbolDB()),
m_jit_interface(system), m_fifo_player(system), m_movie(system)
m_jit_interface(system), m_fifo_player(system)
{
}
@@ -97,7 +96,6 @@ struct System::Impl
JitInterface m_jit_interface;
VideoCommon::CustomResourceManager m_custom_resource_manager;
FifoPlayer m_fifo_player;
Movie::MovieManager m_movie;
};
System::System() : m_impl{std::make_unique<Impl>(*this)}
@@ -229,10 +227,6 @@ 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
{
-5
View File
@@ -80,10 +80,6 @@ namespace MemoryInterface
{
class MemoryInterfaceManager;
}
namespace Movie
{
class MovieManager;
}
namespace PixelEngine
{
class PixelEngineManager;
@@ -177,7 +173,6 @@ 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;
-43
View File
@@ -24,7 +24,6 @@
#include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Uids.h"
#include "Core/Movie.h"
#include "Core/SysConf.h"
#include "Core/System.h"
@@ -85,15 +84,6 @@ static void RestoreFile(const std::string& path_in_nand)
DeleteBackupFile(file_name);
}
static void CopySave(FS::FileSystem* source, FS::FileSystem* dest, const u64 title_id)
{
dest->CreateFullPath(IOS::PID_KERNEL, IOS::PID_KERNEL, Common::GetTitleDataPath(title_id) + '/',
0, {FS::Mode::ReadWrite, FS::Mode::ReadWrite, FS::Mode::ReadWrite});
const auto source_save = WiiSave::MakeNandStorage(source, title_id);
const auto dest_save = WiiSave::MakeNandStorage(dest, title_id);
WiiSave::Copy(source_save.get(), dest_save.get());
}
static bool CopyNandFile(FS::FileSystem* source_fs, const std::string& source_file,
FS::FileSystem* dest_fs, const std::string& dest_file)
{
@@ -123,37 +113,6 @@ static bool CopyNandFile(FS::FileSystem* source_fs, const std::string& source_fi
return true;
}
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())
{
// 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));
}
if (movie.IsMovieActive() && !movie.IsStartingFromClearSave())
{
auto* source_fs = configured_fs.get();
INFO_LOG_FMT(CORE, "Wii Save Init: Copying from configured_fs to session_fs.");
// Copy the current user's save to the Blank NAND
INFO_LOG_FMT(CORE, "Wii Save Init: Copying {0:016x}.", title_id);
CopySave(source_fs, session_fs, title_id);
// Copy Mii data
if (!CopyNandFile(source_fs, Common::GetMiiDatabasePath(), session_fs,
Common::GetMiiDatabasePath()))
{
WARN_LOG_FMT(CORE, "Failed to copy Mii database to the NAND");
}
}
}
static void MoveToBackupIfExists(const std::string& path)
{
if (File::Exists(path))
@@ -313,8 +272,6 @@ void InitializeWiiFileSystemContents(
// Generate a SYSCONF with default settings for the temporary Wii NAND.
SysConf sysconf{fs};
sysconf.Save();
InitializeDeterministicWiiSaves(fs.get(), boot_session_data);
}
if (save_redirect)
-1
View File
@@ -14,7 +14,6 @@
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/Movie.h"
#include "Core/System.h"
#include "VideoCommon/AbstractGfx.h"