NetPlay: Improve settings synchronization and UI
Most settings which affect determinism will now be synced on NetPlay. Additionally, there's a strict sync mode which will sync various enhancements to prevent desync in games that use EFB reads. This also adds a check for all players having the IPL.bin file, and doesn't load it for anyone if someone is missing it. This prevents desyncs caused by mismatched system fonts. Additionally, the NetPlay window was getting too wide with checkboxes, so FlowLayout has been introduced to make the checkboxes take up multiple rows dynamically. However, there's some minor vertical centering issues I haven't been able to solve, but it's better than a ridiculously wide window.
This commit is contained in:
parent
c141511c87
commit
7036299a92
|
@ -72,6 +72,7 @@ public:
|
|||
private:
|
||||
bool valid;
|
||||
bool bCPUThread;
|
||||
bool bJITFollowBranch;
|
||||
bool bEnableCheats;
|
||||
bool bSyncGPUOnSkipIdleHack;
|
||||
bool bFPRF;
|
||||
|
@ -81,6 +82,9 @@ private:
|
|||
bool bLowDCBZHack;
|
||||
bool m_EnableJIT;
|
||||
bool bSyncGPU;
|
||||
int iSyncGpuMaxDistance;
|
||||
int iSyncGpuMinDistance;
|
||||
float fSyncGpuOverclock;
|
||||
bool bFastDiscSpeed;
|
||||
bool bDSPHLE;
|
||||
bool bHLE_BS2;
|
||||
|
@ -103,6 +107,7 @@ void ConfigCache::SaveConfig(const SConfig& config)
|
|||
valid = true;
|
||||
|
||||
bCPUThread = config.bCPUThread;
|
||||
bJITFollowBranch = config.bJITFollowBranch;
|
||||
bEnableCheats = config.bEnableCheats;
|
||||
bSyncGPUOnSkipIdleHack = config.bSyncGPUOnSkipIdleHack;
|
||||
bFPRF = config.bFPRF;
|
||||
|
@ -111,6 +116,9 @@ void ConfigCache::SaveConfig(const SConfig& config)
|
|||
bDCBZOFF = config.bDCBZOFF;
|
||||
m_EnableJIT = config.m_DSPEnableJIT;
|
||||
bSyncGPU = config.bSyncGPU;
|
||||
iSyncGpuMaxDistance = config.iSyncGpuMaxDistance;
|
||||
iSyncGpuMinDistance = config.iSyncGpuMinDistance;
|
||||
fSyncGpuOverclock = config.fSyncGpuOverclock;
|
||||
bFastDiscSpeed = config.bFastDiscSpeed;
|
||||
bDSPHLE = config.bDSPHLE;
|
||||
bHLE_BS2 = config.bHLE_BS2;
|
||||
|
@ -143,6 +151,7 @@ void ConfigCache::RestoreConfig(SConfig* config)
|
|||
valid = false;
|
||||
|
||||
config->bCPUThread = bCPUThread;
|
||||
config->bJITFollowBranch = bJITFollowBranch;
|
||||
config->bEnableCheats = bEnableCheats;
|
||||
config->bSyncGPUOnSkipIdleHack = bSyncGPUOnSkipIdleHack;
|
||||
config->bFPRF = bFPRF;
|
||||
|
@ -152,6 +161,9 @@ void ConfigCache::RestoreConfig(SConfig* config)
|
|||
config->bLowDCBZHack = bLowDCBZHack;
|
||||
config->m_DSPEnableJIT = m_EnableJIT;
|
||||
config->bSyncGPU = bSyncGPU;
|
||||
config->iSyncGpuMaxDistance = iSyncGpuMaxDistance;
|
||||
config->iSyncGpuMinDistance = iSyncGpuMinDistance;
|
||||
config->fSyncGpuOverclock = fSyncGpuOverclock;
|
||||
config->bFastDiscSpeed = bFastDiscSpeed;
|
||||
config->bDSPHLE = bDSPHLE;
|
||||
config->bHLE_BS2 = bHLE_BS2;
|
||||
|
@ -240,7 +252,6 @@ bool BootCore(std::unique_ptr<BootParameters> boot)
|
|||
IniFile::Section* controls_section = game_ini.GetOrCreateSection("Controls");
|
||||
|
||||
core_section->Get("CPUThread", &StartUp.bCPUThread, StartUp.bCPUThread);
|
||||
|
||||
core_section->Get("JITFollowBranch", &StartUp.bJITFollowBranch, StartUp.bJITFollowBranch);
|
||||
core_section->Get("EnableCheats", &StartUp.bEnableCheats, StartUp.bEnableCheats);
|
||||
core_section->Get("SyncOnSkipIdle", &StartUp.bSyncGPUOnSkipIdleHack,
|
||||
|
@ -314,6 +325,7 @@ bool BootCore(std::unique_ptr<BootParameters> boot)
|
|||
{
|
||||
// TODO: remove this once ConfigManager starts using OnionConfig.
|
||||
StartUp.bCPUThread = Config::Get(Config::MAIN_CPU_THREAD);
|
||||
StartUp.bJITFollowBranch = Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH);
|
||||
StartUp.bDSPHLE = Config::Get(Config::MAIN_DSP_HLE);
|
||||
StartUp.bFastDiscSpeed = Config::Get(Config::MAIN_FAST_DISC_SPEED);
|
||||
StartUp.cpu_core = Config::Get(Config::MAIN_CPU_CORE);
|
||||
|
@ -353,6 +365,18 @@ bool BootCore(std::unique_ptr<BootParameters> boot)
|
|||
StartUp.m_EXIDevice[1] = netplay_settings.m_EXIDevice[1];
|
||||
config_cache.bSetEXIDevice[0] = true;
|
||||
config_cache.bSetEXIDevice[1] = true;
|
||||
StartUp.bFPRF = netplay_settings.m_FPRF;
|
||||
StartUp.bAccurateNaNs = netplay_settings.m_AccurateNaNs;
|
||||
StartUp.bSyncGPUOnSkipIdleHack = netplay_settings.m_SyncOnSkipIdle;
|
||||
StartUp.bSyncGPU = netplay_settings.m_SyncGPU;
|
||||
StartUp.iSyncGpuMaxDistance = netplay_settings.m_SyncGpuMaxDistance;
|
||||
StartUp.iSyncGpuMinDistance = netplay_settings.m_SyncGpuMinDistance;
|
||||
StartUp.fSyncGpuOverclock = netplay_settings.m_SyncGpuOverclock;
|
||||
StartUp.bJITFollowBranch = netplay_settings.m_JITFollowBranch;
|
||||
StartUp.bFastDiscSpeed = netplay_settings.m_FastDiscSpeed;
|
||||
StartUp.bMMU = netplay_settings.m_MMU;
|
||||
StartUp.bFastmem = netplay_settings.m_Fastmem;
|
||||
StartUp.bHLE_BS2 = netplay_settings.m_SkipIPL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -432,4 +456,4 @@ void RestoreConfig()
|
|||
config_cache.RestoreConfig(&SConfig::GetInstance());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace BootManager
|
||||
|
|
|
@ -16,8 +16,10 @@ namespace Config
|
|||
// Main.Core
|
||||
|
||||
const ConfigInfo<bool> MAIN_SKIP_IPL{{System::Main, "Core", "SkipIPL"}, true};
|
||||
const ConfigInfo<bool> MAIN_LOAD_IPL_DUMP{{System::Main, "Core", "LoadIPLDump"}, true};
|
||||
const ConfigInfo<PowerPC::CPUCore> MAIN_CPU_CORE{{System::Main, "Core", "CPUCore"},
|
||||
PowerPC::DefaultCPUCore()};
|
||||
const ConfigInfo<bool> MAIN_JIT_FOLLOW_BRANCH{{System::Main, "Core", "JITFollowBranch"}, true};
|
||||
const ConfigInfo<bool> MAIN_FASTMEM{{System::Main, "Core", "Fastmem"}, true};
|
||||
const ConfigInfo<bool> MAIN_DSP_HLE{{System::Main, "Core", "DSPHLE"}, true};
|
||||
const ConfigInfo<int> MAIN_TIMING_VARIANCE{{System::Main, "Core", "TimingVariance"}, 40};
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace Config
|
|||
{
|
||||
// Main.Core
|
||||
|
||||
extern const ConfigInfo<bool> MAIN_SKIP_IPL;
|
||||
extern const ConfigInfo<bool> MAIN_LOAD_IPL_DUMP;
|
||||
extern const ConfigInfo<PowerPC::CPUCore> MAIN_CPU_CORE;
|
||||
extern const ConfigInfo<bool> MAIN_JIT_FOLLOW_BRANCH;
|
||||
extern const ConfigInfo<bool> MAIN_FASTMEM;
|
||||
|
|
|
@ -83,6 +83,7 @@ static const INIToLocationMap& GetINIToLocationMap()
|
|||
static const INIToSectionMap& GetINIToSectionMap()
|
||||
{
|
||||
static const INIToSectionMap ini_to_section = {
|
||||
{"Core", {Config::System::Main, "Core"}},
|
||||
{"Video_Hardware", {Config::System::GFX, "Hardware"}},
|
||||
{"Video_Settings", {Config::System::GFX, "Settings"}},
|
||||
{"Video_Enhancements", {Config::System::GFX, "Enhancements"}},
|
||||
|
@ -315,4 +316,4 @@ std::unique_ptr<Config::ConfigLayerLoader> GenerateLocalGameConfigLoader(const s
|
|||
{
|
||||
return std::make_unique<INIGameConfigLayerLoader>(id, revision, false);
|
||||
}
|
||||
}
|
||||
} // namespace ConfigLoaders
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Common/CommonPaths.h"
|
||||
#include "Common/Config/Config.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/Config/SYSCONFSettings.h"
|
||||
#include "Core/NetPlayProto.h"
|
||||
|
@ -36,11 +37,57 @@ public:
|
|||
layer->Set(Config::MAIN_SLOT_B, static_cast<int>(m_settings.m_EXIDevice[1]));
|
||||
layer->Set(Config::MAIN_WII_SD_CARD_WRITABLE, m_settings.m_WriteToMemcard);
|
||||
layer->Set(Config::MAIN_REDUCE_POLLING_RATE, m_settings.m_ReducePollingRate);
|
||||
|
||||
layer->Set(Config::MAIN_DSP_JIT, m_settings.m_DSPEnableJIT);
|
||||
|
||||
layer->Set(Config::SYSCONF_PROGRESSIVE_SCAN, m_settings.m_ProgressiveScan);
|
||||
layer->Set(Config::SYSCONF_PAL60, m_settings.m_PAL60);
|
||||
layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, m_settings.m_EFBAccessEnable);
|
||||
layer->Set(Config::GFX_HACK_BBOX_ENABLE, m_settings.m_BBoxEnable);
|
||||
layer->Set(Config::GFX_HACK_FORCE_PROGRESSIVE, m_settings.m_ForceProgressive);
|
||||
layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, m_settings.m_EFBToTextureEnable);
|
||||
layer->Set(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, m_settings.m_XFBToTextureEnable);
|
||||
layer->Set(Config::GFX_HACK_DISABLE_COPY_TO_VRAM, m_settings.m_DisableCopyToVRAM);
|
||||
layer->Set(Config::GFX_HACK_IMMEDIATE_XFB, m_settings.m_ImmediateXFBEnable);
|
||||
layer->Set(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, m_settings.m_EFBEmulateFormatChanges);
|
||||
layer->Set(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES,
|
||||
m_settings.m_SafeTextureCacheColorSamples);
|
||||
layer->Set(Config::GFX_PERF_QUERIES_ENABLE, m_settings.m_PerfQueriesEnable);
|
||||
layer->Set(Config::MAIN_FPRF, m_settings.m_FPRF);
|
||||
layer->Set(Config::MAIN_ACCURATE_NANS, m_settings.m_AccurateNaNs);
|
||||
layer->Set(Config::MAIN_SYNC_ON_SKIP_IDLE, m_settings.m_SyncOnSkipIdle);
|
||||
layer->Set(Config::MAIN_SYNC_GPU, m_settings.m_SyncGPU);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_MAX_DISTANCE, m_settings.m_SyncGpuMaxDistance);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_MIN_DISTANCE, m_settings.m_SyncGpuMinDistance);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_OVERCLOCK, m_settings.m_SyncGpuOverclock);
|
||||
layer->Set(Config::MAIN_JIT_FOLLOW_BRANCH, m_settings.m_JITFollowBranch);
|
||||
layer->Set(Config::MAIN_FAST_DISC_SPEED, m_settings.m_FastDiscSpeed);
|
||||
layer->Set(Config::MAIN_MMU, m_settings.m_MMU);
|
||||
layer->Set(Config::MAIN_FASTMEM, m_settings.m_Fastmem);
|
||||
layer->Set(Config::MAIN_SKIP_IPL, m_settings.m_SkipIPL);
|
||||
layer->Set(Config::MAIN_LOAD_IPL_DUMP, m_settings.m_LoadIPLDump);
|
||||
|
||||
if (m_settings.m_StrictSettingsSync)
|
||||
{
|
||||
layer->Set(Config::GFX_HACK_VERTEX_ROUDING, m_settings.m_VertexRounding);
|
||||
layer->Set(Config::GFX_EFB_SCALE, m_settings.m_InternalResolution);
|
||||
layer->Set(Config::GFX_HACK_COPY_EFB_SCALED, m_settings.m_EFBScaledCopy);
|
||||
layer->Set(Config::GFX_FAST_DEPTH_CALC, m_settings.m_FastDepthCalc);
|
||||
layer->Set(Config::GFX_ENABLE_PIXEL_LIGHTING, m_settings.m_EnablePixelLighting);
|
||||
layer->Set(Config::GFX_WIDESCREEN_HACK, m_settings.m_WidescreenHack);
|
||||
layer->Set(Config::GFX_ENHANCE_FORCE_FILTERING, m_settings.m_ForceFiltering);
|
||||
layer->Set(Config::GFX_ENHANCE_MAX_ANISOTROPY, m_settings.m_MaxAnisotropy);
|
||||
layer->Set(Config::GFX_ENHANCE_FORCE_TRUE_COLOR, m_settings.m_ForceTrueColor);
|
||||
layer->Set(Config::GFX_ENHANCE_DISABLE_COPY_FILTER, m_settings.m_DisableCopyFilter);
|
||||
layer->Set(Config::GFX_DISABLE_FOG, m_settings.m_DisableFog);
|
||||
layer->Set(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION,
|
||||
m_settings.m_ArbitraryMipmapDetection);
|
||||
layer->Set(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD,
|
||||
m_settings.m_ArbitraryMipmapDetectionThreshold);
|
||||
layer->Set(Config::GFX_ENABLE_GPU_TEXTURE_DECODING, m_settings.m_EnableGPUTextureDecoding);
|
||||
|
||||
// Disable AA as it isn't deterministic across GPUs
|
||||
layer->Set(Config::GFX_MSAA, 1);
|
||||
layer->Set(Config::GFX_SSAA, false);
|
||||
}
|
||||
|
||||
if (m_settings.m_SyncSaveData)
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Config/Config.h"
|
||||
#include "Common/File.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
@ -19,6 +20,7 @@
|
|||
#include "Common/Swap.h"
|
||||
#include "Common/Timer.h"
|
||||
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
|
@ -102,7 +104,8 @@ CEXIIPL::CEXIIPL()
|
|||
|
||||
// Load whole ROM dump
|
||||
// Note: The Wii doesn't have a copy of the IPL, only fonts.
|
||||
if (!SConfig::GetInstance().bWii && LoadFileToIPL(SConfig::GetInstance().m_strBootROM, 0))
|
||||
if (!SConfig::GetInstance().bWii && Config::Get(Config::MAIN_LOAD_IPL_DUMP) &&
|
||||
LoadFileToIPL(SConfig::GetInstance().m_strBootROM, 0))
|
||||
{
|
||||
// Descramble the encrypted section (contains BS1 and BS2)
|
||||
Descrambler(m_ipl + 0x100, 0x1afe00);
|
||||
|
@ -185,6 +188,17 @@ std::string CEXIIPL::FindIPLDump(const std::string& path_prefix)
|
|||
return ipl_dump_path;
|
||||
}
|
||||
|
||||
bool CEXIIPL::HasIPLDump()
|
||||
{
|
||||
std::string ipl_rom_path = FindIPLDump(File::GetUserPath(D_GCUSER_IDX));
|
||||
|
||||
// If not found, check again in Sys folder
|
||||
if (ipl_rom_path.empty())
|
||||
ipl_rom_path = FindIPLDump(File::GetSysDirectory() + GC_SYS_DIR);
|
||||
|
||||
return !ipl_rom_path.empty();
|
||||
}
|
||||
|
||||
void CEXIIPL::LoadFontFile(const std::string& filename, u32 offset)
|
||||
{
|
||||
// Official IPL fonts are copyrighted. Dolphin ships with a set of free font alternatives but
|
||||
|
@ -192,6 +206,13 @@ void CEXIIPL::LoadFontFile(const std::string& filename, u32 offset)
|
|||
// in some titles. This function check if the user has IPL dumps available and load the fonts
|
||||
// from those dumps instead of loading the bundled fonts
|
||||
|
||||
if (!Config::Get(Config::MAIN_LOAD_IPL_DUMP))
|
||||
{
|
||||
// IPL loading disabled, load bundled font instead
|
||||
LoadFileToIPL(filename, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for IPL dumps in User folder
|
||||
std::string ipl_rom_path = FindIPLDump(File::GetUserPath(D_GCUSER_IDX));
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ public:
|
|||
|
||||
static void Descrambler(u8* data, u32 size);
|
||||
|
||||
static bool HasIPLDump();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
@ -74,6 +76,7 @@ private:
|
|||
u32 CommandRegion() const { return (m_address & ~(1 << 31)) >> 8; }
|
||||
bool LoadFileToIPL(const std::string& filename, u32 offset);
|
||||
void LoadFontFile(const std::string& filename, u32 offset);
|
||||
std::string FindIPLDump(const std::string& path_prefix);
|
||||
|
||||
static std::string FindIPLDump(const std::string& path_prefix);
|
||||
};
|
||||
} // namespace ExpansionInterface
|
||||
|
|
|
@ -424,6 +424,11 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||
|
||||
game_status_packet << static_cast<u32>(status);
|
||||
Send(game_status_packet);
|
||||
|
||||
sf::Packet ipl_status_packet;
|
||||
ipl_status_packet << static_cast<MessageId>(NP_MSG_IPL_STATUS);
|
||||
ipl_status_packet << ExpansionInterface::CEXIIPL::HasIPLDump();
|
||||
Send(ipl_status_packet);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -480,6 +485,45 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||
packet >> tmp;
|
||||
m_net_settings.m_EXIDevice[1] = static_cast<ExpansionInterface::TEXIDevices>(tmp);
|
||||
|
||||
packet >> m_net_settings.m_EFBAccessEnable;
|
||||
packet >> m_net_settings.m_BBoxEnable;
|
||||
packet >> m_net_settings.m_ForceProgressive;
|
||||
packet >> m_net_settings.m_EFBToTextureEnable;
|
||||
packet >> m_net_settings.m_XFBToTextureEnable;
|
||||
packet >> m_net_settings.m_DisableCopyToVRAM;
|
||||
packet >> m_net_settings.m_ImmediateXFBEnable;
|
||||
packet >> m_net_settings.m_EFBEmulateFormatChanges;
|
||||
packet >> m_net_settings.m_SafeTextureCacheColorSamples;
|
||||
packet >> m_net_settings.m_PerfQueriesEnable;
|
||||
packet >> m_net_settings.m_FPRF;
|
||||
packet >> m_net_settings.m_AccurateNaNs;
|
||||
packet >> m_net_settings.m_SyncOnSkipIdle;
|
||||
packet >> m_net_settings.m_SyncGPU;
|
||||
packet >> m_net_settings.m_SyncGpuMaxDistance;
|
||||
packet >> m_net_settings.m_SyncGpuMinDistance;
|
||||
packet >> m_net_settings.m_SyncGpuOverclock;
|
||||
packet >> m_net_settings.m_JITFollowBranch;
|
||||
packet >> m_net_settings.m_FastDiscSpeed;
|
||||
packet >> m_net_settings.m_MMU;
|
||||
packet >> m_net_settings.m_Fastmem;
|
||||
packet >> m_net_settings.m_SkipIPL;
|
||||
packet >> m_net_settings.m_LoadIPLDump;
|
||||
packet >> m_net_settings.m_VertexRounding;
|
||||
packet >> m_net_settings.m_InternalResolution;
|
||||
packet >> m_net_settings.m_EFBScaledCopy;
|
||||
packet >> m_net_settings.m_FastDepthCalc;
|
||||
packet >> m_net_settings.m_EnablePixelLighting;
|
||||
packet >> m_net_settings.m_WidescreenHack;
|
||||
packet >> m_net_settings.m_ForceFiltering;
|
||||
packet >> m_net_settings.m_MaxAnisotropy;
|
||||
packet >> m_net_settings.m_ForceTrueColor;
|
||||
packet >> m_net_settings.m_DisableCopyFilter;
|
||||
packet >> m_net_settings.m_DisableFog;
|
||||
packet >> m_net_settings.m_ArbitraryMipmapDetection;
|
||||
packet >> m_net_settings.m_ArbitraryMipmapDetectionThreshold;
|
||||
packet >> m_net_settings.m_EnableGPUTextureDecoding;
|
||||
packet >> m_net_settings.m_StrictSettingsSync;
|
||||
|
||||
g_netplay_initial_rtc = Common::PacketReadU64(packet);
|
||||
|
||||
packet >> m_net_settings.m_SyncSaveData;
|
||||
|
|
|
@ -37,6 +37,44 @@ struct NetSettings
|
|||
bool m_OCEnable;
|
||||
float m_OCFactor;
|
||||
ExpansionInterface::TEXIDevices m_EXIDevice[2];
|
||||
bool m_EFBAccessEnable;
|
||||
bool m_BBoxEnable;
|
||||
bool m_ForceProgressive;
|
||||
bool m_EFBToTextureEnable;
|
||||
bool m_XFBToTextureEnable;
|
||||
bool m_DisableCopyToVRAM;
|
||||
bool m_ImmediateXFBEnable;
|
||||
bool m_EFBEmulateFormatChanges;
|
||||
int m_SafeTextureCacheColorSamples;
|
||||
bool m_PerfQueriesEnable;
|
||||
bool m_FPRF;
|
||||
bool m_AccurateNaNs;
|
||||
bool m_SyncOnSkipIdle;
|
||||
bool m_SyncGPU;
|
||||
int m_SyncGpuMaxDistance;
|
||||
int m_SyncGpuMinDistance;
|
||||
float m_SyncGpuOverclock;
|
||||
bool m_JITFollowBranch;
|
||||
bool m_FastDiscSpeed;
|
||||
bool m_MMU;
|
||||
bool m_Fastmem;
|
||||
bool m_SkipIPL;
|
||||
bool m_LoadIPLDump;
|
||||
bool m_VertexRounding;
|
||||
int m_InternalResolution;
|
||||
bool m_EFBScaledCopy;
|
||||
bool m_FastDepthCalc;
|
||||
bool m_EnablePixelLighting;
|
||||
bool m_WidescreenHack;
|
||||
bool m_ForceFiltering;
|
||||
int m_MaxAnisotropy;
|
||||
bool m_ForceTrueColor;
|
||||
bool m_DisableCopyFilter;
|
||||
bool m_DisableFog;
|
||||
bool m_ArbitraryMipmapDetection;
|
||||
float m_ArbitraryMipmapDetectionThreshold;
|
||||
bool m_EnableGPUTextureDecoding;
|
||||
bool m_StrictSettingsSync;
|
||||
bool m_SyncSaveData;
|
||||
std::string m_SaveDataRegion;
|
||||
bool m_IsHosting;
|
||||
|
@ -83,6 +121,7 @@ enum
|
|||
NP_MSG_STOP_GAME = 0xA2,
|
||||
NP_MSG_DISABLE_GAME = 0xA3,
|
||||
NP_MSG_GAME_STATUS = 0xA4,
|
||||
NP_MSG_IPL_STATUS = 0xA5,
|
||||
|
||||
NP_MSG_TIMEBASE = 0xB0,
|
||||
NP_MSG_DESYNC_DETECTED = 0xB1,
|
||||
|
|
|
@ -662,6 +662,15 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
|
|||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_IPL_STATUS:
|
||||
{
|
||||
bool status;
|
||||
packet >> status;
|
||||
|
||||
m_players[player.pid].has_ipl_dump = status;
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_TIMEBASE:
|
||||
{
|
||||
u64 timebase = Common::PacketReadU64(packet);
|
||||
|
@ -861,6 +870,12 @@ void NetPlayServer::SetNetSettings(const NetSettings& settings)
|
|||
m_settings = settings;
|
||||
}
|
||||
|
||||
bool NetPlayServer::DoAllPlayersHaveIPLDump() const
|
||||
{
|
||||
return std::all_of(m_players.begin(), m_players.end(),
|
||||
[](const auto& p) { return p.second.has_ipl_dump; });
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
bool NetPlayServer::RequestStartGame()
|
||||
{
|
||||
|
@ -921,6 +936,44 @@ bool NetPlayServer::StartGame()
|
|||
spac << m_settings.m_ReducePollingRate;
|
||||
spac << m_settings.m_EXIDevice[0];
|
||||
spac << m_settings.m_EXIDevice[1];
|
||||
spac << m_settings.m_EFBAccessEnable;
|
||||
spac << m_settings.m_BBoxEnable;
|
||||
spac << m_settings.m_ForceProgressive;
|
||||
spac << m_settings.m_EFBToTextureEnable;
|
||||
spac << m_settings.m_XFBToTextureEnable;
|
||||
spac << m_settings.m_DisableCopyToVRAM;
|
||||
spac << m_settings.m_ImmediateXFBEnable;
|
||||
spac << m_settings.m_EFBEmulateFormatChanges;
|
||||
spac << m_settings.m_SafeTextureCacheColorSamples;
|
||||
spac << m_settings.m_PerfQueriesEnable;
|
||||
spac << m_settings.m_FPRF;
|
||||
spac << m_settings.m_AccurateNaNs;
|
||||
spac << m_settings.m_SyncOnSkipIdle;
|
||||
spac << m_settings.m_SyncGPU;
|
||||
spac << m_settings.m_SyncGpuMaxDistance;
|
||||
spac << m_settings.m_SyncGpuMinDistance;
|
||||
spac << m_settings.m_SyncGpuOverclock;
|
||||
spac << m_settings.m_JITFollowBranch;
|
||||
spac << m_settings.m_FastDiscSpeed;
|
||||
spac << m_settings.m_MMU;
|
||||
spac << m_settings.m_Fastmem;
|
||||
spac << m_settings.m_SkipIPL;
|
||||
spac << m_settings.m_LoadIPLDump;
|
||||
spac << m_settings.m_VertexRounding;
|
||||
spac << m_settings.m_InternalResolution;
|
||||
spac << m_settings.m_EFBScaledCopy;
|
||||
spac << m_settings.m_FastDepthCalc;
|
||||
spac << m_settings.m_EnablePixelLighting;
|
||||
spac << m_settings.m_WidescreenHack;
|
||||
spac << m_settings.m_ForceFiltering;
|
||||
spac << m_settings.m_MaxAnisotropy;
|
||||
spac << m_settings.m_ForceTrueColor;
|
||||
spac << m_settings.m_DisableCopyFilter;
|
||||
spac << m_settings.m_DisableFog;
|
||||
spac << m_settings.m_ArbitraryMipmapDetection;
|
||||
spac << m_settings.m_ArbitraryMipmapDetectionThreshold;
|
||||
spac << m_settings.m_EnableGPUTextureDecoding;
|
||||
spac << m_settings.m_StrictSettingsSync;
|
||||
Common::PacketWriteU64(spac, g_netplay_initial_rtc);
|
||||
spac << m_settings.m_SyncSaveData;
|
||||
spac << region;
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
|
||||
void SetNetSettings(const NetSettings& settings);
|
||||
|
||||
bool DoAllPlayersHaveIPLDump() const;
|
||||
bool StartGame();
|
||||
bool RequestStartGame();
|
||||
|
||||
|
@ -69,6 +70,7 @@ private:
|
|||
std::string name;
|
||||
std::string revision;
|
||||
PlayerGameStatus game_status;
|
||||
bool has_ipl_dump;
|
||||
|
||||
ENetPeer* socket;
|
||||
u32 ping;
|
||||
|
|
|
@ -98,6 +98,7 @@ add_executable(dolphin-emu
|
|||
NetPlay/PadMappingDialog.cpp
|
||||
QtUtils/DoubleClickEventFilter.cpp
|
||||
QtUtils/ElidedButton.cpp
|
||||
QtUtils/FlowLayout.cpp
|
||||
QtUtils/ImageConverter.cpp
|
||||
QtUtils/SignalDaemon.cpp
|
||||
QtUtils/WindowActivationEventFilter.cpp
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
<QtMoc Include="QtUtils\BlockUserInputFilter.h" />
|
||||
<QtMoc Include="QtUtils\DoubleClickEventFilter.h" />
|
||||
<QtMoc Include="QtUtils\ElidedButton.h" />
|
||||
<QtMoc Include="QtUtils\FlowLayout.h" />
|
||||
<QtMoc Include="QtUtils\WindowActivationEventFilter.h" />
|
||||
<QtMoc Include="QtUtils\WrapInScrollArea.h" />
|
||||
<QtMoc Include="RenderWidget.h" />
|
||||
|
@ -176,6 +177,7 @@
|
|||
<ClCompile Include="$(QtMocOutPrefix)ControllersWindow.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)DoubleClickEventFilter.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)ElidedButton.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)FlowLayout.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)EnhancementsWidget.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)FIFOAnalyzer.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)FIFOPlayerWindow.cpp" />
|
||||
|
@ -351,6 +353,7 @@
|
|||
<ClCompile Include="QtUtils\BlockUserInputFilter.cpp" />
|
||||
<ClCompile Include="QtUtils\DoubleClickEventFilter.cpp" />
|
||||
<ClCompile Include="QtUtils\ElidedButton.cpp" />
|
||||
<ClCompile Include="QtUtils\FlowLayout.cpp" />
|
||||
<ClCompile Include="QtUtils\ImageConverter.cpp" />
|
||||
<ClCompile Include="QtUtils\WindowActivationEventFilter.cpp" />
|
||||
<ClCompile Include="QtUtils\WrapInScrollArea.cpp" />
|
||||
|
|
|
@ -31,7 +31,10 @@
|
|||
#include "Common/Config/Config.h"
|
||||
#include "Common/TraversalClient.h"
|
||||
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/Config/SYSCONFSettings.h"
|
||||
#include "Core/ConfigLoaders/GameConfigLoader.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/NetPlayServer.h"
|
||||
|
@ -40,11 +43,14 @@
|
|||
#include "DolphinQt/NetPlay/GameListDialog.h"
|
||||
#include "DolphinQt/NetPlay/MD5Dialog.h"
|
||||
#include "DolphinQt/NetPlay/PadMappingDialog.h"
|
||||
#include "DolphinQt/QtUtils/FlowLayout.h"
|
||||
#include "DolphinQt/QtUtils/QueueOnObject.h"
|
||||
#include "DolphinQt/QtUtils/RunOnObject.h"
|
||||
#include "DolphinQt/Resources.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "UICommon/GameFile.h"
|
||||
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
NetPlayDialog::NetPlayDialog(QWidget* parent)
|
||||
|
@ -89,6 +95,7 @@ void NetPlayDialog::CreateMainLayout()
|
|||
m_sync_save_data_box = new QCheckBox(tr("Sync Saves"));
|
||||
m_record_input_box = new QCheckBox(tr("Record inputs"));
|
||||
m_reduce_polling_rate_box = new QCheckBox(tr("Reduce Polling Rate"));
|
||||
m_strict_settings_sync_box = new QCheckBox(tr("Strict Settings Sync"));
|
||||
m_buffer_label = new QLabel(tr("Buffer:"));
|
||||
m_quit_button = new QPushButton(tr("Quit"));
|
||||
m_splitter = new QSplitter(Qt::Horizontal);
|
||||
|
@ -128,6 +135,10 @@ void NetPlayDialog::CreateMainLayout()
|
|||
m_reduce_polling_rate_box->setToolTip(
|
||||
tr("This will reduce bandwidth usage by polling GameCube controllers only twice per frame. "
|
||||
"Does not affect Wii Remotes."));
|
||||
m_strict_settings_sync_box->setToolTip(
|
||||
tr("This will sync additional graphics settings, and force everyone to the same internal "
|
||||
"resolution.\nMay prevent desync in some games that use EFB reads. Please ensure everyone "
|
||||
"uses the same video backend."));
|
||||
|
||||
m_main_layout->addWidget(m_game_button, 0, 0);
|
||||
m_main_layout->addWidget(m_md5_button, 0, 1);
|
||||
|
@ -136,18 +147,25 @@ void NetPlayDialog::CreateMainLayout()
|
|||
m_splitter->addWidget(m_chat_box);
|
||||
m_splitter->addWidget(m_players_box);
|
||||
|
||||
auto* options_widget = new QHBoxLayout;
|
||||
auto* options_widget = new QGridLayout;
|
||||
auto* options_boxes = new FlowLayout;
|
||||
|
||||
options_widget->addWidget(m_start_button, 0, 0, Qt::AlignVCenter);
|
||||
options_widget->addWidget(m_buffer_label, 0, 1, Qt::AlignVCenter);
|
||||
options_widget->addWidget(m_buffer_size_box, 0, 2, Qt::AlignVCenter);
|
||||
options_widget->addWidget(m_quit_button, 0, 4, Qt::AlignVCenter);
|
||||
options_boxes->addWidget(m_save_sd_box);
|
||||
options_boxes->addWidget(m_load_wii_box);
|
||||
options_boxes->addWidget(m_sync_save_data_box);
|
||||
options_boxes->addWidget(m_record_input_box);
|
||||
options_boxes->addWidget(m_reduce_polling_rate_box);
|
||||
options_boxes->addWidget(m_strict_settings_sync_box);
|
||||
|
||||
options_widget->addLayout(options_boxes, 0, 3, Qt::AlignTop);
|
||||
options_widget->setColumnStretch(3, 1000);
|
||||
|
||||
options_widget->addWidget(m_start_button);
|
||||
options_widget->addWidget(m_buffer_label);
|
||||
options_widget->addWidget(m_buffer_size_box);
|
||||
options_widget->addWidget(m_save_sd_box);
|
||||
options_widget->addWidget(m_load_wii_box);
|
||||
options_widget->addWidget(m_sync_save_data_box);
|
||||
options_widget->addWidget(m_record_input_box);
|
||||
options_widget->addWidget(m_reduce_polling_rate_box);
|
||||
options_widget->addWidget(m_quit_button);
|
||||
m_main_layout->addLayout(options_widget, 2, 0, 1, -1, Qt::AlignRight);
|
||||
m_main_layout->setRowStretch(1, 1000);
|
||||
|
||||
setLayout(m_main_layout);
|
||||
}
|
||||
|
@ -289,28 +307,97 @@ void NetPlayDialog::OnStart()
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_strict_settings_sync_box->isChecked() && Config::Get(Config::GFX_EFB_SCALE) == 0)
|
||||
{
|
||||
QMessageBox::critical(
|
||||
this, tr("Error"),
|
||||
tr("Auto internal resolution is not allowed in strict sync mode, as it depends on window "
|
||||
"size.\n\nPlease select a specific internal resolution."));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto game = FindGameFile(m_current_game);
|
||||
if (!game)
|
||||
{
|
||||
PanicAlertT("Selected game doesn't exist in game list!");
|
||||
return;
|
||||
}
|
||||
|
||||
NetPlay::NetSettings settings;
|
||||
|
||||
// Load GameINI so we can sync the settings from it
|
||||
Config::AddLayer(
|
||||
ConfigLoaders::GenerateGlobalGameConfigLoader(game->GetGameID(), game->GetRevision()));
|
||||
Config::AddLayer(
|
||||
ConfigLoaders::GenerateLocalGameConfigLoader(game->GetGameID(), game->GetRevision()));
|
||||
|
||||
// Copy all relevant settings
|
||||
SConfig& instance = SConfig::GetInstance();
|
||||
settings.m_CPUthread = instance.bCPUThread;
|
||||
settings.m_CPUcore = instance.cpu_core;
|
||||
settings.m_EnableCheats = instance.bEnableCheats;
|
||||
settings.m_SelectedLanguage = instance.SelectedLanguage;
|
||||
settings.m_OverrideGCLanguage = instance.bOverrideGCLanguage;
|
||||
settings.m_CPUthread = Config::Get(Config::MAIN_CPU_THREAD);
|
||||
settings.m_CPUcore = Config::Get(Config::MAIN_CPU_CORE);
|
||||
settings.m_EnableCheats = Config::Get(Config::MAIN_ENABLE_CHEATS);
|
||||
settings.m_SelectedLanguage = Config::Get(Config::MAIN_GC_LANGUAGE);
|
||||
settings.m_OverrideGCLanguage = Config::Get(Config::MAIN_OVERRIDE_GC_LANGUAGE);
|
||||
settings.m_ProgressiveScan = Config::Get(Config::SYSCONF_PROGRESSIVE_SCAN);
|
||||
settings.m_PAL60 = Config::Get(Config::SYSCONF_PAL60);
|
||||
settings.m_DSPHLE = instance.bDSPHLE;
|
||||
settings.m_DSPEnableJIT = instance.m_DSPEnableJIT;
|
||||
settings.m_DSPHLE = Config::Get(Config::MAIN_DSP_HLE);
|
||||
settings.m_DSPEnableJIT = Config::Get(Config::MAIN_DSP_JIT);
|
||||
settings.m_WriteToMemcard = m_save_sd_box->isChecked();
|
||||
settings.m_CopyWiiSave = m_load_wii_box->isChecked();
|
||||
settings.m_OCEnable = instance.m_OCEnable;
|
||||
settings.m_OCFactor = instance.m_OCFactor;
|
||||
settings.m_OCEnable = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
|
||||
settings.m_OCFactor = Config::Get(Config::MAIN_OVERCLOCK);
|
||||
settings.m_ReducePollingRate = m_reduce_polling_rate_box->isChecked();
|
||||
settings.m_EXIDevice[0] = instance.m_EXIDevice[0];
|
||||
settings.m_EXIDevice[1] = instance.m_EXIDevice[1];
|
||||
settings.m_EXIDevice[0] =
|
||||
static_cast<ExpansionInterface::TEXIDevices>(Config::Get(Config::MAIN_SLOT_A));
|
||||
settings.m_EXIDevice[1] =
|
||||
static_cast<ExpansionInterface::TEXIDevices>(Config::Get(Config::MAIN_SLOT_B));
|
||||
settings.m_EFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
|
||||
settings.m_BBoxEnable = Config::Get(Config::GFX_HACK_BBOX_ENABLE);
|
||||
settings.m_ForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE);
|
||||
settings.m_EFBToTextureEnable = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
|
||||
settings.m_XFBToTextureEnable = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
|
||||
settings.m_DisableCopyToVRAM = Config::Get(Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
|
||||
settings.m_ImmediateXFBEnable = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB);
|
||||
settings.m_EFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
|
||||
settings.m_SafeTextureCacheColorSamples =
|
||||
Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES);
|
||||
settings.m_PerfQueriesEnable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);
|
||||
settings.m_FPRF = Config::Get(Config::MAIN_FPRF);
|
||||
settings.m_AccurateNaNs = Config::Get(Config::MAIN_ACCURATE_NANS);
|
||||
settings.m_SyncOnSkipIdle = Config::Get(Config::MAIN_SYNC_ON_SKIP_IDLE);
|
||||
settings.m_SyncGPU = Config::Get(Config::MAIN_SYNC_GPU);
|
||||
settings.m_SyncGpuMaxDistance = Config::Get(Config::MAIN_SYNC_GPU_MAX_DISTANCE);
|
||||
settings.m_SyncGpuMinDistance = Config::Get(Config::MAIN_SYNC_GPU_MIN_DISTANCE);
|
||||
settings.m_SyncGpuOverclock = Config::Get(Config::MAIN_SYNC_GPU_OVERCLOCK);
|
||||
settings.m_JITFollowBranch = Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH);
|
||||
settings.m_FastDiscSpeed = Config::Get(Config::MAIN_FAST_DISC_SPEED);
|
||||
settings.m_MMU = Config::Get(Config::MAIN_MMU);
|
||||
settings.m_Fastmem = Config::Get(Config::MAIN_FASTMEM);
|
||||
settings.m_SkipIPL = Config::Get(Config::MAIN_SKIP_IPL) ||
|
||||
!Settings::Instance().GetNetPlayServer()->DoAllPlayersHaveIPLDump();
|
||||
settings.m_LoadIPLDump = Config::Get(Config::MAIN_LOAD_IPL_DUMP) &&
|
||||
Settings::Instance().GetNetPlayServer()->DoAllPlayersHaveIPLDump();
|
||||
settings.m_VertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUDING);
|
||||
settings.m_InternalResolution = Config::Get(Config::GFX_EFB_SCALE);
|
||||
settings.m_EFBScaledCopy = Config::Get(Config::GFX_HACK_COPY_EFB_SCALED);
|
||||
settings.m_FastDepthCalc = Config::Get(Config::GFX_FAST_DEPTH_CALC);
|
||||
settings.m_EnablePixelLighting = Config::Get(Config::GFX_ENABLE_PIXEL_LIGHTING);
|
||||
settings.m_WidescreenHack = Config::Get(Config::GFX_WIDESCREEN_HACK);
|
||||
settings.m_ForceFiltering = Config::Get(Config::GFX_ENHANCE_FORCE_FILTERING);
|
||||
settings.m_MaxAnisotropy = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
|
||||
settings.m_ForceTrueColor = Config::Get(Config::GFX_ENHANCE_FORCE_TRUE_COLOR);
|
||||
settings.m_DisableCopyFilter = Config::Get(Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
|
||||
settings.m_DisableFog = Config::Get(Config::GFX_DISABLE_FOG);
|
||||
settings.m_ArbitraryMipmapDetection = Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
|
||||
settings.m_ArbitraryMipmapDetectionThreshold =
|
||||
Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD);
|
||||
settings.m_EnableGPUTextureDecoding = Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
|
||||
settings.m_StrictSettingsSync = m_strict_settings_sync_box->isChecked();
|
||||
settings.m_SyncSaveData = m_sync_save_data_box->isChecked();
|
||||
|
||||
// Unload GameINI to restore things to normal
|
||||
Config::RemoveLayer(Config::LayerType::GlobalGame);
|
||||
Config::RemoveLayer(Config::LayerType::LocalGame);
|
||||
|
||||
Settings::Instance().GetNetPlayServer()->SetNetSettings(settings);
|
||||
if (Settings::Instance().GetNetPlayServer()->RequestStartGame())
|
||||
SetOptionsEnabled(false);
|
||||
|
@ -354,6 +441,7 @@ void NetPlayDialog::show(std::string nickname, bool use_traversal)
|
|||
m_load_wii_box->setHidden(!is_hosting);
|
||||
m_sync_save_data_box->setHidden(!is_hosting);
|
||||
m_reduce_polling_rate_box->setHidden(!is_hosting);
|
||||
m_strict_settings_sync_box->setHidden(!is_hosting);
|
||||
m_buffer_size_box->setHidden(!is_hosting);
|
||||
m_buffer_label->setHidden(!is_hosting);
|
||||
m_kick_button->setHidden(!is_hosting);
|
||||
|
@ -564,6 +652,7 @@ void NetPlayDialog::SetOptionsEnabled(bool enabled)
|
|||
m_sync_save_data_box->setEnabled(enabled);
|
||||
m_assign_ports_button->setEnabled(enabled);
|
||||
m_reduce_polling_rate_box->setEnabled(enabled);
|
||||
m_strict_settings_sync_box->setEnabled(enabled);
|
||||
}
|
||||
|
||||
m_record_input_box->setEnabled(enabled);
|
||||
|
|
|
@ -105,6 +105,7 @@ private:
|
|||
QCheckBox* m_sync_save_data_box;
|
||||
QCheckBox* m_record_input_box;
|
||||
QCheckBox* m_reduce_polling_rate_box;
|
||||
QCheckBox* m_strict_settings_sync_box;
|
||||
QPushButton* m_quit_button;
|
||||
QSplitter* m_splitter;
|
||||
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** BSD License Usage
|
||||
** Alternatively, you may use this file under the terms of the BSD license
|
||||
** as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "DolphinQt/QtUtils/FlowLayout.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
FlowLayout::FlowLayout(QWidget* parent, int margin, int h_spacing, int v_spacing)
|
||||
: QLayout(parent), m_h_space(h_spacing), m_v_space(v_spacing)
|
||||
{
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
}
|
||||
|
||||
FlowLayout::FlowLayout(int margin, int h_spacing, int v_spacing)
|
||||
: m_h_space(h_spacing), m_v_space(v_spacing)
|
||||
{
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
}
|
||||
|
||||
FlowLayout::~FlowLayout()
|
||||
{
|
||||
QLayoutItem* item;
|
||||
while ((item = takeAt(0)))
|
||||
delete item;
|
||||
}
|
||||
|
||||
void FlowLayout::addItem(QLayoutItem* item)
|
||||
{
|
||||
m_item_list.append(item);
|
||||
}
|
||||
|
||||
int FlowLayout::horizontalSpacing() const
|
||||
{
|
||||
if (m_h_space >= 0)
|
||||
{
|
||||
return m_h_space;
|
||||
}
|
||||
else
|
||||
{
|
||||
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
|
||||
}
|
||||
}
|
||||
|
||||
int FlowLayout::verticalSpacing() const
|
||||
{
|
||||
if (m_v_space >= 0)
|
||||
{
|
||||
return m_v_space;
|
||||
}
|
||||
else
|
||||
{
|
||||
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
|
||||
}
|
||||
}
|
||||
|
||||
int FlowLayout::count() const
|
||||
{
|
||||
return m_item_list.size();
|
||||
}
|
||||
|
||||
QLayoutItem* FlowLayout::itemAt(int index) const
|
||||
{
|
||||
return m_item_list.value(index);
|
||||
}
|
||||
|
||||
QLayoutItem* FlowLayout::takeAt(int index)
|
||||
{
|
||||
if (index >= 0 && index < m_item_list.size())
|
||||
return m_item_list.takeAt(index);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Qt::Orientations FlowLayout::expandingDirections() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FlowLayout::hasHeightForWidth() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int FlowLayout::heightForWidth(int width) const
|
||||
{
|
||||
int height = doLayout(QRect(0, 0, width, 0), true);
|
||||
return height;
|
||||
}
|
||||
|
||||
void FlowLayout::setGeometry(const QRect& rect)
|
||||
{
|
||||
QLayout::setGeometry(rect);
|
||||
doLayout(rect, false);
|
||||
}
|
||||
|
||||
QSize FlowLayout::sizeHint() const
|
||||
{
|
||||
return minimumSize();
|
||||
}
|
||||
|
||||
QSize FlowLayout::minimumSize() const
|
||||
{
|
||||
QSize size;
|
||||
for (const auto& item : m_item_list)
|
||||
size = size.expandedTo(item->minimumSize());
|
||||
|
||||
size += QSize(2 * margin(), 2 * margin());
|
||||
return size;
|
||||
}
|
||||
|
||||
int FlowLayout::doLayout(const QRect& rect, bool testOnly) const
|
||||
{
|
||||
int left, top, right, bottom;
|
||||
getContentsMargins(&left, &top, &right, &bottom);
|
||||
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
|
||||
int x = effectiveRect.x();
|
||||
int y = effectiveRect.y();
|
||||
int lineHeight = 0;
|
||||
|
||||
for (const auto& item : m_item_list)
|
||||
{
|
||||
QWidget* wid = item->widget();
|
||||
int spaceX = horizontalSpacing();
|
||||
if (spaceX == -1)
|
||||
spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton,
|
||||
Qt::Horizontal);
|
||||
int spaceY = verticalSpacing();
|
||||
if (spaceY == -1)
|
||||
spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton,
|
||||
Qt::Vertical);
|
||||
int nextX = x + item->sizeHint().width() + spaceX;
|
||||
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0)
|
||||
{
|
||||
x = effectiveRect.x();
|
||||
y = y + lineHeight + spaceY;
|
||||
nextX = x + item->sizeHint().width() + spaceX;
|
||||
lineHeight = 0;
|
||||
}
|
||||
|
||||
if (!testOnly)
|
||||
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
|
||||
|
||||
x = nextX;
|
||||
lineHeight = qMax(lineHeight, item->sizeHint().height());
|
||||
}
|
||||
return y + lineHeight - rect.y() + bottom;
|
||||
}
|
||||
|
||||
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
|
||||
{
|
||||
QObject* parent = this->parent();
|
||||
if (!parent)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (parent->isWidgetType())
|
||||
{
|
||||
QWidget* pw = static_cast<QWidget*>(parent);
|
||||
return pw->style()->pixelMetric(pm, 0, pw);
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<QLayout*>(parent)->spacing();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** BSD License Usage
|
||||
** Alternatively, you may use this file under the terms of the BSD license
|
||||
** as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QLayout>
|
||||
#include <QRect>
|
||||
#include <QStyle>
|
||||
|
||||
class FlowLayout : public QLayout
|
||||
{
|
||||
public:
|
||||
explicit FlowLayout(QWidget* parent, int margin = -1, int h_spacing = -1, int v_spacing = -1);
|
||||
explicit FlowLayout(int margin = -1, int h_spacing = -1, int v_spacing = -1);
|
||||
~FlowLayout();
|
||||
|
||||
void addItem(QLayoutItem* item) override;
|
||||
int horizontalSpacing() const;
|
||||
int verticalSpacing() const;
|
||||
Qt::Orientations expandingDirections() const override;
|
||||
bool hasHeightForWidth() const override;
|
||||
int heightForWidth(int) const override;
|
||||
int count() const override;
|
||||
QLayoutItem* itemAt(int index) const override;
|
||||
QSize minimumSize() const override;
|
||||
void setGeometry(const QRect& rect) override;
|
||||
QSize sizeHint() const override;
|
||||
QLayoutItem* takeAt(int index) override;
|
||||
|
||||
private:
|
||||
int doLayout(const QRect& rect, bool testOnly) const;
|
||||
int smartSpacing(QStyle::PixelMetric pm) const;
|
||||
|
||||
QList<QLayoutItem*> m_item_list;
|
||||
int m_h_space;
|
||||
int m_v_space;
|
||||
};
|
|
@ -13,6 +13,7 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <cmath>
|
||||
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
|
@ -101,13 +102,15 @@ void AdvancedPane::ConnectLayout()
|
|||
m_cpu_clock_override_checkbox->setChecked(SConfig::GetInstance().m_OCEnable);
|
||||
connect(m_cpu_clock_override_checkbox, &QCheckBox::toggled, [this](bool enable_clock_override) {
|
||||
SConfig::GetInstance().m_OCEnable = enable_clock_override;
|
||||
Config::SetBaseOrCurrent(Config::MAIN_OVERCLOCK_ENABLE, enable_clock_override);
|
||||
Update();
|
||||
});
|
||||
|
||||
connect(m_cpu_clock_override_slider, &QSlider::valueChanged, [this](int oc_factor) {
|
||||
// Vaguely exponential scaling?
|
||||
SConfig::GetInstance().m_OCFactor =
|
||||
std::exp2f((m_cpu_clock_override_slider->value() - 100.f) / 25.f);
|
||||
const float factor = std::exp2f((m_cpu_clock_override_slider->value() - 100.f) / 25.f);
|
||||
SConfig::GetInstance().m_OCFactor = factor;
|
||||
Config::SetBaseOrCurrent(Config::MAIN_OVERCLOCK, factor);
|
||||
Update();
|
||||
});
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "AudioCommon/AudioCommon.h"
|
||||
#include "AudioCommon/WASAPIStream.h"
|
||||
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
|
||||
|
@ -222,7 +223,9 @@ void AudioPane::SaveSettings()
|
|||
|
||||
// DSP
|
||||
SConfig::GetInstance().bDSPHLE = m_dsp_hle->isChecked();
|
||||
Config::SetBaseOrCurrent(Config::MAIN_DSP_HLE, m_dsp_hle->isChecked());
|
||||
SConfig::GetInstance().m_DSPEnableJIT = m_dsp_lle->isChecked();
|
||||
Config::SetBaseOrCurrent(Config::MAIN_DSP_JIT, m_dsp_lle->isChecked());
|
||||
|
||||
// Backend
|
||||
const auto selection =
|
||||
|
|
|
@ -341,8 +341,12 @@ void GameCubePane::SaveSettings()
|
|||
|
||||
// IPL Settings
|
||||
params.bHLE_BS2 = m_skip_main_menu->isChecked();
|
||||
Config::SetBaseOrCurrent(Config::MAIN_SKIP_IPL, m_skip_main_menu->isChecked());
|
||||
params.SelectedLanguage = m_language_combo->currentIndex();
|
||||
Config::SetBaseOrCurrent(Config::MAIN_GC_LANGUAGE, m_language_combo->currentIndex());
|
||||
params.bOverrideGCLanguage = m_override_language_ntsc->isChecked();
|
||||
Config::SetBaseOrCurrent(Config::MAIN_OVERRIDE_GC_LANGUAGE,
|
||||
m_override_language_ntsc->isChecked());
|
||||
|
||||
for (int i = 0; i < SLOT_COUNT; i++)
|
||||
{
|
||||
|
@ -390,6 +394,18 @@ void GameCubePane::SaveSettings()
|
|||
}
|
||||
|
||||
SConfig::GetInstance().m_EXIDevice[i] = dev;
|
||||
switch (i)
|
||||
{
|
||||
case SLOT_A_INDEX:
|
||||
Config::SetBaseOrCurrent(Config::MAIN_SLOT_A, dev);
|
||||
break;
|
||||
case SLOT_B_INDEX:
|
||||
Config::SetBaseOrCurrent(Config::MAIN_SLOT_B, dev);
|
||||
break;
|
||||
case SLOT_SP1_INDEX:
|
||||
Config::SetBaseOrCurrent(Config::MAIN_SERIAL_PORT_1, dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LoadSettings();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <QWidget>
|
||||
|
||||
#include "Core/Analytics.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/Config/UISettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
|
@ -291,7 +292,9 @@ void GeneralPane::OnSaveConfig()
|
|||
Settings::Instance().SetAnalyticsEnabled(m_checkbox_enable_analytics->isChecked());
|
||||
#endif
|
||||
settings.bCPUThread = m_checkbox_dualcore->isChecked();
|
||||
Config::SetBaseOrCurrent(Config::MAIN_CPU_THREAD, m_checkbox_dualcore->isChecked());
|
||||
Settings::Instance().SetCheatsEnabled(m_checkbox_cheats->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::MAIN_ENABLE_CHEATS, m_checkbox_cheats->isChecked());
|
||||
settings.m_EmulationSpeed = m_combobox_speedlimit->currentIndex() * 0.1f;
|
||||
|
||||
for (size_t i = 0; i < m_cpu_cores.size(); ++i)
|
||||
|
@ -299,6 +302,7 @@ void GeneralPane::OnSaveConfig()
|
|||
if (m_cpu_cores[i]->isChecked())
|
||||
{
|
||||
settings.cpu_core = PowerPC::AvailableCPUCores()[i];
|
||||
Config::SetBaseOrCurrent(Config::MAIN_CPU_CORE, PowerPC::AvailableCPUCores()[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue