From 8ae10b3e123fb9dd9369084d474e6184d23c88f9 Mon Sep 17 00:00:00 2001 From: Rachel Bryk Date: Tue, 3 Sep 2013 15:50:41 -0400 Subject: [PATCH] [NetPlay] Allow recording movies during netplay. Fixes issue 6207. --- Source/Core/Core/Src/HW/SI.cpp | 5 ++++- Source/Core/Core/Src/Movie.cpp | 22 +++++++++++++++--- Source/Core/Core/Src/Movie.h | 4 +++- Source/Core/Core/Src/NetPlayClient.cpp | 30 ++++++++++++++++++++++++- Source/Core/Core/Src/NetPlayClient.h | 5 +++++ Source/Core/DolphinWX/Src/NetWindow.cpp | 8 +++++++ Source/Core/DolphinWX/Src/NetWindow.h | 3 +++ 7 files changed, 71 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Src/HW/SI.cpp b/Source/Core/Core/Src/HW/SI.cpp index 5574ae536e..ff9057aa4f 100644 --- a/Source/Core/Core/Src/HW/SI.cpp +++ b/Source/Core/Core/Src/HW/SI.cpp @@ -644,7 +644,10 @@ int GetTicksToNextSIPoll() // Poll for input at regular intervals (once per frame) when playing or recording a movie if (Movie::IsPlayingInput() || Movie::IsRecordingInput()) { - return SystemTimers::GetTicksPerSecond() / VideoInterface::TargetRefreshRate; + if (Movie::IsNetPlayRecording()) + return SystemTimers::GetTicksPerSecond() / VideoInterface::TargetRefreshRate / 2; + else + return SystemTimers::GetTicksPerSecond() / VideoInterface::TargetRefreshRate; } if (NetPlay::IsNetPlayRunning()) return SystemTimers::GetTicksPerSecond() / VideoInterface::TargetRefreshRate / 2; diff --git a/Source/Core/Core/Src/Movie.cpp b/Source/Core/Core/Src/Movie.cpp index d22f625fce..5e9804cd25 100644 --- a/Source/Core/Core/Src/Movie.cpp +++ b/Source/Core/Core/Src/Movie.cpp @@ -24,6 +24,7 @@ #include "../../Common/Src/NandPaths.h" #include "polarssl/md5.h" #include "scmrev.h" +#include "NetPlayClient.h" // The chunk to allocate movie data in multiples of. #define DTM_BASE_LENGTH (1024) @@ -50,8 +51,8 @@ u64 g_currentFrame = 0, g_totalFrames = 0; // VI u64 g_currentLagCount = 0, g_totalLagCount = 0; // just stats u64 g_currentInputCount = 0, g_totalInputCount = 0; // just stats u64 g_recordingStartTime; // seconds since 1970 that recording started -bool bSaveConfig, bSkipIdle, bDualCore, bProgressive, bDSPHLE, bFastDiscSpeed = false; -bool bMemcard, g_bClearSave, bSyncGPU = false; +bool bSaveConfig = false, bSkipIdle = false, bDualCore = false, bProgressive = false, bDSPHLE = false, bFastDiscSpeed = false; +bool bMemcard = false, g_bClearSave = false, bSyncGPU = false, bNetPlay = false; std::string videoBackend = "unknown"; int iCPUCore = 1; bool g_bDiscChange = false; @@ -360,6 +361,11 @@ bool IsSyncGPU() return bSyncGPU; } +bool IsNetPlayRecording() +{ + return bNetPlay; +} + void ChangePads(bool instantly) { if (Core::GetState() == Core::CORE_UNINITIALIZED) @@ -409,7 +415,14 @@ bool BeginRecordingInput(int controllers) g_currentFrame = g_totalFrames = 0; g_currentLagCount = g_totalLagCount = 0; g_currentInputCount = g_totalInputCount = 0; - g_recordingStartTime = Common::Timer::GetLocalTimeSinceJan1970(); + if (NetPlay::IsNetPlayRunning()) + { + bNetPlay = true; + g_recordingStartTime = NETPLAY_INITIAL_GCTIME; + } + else + g_recordingStartTime = Common::Timer::GetLocalTimeSinceJan1970(); + g_rerecords = 0; for (int i = 0; i < 4; i++) @@ -682,6 +695,7 @@ void ReadHeader() bMemcard = tmpHeader.bMemcard; bongos = tmpHeader.bongos; bSyncGPU = tmpHeader.bSyncGPU; + bNetPlay = tmpHeader.bNetPlay; memcpy(revision, tmpHeader.revision, ARRAYSIZE(revision)); } else @@ -1108,6 +1122,7 @@ void SaveRecording(const char *filename) header.bMemcard = bMemcard; header.bClearSave = g_bClearSave; header.bSyncGPU = bSyncGPU; + header.bNetPlay = bNetPlay; strncpy((char *)header.discChange, g_discChange.c_str(),ARRAYSIZE(header.discChange)); strncpy((char *)header.author, author.c_str(),ARRAYSIZE(header.author)); memcpy(header.md5,MD5,16); @@ -1168,6 +1183,7 @@ void GetSettings() videoBackend = g_video_backend->GetName(); bSyncGPU = SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU; iCPUCore = SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore; + bNetPlay = NetPlay::IsNetPlayRunning(); if (!Core::g_CoreStartupParameter.bWii) g_bClearSave = !File::Exists(SConfig::GetInstance().m_strMemoryCardA); bMemcard = SConfig::GetInstance().m_EXIDevice[0] == EXIDEVICE_MEMORYCARD; diff --git a/Source/Core/Core/Src/Movie.h b/Source/Core/Core/Src/Movie.h index 27ac18e1b6..423393c7a4 100644 --- a/Source/Core/Core/Src/Movie.h +++ b/Source/Core/Core/Src/Movie.h @@ -107,7 +107,8 @@ struct DTMHeader { bool bClearSave; // Create a new memory card when playing back a movie if true u8 bongos; bool bSyncGPU; - u8 reserved[14]; // Padding for any new config options + bool bNetPlay; + u8 reserved[13]; // Padding for any new config options u8 discChange[40]; // Name of iso file to switch to, for two disc games. u8 revision[20]; // Git hash u8 reserved2[27]; // Make heading 256 bytes, just because we can @@ -142,6 +143,7 @@ bool IsUsingMemcard(); bool IsSyncGPU(); void SetGraphicsConfig(); void GetSettings(); +bool IsNetPlayRecording(); bool IsUsingPad(int controller); bool IsUsingWiimote(int wiimote); diff --git a/Source/Core/Core/Src/NetPlayClient.cpp b/Source/Core/Core/Src/NetPlayClient.cpp index 428a217fed..4a568c9607 100644 --- a/Source/Core/Core/Src/NetPlayClient.cpp +++ b/Source/Core/Core/Src/NetPlayClient.cpp @@ -17,6 +17,7 @@ // for wiimote/ OSD messages #include "Core.h" #include "ConfigManager.h" +#include "Movie.h" std::mutex crit_netplay_client; static NetPlayClient * netplay_client = NULL; @@ -420,6 +421,21 @@ bool NetPlayClient::StartGame(const std::string &path) ClearBuffers(); + if (m_dialog->IsRecording()) + { + + if (Movie::IsReadOnly()) + Movie::SetReadOnly(false); + + u8 controllers_mask = 0; + for (unsigned int i = 0; i < 4; ++i) + { + if (m_pad_map[i] > 0) + controllers_mask |= (1 << i); + } + Movie::BeginRecordingInput(controllers_mask); + } + // boot game m_dialog->BootGame(path); @@ -527,6 +543,18 @@ bool NetPlayClient::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_stat Common::SleepCurrentThread(1); } + SPADStatus tmp; + tmp.stickY = ((u8*)&netvalues->nHi)[0]; + tmp.stickX = ((u8*)&netvalues->nHi)[1]; + tmp.button = ((u16*)&netvalues->nHi)[1]; + + tmp.substickX = ((u8*)&netvalues->nLo)[3]; + tmp.substickY = ((u8*)&netvalues->nLo)[2]; + tmp.triggerLeft = ((u8*)&netvalues->nLo)[1]; + tmp.triggerRight = ((u8*)&netvalues->nLo)[0]; + Movie::RecordInput(&tmp, pad_nb); + Movie::InputUpdate(); + return true; } @@ -634,7 +662,7 @@ u32 CEXIIPL::NetPlay_GetGCTime() std::lock_guard lk(crit_netplay_client); if (netplay_client) - return 1272737767; // watev + return NETPLAY_INITIAL_GCTIME; // watev else return 0; } diff --git a/Source/Core/Core/Src/NetPlayClient.h b/Source/Core/Core/Src/NetPlayClient.h index a5aea6e472..db949aaa7c 100644 --- a/Source/Core/Core/Src/NetPlayClient.h +++ b/Source/Core/Core/Src/NetPlayClient.h @@ -22,6 +22,8 @@ #include "FifoQueue.h" +const int NETPLAY_INITIAL_GCTIME = 1272737767; + class NetPad { public: @@ -46,6 +48,7 @@ public: virtual void OnMsgChangeGame(const std::string& filename) = 0; virtual void OnMsgStartGame() = 0; virtual void OnMsgStopGame() = 0; + virtual bool IsRecording() = 0; }; extern NetSettings g_NetPlaySettings; @@ -117,6 +120,8 @@ protected: PadMapping m_pad_map[4]; + bool m_is_recording; + private: void UpdateDevices(); void SendPadState(const PadMapping in_game_pad, const NetPad& np); diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index a31f9c1cb1..020ed4e72c 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -354,6 +354,9 @@ NetPlayDiag::NetPlayDiag(wxWindow* const parent, const CGameListCtrl* const game bottom_szr->Add(m_memcard_write, 0, wxCENTER); } + m_record_chkbox = new wxCheckBox(panel, wxID_ANY, _("Record input")); + bottom_szr->Add(m_record_chkbox, 0, wxCENTER); + bottom_szr->AddStretchSpacer(1); bottom_szr->Add(quit_btn); @@ -565,6 +568,11 @@ void NetPlayDiag::OnConfigPads(wxCommandEvent&) netplay_server->SetPadMapping(mapping); } +bool NetPlayDiag::IsRecording() +{ + return m_record_chkbox->GetValue(); +} + ChangeGameDiag::ChangeGameDiag(wxWindow* const parent, const CGameListCtrl* const game_list, wxString& game_name) : wxDialog(parent, wxID_ANY, _("Change Game"), wxDefaultPosition, wxDefaultSize) , m_game_name(game_name) diff --git a/Source/Core/DolphinWX/Src/NetWindow.h b/Source/Core/DolphinWX/Src/NetWindow.h index 3f8502a6ee..f271f12afe 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.h +++ b/Source/Core/DolphinWX/Src/NetWindow.h @@ -81,6 +81,8 @@ public: static NetPlayDiag *&GetInstance() { return npd; }; + bool IsRecording(); + private: DECLARE_EVENT_TABLE() @@ -97,6 +99,7 @@ private: wxTextCtrl* m_chat_text; wxTextCtrl* m_chat_msg_text; wxCheckBox* m_memcard_write; + wxCheckBox* m_record_chkbox; std::string m_selected_game; wxButton* m_game_btn;