Merge pull request #3859 from Aestek/feature/netplay-md5

Netplay: add md5 testing
This commit is contained in:
Anthony Serna
2016-07-18 09:20:37 -05:00
committed by GitHub
22 changed files with 538 additions and 45 deletions

View File

@ -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

View File

@ -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" />

View File

@ -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>

View File

@ -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,

View File

@ -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);

View 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();
}

View 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;
};

View File

@ -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);

View File

@ -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;