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