Merge pull request #6271 from JosJuice/load-state-at-boot
Redesign the ability to load state at boot
This commit is contained in:
commit
3bc61ed363
|
@ -48,11 +48,15 @@
|
|||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
BootParameters::BootParameters(Parameters&& parameters_) : parameters(std::move(parameters_))
|
||||
BootParameters::BootParameters(Parameters&& parameters_,
|
||||
const std::optional<std::string>& savestate_path_)
|
||||
: parameters(std::move(parameters_)), savestate_path(savestate_path_)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<BootParameters> BootParameters::GenerateFromFile(const std::string& path)
|
||||
std::unique_ptr<BootParameters>
|
||||
BootParameters::GenerateFromFile(const std::string& path,
|
||||
const std::optional<std::string>& savestate_path)
|
||||
{
|
||||
const bool is_drive = cdio_is_cdrom(path);
|
||||
// Check if the file exist, we may have gotten it from a --elf command line
|
||||
|
@ -73,13 +77,19 @@ std::unique_ptr<BootParameters> BootParameters::GenerateFromFile(const std::stri
|
|||
{
|
||||
std::unique_ptr<DiscIO::Volume> volume = DiscIO::CreateVolumeFromFilename(path);
|
||||
if (volume)
|
||||
return std::make_unique<BootParameters>(Disc{path, std::move(volume)});
|
||||
return std::make_unique<BootParameters>(Disc{path, std::move(volume)}, savestate_path);
|
||||
|
||||
if (extension == ".elf")
|
||||
return std::make_unique<BootParameters>(Executable{path, std::make_unique<ElfReader>(path)});
|
||||
{
|
||||
return std::make_unique<BootParameters>(Executable{path, std::make_unique<ElfReader>(path)},
|
||||
savestate_path);
|
||||
}
|
||||
|
||||
if (extension == ".dol")
|
||||
return std::make_unique<BootParameters>(Executable{path, std::make_unique<DolReader>(path)});
|
||||
{
|
||||
return std::make_unique<BootParameters>(Executable{path, std::make_unique<DolReader>(path)},
|
||||
savestate_path);
|
||||
}
|
||||
|
||||
if (is_drive)
|
||||
{
|
||||
|
@ -97,10 +107,10 @@ std::unique_ptr<BootParameters> BootParameters::GenerateFromFile(const std::stri
|
|||
}
|
||||
|
||||
if (extension == ".dff")
|
||||
return std::make_unique<BootParameters>(DFF{path});
|
||||
return std::make_unique<BootParameters>(DFF{path}, savestate_path);
|
||||
|
||||
if (extension == ".wad")
|
||||
return std::make_unique<BootParameters>(DiscIO::WiiWAD{path});
|
||||
return std::make_unique<BootParameters>(DiscIO::WiiWAD{path}, savestate_path);
|
||||
|
||||
PanicAlertT("Could not recognize file %s", path.c_str());
|
||||
return {};
|
||||
|
|
|
@ -67,12 +67,15 @@ struct BootParameters
|
|||
std::string dff_path;
|
||||
};
|
||||
|
||||
static std::unique_ptr<BootParameters> GenerateFromFile(const std::string& path);
|
||||
static std::unique_ptr<BootParameters>
|
||||
GenerateFromFile(const std::string& boot_path,
|
||||
const std::optional<std::string>& savestate_path = {});
|
||||
|
||||
using Parameters = std::variant<Disc, Executable, DiscIO::WiiWAD, NANDTitle, IPL, DFF>;
|
||||
BootParameters(Parameters&& parameters_);
|
||||
BootParameters(Parameters&& parameters_, const std::optional<std::string>& savestate_path_ = {});
|
||||
|
||||
Parameters parameters;
|
||||
std::optional<std::string> savestate_path;
|
||||
};
|
||||
|
||||
class CBoot
|
||||
|
|
|
@ -382,8 +382,10 @@ bool BootCore(std::unique_ptr<BootParameters> boot)
|
|||
std::holds_alternative<BootParameters::Disc>(boot->parameters);
|
||||
if (load_ipl)
|
||||
{
|
||||
return Core::Init(std::make_unique<BootParameters>(BootParameters::IPL{
|
||||
StartUp.m_region, std::move(std::get<BootParameters::Disc>(boot->parameters))}));
|
||||
return Core::Init(std::make_unique<BootParameters>(
|
||||
BootParameters::IPL{StartUp.m_region,
|
||||
std::move(std::get<BootParameters::Disc>(boot->parameters))},
|
||||
boot->savestate_path));
|
||||
}
|
||||
return Core::Init(std::move(boot));
|
||||
}
|
||||
|
|
|
@ -96,7 +96,6 @@ static bool s_hardware_initialized = false;
|
|||
static bool s_is_started = false;
|
||||
static Common::Flag s_is_booting;
|
||||
static void* s_window_handle = nullptr;
|
||||
static std::string s_state_filename;
|
||||
static std::thread s_emu_thread;
|
||||
static StateChangedCallbackFunc s_on_state_changed_callback;
|
||||
|
||||
|
@ -136,15 +135,6 @@ void SetIsThrottlerTempDisabled(bool disable)
|
|||
s_is_throttler_temp_disabled = disable;
|
||||
}
|
||||
|
||||
std::string GetStateFileName()
|
||||
{
|
||||
return s_state_filename;
|
||||
}
|
||||
void SetStateFileName(const std::string& val)
|
||||
{
|
||||
s_state_filename = val;
|
||||
}
|
||||
|
||||
void FrameUpdateOnCPUThread()
|
||||
{
|
||||
if (NetPlay::IsNetPlayRunning())
|
||||
|
@ -328,7 +318,7 @@ static void CPUSetInitialExecutionState()
|
|||
}
|
||||
|
||||
// Create the CPU thread, which is a CPU + Video thread in Single Core mode.
|
||||
static void CpuThread()
|
||||
static void CpuThread(const std::optional<std::string>& savestate_path)
|
||||
{
|
||||
DeclareAsCPUThread();
|
||||
|
||||
|
@ -351,17 +341,8 @@ static void CpuThread()
|
|||
if (_CoreParameter.bFastmem)
|
||||
EMM::InstallExceptionHandler(); // Let's run under memory watch
|
||||
|
||||
if (!s_state_filename.empty())
|
||||
{
|
||||
// Needs to PauseAndLock the Core
|
||||
// NOTE: EmuThread should have left us in State::Stepping so nothing will happen
|
||||
// until after the job is serviced.
|
||||
QueueHostJob([] {
|
||||
// Recheck in case Movie cleared it since.
|
||||
if (!s_state_filename.empty())
|
||||
::State::LoadAs(s_state_filename);
|
||||
});
|
||||
}
|
||||
if (savestate_path)
|
||||
QueueHostJob([&savestate_path] { ::State::LoadAs(*savestate_path); });
|
||||
|
||||
s_is_started = true;
|
||||
CPUSetInitialExecutionState();
|
||||
|
@ -399,7 +380,7 @@ static void CpuThread()
|
|||
EMM::UninstallExceptionHandler();
|
||||
}
|
||||
|
||||
static void FifoPlayerThread()
|
||||
static void FifoPlayerThread(const std::optional<std::string>& savestate_path)
|
||||
{
|
||||
DeclareAsCPUThread();
|
||||
const SConfig& _CoreParameter = SConfig::GetInstance();
|
||||
|
@ -535,15 +516,20 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
|||
Keyboard::LoadConfig();
|
||||
}
|
||||
|
||||
const std::optional<std::string> savestate_path = boot->savestate_path;
|
||||
|
||||
// Load and Init Wiimotes - only if we are booting in Wii mode
|
||||
if (core_parameter.bWii && !SConfig::GetInstance().m_bt_passthrough_enabled)
|
||||
{
|
||||
if (init_controllers)
|
||||
Wiimote::Initialize(!s_state_filename.empty() ?
|
||||
Wiimote::InitializeMode::DO_WAIT_FOR_WIIMOTES :
|
||||
Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
|
||||
{
|
||||
Wiimote::Initialize(savestate_path ? Wiimote::InitializeMode::DO_WAIT_FOR_WIIMOTES :
|
||||
Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
|
||||
}
|
||||
else
|
||||
{
|
||||
Wiimote::LoadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
Common::ScopeGuard controller_guard{[init_controllers] {
|
||||
|
@ -570,7 +556,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
|||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
|
||||
// Determine the CPU thread function
|
||||
void (*cpuThreadFunc)();
|
||||
void (*cpuThreadFunc)(const std::optional<std::string>& savestate_path);
|
||||
if (std::holds_alternative<BootParameters::DFF>(boot->parameters))
|
||||
cpuThreadFunc = FifoPlayerThread;
|
||||
else
|
||||
|
@ -611,7 +597,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
|||
Host_Message(WM_USER_CREATE);
|
||||
|
||||
// Spawn the CPU thread
|
||||
s_cpu_thread = std::thread(cpuThreadFunc);
|
||||
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path);
|
||||
|
||||
// become the GPU thread
|
||||
Fifo::RunGpuLoop();
|
||||
|
@ -629,7 +615,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
|||
Common::SetCurrentThreadName("Emuthread - Idle");
|
||||
|
||||
// Spawn the CPU+GPU thread
|
||||
s_cpu_thread = std::thread(cpuThreadFunc);
|
||||
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path);
|
||||
|
||||
while (CPU::GetState() != CPU::State::PowerDown)
|
||||
{
|
||||
|
|
|
@ -64,9 +64,6 @@ void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _
|
|||
// This displays messages in a user-visible way.
|
||||
void DisplayMessage(const std::string& message, int time_in_ms);
|
||||
|
||||
std::string GetStateFileName();
|
||||
void SetStateFileName(const std::string& val);
|
||||
|
||||
void FrameUpdateOnCPUThread();
|
||||
|
||||
bool ShouldSkipFrame(int skipped);
|
||||
|
|
|
@ -232,8 +232,6 @@ void Init(const BootParameters& boot)
|
|||
}
|
||||
|
||||
memset(&s_padState, 0, sizeof(s_padState));
|
||||
if (!tmpHeader.bFromSaveState || !IsPlayingInput())
|
||||
Core::SetStateFileName("");
|
||||
|
||||
for (auto& disp : s_InputDisplay)
|
||||
disp.clear();
|
||||
|
@ -865,12 +863,12 @@ void ReadHeader()
|
|||
}
|
||||
|
||||
// NOTE: Host Thread
|
||||
bool PlayInput(const std::string& filename)
|
||||
bool PlayInput(const std::string& movie_path, std::optional<std::string>* savestate_path)
|
||||
{
|
||||
if (s_playMode != MODE_NONE)
|
||||
return false;
|
||||
|
||||
File::IOFile recording_file(filename, "rb");
|
||||
File::IOFile recording_file(movie_path, "rb");
|
||||
if (!recording_file.ReadArray(&tmpHeader, 1))
|
||||
return false;
|
||||
|
||||
|
@ -902,13 +900,13 @@ bool PlayInput(const std::string& filename)
|
|||
recording_file.Close();
|
||||
|
||||
// Load savestate (and skip to frame data)
|
||||
if (tmpHeader.bFromSaveState)
|
||||
if (tmpHeader.bFromSaveState && savestate_path)
|
||||
{
|
||||
const std::string stateFilename = filename + ".sav";
|
||||
if (File::Exists(stateFilename))
|
||||
Core::SetStateFileName(stateFilename);
|
||||
const std::string savestate_path_temp = movie_path + ".sav";
|
||||
if (File::Exists(savestate_path_temp))
|
||||
*savestate_path = savestate_path_temp;
|
||||
s_bRecordingFromSaveState = true;
|
||||
Movie::LoadInput(filename);
|
||||
Movie::LoadInput(movie_path);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -928,12 +926,12 @@ void DoState(PointerWrap& p)
|
|||
}
|
||||
|
||||
// NOTE: Host Thread
|
||||
void LoadInput(const std::string& filename)
|
||||
void LoadInput(const std::string& movie_path)
|
||||
{
|
||||
File::IOFile t_record;
|
||||
if (!t_record.Open(filename, "r+b"))
|
||||
if (!t_record.Open(movie_path, "r+b"))
|
||||
{
|
||||
PanicAlertT("Failed to read %s", filename.c_str());
|
||||
PanicAlertT("Failed to read %s", movie_path.c_str());
|
||||
EndPlayInput(false);
|
||||
return;
|
||||
}
|
||||
|
@ -942,7 +940,7 @@ void LoadInput(const std::string& filename)
|
|||
|
||||
if (!IsMovieHeader(tmpHeader.filetype))
|
||||
{
|
||||
PanicAlertT("Savestate movie %s is corrupted, movie recording stopping...", filename.c_str());
|
||||
PanicAlertT("Savestate movie %s is corrupted, movie recording stopping...", movie_path.c_str());
|
||||
EndPlayInput(false);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
@ -157,8 +158,8 @@ bool BeginRecordingInput(int controllers);
|
|||
void RecordInput(GCPadStatus* PadStatus, int controllerID);
|
||||
void RecordWiimote(int wiimote, u8* data, u8 size);
|
||||
|
||||
bool PlayInput(const std::string& filename);
|
||||
void LoadInput(const std::string& filename);
|
||||
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, u8* data, const struct WiimoteEmu::ReportFeatures& rptf, int ext,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QProgressDialog>
|
||||
|
||||
#include <future>
|
||||
#include <optional>
|
||||
|
||||
#include "Common/Version.h"
|
||||
|
||||
|
@ -164,7 +165,7 @@ void MainWindow::CreateComponents()
|
|||
m_fifo_window = new FIFOPlayerWindow(this);
|
||||
|
||||
connect(m_fifo_window, &FIFOPlayerWindow::LoadFIFORequested, this,
|
||||
static_cast<void (MainWindow::*)(const QString&)>(&MainWindow::StartGame));
|
||||
[this](const QString& path) { StartGame(path); });
|
||||
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
m_graphics_window = new GraphicsWindow(
|
||||
|
@ -192,7 +193,7 @@ void MainWindow::ConnectMenuBar()
|
|||
|
||||
// Emulation
|
||||
connect(m_menu_bar, &MenuBar::Pause, this, &MainWindow::Pause);
|
||||
connect(m_menu_bar, &MenuBar::Play, this, &MainWindow::Play);
|
||||
connect(m_menu_bar, &MenuBar::Play, this, [this]() { Play(); });
|
||||
connect(m_menu_bar, &MenuBar::Stop, this, &MainWindow::RequestStop);
|
||||
connect(m_menu_bar, &MenuBar::Reset, this, &MainWindow::Reset);
|
||||
connect(m_menu_bar, &MenuBar::Fullscreen, this, &MainWindow::FullScreen);
|
||||
|
@ -278,7 +279,7 @@ void MainWindow::ConnectToolBar()
|
|||
{
|
||||
addToolBar(m_tool_bar);
|
||||
connect(m_tool_bar, &ToolBar::OpenPressed, this, &MainWindow::Open);
|
||||
connect(m_tool_bar, &ToolBar::PlayPressed, this, &MainWindow::Play);
|
||||
connect(m_tool_bar, &ToolBar::PlayPressed, this, [this]() { Play(); });
|
||||
connect(m_tool_bar, &ToolBar::PausePressed, this, &MainWindow::Pause);
|
||||
connect(m_tool_bar, &ToolBar::StopPressed, this, &MainWindow::RequestStop);
|
||||
connect(m_tool_bar, &ToolBar::FullScreenPressed, this, &MainWindow::FullScreen);
|
||||
|
@ -290,7 +291,7 @@ void MainWindow::ConnectToolBar()
|
|||
|
||||
void MainWindow::ConnectGameList()
|
||||
{
|
||||
connect(m_game_list, &GameList::GameSelected, this, &MainWindow::Play);
|
||||
connect(m_game_list, &GameList::GameSelected, this, [this]() { Play(); });
|
||||
connect(m_game_list, &GameList::NetPlayHost, this, &MainWindow::NetPlayHost);
|
||||
|
||||
connect(m_game_list, &GameList::OpenGeneralSettings, this, &MainWindow::ShowGeneralWindow);
|
||||
|
@ -327,7 +328,7 @@ void MainWindow::Open()
|
|||
StartGame(file);
|
||||
}
|
||||
|
||||
void MainWindow::Play()
|
||||
void MainWindow::Play(const std::optional<std::string>& savestate_path)
|
||||
{
|
||||
// If we're in a paused game, start it up again.
|
||||
// Otherwise, play the selected game, if there is one.
|
||||
|
@ -343,14 +344,14 @@ void MainWindow::Play()
|
|||
QSharedPointer<GameFile> selection = m_game_list->GetSelectedGame();
|
||||
if (selection)
|
||||
{
|
||||
StartGame(selection->GetFilePath());
|
||||
StartGame(selection->GetFilePath(), savestate_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto default_path = QString::fromStdString(SConfig::GetInstance().m_strDefaultISO);
|
||||
if (!default_path.isEmpty() && QFile::exists(default_path))
|
||||
{
|
||||
StartGame(default_path);
|
||||
StartGame(default_path, savestate_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -472,9 +473,9 @@ void MainWindow::ScreenShot()
|
|||
Core::SaveScreenShot();
|
||||
}
|
||||
|
||||
void MainWindow::StartGame(const QString& path)
|
||||
void MainWindow::StartGame(const QString& path, const std::optional<std::string>& savestate_path)
|
||||
{
|
||||
StartGame(BootParameters::GenerateFromFile(path.toStdString()));
|
||||
StartGame(BootParameters::GenerateFromFile(path.toStdString(), savestate_path));
|
||||
}
|
||||
|
||||
void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
|
||||
|
@ -680,7 +681,7 @@ void MainWindow::NetPlayInit()
|
|||
m_netplay_dialog = new NetPlayDialog(this);
|
||||
|
||||
connect(m_netplay_dialog, &NetPlayDialog::Boot, this,
|
||||
static_cast<void (MainWindow::*)(const QString&)>(&MainWindow::StartGame));
|
||||
[this](const QString& path) { StartGame(path); });
|
||||
connect(m_netplay_dialog, &NetPlayDialog::Stop, this, &MainWindow::RequestStop);
|
||||
connect(m_netplay_dialog, &NetPlayDialog::rejected, this, &MainWindow::NetPlayQuit);
|
||||
connect(m_netplay_setup_dialog, &NetPlaySetupDialog::Join, this, &MainWindow::NetPlayJoin);
|
||||
|
@ -938,11 +939,12 @@ void MainWindow::OnPlayRecording()
|
|||
emit ReadOnlyModeChanged(true);
|
||||
}
|
||||
|
||||
if (Movie::PlayInput(dtm_file.toStdString()))
|
||||
std::optional<std::string> savestate_path;
|
||||
if (Movie::PlayInput(dtm_file.toStdString(), &savestate_path))
|
||||
{
|
||||
emit RecordingStatusChanged(true);
|
||||
|
||||
Play();
|
||||
Play(savestate_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <QToolBar>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "DolphinQt2/GameList/GameList.h"
|
||||
#include "DolphinQt2/MenuBar.h"
|
||||
|
@ -47,7 +48,7 @@ signals:
|
|||
|
||||
private:
|
||||
void Open();
|
||||
void Play();
|
||||
void Play(const std::optional<std::string>& savestate_path = {});
|
||||
void Pause();
|
||||
|
||||
// May ask for confirmation. Returns whether or not it actually stopped.
|
||||
|
@ -86,7 +87,7 @@ private:
|
|||
|
||||
void InitCoreCallbacks();
|
||||
|
||||
void StartGame(const QString& path);
|
||||
void StartGame(const QString& path, const std::optional<std::string>& savestate_path = {});
|
||||
void StartGame(std::unique_ptr<BootParameters>&& parameters);
|
||||
void ShowRenderWidget();
|
||||
void HideRenderWidget();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -130,8 +131,9 @@ void CRenderFrame::OnDropFiles(wxDropFilesEvent& event)
|
|||
main_frame->GetMenuBar()->FindItem(IDM_RECORD_READ_ONLY)->Check(true);
|
||||
}
|
||||
|
||||
if (Movie::PlayInput(filepath))
|
||||
main_frame->BootGame("");
|
||||
std::optional<std::string> savestate_path;
|
||||
if (Movie::PlayInput(filepath, &savestate_path))
|
||||
main_frame->BootGame("", savestate_path);
|
||||
}
|
||||
else if (!Core::IsRunning())
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wx/bitmap.h>
|
||||
|
@ -105,7 +106,7 @@ public:
|
|||
void ToggleLogConfigWindow(bool bShow);
|
||||
void StatusBarMessage(const char* format, ...);
|
||||
void ClearStatusBar();
|
||||
void BootGame(const std::string& filename);
|
||||
void BootGame(const std::string& filename, const std::optional<std::string>& savestate_path = {});
|
||||
void StartGame(std::unique_ptr<BootParameters> boot);
|
||||
bool RendererHasFocus();
|
||||
bool RendererIsFullscreen();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <cstdio>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wx/app.h>
|
||||
|
@ -301,7 +302,7 @@ void CFrame::OpenGeneralConfiguration(wxWindowID tab_id)
|
|||
// 1. Show the game list and boot the selected game.
|
||||
// 2. Default ISO
|
||||
// 3. Boot last selected game
|
||||
void CFrame::BootGame(const std::string& filename)
|
||||
void CFrame::BootGame(const std::string& filename, const std::optional<std::string>& savestate_path)
|
||||
{
|
||||
std::string bootfile = filename;
|
||||
SConfig& StartUp = SConfig::GetInstance();
|
||||
|
@ -331,7 +332,7 @@ void CFrame::BootGame(const std::string& filename)
|
|||
}
|
||||
if (!bootfile.empty())
|
||||
{
|
||||
StartGame(BootParameters::GenerateFromFile(bootfile));
|
||||
StartGame(BootParameters::GenerateFromFile(bootfile, savestate_path));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,8 +514,9 @@ void CFrame::OnPlayRecording(wxCommandEvent& WXUNUSED(event))
|
|||
GetMenuBar()->FindItem(IDM_RECORD_READ_ONLY)->Check();
|
||||
}
|
||||
|
||||
if (Movie::PlayInput(WxStrToStr(path)))
|
||||
BootGame("");
|
||||
std::optional<std::string> savestate_path;
|
||||
if (Movie::PlayInput(WxStrToStr(path), &savestate_path))
|
||||
BootGame("", savestate_path);
|
||||
}
|
||||
|
||||
void CFrame::OnStopRecording(wxCommandEvent& WXUNUSED(event))
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <OptionParser.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <wx/app.h>
|
||||
|
@ -256,12 +257,18 @@ void DolphinApp::AfterInit()
|
|||
|
||||
if (m_play_movie && !m_movie_file.empty())
|
||||
{
|
||||
if (Movie::PlayInput(WxStrToStr(m_movie_file)))
|
||||
std::optional<std::string> savestate_path;
|
||||
if (Movie::PlayInput(WxStrToStr(m_movie_file), &savestate_path))
|
||||
{
|
||||
if (m_boot)
|
||||
{
|
||||
m_boot->savestate_path = savestate_path;
|
||||
main_frame->StartGame(std::move(m_boot));
|
||||
}
|
||||
else
|
||||
main_frame->BootGame("");
|
||||
{
|
||||
main_frame->BootGame("", savestate_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
// First check if we have an exec command line.
|
||||
|
|
Loading…
Reference in New Issue