mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
Merge pull request #3859 from Aestek/feature/netplay-md5
Netplay: add md5 testing
This commit is contained in:
commit
1a81735527
@ -30,6 +30,7 @@ set(SRCS Analytics.cpp
|
||||
Version.cpp
|
||||
x64ABI.cpp
|
||||
x64Emitter.cpp
|
||||
MD5.cpp
|
||||
Crypto/bn.cpp
|
||||
Crypto/ec.cpp
|
||||
Logging/LogManager.cpp)
|
||||
|
@ -114,6 +114,7 @@
|
||||
<ClInclude Include="JitRegister.h" />
|
||||
<ClInclude Include="LinearDiskCache.h" />
|
||||
<ClInclude Include="MathUtil.h" />
|
||||
<ClInclude Include="MD5.h" />
|
||||
<ClInclude Include="MemArena.h" />
|
||||
<ClInclude Include="MemoryUtil.h" />
|
||||
<ClInclude Include="MsgHandler.h" />
|
||||
@ -158,6 +159,7 @@
|
||||
<ClCompile Include="JitRegister.cpp" />
|
||||
<ClCompile Include="Logging\ConsoleListenerWin.cpp" />
|
||||
<ClCompile Include="MathUtil.cpp" />
|
||||
<ClCompile Include="MD5.cpp" />
|
||||
<ClCompile Include="MemArena.cpp" />
|
||||
<ClCompile Include="MemoryUtil.cpp" />
|
||||
<ClCompile Include="Misc.cpp" />
|
||||
|
@ -118,6 +118,8 @@
|
||||
|
||||
#define WII_STATE "state.dat"
|
||||
|
||||
#define WII_SDCARD "sd.raw"
|
||||
|
||||
#define WII_SETTING "setting.txt"
|
||||
|
||||
#define GECKO_CODE_HANDLER "codehandler.bin"
|
||||
|
@ -793,6 +793,7 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
||||
s_user_paths[F_ARAMDUMP_IDX] = s_user_paths[D_DUMP_IDX] + ARAM_DUMP;
|
||||
s_user_paths[F_FAKEVMEMDUMP_IDX] = s_user_paths[D_DUMP_IDX] + FAKEVMEM_DUMP;
|
||||
s_user_paths[F_GCSRAM_IDX] = s_user_paths[D_GCUSER_IDX] + GC_SRAM;
|
||||
s_user_paths[F_WIISDCARD_IDX] = s_user_paths[D_WIIROOT_IDX] + DIR_SEP WII_SDCARD;
|
||||
|
||||
s_user_paths[D_MEMORYWATCHER_IDX] = s_user_paths[D_USER_IDX] + MEMORYWATCHER_DIR DIR_SEP;
|
||||
s_user_paths[F_MEMORYWATCHERLOCATIONS_IDX] =
|
||||
|
@ -55,6 +55,7 @@ enum
|
||||
F_GCSRAM_IDX,
|
||||
F_MEMORYWATCHERLOCATIONS_IDX,
|
||||
F_MEMORYWATCHERSOCKET_IDX,
|
||||
F_WIISDCARD_IDX,
|
||||
NUM_PATH_INDICES
|
||||
};
|
||||
|
||||
|
52
Source/Core/Common/MD5.cpp
Normal file
52
Source/Core/Common/MD5.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <mbedtls/md5.h>
|
||||
#include <string>
|
||||
|
||||
#include "Common/MD5.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "DiscIO/Blob.h"
|
||||
|
||||
namespace MD5
|
||||
{
|
||||
std::string MD5Sum(const std::string& file_path, std::function<bool(int)> report_progress)
|
||||
{
|
||||
std::string output_string;
|
||||
std::vector<u8> data(8 * 1024 * 1024);
|
||||
u64 read_offset = 0;
|
||||
mbedtls_md5_context ctx;
|
||||
|
||||
std::unique_ptr<DiscIO::IBlobReader> file(DiscIO::CreateBlobReader(file_path));
|
||||
u64 game_size = file->GetDataSize();
|
||||
|
||||
mbedtls_md5_starts(&ctx);
|
||||
|
||||
while (read_offset < game_size)
|
||||
{
|
||||
size_t read_size = std::min(static_cast<u64>(data.size()), game_size - read_offset);
|
||||
if (!file->Read(read_offset, read_size, data.data()))
|
||||
return output_string;
|
||||
|
||||
mbedtls_md5_update(&ctx, data.data(), read_size);
|
||||
read_offset += read_size;
|
||||
|
||||
int progress =
|
||||
static_cast<int>(static_cast<float>(read_offset) / static_cast<float>(game_size) * 100);
|
||||
if (!report_progress(progress))
|
||||
return output_string;
|
||||
}
|
||||
|
||||
std::array<u8, 16> output;
|
||||
mbedtls_md5_finish(&ctx, output.data());
|
||||
|
||||
// Convert to hex
|
||||
for (u8 n : output)
|
||||
output_string += StringFromFormat("%02x", n);
|
||||
|
||||
return output_string;
|
||||
}
|
||||
}
|
13
Source/Core/Common/MD5.h
Normal file
13
Source/Core/Common/MD5.h
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace MD5
|
||||
{
|
||||
std::string MD5Sum(const std::string& file_name, std::function<bool(int)> progress);
|
||||
}
|
@ -62,7 +62,7 @@ void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
|
||||
|
||||
void CWII_IPC_HLE_Device_sdio_slot0::OpenInternal()
|
||||
{
|
||||
const std::string filename = File::GetUserPath(D_WIIROOT_IDX) + "/sd.raw";
|
||||
const std::string filename = File::GetUserPath(F_WIISDCARD_IDX);
|
||||
m_Card.Open(filename, "r+b");
|
||||
if (!m_Card)
|
||||
{
|
||||
|
@ -4,10 +4,15 @@
|
||||
|
||||
#include "Core/NetPlayClient.h"
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <mbedtls/md5.h>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include "Common/Common.h"
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/ENetUtil.h"
|
||||
#include "Common/MD5.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/Timer.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
@ -19,6 +24,8 @@
|
||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/NetPlayClient.h"
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
|
||||
static std::mutex crit_netplay_client;
|
||||
@ -500,6 +507,55 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_COMPUTE_MD5:
|
||||
{
|
||||
std::string file_identifier;
|
||||
packet >> file_identifier;
|
||||
|
||||
ComputeMD5(file_identifier);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_MD5_PROGRESS:
|
||||
{
|
||||
PlayerId pid;
|
||||
int progress;
|
||||
packet >> pid;
|
||||
packet >> progress;
|
||||
|
||||
m_dialog->SetMD5Progress(pid, progress);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_MD5_RESULT:
|
||||
{
|
||||
PlayerId pid;
|
||||
std::string result;
|
||||
packet >> pid;
|
||||
packet >> result;
|
||||
|
||||
m_dialog->SetMD5Result(pid, result);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_MD5_ERROR:
|
||||
{
|
||||
PlayerId pid;
|
||||
std::string error;
|
||||
packet >> pid;
|
||||
packet >> error;
|
||||
|
||||
m_dialog->SetMD5Result(pid, error);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_MD5_ABORT:
|
||||
{
|
||||
m_should_compute_MD5 = false;
|
||||
m_dialog->AbortMD5();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PanicAlertT("Unknown message received with id : %d", mid);
|
||||
break;
|
||||
@ -1142,6 +1198,47 @@ bool NetPlayClient::DoAllPlayersHaveGame()
|
||||
[](auto entry) { return entry.second.game_status == PlayerGameStatus::Ok; });
|
||||
}
|
||||
|
||||
void NetPlayClient::ComputeMD5(const std::string& file_identifier)
|
||||
{
|
||||
if (m_should_compute_MD5)
|
||||
return;
|
||||
|
||||
m_dialog->ShowMD5Dialog(file_identifier);
|
||||
m_should_compute_MD5 = true;
|
||||
|
||||
std::string file;
|
||||
if (file_identifier == WII_SDCARD)
|
||||
file = File::GetUserPath(F_WIISDCARD_IDX);
|
||||
else
|
||||
file = m_dialog->FindGame(file_identifier);
|
||||
|
||||
if (file.empty() || !File::Exists(file))
|
||||
{
|
||||
sf::Packet spac;
|
||||
spac << static_cast<MessageId>(NP_MSG_MD5_ERROR);
|
||||
spac << "file not found";
|
||||
Send(spac);
|
||||
return;
|
||||
}
|
||||
|
||||
m_MD5_thread = std::thread([this, file]() {
|
||||
std::string sum = MD5::MD5Sum(file, [&](int progress) {
|
||||
sf::Packet spac;
|
||||
spac << static_cast<MessageId>(NP_MSG_MD5_PROGRESS);
|
||||
spac << progress;
|
||||
Send(spac);
|
||||
|
||||
return m_should_compute_MD5;
|
||||
});
|
||||
|
||||
sf::Packet spac;
|
||||
spac << static_cast<MessageId>(NP_MSG_MD5_RESULT);
|
||||
spac << sum;
|
||||
Send(spac);
|
||||
});
|
||||
m_MD5_thread.detach();
|
||||
}
|
||||
|
||||
// stuff hacked into dolphin
|
||||
|
||||
// called from ---CPU--- thread
|
||||
|
@ -34,6 +34,10 @@ public:
|
||||
virtual void OnMsgStopGame() = 0;
|
||||
virtual bool IsRecording() = 0;
|
||||
virtual std::string FindGame(const std::string& game) = 0;
|
||||
virtual void ShowMD5Dialog(const std::string& file_identifier) = 0;
|
||||
virtual void SetMD5Progress(int pid, int progress) = 0;
|
||||
virtual void SetMD5Result(int pid, const std::string& result) = 0;
|
||||
virtual void AbortMD5() = 0;
|
||||
};
|
||||
|
||||
enum class PlayerGameStatus
|
||||
@ -152,6 +156,7 @@ private:
|
||||
void Send(sf::Packet& packet);
|
||||
void Disconnect();
|
||||
bool Connect();
|
||||
void ComputeMD5(const std::string& file_identifier);
|
||||
|
||||
bool m_is_connected = false;
|
||||
ConnectionState m_connection_state = ConnectionState::Failure;
|
||||
@ -162,6 +167,8 @@ private:
|
||||
std::string m_player_name;
|
||||
bool m_connecting = false;
|
||||
TraversalClient* m_traversal_client = nullptr;
|
||||
std::thread m_MD5_thread;
|
||||
bool m_should_compute_MD5 = false;
|
||||
|
||||
u32 m_timebase_frame = 0;
|
||||
};
|
||||
|
@ -58,6 +58,12 @@ enum
|
||||
NP_MSG_TIMEBASE = 0xB0,
|
||||
NP_MSG_DESYNC_DETECTED = 0xB1,
|
||||
|
||||
NP_MSG_COMPUTE_MD5 = 0xC0,
|
||||
NP_MSG_MD5_PROGRESS = 0xC1,
|
||||
NP_MSG_MD5_RESULT = 0xC2,
|
||||
NP_MSG_MD5_ABORT = 0xC3,
|
||||
NP_MSG_MD5_ERROR = 0xC4,
|
||||
|
||||
NP_MSG_READY = 0xD0,
|
||||
NP_MSG_NOT_READY = 0xD1,
|
||||
|
||||
|
@ -664,6 +664,49 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_MD5_PROGRESS:
|
||||
{
|
||||
int progress;
|
||||
packet >> progress;
|
||||
|
||||
sf::Packet spac;
|
||||
spac << static_cast<MessageId>(NP_MSG_MD5_PROGRESS);
|
||||
spac << player.pid;
|
||||
spac << progress;
|
||||
|
||||
SendToClients(spac);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_MD5_RESULT:
|
||||
{
|
||||
std::string result;
|
||||
packet >> result;
|
||||
|
||||
sf::Packet spac;
|
||||
spac << static_cast<MessageId>(NP_MSG_MD5_RESULT);
|
||||
spac << player.pid;
|
||||
spac << result;
|
||||
|
||||
SendToClients(spac);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_MD5_ERROR:
|
||||
{
|
||||
std::string error;
|
||||
packet >> error;
|
||||
|
||||
sf::Packet spac;
|
||||
spac << static_cast<MessageId>(NP_MSG_MD5_ERROR);
|
||||
spac << player.pid;
|
||||
spac << error;
|
||||
|
||||
SendToClients(spac);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PanicAlertT("Unknown message with id:%d received from player:%d Kicking player!", mid,
|
||||
player.pid);
|
||||
@ -685,8 +728,8 @@ void NetPlayServer::OnTraversalStateChanged()
|
||||
void NetPlayServer::SendChatMessage(const std::string& msg)
|
||||
{
|
||||
auto spac = std::make_unique<sf::Packet>();
|
||||
*spac << (MessageId)NP_MSG_CHAT_MESSAGE;
|
||||
*spac << (PlayerId)0; // server id always 0
|
||||
*spac << static_cast<MessageId>(NP_MSG_CHAT_MESSAGE);
|
||||
*spac << static_cast<PlayerId>(0); // server id always 0
|
||||
*spac << msg;
|
||||
|
||||
SendAsyncToClients(std::move(spac));
|
||||
@ -701,7 +744,7 @@ bool NetPlayServer::ChangeGame(const std::string& game)
|
||||
|
||||
// send changed game to clients
|
||||
auto spac = std::make_unique<sf::Packet>();
|
||||
*spac << (MessageId)NP_MSG_CHANGE_GAME;
|
||||
*spac << static_cast<MessageId>(NP_MSG_CHANGE_GAME);
|
||||
*spac << game;
|
||||
|
||||
SendAsyncToClients(std::move(spac));
|
||||
@ -709,6 +752,29 @@ bool NetPlayServer::ChangeGame(const std::string& game)
|
||||
return true;
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
bool NetPlayServer::ComputeMD5(const std::string& file_identifier)
|
||||
{
|
||||
auto spac = std::make_unique<sf::Packet>();
|
||||
*spac << static_cast<MessageId>(NP_MSG_COMPUTE_MD5);
|
||||
*spac << file_identifier;
|
||||
|
||||
SendAsyncToClients(std::move(spac));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
bool NetPlayServer::AbortMD5()
|
||||
{
|
||||
auto spac = std::make_unique<sf::Packet>();
|
||||
*spac << static_cast<MessageId>(NP_MSG_MD5_ABORT);
|
||||
|
||||
SendAsyncToClients(std::move(spac));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
void NetPlayServer::SetNetSettings(const NetSettings& settings)
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
enum class PlayerGameStatus;
|
||||
|
||||
class NetPlayUI;
|
||||
enum class PlayerGameStatus;
|
||||
|
||||
class NetPlayServer : public TraversalClientClient
|
||||
{
|
||||
@ -31,6 +32,8 @@ public:
|
||||
~NetPlayServer();
|
||||
|
||||
bool ChangeGame(const std::string& game);
|
||||
bool ComputeMD5(const std::string& file_identifier);
|
||||
bool AbortMD5();
|
||||
void SendChatMessage(const std::string& msg);
|
||||
|
||||
void SetNetSettings(const NetSettings& settings);
|
||||
|
@ -34,6 +34,7 @@ set(GUI_SRCS
|
||||
Debugger/WatchView.cpp
|
||||
Debugger/WatchWindow.cpp
|
||||
NetPlay/ChangeGameDialog.cpp
|
||||
NetPlay/MD5Dialog.cpp
|
||||
NetPlay/NetPlaySetupFrame.cpp
|
||||
NetPlay/NetWindow.cpp
|
||||
NetPlay/PadMapDialog.cpp
|
||||
|
@ -89,6 +89,7 @@
|
||||
<ClCompile Include="Debugger\WatchView.cpp" />
|
||||
<ClCompile Include="Debugger\WatchWindow.cpp" />
|
||||
<ClCompile Include="NetPlay\ChangeGameDialog.cpp" />
|
||||
<ClCompile Include="NetPlay\MD5Dialog.cpp" />
|
||||
<ClCompile Include="NetPlay\NetPlaySetupFrame.cpp" />
|
||||
<ClCompile Include="NetPlay\NetWindow.cpp" />
|
||||
<ClCompile Include="FifoPlayerDlg.cpp" />
|
||||
@ -127,6 +128,7 @@
|
||||
<ClInclude Include="Config\PathConfigPane.h" />
|
||||
<ClInclude Include="Config\WiiConfigPane.h" />
|
||||
<ClInclude Include="NetPlay\ChangeGameDialog.h" />
|
||||
<ClInclude Include="NetPlay\MD5Dialog.h" />
|
||||
<ClInclude Include="NetPlay\NetPlaySetupFrame.h" />
|
||||
<ClInclude Include="NetPlay\PadMapDialog.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
|
@ -360,6 +360,9 @@
|
||||
<ClInclude Include="NetPlay\ChangeGameDialog.h">
|
||||
<Filter>GUI\NetPlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NetPlay\MD5Dialog.h">
|
||||
<Filter>GUI\NetPlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NetPlay\PadMapDialog.h">
|
||||
<Filter>GUI\NetPlay</Filter>
|
||||
</ClInclude>
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/IniFile.h"
|
||||
#include "Common/MD5.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/SysConf.h"
|
||||
#include "Core/ActionReplay.h"
|
||||
@ -1304,42 +1305,13 @@ void CISOProperties::OnEditConfig(wxCommandEvent& WXUNUSED(event))
|
||||
|
||||
void CISOProperties::OnComputeMD5Sum(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
u8 output[16];
|
||||
std::string output_string;
|
||||
std::vector<u8> data(8 * 1024 * 1024);
|
||||
u64 read_offset = 0;
|
||||
mbedtls_md5_context ctx;
|
||||
|
||||
std::unique_ptr<DiscIO::IBlobReader> file(
|
||||
DiscIO::CreateBlobReader(OpenGameListItem.GetFileName()));
|
||||
u64 game_size = file->GetDataSize();
|
||||
|
||||
wxProgressDialog progressDialog(_("Computing MD5 checksum"), _("Working..."), 1000, this,
|
||||
wxProgressDialog progressDialog(_("Computing MD5 checksum"), _("Working..."), 100, this,
|
||||
wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME |
|
||||
wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_SMOOTH);
|
||||
|
||||
mbedtls_md5_starts(&ctx);
|
||||
|
||||
while (read_offset < game_size)
|
||||
{
|
||||
if (!progressDialog.Update((int)((double)read_offset / (double)game_size * 1000)))
|
||||
return;
|
||||
|
||||
size_t read_size = std::min((u64)data.size(), game_size - read_offset);
|
||||
if (!file->Read(read_offset, read_size, data.data()))
|
||||
return;
|
||||
|
||||
mbedtls_md5_update(&ctx, data.data(), read_size);
|
||||
read_offset += read_size;
|
||||
}
|
||||
|
||||
mbedtls_md5_finish(&ctx, output);
|
||||
|
||||
// Convert to hex
|
||||
for (int a = 0; a < 16; ++a)
|
||||
output_string += StringFromFormat("%02x", output[a]);
|
||||
|
||||
m_MD5Sum->SetValue(output_string);
|
||||
m_MD5Sum->SetValue(MD5::MD5Sum(OpenGameListItem.GetFileName(), [&progressDialog](int progress) {
|
||||
return progressDialog.Update(progress);
|
||||
}));
|
||||
}
|
||||
|
||||
// Opens all pre-defined INIs for the game. If there are multiple ones,
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "DolphinWX/NetPlay/NetWindow.h"
|
||||
|
||||
ChangeGameDialog::ChangeGameDialog(wxWindow* parent, const CGameListCtrl* const game_list)
|
||||
: wxDialog(parent, wxID_ANY, _("Change Game"))
|
||||
: wxDialog(parent, wxID_ANY, _("Select Game"))
|
||||
{
|
||||
m_game_lbox =
|
||||
new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxLB_SORT);
|
||||
@ -18,7 +18,7 @@ ChangeGameDialog::ChangeGameDialog(wxWindow* parent, const CGameListCtrl* const
|
||||
|
||||
NetPlayDialog::FillWithGameNames(m_game_lbox, *game_list);
|
||||
|
||||
wxButton* const ok_btn = new wxButton(this, wxID_OK, _("Change"));
|
||||
wxButton* const ok_btn = new wxButton(this, wxID_OK, _("Select"));
|
||||
ok_btn->Bind(wxEVT_BUTTON, &ChangeGameDialog::OnPick, this);
|
||||
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxVERTICAL);
|
||||
|
100
Source/Core/DolphinWX/NetPlay/MD5Dialog.cpp
Normal file
100
Source/Core/DolphinWX/NetPlay/MD5Dialog.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <wx/button.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/gauge.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
#include "Common/StringUtil.h"
|
||||
#include "DolphinWX/NetPlay/MD5Dialog.h"
|
||||
#include "DolphinWX/NetPlay/NetWindow.h"
|
||||
|
||||
MD5Dialog::MD5Dialog(wxWindow* parent, NetPlayServer* server, std::vector<const Player*> players,
|
||||
const std::string& game)
|
||||
: wxDialog(parent, wxID_ANY, _("MD5 Checksum")), m_parent(parent), m_netplay_server(server)
|
||||
{
|
||||
Bind(wxEVT_CLOSE_WINDOW, &MD5Dialog::OnClose, this);
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
main_sizer->Add(new wxStaticText(this, wxID_ANY, _("Computing MD5 Checksum for:") + "\n" + game,
|
||||
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL),
|
||||
0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
|
||||
|
||||
for (const Player* player : players)
|
||||
{
|
||||
wxStaticBoxSizer* const player_szr = new wxStaticBoxSizer(
|
||||
wxVERTICAL, this, player->name + " (p" + std::to_string(player->pid) + ")");
|
||||
|
||||
wxGauge* gauge = new wxGauge(this, wxID_ANY, 100);
|
||||
m_progress_bars[player->pid] = gauge;
|
||||
player_szr->Add(gauge, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_result_labels[player->pid] =
|
||||
new wxStaticText(this, wxID_ANY, _("Computing..."), wxDefaultPosition, wxSize(250, 20),
|
||||
wxALIGN_CENTRE_HORIZONTAL);
|
||||
|
||||
m_result_labels[player->pid]->SetSize(250, 15);
|
||||
player_szr->Add(m_result_labels[player->pid], 0, wxALL, 5);
|
||||
|
||||
main_sizer->Add(player_szr, 0, wxEXPAND | wxALL, 5);
|
||||
}
|
||||
|
||||
m_final_result_label =
|
||||
new wxStaticText(this, wxID_ANY,
|
||||
" ", // so it takes space
|
||||
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL);
|
||||
main_sizer->Add(m_final_result_label, 1, wxALL, 5);
|
||||
|
||||
wxButton* close_btn = new wxButton(this, wxID_ANY, _("Close"));
|
||||
close_btn->Bind(wxEVT_BUTTON, &MD5Dialog::OnCloseBtnPressed, this);
|
||||
main_sizer->Add(close_btn, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
SetSizerAndFit(main_sizer);
|
||||
SetFocus();
|
||||
Center();
|
||||
}
|
||||
|
||||
void MD5Dialog::SetProgress(int pid, int progress)
|
||||
{
|
||||
if (m_progress_bars[pid] == nullptr)
|
||||
return;
|
||||
|
||||
m_progress_bars[pid]->SetValue(progress);
|
||||
m_result_labels[pid]->SetLabel(_("Computing: ") + std::to_string(progress) + "%");
|
||||
Update();
|
||||
}
|
||||
|
||||
void MD5Dialog::SetResult(int pid, const std::string& result)
|
||||
{
|
||||
if (m_result_labels[pid] == nullptr)
|
||||
return;
|
||||
|
||||
m_result_labels[pid]->SetLabel(result);
|
||||
m_hashes.push_back(result);
|
||||
|
||||
if (m_hashes.size() <= 1)
|
||||
return;
|
||||
|
||||
wxString label = AllHashesMatch() ? _("Hashes match!") : _("Hashes do not match.");
|
||||
m_final_result_label->SetLabel(label);
|
||||
}
|
||||
|
||||
bool MD5Dialog::AllHashesMatch() const
|
||||
{
|
||||
return std::adjacent_find(m_hashes.begin(), m_hashes.end(), std::not_equal_to<>()) ==
|
||||
m_hashes.end();
|
||||
}
|
||||
|
||||
void MD5Dialog::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
m_netplay_server->AbortMD5();
|
||||
}
|
||||
|
||||
void MD5Dialog::OnCloseBtnPressed(wxCommandEvent&)
|
||||
{
|
||||
Close();
|
||||
}
|
40
Source/Core/DolphinWX/NetPlay/MD5Dialog.h
Normal file
40
Source/Core/DolphinWX/NetPlay/MD5Dialog.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <vector>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
class NetPlayServer;
|
||||
class Player;
|
||||
class wxCloseEvent;
|
||||
class wxGauge;
|
||||
class wxStaticText;
|
||||
class wxWindow;
|
||||
|
||||
class MD5Dialog final : public wxDialog
|
||||
{
|
||||
public:
|
||||
MD5Dialog(wxWindow* parent, NetPlayServer* server, std::vector<const Player*> players,
|
||||
const std::string& game);
|
||||
|
||||
void SetProgress(int pid, int progress);
|
||||
void SetResult(int pid, const std::string& result);
|
||||
|
||||
private:
|
||||
bool AllHashesMatch() const;
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnCloseBtnPressed(wxCommandEvent& event);
|
||||
|
||||
wxWindow* m_parent;
|
||||
wxStaticText* m_final_result_label;
|
||||
NetPlayServer* m_netplay_server;
|
||||
std::map<int, wxGauge*> m_progress_bars;
|
||||
std::map<int, wxStaticText*> m_result_labels;
|
||||
std::vector<std::string> m_hashes;
|
||||
};
|
@ -6,6 +6,7 @@
|
||||
#include <cstddef>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <wx/button.h>
|
||||
#include <wx/checkbox.h>
|
||||
@ -23,6 +24,7 @@
|
||||
#include <wx/string.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FifoQueue.h"
|
||||
#include "Common/FileUtil.h"
|
||||
@ -44,6 +46,7 @@
|
||||
#include "DolphinWX/NetPlay/NetWindow.h"
|
||||
#include "DolphinWX/NetPlay/PadMapDialog.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "MD5Dialog.h"
|
||||
|
||||
NetPlayServer* NetPlayDialog::netplay_server = nullptr;
|
||||
NetPlayClient* NetPlayDialog::netplay_client = nullptr;
|
||||
@ -120,7 +123,8 @@ NetPlayDialog::NetPlayDialog(wxWindow* const parent, const CGameListCtrl* const
|
||||
|
||||
wxPanel* const panel = new wxPanel(this);
|
||||
|
||||
// top crap
|
||||
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_game_btn = new wxButton(panel, wxID_ANY, StrToWxStr(m_selected_game).Prepend(_(" Game : ")),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
||||
|
||||
@ -129,6 +133,21 @@ NetPlayDialog::NetPlayDialog(wxWindow* const parent, const CGameListCtrl* const
|
||||
else
|
||||
m_game_btn->Disable();
|
||||
|
||||
top_szr->Add(m_game_btn, 1, wxALL | wxEXPAND);
|
||||
|
||||
if (m_is_hosting)
|
||||
{
|
||||
m_MD5_choice = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxSize(150, -1));
|
||||
m_MD5_choice->Bind(wxEVT_CHOICE, &NetPlayDialog::OnMD5ComputeRequested, this);
|
||||
m_MD5_choice->Append(_("MD5 check..."));
|
||||
m_MD5_choice->Append(_("Curent game"));
|
||||
m_MD5_choice->Append(_("Other game"));
|
||||
m_MD5_choice->Append(_("SD card"));
|
||||
m_MD5_choice->SetSelection(0);
|
||||
|
||||
top_szr->Add(m_MD5_choice, 0, wxALL);
|
||||
}
|
||||
|
||||
// middle crap
|
||||
|
||||
// chat
|
||||
@ -232,7 +251,7 @@ NetPlayDialog::NetPlayDialog(wxWindow* const parent, const CGameListCtrl* const
|
||||
|
||||
// main sizer
|
||||
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
main_szr->Add(m_game_btn, 0, wxEXPAND | wxALL, 5);
|
||||
main_szr->Add(top_szr, 0, wxEXPAND | wxALL, 5);
|
||||
main_szr->Add(mid_szr, 1, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||
main_szr->Add(bottom_szr, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
@ -471,6 +490,31 @@ void NetPlayDialog::OnThread(wxThreadEvent& event)
|
||||
netplay_client->StopGame();
|
||||
}
|
||||
break;
|
||||
case NP_GUI_EVT_DISPLAY_MD5_DIALOG:
|
||||
{
|
||||
m_MD5_dialog = new MD5Dialog(this, netplay_server, netplay_client->GetPlayers(),
|
||||
event.GetString().ToStdString());
|
||||
m_MD5_dialog->Show();
|
||||
}
|
||||
break;
|
||||
case NP_GUI_EVT_MD5_PROGRESS:
|
||||
{
|
||||
if (m_MD5_dialog == nullptr || m_MD5_dialog->IsBeingDeleted())
|
||||
break;
|
||||
|
||||
std::pair<int, int> payload = event.GetPayload<std::pair<int, int>>();
|
||||
m_MD5_dialog->SetProgress(payload.first, payload.second);
|
||||
}
|
||||
break;
|
||||
case NP_GUI_EVT_MD5_RESULT:
|
||||
{
|
||||
if (m_MD5_dialog == nullptr || m_MD5_dialog->IsBeingDeleted())
|
||||
break;
|
||||
|
||||
std::pair<int, std::string> payload = event.GetPayload<std::pair<int, std::string>>();
|
||||
m_MD5_dialog->SetResult(payload.first, payload.second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// chat messages
|
||||
@ -485,10 +529,10 @@ void NetPlayDialog::OnThread(wxThreadEvent& event)
|
||||
|
||||
void NetPlayDialog::OnChangeGame(wxCommandEvent&)
|
||||
{
|
||||
ChangeGameDialog cgd(this, m_game_list);
|
||||
cgd.ShowModal();
|
||||
ChangeGameDialog change_game_dialog(this, m_game_list);
|
||||
change_game_dialog.ShowModal();
|
||||
|
||||
wxString game_name = cgd.GetChosenGameName();
|
||||
wxString game_name = change_game_dialog.GetChosenGameName();
|
||||
if (game_name.empty())
|
||||
return;
|
||||
|
||||
@ -497,6 +541,66 @@ void NetPlayDialog::OnChangeGame(wxCommandEvent&)
|
||||
m_game_btn->SetLabel(game_name.Prepend(_(" Game : ")));
|
||||
}
|
||||
|
||||
void NetPlayDialog::OnMD5ComputeRequested(wxCommandEvent&)
|
||||
{
|
||||
MD5Target selection = static_cast<MD5Target>(m_MD5_choice->GetSelection());
|
||||
std::string file_identifier;
|
||||
ChangeGameDialog change_game_dialog(this, m_game_list);
|
||||
|
||||
m_MD5_choice->SetSelection(0);
|
||||
|
||||
switch (selection)
|
||||
{
|
||||
case MD5Target::CurrentGame:
|
||||
file_identifier = m_selected_game;
|
||||
break;
|
||||
|
||||
case MD5Target::OtherGame:
|
||||
change_game_dialog.ShowModal();
|
||||
|
||||
file_identifier = WxStrToStr(change_game_dialog.GetChosenGameName());
|
||||
if (file_identifier.empty())
|
||||
return;
|
||||
break;
|
||||
|
||||
case MD5Target::SdCard:
|
||||
file_identifier = WII_SDCARD;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
netplay_server->ComputeMD5(file_identifier);
|
||||
}
|
||||
|
||||
void NetPlayDialog::ShowMD5Dialog(const std::string& file_identifier)
|
||||
{
|
||||
wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_DISPLAY_MD5_DIALOG);
|
||||
evt.SetString(file_identifier);
|
||||
GetEventHandler()->AddPendingEvent(evt);
|
||||
}
|
||||
|
||||
void NetPlayDialog::SetMD5Progress(int pid, int progress)
|
||||
{
|
||||
wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_MD5_PROGRESS);
|
||||
evt.SetPayload(std::pair<int, int>(pid, progress));
|
||||
GetEventHandler()->AddPendingEvent(evt);
|
||||
}
|
||||
|
||||
void NetPlayDialog::SetMD5Result(int pid, const std::string& result)
|
||||
{
|
||||
wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_MD5_RESULT);
|
||||
evt.SetPayload(std::pair<int, std::string>(pid, result));
|
||||
GetEventHandler()->AddPendingEvent(evt);
|
||||
}
|
||||
|
||||
void NetPlayDialog::AbortMD5()
|
||||
{
|
||||
if (m_MD5_dialog != nullptr && !m_MD5_dialog->IsBeingDeleted())
|
||||
m_MD5_dialog->Destroy();
|
||||
}
|
||||
|
||||
void NetPlayDialog::OnAssignPads(wxCommandEvent&)
|
||||
{
|
||||
PadMapDialog pmd(this, netplay_server, netplay_client);
|
||||
|
@ -14,12 +14,13 @@
|
||||
#include "Core/NetPlayServer.h"
|
||||
|
||||
class CGameListCtrl;
|
||||
class MD5Dialog;
|
||||
class wxButton;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
class wxListBox;
|
||||
class wxString;
|
||||
class wxStaticText;
|
||||
class wxString;
|
||||
class wxTextCtrl;
|
||||
|
||||
enum
|
||||
@ -27,6 +28,9 @@ enum
|
||||
NP_GUI_EVT_CHANGE_GAME = 45,
|
||||
NP_GUI_EVT_START_GAME,
|
||||
NP_GUI_EVT_STOP_GAME,
|
||||
NP_GUI_EVT_DISPLAY_MD5_DIALOG,
|
||||
NP_GUI_EVT_MD5_PROGRESS,
|
||||
NP_GUI_EVT_MD5_RESULT,
|
||||
};
|
||||
|
||||
enum
|
||||
@ -34,6 +38,14 @@ enum
|
||||
INITIAL_PAD_BUFFER_SIZE = 5
|
||||
};
|
||||
|
||||
// IDs are UI-dependent here
|
||||
enum class MD5Target
|
||||
{
|
||||
CurrentGame = 1,
|
||||
OtherGame = 2,
|
||||
SdCard = 3
|
||||
};
|
||||
|
||||
class NetPlayDialog : public wxFrame, public NetPlayUI
|
||||
{
|
||||
public:
|
||||
@ -52,6 +64,11 @@ public:
|
||||
void Update() override;
|
||||
void AppendChat(const std::string& msg) override;
|
||||
|
||||
void ShowMD5Dialog(const std::string& file_identifier) override;
|
||||
void SetMD5Progress(int pid, int progress) override;
|
||||
void SetMD5Result(int pid, const std::string& result) override;
|
||||
void AbortMD5() override;
|
||||
|
||||
void OnMsgChangeGame(const std::string& filename) override;
|
||||
void OnMsgStartGame() override;
|
||||
void OnMsgStopGame() override;
|
||||
@ -68,6 +85,7 @@ private:
|
||||
void OnQuit(wxCommandEvent& event);
|
||||
void OnThread(wxThreadEvent& event);
|
||||
void OnChangeGame(wxCommandEvent& event);
|
||||
void OnMD5ComputeRequested(wxCommandEvent& event);
|
||||
void OnAdjustBuffer(wxCommandEvent& event);
|
||||
void OnAssignPads(wxCommandEvent& event);
|
||||
void OnKick(wxCommandEvent& event);
|
||||
@ -94,6 +112,8 @@ private:
|
||||
wxStaticText* m_host_label;
|
||||
wxChoice* m_host_type_choice;
|
||||
wxButton* m_host_copy_btn;
|
||||
wxChoice* m_MD5_choice;
|
||||
MD5Dialog* m_MD5_dialog = nullptr;
|
||||
bool m_host_copy_btn_is_retry;
|
||||
bool m_is_hosting;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user