mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-12 23:48:58 +01:00
Merge pull request #10235 from AdmiralCurtiss/netplay-save-sync-boot
Netplay: Fix possible Wii save restore race condition between Netplay and CPU threads on game shutdown by making the Wii Save Sync data part of the BootParameters.
This commit is contained in:
commit
ba62019eb5
@ -549,8 +549,7 @@ static float GetRenderSurfaceScale(JNIEnv* env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Run(JNIEnv* env, const std::vector<std::string>& paths, bool riivolution,
|
static void Run(JNIEnv* env, const std::vector<std::string>& paths, bool riivolution,
|
||||||
const std::optional<std::string>& savestate_path = {},
|
BootSessionData boot_session_data = BootSessionData())
|
||||||
bool delete_savestate = false)
|
|
||||||
{
|
{
|
||||||
ASSERT(!paths.empty());
|
ASSERT(!paths.empty());
|
||||||
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Running : %s", paths[0].c_str());
|
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Running : %s", paths[0].c_str());
|
||||||
@ -561,9 +560,8 @@ static void Run(JNIEnv* env, const std::vector<std::string>& paths, bool riivolu
|
|||||||
|
|
||||||
s_have_wm_user_stop = false;
|
s_have_wm_user_stop = false;
|
||||||
|
|
||||||
std::unique_ptr<BootParameters> boot = BootParameters::GenerateFromFile(paths, savestate_path);
|
std::unique_ptr<BootParameters> boot =
|
||||||
if (boot)
|
BootParameters::GenerateFromFile(paths, std::move(boot_session_data));
|
||||||
boot->delete_savestate = delete_savestate;
|
|
||||||
|
|
||||||
if (riivolution && std::holds_alternative<BootParameters::Disc>(boot->parameters))
|
if (riivolution && std::holds_alternative<BootParameters::Disc>(boot->parameters))
|
||||||
{
|
{
|
||||||
@ -638,8 +636,10 @@ Java_org_dolphinemu_dolphinemu_NativeLibrary_Run___3Ljava_lang_String_2ZLjava_la
|
|||||||
JNIEnv* env, jclass, jobjectArray jPaths, jboolean jRiivolution, jstring jSavestate,
|
JNIEnv* env, jclass, jobjectArray jPaths, jboolean jRiivolution, jstring jSavestate,
|
||||||
jboolean jDeleteSavestate)
|
jboolean jDeleteSavestate)
|
||||||
{
|
{
|
||||||
Run(env, JStringArrayToVector(env, jPaths), jRiivolution, GetJString(env, jSavestate),
|
DeleteSavestateAfterBoot delete_state =
|
||||||
jDeleteSavestate);
|
jDeleteSavestate ? DeleteSavestateAfterBoot::Yes : DeleteSavestateAfterBoot::No;
|
||||||
|
Run(env, JStringArrayToVector(env, jPaths), jRiivolution,
|
||||||
|
BootSessionData(GetJString(env, jSavestate), delete_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ChangeDisc(JNIEnv* env, jclass,
|
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ChangeDisc(JNIEnv* env, jclass,
|
||||||
|
@ -112,22 +112,77 @@ static std::vector<std::string> ReadM3UFile(const std::string& m3u_path,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BootParameters::BootParameters(Parameters&& parameters_,
|
BootSessionData::BootSessionData()
|
||||||
const std::optional<std::string>& savestate_path_)
|
|
||||||
: parameters(std::move(parameters_)), savestate_path(savestate_path_)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<BootParameters>
|
BootSessionData::BootSessionData(std::optional<std::string> savestate_path,
|
||||||
BootParameters::GenerateFromFile(std::string boot_path,
|
DeleteSavestateAfterBoot delete_savestate)
|
||||||
const std::optional<std::string>& savestate_path)
|
: m_savestate_path(std::move(savestate_path)), m_delete_savestate(delete_savestate)
|
||||||
{
|
{
|
||||||
return GenerateFromFile(std::vector<std::string>{std::move(boot_path)}, savestate_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<BootParameters>
|
BootSessionData::BootSessionData(BootSessionData&& other) = default;
|
||||||
BootParameters::GenerateFromFile(std::vector<std::string> paths,
|
|
||||||
const std::optional<std::string>& savestate_path)
|
BootSessionData& BootSessionData::operator=(BootSessionData&& other) = default;
|
||||||
|
|
||||||
|
BootSessionData::~BootSessionData() = default;
|
||||||
|
|
||||||
|
const std::optional<std::string>& BootSessionData::GetSavestatePath() const
|
||||||
|
{
|
||||||
|
return m_savestate_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteSavestateAfterBoot BootSessionData::GetDeleteSavestate() const
|
||||||
|
{
|
||||||
|
return m_delete_savestate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BootSessionData::SetSavestateData(std::optional<std::string> savestate_path,
|
||||||
|
DeleteSavestateAfterBoot delete_savestate)
|
||||||
|
{
|
||||||
|
m_savestate_path = std::move(savestate_path);
|
||||||
|
m_delete_savestate = delete_savestate;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOS::HLE::FS::FileSystem* BootSessionData::GetWiiSyncFS() const
|
||||||
|
{
|
||||||
|
return m_wii_sync_fs.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<u64>& BootSessionData::GetWiiSyncTitles() const
|
||||||
|
{
|
||||||
|
return m_wii_sync_titles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BootSessionData::InvokeWiiSyncCleanup() const
|
||||||
|
{
|
||||||
|
if (m_wii_sync_cleanup)
|
||||||
|
m_wii_sync_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BootSessionData::SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs,
|
||||||
|
std::vector<u64> titles, WiiSyncCleanupFunction cleanup)
|
||||||
|
{
|
||||||
|
m_wii_sync_fs = std::move(fs);
|
||||||
|
m_wii_sync_titles = std::move(titles);
|
||||||
|
m_wii_sync_cleanup = std::move(cleanup);
|
||||||
|
}
|
||||||
|
|
||||||
|
BootParameters::BootParameters(Parameters&& parameters_, BootSessionData boot_session_data_)
|
||||||
|
: parameters(std::move(parameters_)), boot_session_data(std::move(boot_session_data_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<BootParameters> BootParameters::GenerateFromFile(std::string boot_path,
|
||||||
|
BootSessionData boot_session_data_)
|
||||||
|
{
|
||||||
|
return GenerateFromFile(std::vector<std::string>{std::move(boot_path)},
|
||||||
|
std::move(boot_session_data_));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<BootParameters> BootParameters::GenerateFromFile(std::vector<std::string> paths,
|
||||||
|
BootSessionData boot_session_data_)
|
||||||
{
|
{
|
||||||
ASSERT(!paths.empty());
|
ASSERT(!paths.empty());
|
||||||
|
|
||||||
@ -176,21 +231,21 @@ BootParameters::GenerateFromFile(std::vector<std::string> paths,
|
|||||||
if (disc)
|
if (disc)
|
||||||
{
|
{
|
||||||
return std::make_unique<BootParameters>(Disc{std::move(path), std::move(disc), paths},
|
return std::make_unique<BootParameters>(Disc{std::move(path), std::move(disc), paths},
|
||||||
savestate_path);
|
std::move(boot_session_data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extension == ".elf")
|
if (extension == ".elf")
|
||||||
{
|
{
|
||||||
auto elf_reader = std::make_unique<ElfReader>(path);
|
auto elf_reader = std::make_unique<ElfReader>(path);
|
||||||
return std::make_unique<BootParameters>(Executable{std::move(path), std::move(elf_reader)},
|
return std::make_unique<BootParameters>(Executable{std::move(path), std::move(elf_reader)},
|
||||||
savestate_path);
|
std::move(boot_session_data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extension == ".dol")
|
if (extension == ".dol")
|
||||||
{
|
{
|
||||||
auto dol_reader = std::make_unique<DolReader>(path);
|
auto dol_reader = std::make_unique<DolReader>(path);
|
||||||
return std::make_unique<BootParameters>(Executable{std::move(path), std::move(dol_reader)},
|
return std::make_unique<BootParameters>(Executable{std::move(path), std::move(dol_reader)},
|
||||||
savestate_path);
|
std::move(boot_session_data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_drive)
|
if (is_drive)
|
||||||
@ -209,13 +264,13 @@ BootParameters::GenerateFromFile(std::vector<std::string> paths,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (extension == ".dff")
|
if (extension == ".dff")
|
||||||
return std::make_unique<BootParameters>(DFF{std::move(path)}, savestate_path);
|
return std::make_unique<BootParameters>(DFF{std::move(path)}, std::move(boot_session_data_));
|
||||||
|
|
||||||
if (extension == ".wad")
|
if (extension == ".wad")
|
||||||
{
|
{
|
||||||
std::unique_ptr<DiscIO::VolumeWAD> wad = DiscIO::CreateWAD(std::move(path));
|
std::unique_ptr<DiscIO::VolumeWAD> wad = DiscIO::CreateWAD(std::move(path));
|
||||||
if (wad)
|
if (wad)
|
||||||
return std::make_unique<BootParameters>(std::move(*wad), savestate_path);
|
return std::make_unique<BootParameters>(std::move(*wad), std::move(boot_session_data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extension == ".json")
|
if (extension == ".json")
|
||||||
@ -223,7 +278,7 @@ BootParameters::GenerateFromFile(std::vector<std::string> paths,
|
|||||||
auto descriptor = DiscIO::ParseGameModDescriptorFile(path);
|
auto descriptor = DiscIO::ParseGameModDescriptorFile(path);
|
||||||
if (descriptor)
|
if (descriptor)
|
||||||
{
|
{
|
||||||
auto boot_params = GenerateFromFile(descriptor->base_file, savestate_path);
|
auto boot_params = GenerateFromFile(descriptor->base_file, std::move(boot_session_data_));
|
||||||
if (!boot_params)
|
if (!boot_params)
|
||||||
{
|
{
|
||||||
PanicAlertFmtT("Could not recognize file {0}", descriptor->base_file);
|
PanicAlertFmtT("Could not recognize file {0}", descriptor->base_file);
|
||||||
|
@ -24,6 +24,11 @@ namespace File
|
|||||||
class IOFile;
|
class IOFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace IOS::HLE::FS
|
||||||
|
{
|
||||||
|
class FileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
struct RegionSetting
|
struct RegionSetting
|
||||||
{
|
{
|
||||||
std::string area;
|
std::string area;
|
||||||
@ -34,6 +39,46 @@ struct RegionSetting
|
|||||||
|
|
||||||
class BootExecutableReader;
|
class BootExecutableReader;
|
||||||
|
|
||||||
|
enum class DeleteSavestateAfterBoot : u8
|
||||||
|
{
|
||||||
|
No,
|
||||||
|
Yes
|
||||||
|
};
|
||||||
|
|
||||||
|
class BootSessionData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BootSessionData();
|
||||||
|
BootSessionData(std::optional<std::string> savestate_path,
|
||||||
|
DeleteSavestateAfterBoot delete_savestate);
|
||||||
|
BootSessionData(const BootSessionData& other) = delete;
|
||||||
|
BootSessionData(BootSessionData&& other);
|
||||||
|
BootSessionData& operator=(const BootSessionData& other) = delete;
|
||||||
|
BootSessionData& operator=(BootSessionData&& other);
|
||||||
|
~BootSessionData();
|
||||||
|
|
||||||
|
const std::optional<std::string>& GetSavestatePath() const;
|
||||||
|
DeleteSavestateAfterBoot GetDeleteSavestate() const;
|
||||||
|
void SetSavestateData(std::optional<std::string> savestate_path,
|
||||||
|
DeleteSavestateAfterBoot delete_savestate);
|
||||||
|
|
||||||
|
using WiiSyncCleanupFunction = std::function<void()>;
|
||||||
|
|
||||||
|
IOS::HLE::FS::FileSystem* GetWiiSyncFS() const;
|
||||||
|
const std::vector<u64>& GetWiiSyncTitles() const;
|
||||||
|
void InvokeWiiSyncCleanup() const;
|
||||||
|
void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, std::vector<u64> titles,
|
||||||
|
WiiSyncCleanupFunction cleanup);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<std::string> m_savestate_path;
|
||||||
|
DeleteSavestateAfterBoot m_delete_savestate = DeleteSavestateAfterBoot::No;
|
||||||
|
|
||||||
|
std::unique_ptr<IOS::HLE::FS::FileSystem> m_wii_sync_fs;
|
||||||
|
std::vector<u64> m_wii_sync_titles;
|
||||||
|
WiiSyncCleanupFunction m_wii_sync_cleanup;
|
||||||
|
};
|
||||||
|
|
||||||
struct BootParameters
|
struct BootParameters
|
||||||
{
|
{
|
||||||
struct Disc
|
struct Disc
|
||||||
@ -70,18 +115,17 @@ struct BootParameters
|
|||||||
};
|
};
|
||||||
|
|
||||||
static std::unique_ptr<BootParameters>
|
static std::unique_ptr<BootParameters>
|
||||||
GenerateFromFile(std::string boot_path, const std::optional<std::string>& savestate_path = {});
|
GenerateFromFile(std::string boot_path, BootSessionData boot_session_data_ = BootSessionData());
|
||||||
static std::unique_ptr<BootParameters>
|
static std::unique_ptr<BootParameters>
|
||||||
GenerateFromFile(std::vector<std::string> paths,
|
GenerateFromFile(std::vector<std::string> paths,
|
||||||
const std::optional<std::string>& savestate_path = {});
|
BootSessionData boot_session_data_ = BootSessionData());
|
||||||
|
|
||||||
using Parameters = std::variant<Disc, Executable, DiscIO::VolumeWAD, NANDTitle, IPL, DFF>;
|
using Parameters = std::variant<Disc, Executable, DiscIO::VolumeWAD, NANDTitle, IPL, DFF>;
|
||||||
BootParameters(Parameters&& parameters_, const std::optional<std::string>& savestate_path_ = {});
|
BootParameters(Parameters&& parameters_, BootSessionData boot_session_data_ = BootSessionData());
|
||||||
|
|
||||||
Parameters parameters;
|
Parameters parameters;
|
||||||
std::vector<DiscIO::Riivolution::Patch> riivolution_patches;
|
std::vector<DiscIO::Riivolution::Patch> riivolution_patches;
|
||||||
std::optional<std::string> savestate_path;
|
BootSessionData boot_session_data;
|
||||||
bool delete_savestate = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CBoot
|
class CBoot
|
||||||
|
@ -450,7 +450,7 @@ bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
|
|||||||
std::make_unique<BootParameters>(
|
std::make_unique<BootParameters>(
|
||||||
BootParameters::IPL{StartUp.m_region,
|
BootParameters::IPL{StartUp.m_region,
|
||||||
std::move(std::get<BootParameters::Disc>(boot->parameters))},
|
std::move(std::get<BootParameters::Disc>(boot->parameters))},
|
||||||
boot->savestate_path),
|
std::move(boot->boot_session_data)),
|
||||||
wsi);
|
wsi);
|
||||||
}
|
}
|
||||||
return Core::Init(std::move(boot), wsi);
|
return Core::Init(std::move(boot), wsi);
|
||||||
|
@ -479,8 +479,10 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
|||||||
Keyboard::LoadConfig();
|
Keyboard::LoadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<std::string> savestate_path = boot->savestate_path;
|
BootSessionData boot_session_data = std::move(boot->boot_session_data);
|
||||||
const bool delete_savestate = boot->delete_savestate;
|
const std::optional<std::string>& savestate_path = boot_session_data.GetSavestatePath();
|
||||||
|
const bool delete_savestate =
|
||||||
|
boot_session_data.GetDeleteSavestate() == DeleteSavestateAfterBoot::Yes;
|
||||||
|
|
||||||
// Load and Init Wiimotes - only if we are booting in Wii mode
|
// Load and Init Wiimotes - only if we are booting in Wii mode
|
||||||
bool init_wiimotes = false;
|
bool init_wiimotes = false;
|
||||||
@ -615,9 +617,12 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
|||||||
// Initialise Wii filesystem contents.
|
// Initialise Wii filesystem contents.
|
||||||
// This is done here after Boot and not in BootManager to ensure that we operate
|
// This is done here after Boot and not in BootManager to ensure that we operate
|
||||||
// with the correct title context since save copying requires title directories to exist.
|
// with the correct title context since save copying requires title directories to exist.
|
||||||
Common::ScopeGuard wiifs_guard{&Core::CleanUpWiiFileSystemContents};
|
Common::ScopeGuard wiifs_guard{[&boot_session_data] {
|
||||||
|
Core::CleanUpWiiFileSystemContents(boot_session_data);
|
||||||
|
boot_session_data.InvokeWiiSyncCleanup();
|
||||||
|
}};
|
||||||
if (SConfig::GetInstance().bWii)
|
if (SConfig::GetInstance().bWii)
|
||||||
Core::InitializeWiiFileSystemContents(savegame_redirect);
|
Core::InitializeWiiFileSystemContents(savegame_redirect, boot_session_data);
|
||||||
else
|
else
|
||||||
wiifs_guard.Dismiss();
|
wiifs_guard.Dismiss();
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "Common/Version.h"
|
#include "Common/Version.h"
|
||||||
|
|
||||||
#include "Core/ActionReplay.h"
|
#include "Core/ActionReplay.h"
|
||||||
|
#include "Core/Boot/Boot.h"
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
#include "Core/Config/NetplaySettings.h"
|
#include "Core/Config/NetplaySettings.h"
|
||||||
#include "Core/Config/SessionSettings.h"
|
#include "Core/Config/SessionSettings.h"
|
||||||
@ -75,8 +76,6 @@ using namespace WiimoteCommon;
|
|||||||
|
|
||||||
static std::mutex crit_netplay_client;
|
static std::mutex crit_netplay_client;
|
||||||
static NetPlayClient* netplay_client = nullptr;
|
static NetPlayClient* netplay_client = nullptr;
|
||||||
static std::unique_ptr<IOS::HLE::FS::FileSystem> s_wii_sync_fs;
|
|
||||||
static std::vector<u64> s_wii_sync_titles;
|
|
||||||
static bool s_si_poll_batching = false;
|
static bool s_si_poll_batching = false;
|
||||||
|
|
||||||
// called from ---GUI--- thread
|
// called from ---GUI--- thread
|
||||||
@ -1191,7 +1190,7 @@ void NetPlayClient::OnSyncSaveDataWii(sf::Packet& packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWiiSyncData(std::move(temp_fs), titles);
|
SetWiiSyncData(std::move(temp_fs), std::move(titles));
|
||||||
SyncSaveDataResponse(true);
|
SyncSaveDataResponse(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1721,7 +1720,14 @@ bool NetPlayClient::StartGame(const std::string& path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// boot game
|
// boot game
|
||||||
m_dialog->BootGame(path);
|
auto boot_session_data = std::make_unique<BootSessionData>();
|
||||||
|
boot_session_data->SetWiiSyncData(std::move(m_wii_sync_fs), std::move(m_wii_sync_titles), [] {
|
||||||
|
// on emulation end clean up the Wii save sync directory -- see OnSyncSaveDataWii()
|
||||||
|
const std::string path = File::GetUserPath(D_USER_IDX) + "Wii" GC_MEMCARD_NETPLAY DIR_SEP;
|
||||||
|
if (File::Exists(path))
|
||||||
|
File::DeleteDirRecursively(path);
|
||||||
|
});
|
||||||
|
m_dialog->BootGame(path, std::move(boot_session_data));
|
||||||
|
|
||||||
UpdateDevices();
|
UpdateDevices();
|
||||||
|
|
||||||
@ -2251,8 +2257,6 @@ bool NetPlayClient::StopGame()
|
|||||||
// stop game
|
// stop game
|
||||||
m_dialog->StopGame();
|
m_dialog->StopGame();
|
||||||
|
|
||||||
ClearWiiSyncData();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2496,6 +2500,13 @@ void NetPlayClient::AdjustPadBufferSize(const unsigned int size)
|
|||||||
m_dialog->OnPadBufferChanged(size);
|
m_dialog->OnPadBufferChanged(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetPlayClient::SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs,
|
||||||
|
std::vector<u64> titles)
|
||||||
|
{
|
||||||
|
m_wii_sync_fs = std::move(fs);
|
||||||
|
m_wii_sync_titles = std::move(titles);
|
||||||
|
}
|
||||||
|
|
||||||
SyncIdentifier NetPlayClient::GetSDCardIdentifier()
|
SyncIdentifier NetPlayClient::GetSDCardIdentifier()
|
||||||
{
|
{
|
||||||
return SyncIdentifier{{}, "sd", {}, {}, {}, {}};
|
return SyncIdentifier{{}, "sd", {}, {}, {}, {}};
|
||||||
@ -2538,33 +2549,6 @@ const NetSettings& GetNetSettings()
|
|||||||
return netplay_client->GetNetSettings();
|
return netplay_client->GetNetSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
IOS::HLE::FS::FileSystem* GetWiiSyncFS()
|
|
||||||
{
|
|
||||||
return s_wii_sync_fs.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<u64>& GetWiiSyncTitles()
|
|
||||||
{
|
|
||||||
return s_wii_sync_titles;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, const std::vector<u64>& titles)
|
|
||||||
{
|
|
||||||
s_wii_sync_fs = std::move(fs);
|
|
||||||
s_wii_sync_titles.insert(s_wii_sync_titles.end(), titles.begin(), titles.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearWiiSyncData()
|
|
||||||
{
|
|
||||||
// We're just assuming it will always be here because it is
|
|
||||||
const std::string path = File::GetUserPath(D_USER_IDX) + "Wii" GC_MEMCARD_NETPLAY DIR_SEP;
|
|
||||||
if (File::Exists(path))
|
|
||||||
File::DeleteDirRecursively(path);
|
|
||||||
|
|
||||||
s_wii_sync_fs.reset();
|
|
||||||
s_wii_sync_titles.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSIPollBatching(bool state)
|
void SetSIPollBatching(bool state)
|
||||||
{
|
{
|
||||||
s_si_poll_batching = state;
|
s_si_poll_batching = state;
|
||||||
|
@ -23,6 +23,13 @@
|
|||||||
#include "Core/SyncIdentifier.h"
|
#include "Core/SyncIdentifier.h"
|
||||||
#include "InputCommon/GCPadStatus.h"
|
#include "InputCommon/GCPadStatus.h"
|
||||||
|
|
||||||
|
class BootSessionData;
|
||||||
|
|
||||||
|
namespace IOS::HLE::FS
|
||||||
|
{
|
||||||
|
class FileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
namespace UICommon
|
namespace UICommon
|
||||||
{
|
{
|
||||||
class GameFile;
|
class GameFile;
|
||||||
@ -34,7 +41,8 @@ class NetPlayUI
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~NetPlayUI() {}
|
virtual ~NetPlayUI() {}
|
||||||
virtual void BootGame(const std::string& filename) = 0;
|
virtual void BootGame(const std::string& filename,
|
||||||
|
std::unique_ptr<BootSessionData> boot_session_data) = 0;
|
||||||
virtual void StopGame() = 0;
|
virtual void StopGame() = 0;
|
||||||
virtual bool IsHosting() const = 0;
|
virtual bool IsHosting() const = 0;
|
||||||
|
|
||||||
@ -77,6 +85,8 @@ public:
|
|||||||
const std::vector<int>& players) = 0;
|
const std::vector<int>& players) = 0;
|
||||||
virtual void HideChunkedProgressDialog() = 0;
|
virtual void HideChunkedProgressDialog() = 0;
|
||||||
virtual void SetChunkedProgress(int pid, u64 progress) = 0;
|
virtual void SetChunkedProgress(int pid, u64 progress) = 0;
|
||||||
|
|
||||||
|
virtual void SetHostWiiSyncTitles(std::vector<u64> titles) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Player
|
class Player
|
||||||
@ -147,6 +157,8 @@ public:
|
|||||||
|
|
||||||
void AdjustPadBufferSize(unsigned int size);
|
void AdjustPadBufferSize(unsigned int size);
|
||||||
|
|
||||||
|
void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, std::vector<u64> titles);
|
||||||
|
|
||||||
static SyncIdentifier GetSDCardIdentifier();
|
static SyncIdentifier GetSDCardIdentifier();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -313,6 +325,9 @@ private:
|
|||||||
|
|
||||||
u64 m_initial_rtc = 0;
|
u64 m_initial_rtc = 0;
|
||||||
u32 m_timebase_frame = 0;
|
u32 m_timebase_frame = 0;
|
||||||
|
|
||||||
|
std::unique_ptr<IOS::HLE::FS::FileSystem> m_wii_sync_fs;
|
||||||
|
std::vector<u64> m_wii_sync_titles;
|
||||||
};
|
};
|
||||||
|
|
||||||
void NetPlay_Enable(NetPlayClient* const np);
|
void NetPlay_Enable(NetPlayClient* const np);
|
||||||
|
@ -257,10 +257,6 @@ bool IsNetPlayRunning();
|
|||||||
// Precondition: A netplay client instance must be present. In other words,
|
// Precondition: A netplay client instance must be present. In other words,
|
||||||
// IsNetPlayRunning() must be true before calling this.
|
// IsNetPlayRunning() must be true before calling this.
|
||||||
const NetSettings& GetNetSettings();
|
const NetSettings& GetNetSettings();
|
||||||
IOS::HLE::FS::FileSystem* GetWiiSyncFS();
|
|
||||||
const std::vector<u64>& GetWiiSyncTitles();
|
|
||||||
void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, const std::vector<u64>& titles);
|
|
||||||
void ClearWiiSyncData();
|
|
||||||
void SetSIPollBatching(bool state);
|
void SetSIPollBatching(bool state);
|
||||||
void SendPowerButtonEvent();
|
void SendPowerButtonEvent();
|
||||||
bool IsSyncingAllWiiSaves();
|
bool IsSyncingAllWiiSaves();
|
||||||
|
@ -1819,7 +1819,7 @@ bool NetPlayServer::SyncSaveData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set titles for host-side loading in WiiRoot
|
// Set titles for host-side loading in WiiRoot
|
||||||
SetWiiSyncData(nullptr, titles);
|
m_dialog->SetHostWiiSyncTitles(std::move(titles));
|
||||||
|
|
||||||
SendChunkedToClients(std::move(pac), 1, "Wii Save Synchronization");
|
SendChunkedToClients(std::move(pac), 1, "Wii Save Synchronization");
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/NandPaths.h"
|
#include "Common/NandPaths.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
#include "Core/Boot/Boot.h"
|
||||||
#include "Core/CommonTitles.h"
|
#include "Core/CommonTitles.h"
|
||||||
#include "Core/Config/SessionSettings.h"
|
#include "Core/Config/SessionSettings.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
@ -114,7 +115,8 @@ static bool CopyNandFile(FS::FileSystem* source_fs, const std::string& source_fi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitializeDeterministicWiiSaves(FS::FileSystem* session_fs)
|
static void InitializeDeterministicWiiSaves(FS::FileSystem* session_fs,
|
||||||
|
const BootSessionData& boot_session_data)
|
||||||
{
|
{
|
||||||
const u64 title_id = SConfig::GetInstance().GetTitleID();
|
const u64 title_id = SConfig::GetInstance().GetTitleID();
|
||||||
const auto configured_fs = FS::MakeFileSystem(FS::Location::Configured);
|
const auto configured_fs = FS::MakeFileSystem(FS::Location::Configured);
|
||||||
@ -136,8 +138,8 @@ static void InitializeDeterministicWiiSaves(FS::FileSystem* session_fs)
|
|||||||
(Movie::IsMovieActive() && !Movie::IsStartingFromClearSave()))
|
(Movie::IsMovieActive() && !Movie::IsStartingFromClearSave()))
|
||||||
{
|
{
|
||||||
// Copy the current user's save to the Blank NAND
|
// Copy the current user's save to the Blank NAND
|
||||||
auto* sync_fs = NetPlay::GetWiiSyncFS();
|
auto* sync_fs = boot_session_data.GetWiiSyncFS();
|
||||||
auto& sync_titles = NetPlay::GetWiiSyncTitles();
|
auto& sync_titles = boot_session_data.GetWiiSyncTitles();
|
||||||
if (sync_fs)
|
if (sync_fs)
|
||||||
{
|
{
|
||||||
for (const u64 title : sync_titles)
|
for (const u64 title : sync_titles)
|
||||||
@ -298,7 +300,8 @@ static bool CopySysmenuFilesToFS(FS::FileSystem* fs, const std::string& host_sou
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InitializeWiiFileSystemContents(
|
void InitializeWiiFileSystemContents(
|
||||||
std::optional<DiscIO::Riivolution::SavegameRedirect> save_redirect)
|
std::optional<DiscIO::Riivolution::SavegameRedirect> save_redirect,
|
||||||
|
const BootSessionData& boot_session_data)
|
||||||
{
|
{
|
||||||
const auto fs = IOS::HLE::GetIOS()->GetFS();
|
const auto fs = IOS::HLE::GetIOS()->GetFS();
|
||||||
|
|
||||||
@ -315,7 +318,7 @@ void InitializeWiiFileSystemContents(
|
|||||||
SysConf sysconf{fs};
|
SysConf sysconf{fs};
|
||||||
sysconf.Save();
|
sysconf.Save();
|
||||||
|
|
||||||
InitializeDeterministicWiiSaves(fs.get());
|
InitializeDeterministicWiiSaves(fs.get(), boot_session_data);
|
||||||
}
|
}
|
||||||
else if (save_redirect)
|
else if (save_redirect)
|
||||||
{
|
{
|
||||||
@ -336,10 +339,10 @@ void InitializeWiiFileSystemContents(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CleanUpWiiFileSystemContents()
|
void CleanUpWiiFileSystemContents(const BootSessionData& boot_session_data)
|
||||||
{
|
{
|
||||||
if (!WiiRootIsTemporary() || !Config::Get(Config::SESSION_SAVE_DATA_WRITABLE) ||
|
if (!WiiRootIsTemporary() || !Config::Get(Config::SESSION_SAVE_DATA_WRITABLE) ||
|
||||||
NetPlay::GetWiiSyncFS())
|
boot_session_data.GetWiiSyncFS())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "DiscIO/RiivolutionPatcher.h"
|
#include "DiscIO/RiivolutionPatcher.h"
|
||||||
|
|
||||||
|
class BootSessionData;
|
||||||
|
|
||||||
namespace IOS::HLE::FS
|
namespace IOS::HLE::FS
|
||||||
{
|
{
|
||||||
struct NandRedirect;
|
struct NandRedirect;
|
||||||
@ -32,8 +34,9 @@ void RestoreWiiSettings(RestoreReason reason);
|
|||||||
|
|
||||||
// Initialize or clean up the filesystem contents.
|
// Initialize or clean up the filesystem contents.
|
||||||
void InitializeWiiFileSystemContents(
|
void InitializeWiiFileSystemContents(
|
||||||
std::optional<DiscIO::Riivolution::SavegameRedirect> save_redirect);
|
std::optional<DiscIO::Riivolution::SavegameRedirect> save_redirect,
|
||||||
void CleanUpWiiFileSystemContents();
|
const BootSessionData& boot_session_data);
|
||||||
|
void CleanUpWiiFileSystemContents(const BootSessionData& boot_session_data);
|
||||||
|
|
||||||
const std::vector<IOS::HLE::FS::NandRedirect>& GetActiveNandRedirects();
|
const std::vector<IOS::HLE::FS::NandRedirect>& GetActiveNandRedirects();
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
@ -187,7 +187,8 @@ int main(int argc, char* argv[])
|
|||||||
const std::list<std::string> paths_list = options.all("exec");
|
const std::list<std::string> paths_list = options.all("exec");
|
||||||
const std::vector<std::string> paths{std::make_move_iterator(std::begin(paths_list)),
|
const std::vector<std::string> paths{std::make_move_iterator(std::begin(paths_list)),
|
||||||
std::make_move_iterator(std::end(paths_list))};
|
std::make_move_iterator(std::end(paths_list))};
|
||||||
boot = BootParameters::GenerateFromFile(paths, save_state_path);
|
boot = BootParameters::GenerateFromFile(
|
||||||
|
paths, BootSessionData(save_state_path, DeleteSavestateAfterBoot::No));
|
||||||
game_specified = true;
|
game_specified = true;
|
||||||
}
|
}
|
||||||
else if (options.is_set("nand_title"))
|
else if (options.is_set("nand_title"))
|
||||||
@ -204,7 +205,8 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
else if (args.size())
|
else if (args.size())
|
||||||
{
|
{
|
||||||
boot = BootParameters::GenerateFromFile(args.front(), save_state_path);
|
boot = BootParameters::GenerateFromFile(
|
||||||
|
args.front(), BootSessionData(save_state_path, DeleteSavestateAfterBoot::No));
|
||||||
args.erase(args.begin());
|
args.erase(args.begin());
|
||||||
game_specified = true;
|
game_specified = true;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
|
|||||||
const std::list<std::string> paths_list = options.all("exec");
|
const std::list<std::string> paths_list = options.all("exec");
|
||||||
const std::vector<std::string> paths{std::make_move_iterator(std::begin(paths_list)),
|
const std::vector<std::string> paths{std::make_move_iterator(std::begin(paths_list)),
|
||||||
std::make_move_iterator(std::end(paths_list))};
|
std::make_move_iterator(std::end(paths_list))};
|
||||||
boot = BootParameters::GenerateFromFile(paths, save_state_path);
|
boot = BootParameters::GenerateFromFile(
|
||||||
|
paths, BootSessionData(save_state_path, DeleteSavestateAfterBoot::No));
|
||||||
game_specified = true;
|
game_specified = true;
|
||||||
}
|
}
|
||||||
else if (options.is_set("nand_title"))
|
else if (options.is_set("nand_title"))
|
||||||
@ -216,7 +217,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
|
|||||||
}
|
}
|
||||||
else if (!args.empty())
|
else if (!args.empty())
|
||||||
{
|
{
|
||||||
boot = BootParameters::GenerateFromFile(args.front(), save_state_path);
|
boot = BootParameters::GenerateFromFile(
|
||||||
|
args.front(), BootSessionData(save_state_path, DeleteSavestateAfterBoot::No));
|
||||||
game_specified = true;
|
game_specified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,8 +244,13 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
|
|||||||
|
|
||||||
if (!movie_path.empty())
|
if (!movie_path.empty())
|
||||||
{
|
{
|
||||||
if (Movie::PlayInput(movie_path, &m_pending_boot->savestate_path))
|
std::optional<std::string> savestate_path;
|
||||||
|
if (Movie::PlayInput(movie_path, &savestate_path))
|
||||||
|
{
|
||||||
|
m_pending_boot->boot_session_data.SetSavestateData(std::move(savestate_path),
|
||||||
|
DeleteSavestateAfterBoot::No);
|
||||||
emit RecordingStatusChanged(true);
|
emit RecordingStatusChanged(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,14 +773,16 @@ void MainWindow::Play(const std::optional<std::string>& savestate_path)
|
|||||||
std::shared_ptr<const UICommon::GameFile> selection = m_game_list->GetSelectedGame();
|
std::shared_ptr<const UICommon::GameFile> selection = m_game_list->GetSelectedGame();
|
||||||
if (selection)
|
if (selection)
|
||||||
{
|
{
|
||||||
StartGame(selection->GetFilePath(), ScanForSecondDisc::Yes, savestate_path);
|
StartGame(selection->GetFilePath(), ScanForSecondDisc::Yes,
|
||||||
|
std::make_unique<BootSessionData>(savestate_path, DeleteSavestateAfterBoot::No));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const QString default_path = QString::fromStdString(Config::Get(Config::MAIN_DEFAULT_ISO));
|
const QString default_path = QString::fromStdString(Config::Get(Config::MAIN_DEFAULT_ISO));
|
||||||
if (!default_path.isEmpty() && QFile::exists(default_path))
|
if (!default_path.isEmpty() && QFile::exists(default_path))
|
||||||
{
|
{
|
||||||
StartGame(default_path, ScanForSecondDisc::Yes, savestate_path);
|
StartGame(default_path, ScanForSecondDisc::Yes,
|
||||||
|
std::make_unique<BootSessionData>(savestate_path, DeleteSavestateAfterBoot::No));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -978,7 +985,7 @@ void MainWindow::ScreenShot()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::ScanForSecondDiscAndStartGame(const UICommon::GameFile& game,
|
void MainWindow::ScanForSecondDiscAndStartGame(const UICommon::GameFile& game,
|
||||||
const std::optional<std::string>& savestate_path)
|
std::unique_ptr<BootSessionData> boot_session_data)
|
||||||
{
|
{
|
||||||
auto second_game = m_game_list->FindSecondDisc(game);
|
auto second_game = m_game_list->FindSecondDisc(game);
|
||||||
|
|
||||||
@ -986,35 +993,37 @@ void MainWindow::ScanForSecondDiscAndStartGame(const UICommon::GameFile& game,
|
|||||||
if (second_game != nullptr)
|
if (second_game != nullptr)
|
||||||
paths.push_back(second_game->GetFilePath());
|
paths.push_back(second_game->GetFilePath());
|
||||||
|
|
||||||
StartGame(paths, savestate_path);
|
StartGame(paths, std::move(boot_session_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::StartGame(const QString& path, ScanForSecondDisc scan,
|
void MainWindow::StartGame(const QString& path, ScanForSecondDisc scan,
|
||||||
const std::optional<std::string>& savestate_path)
|
std::unique_ptr<BootSessionData> boot_session_data)
|
||||||
{
|
{
|
||||||
StartGame(path.toStdString(), scan, savestate_path);
|
StartGame(path.toStdString(), scan, std::move(boot_session_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::StartGame(const std::string& path, ScanForSecondDisc scan,
|
void MainWindow::StartGame(const std::string& path, ScanForSecondDisc scan,
|
||||||
const std::optional<std::string>& savestate_path)
|
std::unique_ptr<BootSessionData> boot_session_data)
|
||||||
{
|
{
|
||||||
if (scan == ScanForSecondDisc::Yes)
|
if (scan == ScanForSecondDisc::Yes)
|
||||||
{
|
{
|
||||||
std::shared_ptr<const UICommon::GameFile> game = m_game_list->FindGame(path);
|
std::shared_ptr<const UICommon::GameFile> game = m_game_list->FindGame(path);
|
||||||
if (game != nullptr)
|
if (game != nullptr)
|
||||||
{
|
{
|
||||||
ScanForSecondDiscAndStartGame(*game, savestate_path);
|
ScanForSecondDiscAndStartGame(*game, std::move(boot_session_data));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartGame(BootParameters::GenerateFromFile(path, savestate_path));
|
StartGame(BootParameters::GenerateFromFile(
|
||||||
|
path, boot_session_data ? std::move(*boot_session_data) : BootSessionData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::StartGame(const std::vector<std::string>& paths,
|
void MainWindow::StartGame(const std::vector<std::string>& paths,
|
||||||
const std::optional<std::string>& savestate_path)
|
std::unique_ptr<BootSessionData> boot_session_data)
|
||||||
{
|
{
|
||||||
StartGame(BootParameters::GenerateFromFile(paths, savestate_path));
|
StartGame(BootParameters::GenerateFromFile(
|
||||||
|
paths, boot_session_data ? std::move(*boot_session_data) : BootSessionData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
|
void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
|
||||||
@ -1363,13 +1372,15 @@ void MainWindow::NetPlayInit()
|
|||||||
{
|
{
|
||||||
const auto& game_list_model = m_game_list->GetGameListModel();
|
const auto& game_list_model = m_game_list->GetGameListModel();
|
||||||
m_netplay_setup_dialog = new NetPlaySetupDialog(game_list_model, this);
|
m_netplay_setup_dialog = new NetPlaySetupDialog(game_list_model, this);
|
||||||
m_netplay_dialog = new NetPlayDialog(game_list_model);
|
m_netplay_dialog = new NetPlayDialog(
|
||||||
|
game_list_model,
|
||||||
|
[this](const std::string& path, std::unique_ptr<BootSessionData> boot_session_data) {
|
||||||
|
StartGame(path, ScanForSecondDisc::Yes, std::move(boot_session_data));
|
||||||
|
});
|
||||||
#ifdef USE_DISCORD_PRESENCE
|
#ifdef USE_DISCORD_PRESENCE
|
||||||
m_netplay_discord = new DiscordHandler(this);
|
m_netplay_discord = new DiscordHandler(this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(m_netplay_dialog, &NetPlayDialog::Boot, this,
|
|
||||||
[this](const QString& path) { StartGame(path, ScanForSecondDisc::Yes); });
|
|
||||||
connect(m_netplay_dialog, &NetPlayDialog::Stop, this, &MainWindow::ForceStop);
|
connect(m_netplay_dialog, &NetPlayDialog::Stop, this, &MainWindow::ForceStop);
|
||||||
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);
|
||||||
@ -1818,8 +1829,7 @@ void MainWindow::ShowRiivolutionBootWidget(const UICommon::GameFile& game)
|
|||||||
std::vector<std::string> paths = {game.GetFilePath()};
|
std::vector<std::string> paths = {game.GetFilePath()};
|
||||||
if (second_game != nullptr)
|
if (second_game != nullptr)
|
||||||
paths.push_back(second_game->GetFilePath());
|
paths.push_back(second_game->GetFilePath());
|
||||||
std::unique_ptr<BootParameters> boot_params =
|
std::unique_ptr<BootParameters> boot_params = BootParameters::GenerateFromFile(paths);
|
||||||
BootParameters::GenerateFromFile(paths, std::nullopt);
|
|
||||||
if (!boot_params)
|
if (!boot_params)
|
||||||
return;
|
return;
|
||||||
if (!std::holds_alternative<BootParameters::Disc>(boot_params->parameters))
|
if (!std::holds_alternative<BootParameters::Disc>(boot_params->parameters))
|
||||||
|
@ -15,6 +15,7 @@ class QStackedWidget;
|
|||||||
class QString;
|
class QString;
|
||||||
|
|
||||||
class BreakpointWidget;
|
class BreakpointWidget;
|
||||||
|
class BootSessionData;
|
||||||
struct BootParameters;
|
struct BootParameters;
|
||||||
class CheatsManager;
|
class CheatsManager;
|
||||||
class CodeWidget;
|
class CodeWidget;
|
||||||
@ -132,13 +133,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void ScanForSecondDiscAndStartGame(const UICommon::GameFile& game,
|
void ScanForSecondDiscAndStartGame(const UICommon::GameFile& game,
|
||||||
const std::optional<std::string>& savestate_path = {});
|
std::unique_ptr<BootSessionData> boot_session_data = nullptr);
|
||||||
void StartGame(const QString& path, ScanForSecondDisc scan,
|
void StartGame(const QString& path, ScanForSecondDisc scan,
|
||||||
const std::optional<std::string>& savestate_path = {});
|
std::unique_ptr<BootSessionData> boot_session_data = nullptr);
|
||||||
void StartGame(const std::string& path, ScanForSecondDisc scan,
|
void StartGame(const std::string& path, ScanForSecondDisc scan,
|
||||||
const std::optional<std::string>& savestate_path = {});
|
std::unique_ptr<BootSessionData> boot_session_data = nullptr);
|
||||||
void StartGame(const std::vector<std::string>& paths,
|
void StartGame(const std::vector<std::string>& paths,
|
||||||
const std::optional<std::string>& savestate_path = {});
|
std::unique_ptr<BootSessionData> boot_session_data = nullptr);
|
||||||
void StartGame(std::unique_ptr<BootParameters>&& parameters);
|
void StartGame(std::unique_ptr<BootParameters>&& parameters);
|
||||||
void ShowRenderWidget();
|
void ShowRenderWidget();
|
||||||
void HideRenderWidget(bool reinit = true, bool is_exit = false);
|
void HideRenderWidget(bool reinit = true, bool is_exit = false);
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/TraversalClient.h"
|
#include "Common/TraversalClient.h"
|
||||||
|
|
||||||
|
#include "Core/Boot/Boot.h"
|
||||||
#include "Core/Config/GraphicsSettings.h"
|
#include "Core/Config/GraphicsSettings.h"
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
#include "Core/Config/NetplaySettings.h"
|
#include "Core/Config/NetplaySettings.h"
|
||||||
@ -39,6 +40,7 @@
|
|||||||
#ifdef HAS_LIBMGBA
|
#ifdef HAS_LIBMGBA
|
||||||
#include "Core/HW/GBACore.h"
|
#include "Core/HW/GBACore.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "Core/IOS/FS/FileSystem.h"
|
||||||
#include "Core/NetPlayServer.h"
|
#include "Core/NetPlayServer.h"
|
||||||
#include "Core/SyncIdentifier.h"
|
#include "Core/SyncIdentifier.h"
|
||||||
|
|
||||||
@ -62,8 +64,10 @@
|
|||||||
#include "VideoCommon/RenderBase.h"
|
#include "VideoCommon/RenderBase.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
NetPlayDialog::NetPlayDialog(const GameListModel& game_list_model, QWidget* parent)
|
NetPlayDialog::NetPlayDialog(const GameListModel& game_list_model,
|
||||||
: QDialog(parent), m_game_list_model(game_list_model)
|
StartGameCallback start_game_callback, QWidget* parent)
|
||||||
|
: QDialog(parent), m_game_list_model(game_list_model),
|
||||||
|
m_start_game_callback(std::move(start_game_callback))
|
||||||
{
|
{
|
||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
@ -682,10 +686,11 @@ void NetPlayDialog::UpdateGUI()
|
|||||||
|
|
||||||
// NetPlayUI methods
|
// NetPlayUI methods
|
||||||
|
|
||||||
void NetPlayDialog::BootGame(const std::string& filename)
|
void NetPlayDialog::BootGame(const std::string& filename,
|
||||||
|
std::unique_ptr<BootSessionData> boot_session_data)
|
||||||
{
|
{
|
||||||
m_got_stop_request = false;
|
m_got_stop_request = false;
|
||||||
emit Boot(QString::fromStdString(filename));
|
m_start_game_callback(filename, std::move(boot_session_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetPlayDialog::StopGame()
|
void NetPlayDialog::StopGame()
|
||||||
@ -1173,3 +1178,10 @@ void NetPlayDialog::SetChunkedProgress(const int pid, const u64 progress)
|
|||||||
m_chunked_progress_dialog->SetProgress(pid, progress);
|
m_chunked_progress_dialog->SetProgress(pid, progress);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetPlayDialog::SetHostWiiSyncTitles(std::vector<u64> titles)
|
||||||
|
{
|
||||||
|
auto client = Settings::Instance().GetNetPlayClient();
|
||||||
|
if (client)
|
||||||
|
client->SetWiiSyncData(nullptr, std::move(titles));
|
||||||
|
}
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
|
|
||||||
@ -11,6 +15,7 @@
|
|||||||
#include "DolphinQt/GameList/GameListModel.h"
|
#include "DolphinQt/GameList/GameListModel.h"
|
||||||
#include "VideoCommon/OnScreenDisplay.h"
|
#include "VideoCommon/OnScreenDisplay.h"
|
||||||
|
|
||||||
|
class BootSessionData;
|
||||||
class ChunkedProgressDialog;
|
class ChunkedProgressDialog;
|
||||||
class MD5Dialog;
|
class MD5Dialog;
|
||||||
class PadMappingDialog;
|
class PadMappingDialog;
|
||||||
@ -30,14 +35,19 @@ class NetPlayDialog : public QDialog, public NetPlay::NetPlayUI
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit NetPlayDialog(const GameListModel& game_list_model, QWidget* parent = nullptr);
|
using StartGameCallback = std::function<void(const std::string& path,
|
||||||
|
std::unique_ptr<BootSessionData> boot_session_data)>;
|
||||||
|
|
||||||
|
explicit NetPlayDialog(const GameListModel& game_list_model,
|
||||||
|
StartGameCallback start_game_callback, QWidget* parent = nullptr);
|
||||||
~NetPlayDialog();
|
~NetPlayDialog();
|
||||||
|
|
||||||
void show(std::string nickname, bool use_traversal);
|
void show(std::string nickname, bool use_traversal);
|
||||||
void reject() override;
|
void reject() override;
|
||||||
|
|
||||||
// NetPlayUI methods
|
// NetPlayUI methods
|
||||||
void BootGame(const std::string& filename) override;
|
void BootGame(const std::string& filename,
|
||||||
|
std::unique_ptr<BootSessionData> boot_session_data) override;
|
||||||
void StopGame() override;
|
void StopGame() override;
|
||||||
bool IsHosting() const override;
|
bool IsHosting() const override;
|
||||||
|
|
||||||
@ -84,8 +94,10 @@ public:
|
|||||||
const std::vector<int>& players) override;
|
const std::vector<int>& players) override;
|
||||||
void HideChunkedProgressDialog() override;
|
void HideChunkedProgressDialog() override;
|
||||||
void SetChunkedProgress(int pid, u64 progress) override;
|
void SetChunkedProgress(int pid, u64 progress) override;
|
||||||
|
|
||||||
|
void SetHostWiiSyncTitles(std::vector<u64> titles) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Boot(const QString& filename);
|
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -162,4 +174,6 @@ private:
|
|||||||
int m_player_count = 0;
|
int m_player_count = 0;
|
||||||
int m_old_player_count = 0;
|
int m_old_player_count = 0;
|
||||||
bool m_host_input_authority = false;
|
bool m_host_input_authority = false;
|
||||||
|
|
||||||
|
StartGameCallback m_start_game_callback;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user