Permalink
Browse files

Merge pull request #7535 from UnclePunch/synccodes

Netplay: Sync AR and gecko codes with clients
  • Loading branch information...
delroth committed Nov 13, 2018
2 parents 41333fa + 469f293 commit 6b7a1ca6d182d8d2469618e996bcad5eb091a0bb
@@ -83,6 +83,7 @@ enum
// General lock. Protects codes list and internal log.
static std::mutex s_lock;
static std::vector<ARCode> s_active_codes;
static std::vector<ARCode> s_synced_codes;
static std::vector<std::string> s_internal_log;
static std::atomic<bool> s_use_internal_log{false};
// pointer to the code currently being run, (used by log messages that include the code name)
@@ -123,6 +124,37 @@ void ApplyCodes(const std::vector<ARCode>& codes)
s_active_codes.shrink_to_fit();
}
void SetSyncedCodesAsActive()
{
s_active_codes.clear();
s_active_codes.reserve(s_synced_codes.size());
s_active_codes = s_synced_codes;
}
void UpdateSyncedCodes(const std::vector<ARCode>& codes)
{
s_synced_codes.clear();
s_synced_codes.reserve(codes.size());
std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_synced_codes),
[](const ARCode& code) { return code.active; });
s_synced_codes.shrink_to_fit();
}
std::vector<ARCode> ApplyAndReturnCodes(const std::vector<ARCode>& codes)
{
if (SConfig::GetInstance().bEnableCheats)
{
std::lock_guard<std::mutex> guard(s_lock);
s_disable_logging = false;
s_active_codes.clear();
std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_active_codes),
[](const ARCode& code) { return code.active; });
}
s_active_codes.shrink_to_fit();
return s_active_codes;
}
void AddCode(ARCode code)
{
if (!SConfig::GetInstance().bEnableCheats)
@@ -35,6 +35,9 @@ struct ARCode
void RunAllActive();
void ApplyCodes(const std::vector<ARCode>& codes);
void SetSyncedCodesAsActive();
void UpdateSyncedCodes(const std::vector<ARCode>& codes);
std::vector<ARCode> ApplyAndReturnCodes(const std::vector<ARCode>& codes);
void AddCode(ARCode new_code);
void LoadAndApplyCodes(const IniFile& global_ini, const IniFile& local_ini);
@@ -44,6 +44,7 @@ const ConfigInfo<std::string> MAIN_GCI_FOLDER_B_PATH_OVERRIDE{
{System::Main, "Core", "GCIFolderBPathOverride"}, ""};
const ConfigInfo<bool> MAIN_GCI_FOLDER_CURRENT_GAME_ONLY{
{System::Main, "Core", "GCIFolderCurrentGameOnly"}, false};
const ConfigInfo<bool> MAIN_CODE_SYNC_OVERRIDE{{System::Main, "Core", "CheatSyncOverride"}, false};
const ConfigInfo<int> MAIN_SLOT_A{{System::Main, "Core", "SlotA"},
ExpansionInterface::EXIDEVICE_MEMORYCARDFOLDER};
const ConfigInfo<int> MAIN_SLOT_B{{System::Main, "Core", "SlotB"},
@@ -41,6 +41,7 @@ extern const ConfigInfo<std::string> MAIN_AGP_CART_A_PATH;
extern const ConfigInfo<std::string> MAIN_AGP_CART_B_PATH;
extern const ConfigInfo<std::string> MAIN_GCI_FOLDER_A_PATH_OVERRIDE;
extern const ConfigInfo<std::string> MAIN_GCI_FOLDER_B_PATH_OVERRIDE;
extern const ConfigInfo<bool> MAIN_CODE_SYNC_OVERRIDE;
extern const ConfigInfo<bool> MAIN_GCI_FOLDER_CURRENT_GAME_ONLY;
extern const ConfigInfo<int> MAIN_SLOT_A;
extern const ConfigInfo<int> MAIN_SLOT_B;
@@ -40,6 +40,7 @@ const ConfigInfo<bool> NETPLAY_WRITE_SAVE_SDCARD_DATA{
{System::Main, "NetPlay", "WriteSaveSDCardData"}, false};
const ConfigInfo<bool> NETPLAY_LOAD_WII_SAVE{{System::Main, "NetPlay", "LoadWiiSave"}, false};
const ConfigInfo<bool> NETPLAY_SYNC_SAVES{{System::Main, "NetPlay", "SyncSaves"}, true};
const ConfigInfo<bool> NETPLAY_SYNC_CODES{{System::Main, "NetPlay", "SyncCodes"}, true};
const ConfigInfo<bool> NETPLAY_RECORD_INPUTS{{System::Main, "NetPlay", "RecordInputs"}, false};
const ConfigInfo<bool> NETPLAY_REDUCE_POLLING_RATE{{System::Main, "NetPlay", "ReducePollingRate"},
false};
@@ -36,6 +36,7 @@ extern const ConfigInfo<u32> NETPLAY_CLIENT_BUFFER_SIZE;
extern const ConfigInfo<bool> NETPLAY_WRITE_SAVE_SDCARD_DATA;
extern const ConfigInfo<bool> NETPLAY_LOAD_WII_SAVE;
extern const ConfigInfo<bool> NETPLAY_SYNC_SAVES;
extern const ConfigInfo<bool> NETPLAY_SYNC_CODES;
extern const ConfigInfo<bool> NETPLAY_RECORD_INPUTS;
extern const ConfigInfo<bool> NETPLAY_REDUCE_POLLING_RATE;
extern const ConfigInfo<bool> NETPLAY_STRICT_SETTINGS_SYNC;
@@ -106,6 +106,13 @@ class NetPlayConfigLayerLoader final : public Config::ConfigLayerLoader
layer->Set(Config::MAIN_GCI_FOLDER_CURRENT_GAME_ONLY, true);
}
// Check To Override Client's Cheat Codes
if (m_settings.m_SyncCodes && !m_settings.m_IsHosting)
{
// Raise flag to use host's codes
layer->Set(Config::MAIN_CODE_SYNC_OVERRIDE, true);
}
}
void Save(Config::Layer* layer) override
@@ -61,6 +61,7 @@ enum class Installation
static Installation s_code_handler_installed = Installation::Uninstalled;
// the currently active codes
static std::vector<GeckoCode> s_active_codes;
static std::vector<GeckoCode> s_synced_codes;
static std::mutex s_active_codes_lock;
void SetActiveCodes(const std::vector<GeckoCode>& gcodes)
@@ -79,6 +80,40 @@ void SetActiveCodes(const std::vector<GeckoCode>& gcodes)
s_code_handler_installed = Installation::Uninstalled;
}
void SetSyncedCodesAsActive()
{
s_active_codes.clear();
s_active_codes.reserve(s_synced_codes.size());
s_active_codes = s_synced_codes;
}
void UpdateSyncedCodes(const std::vector<GeckoCode>& gcodes)
{
s_synced_codes.clear();
s_synced_codes.reserve(gcodes.size());
std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_synced_codes),
[](const GeckoCode& code) { return code.enabled; });
s_synced_codes.shrink_to_fit();
}
std::vector<GeckoCode> SetAndReturnActiveCodes(const std::vector<GeckoCode>& gcodes)
{
std::lock_guard<std::mutex> lk(s_active_codes_lock);
s_active_codes.clear();
if (SConfig::GetInstance().bEnableCheats)
{
s_active_codes.reserve(gcodes.size());
std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_active_codes),
[](const GeckoCode& code) { return code.enabled; });
}
s_active_codes.shrink_to_fit();
s_code_handler_installed = Installation::Uninstalled;
return s_active_codes;
}
// Requires s_active_codes_lock
// NOTE: Refer to "codehandleronly.s" from Gecko OS.
static Installation InstallCodeHandlerLocked()
@@ -59,6 +59,9 @@ constexpr u32 HLE_TRAMPOLINE_ADDRESS = INSTALLER_END_ADDRESS - 4;
constexpr u32 MAGIC_GAMEID = 0xD01F1BAD;
void SetActiveCodes(const std::vector<GeckoCode>& gcodes);
void SetSyncedCodesAsActive();
void UpdateSyncedCodes(const std::vector<GeckoCode>& gcodes);
std::vector<GeckoCode> SetAndReturnActiveCodes(const std::vector<GeckoCode>& gcodes);
void RunCodeHandler();
void Shutdown();
void DoState(PointerWrap&);
@@ -33,8 +33,10 @@
#include "Common/StringUtil.h"
#include "Common/Timer.h"
#include "Common/Version.h"
#include "Core/ActionReplay.h"
#include "Core/Config/NetplaySettings.h"
#include "Core/ConfigManager.h"
#include "Core/GeckoCode.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/SI/SI_DeviceGCController.h"
@@ -550,6 +552,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> m_net_settings.m_SyncSaveData;
packet >> m_net_settings.m_SaveDataRegion;
packet >> m_net_settings.m_SyncCodes;
m_net_settings.m_IsHosting = m_local_player->IsHost();
m_net_settings.m_HostInputAuthority = m_host_input_authority;
@@ -651,6 +654,9 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
{
case SYNC_SAVE_DATA_NOTIFY:
{
if (m_local_player->IsHost())
return 0;
packet >> m_sync_save_data_count;
m_sync_save_data_success_count = 0;
@@ -830,6 +836,163 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
}
break;
case NP_MSG_SYNC_CODES:
{
// Recieve Data Packet
MessageId sub_id;
packet >> sub_id;
// Check Which Operation to Perform with This Packet
switch (sub_id)
{
case SYNC_CODES_NOTIFY:
{
// Set both codes as unsynced
m_sync_gecko_codes_complete = false;
m_sync_ar_codes_complete = false;
}
break;
case SYNC_CODES_NOTIFY_GECKO:
{
// Return if this is the host
if (m_local_player->IsHost())
return 0;
// Receive Number of Codelines to Receive
packet >> m_sync_gecko_codes_count;
m_sync_gecko_codes_success_count = 0;
NOTICE_LOG(ACTIONREPLAY, "Receiving %d Gecko codelines", m_sync_gecko_codes_count);
// Check if no codes to sync, if so return as finished
if (m_sync_gecko_codes_count == 0)
{
m_sync_gecko_codes_complete = true;
SyncCodeResponse(true);
}
else
m_dialog->AppendChat(GetStringT("Synchronizing gecko codes..."));
}
break;
case SYNC_CODES_DATA_GECKO:
{
// Return if this is the host
if (m_local_player->IsHost())
return 0;
// Create a synced code vector
std::vector<Gecko::GeckoCode> synced_codes;
// Create a GeckoCode
Gecko::GeckoCode gcode;
gcode = Gecko::GeckoCode();
// Initialize gcode
gcode.name = "Synced Codes";
gcode.enabled = true;
// Receive code contents from packet
for (int i = 0; i < m_sync_gecko_codes_count; i++)
{
Gecko::GeckoCode::Code new_code;
packet >> new_code.address;
packet >> new_code.data;
NOTICE_LOG(ACTIONREPLAY, "Received %08x %08x", new_code.address, new_code.data);
gcode.codes.push_back(std::move(new_code));
if (++m_sync_gecko_codes_success_count >= m_sync_gecko_codes_count)
{
m_sync_gecko_codes_complete = true;
SyncCodeResponse(true);
}
}
// Add gcode containing all codes to Gecko Code vector
synced_codes.push_back(std::move(gcode));
// Clear Vector if received 0 codes (match host's end when using no codes)
if (m_sync_gecko_codes_count == 0)
synced_codes.clear();
// Copy this to the vector located in GeckoCode.cpp
Gecko::UpdateSyncedCodes(synced_codes);
}
break;
case SYNC_CODES_NOTIFY_AR:
{
// Return if this is the host
if (m_local_player->IsHost())
return 0;
// Receive Number of Codelines to Receive
packet >> m_sync_ar_codes_count;
m_sync_ar_codes_success_count = 0;
NOTICE_LOG(ACTIONREPLAY, "Receiving %d AR codelines", m_sync_ar_codes_count);
// Check if no codes to sync, if so return as finished
if (m_sync_ar_codes_count == 0)
{
m_sync_ar_codes_complete = true;
SyncCodeResponse(true);
}
else
m_dialog->AppendChat(GetStringT("Synchronizing AR codes..."));
}
break;
case SYNC_CODES_DATA_AR:
{
// Return if this is the host
if (m_local_player->IsHost())
return 0;
// Create a synced code vector
std::vector<ActionReplay::ARCode> synced_codes;
// Create an ARCode
ActionReplay::ARCode arcode;
arcode = ActionReplay::ARCode();
// Initialize arcode
arcode.name = "Synced Codes";
arcode.active = true;
// Receive code contents from packet
for (int i = 0; i < m_sync_ar_codes_count; i++)
{
ActionReplay::AREntry new_code;
packet >> new_code.cmd_addr;
packet >> new_code.value;
NOTICE_LOG(ACTIONREPLAY, "Received %08x %08x", new_code.cmd_addr, new_code.value);
arcode.ops.push_back(new_code);
if (++m_sync_ar_codes_success_count >= m_sync_ar_codes_count)
{
m_sync_ar_codes_complete = true;
SyncCodeResponse(true);
}
}
// Add arcode containing all codes to AR Code vector
synced_codes.push_back(std::move(arcode));
// Clear Vector if received 0 codes (match host's end when using no codes)
if (m_sync_ar_codes_count == 0)
synced_codes.clear();
// Copy this to the vector located in ActionReplay.cpp
ActionReplay::UpdateSyncedCodes(synced_codes);
}
break;
}
}
break;
case NP_MSG_COMPUTE_MD5:
{
std::string file_identifier;
@@ -1200,6 +1363,34 @@ void NetPlayClient::SyncSaveDataResponse(const bool success)
}
}
void NetPlayClient::SyncCodeResponse(const bool success)
{
// If something failed, immediately report back that code sync failed
if (!success)
{
m_dialog->AppendChat(GetStringT("Error processing Codes."));
sf::Packet response_packet;
response_packet << static_cast<MessageId>(NP_MSG_SYNC_CODES);
response_packet << static_cast<MessageId>(SYNC_CODES_FAILURE);
Send(response_packet);
return;
}
// If both gecko and AR codes have completely finished transferring, report back as successful
if (m_sync_gecko_codes_complete && m_sync_ar_codes_complete)
{
m_dialog->AppendChat(GetStringT("Codes received!"));
sf::Packet response_packet;
response_packet << static_cast<MessageId>(NP_MSG_SYNC_CODES);
response_packet << static_cast<MessageId>(SYNC_CODES_SUCCESS);
Send(response_packet);
}
}
bool NetPlayClient::DecompressPacketIntoFile(sf::Packet& packet, const std::string& file_path)
{
u64 file_size = Common::PacketReadU64(packet);
Oops, something went wrong.

0 comments on commit 6b7a1ca

Please sign in to comment.