From ebce13fba705687bd59ea39d938ef9de7c12a008 Mon Sep 17 00:00:00 2001 From: "baby.lueshi" Date: Mon, 11 Jul 2011 20:15:05 +0000 Subject: [PATCH] The read-only movie flag now taken into account for save states. Fixes Issue 4463. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7674 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/Movie.cpp | 143 ++++++++++++++--------- Source/Core/Core/Src/Movie.h | 9 +- Source/Core/DolphinWX/Src/FrameTools.cpp | 6 + 3 files changed, 98 insertions(+), 60 deletions(-) diff --git a/Source/Core/Core/Src/Movie.cpp b/Source/Core/Core/Src/Movie.cpp index a8488de7f3..5bfd5fbc24 100644 --- a/Source/Core/Core/Src/Movie.cpp +++ b/Source/Core/Core/Src/Movie.cpp @@ -18,6 +18,7 @@ #include "Movie.h" #include "Core.h" +#include "ConfigManager.h" #include "Thread.h" #include "FileUtil.h" #include "PowerPC/PowerPC.h" @@ -25,15 +26,6 @@ #include "HW/Wiimote.h" #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "VideoBackendBase.h" - -#ifdef WIN32 -#include //_chsize_s -#include -#include -#include -#else -#include //truncate -#endif #include "State.h" // large enough for just over 24 hours of single-player recording @@ -166,6 +158,11 @@ bool IsPlayingInput() return (g_playMode == MODE_PLAYING); } +bool IsReadOnly() +{ + return g_bReadOnly; +} + bool IsUsingPad(int controller) { return ((g_numPads & (1 << controller)) != 0); @@ -178,18 +175,37 @@ bool IsUsingWiimote(int wiimote) void ChangePads(bool instantly) { - if (Core::GetState() != Core::CORE_UNINITIALIZED) - { - for (int i = 0; i < 4; i++) - if (instantly) // Changes from savestates need to be instantaneous - SerialInterface::AddDevice(IsUsingPad(i) ? SI_GC_CONTROLLER : SI_NONE, i); - else - SerialInterface::ChangeDevice(IsUsingPad(i) ? SI_GC_CONTROLLER : SI_NONE, i); - } + if (Core::GetState() == Core::CORE_UNINITIALIZED) + return; + + int controllers = 0; + + for (int i = 0; i < 4; i++) + if (SConfig::GetInstance().m_SIDevice[i] == SI_GC_CONTROLLER) + controllers |= (1 << i); + + if (instantly && (g_numPads & 0x0F) == controllers) + return; + + for (int i = 0; i < 4; i++) + if (instantly) // Changes from savestates need to be instantaneous + SerialInterface::AddDevice(IsUsingPad(i) ? SI_GC_CONTROLLER : SI_NONE, i); + else + SerialInterface::ChangeDevice(IsUsingPad(i) ? SI_GC_CONTROLLER : SI_NONE, i); } -void ChangeWiiPads() +void ChangeWiiPads(bool instantly) { + int controllers = 0; + + for (int i = 0; i < 4; i++) + if (g_wiimote_sources[i] != WIIMOTE_SRC_NONE) + controllers |= (1 << i); + + // This is important for Wiimotes, because they can desync easily if they get re-activated + if (instantly && (g_numPads >> 4) == controllers) + return; + for (int i = 0; i < 4; i++) { g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE; @@ -213,9 +229,7 @@ bool BeginRecordingInput(int controllers) g_numPads = controllers; - g_frameCounter = 0; - g_lagCounter = 0; - g_InputCounter = 0; + g_frameCounter = g_lagCounter = g_InputCounter = 0; g_rerecords = 0; g_playMode = MODE_RECORDING; inputOffset = 0; @@ -415,14 +429,15 @@ void LoadInput(const char *filename) EndPlayInput(false); return; } - - tmpHeader.numRerecords++; + + if (!g_bReadOnly) + tmpHeader.numRerecords++; t_record.Seek(0, SEEK_SET); t_record.WriteArray(&tmpHeader, 1); g_frameCounter = tmpHeader.frameCount; - g_totalFrameCount = tmpHeader.frameCount; + g_totalFrameCount = (tmpHeader.totalFrameCount ? tmpHeader.totalFrameCount : tmpHeader.frameCount); g_InputCounter = tmpHeader.InputCount; g_numPads = tmpHeader.numControllers; @@ -430,20 +445,27 @@ void LoadInput(const char *filename) ChangePads(true); if (Core::g_CoreStartupParameter.bWii) - ChangeWiiPads(); + ChangeWiiPads(true); inputOffset = t_record.GetSize() - 256; delete tmpInput; tmpInput = new u8[MAX_DTM_LENGTH]; t_record.ReadArray(tmpInput, inputOffset); - t_record.Close(); - g_rerecords = tmpHeader.numRerecords; - - Core::DisplayMessage("Resuming movie recording", 2000); - - g_playMode = MODE_RECORDING; + + if (g_bReadOnly) + { + tmpLength = inputOffset; + inputOffset = tmpHeader.frameStart; + Core::DisplayMessage("Resuming movie playback", 2000); + g_playMode = MODE_PLAYING; + } + else + { + Core::DisplayMessage("Resuming movie recording", 2000); + g_playMode = MODE_RECORDING; + } } void PlayController(SPADStatus *PadStatus, int controllerID) @@ -599,36 +621,41 @@ void SaveRecording(const char *filename) { File::IOFile save_record(filename, "wb"); - // NOTE: Eventually this will not happen in - // read-only mode, but we need a way for the save state to - // store the current point in the file first. - // if (!g_bReadOnly) + // Create the real header now and write it + DTMHeader header; + memset(&header, 0, sizeof(DTMHeader)); + + header.filetype[0] = 'D'; header.filetype[1] = 'T'; header.filetype[2] = 'M'; header.filetype[3] = 0x1A; + strncpy((char *)header.gameID, Core::g_CoreStartupParameter.GetUniqueID().c_str(), 6); + header.bWii = Core::g_CoreStartupParameter.bWii; + header.numControllers = g_numPads & (Core::g_CoreStartupParameter.bWii ? 0xFF : 0x0F); + + header.bFromSaveState = g_bRecordingFromSaveState; + header.frameCount = g_frameCounter; + header.lagCount = g_lagCounter; + header.numRerecords = g_rerecords; + header.InputCount = g_InputCounter; + + // TODO + header.uniqueID = 0; + // header.author; + // header.videoBackend; + // header.audioEmulator; + + if (g_bReadOnly) { - // Create the real header now and write it - DTMHeader header; - memset(&header, 0, sizeof(DTMHeader)); - - header.filetype[0] = 'D'; header.filetype[1] = 'T'; header.filetype[2] = 'M'; header.filetype[3] = 0x1A; - strncpy((char *)header.gameID, Core::g_CoreStartupParameter.GetUniqueID().c_str(), 6); - header.bWii = Core::g_CoreStartupParameter.bWii; - header.numControllers = g_numPads & (Core::g_CoreStartupParameter.bWii ? 0xFF : 0x0F); - - header.bFromSaveState = g_bRecordingFromSaveState; - header.frameCount = g_frameCounter; - header.lagCount = g_lagCounter; - header.numRerecords = g_rerecords; - header.InputCount = g_InputCounter; - - // TODO - header.uniqueID = 0; - // header.author; - // header.videoBackend; - // header.audioEmulator; - - save_record.WriteArray(&header, 1); + header.frameStart = inputOffset; + header.totalFrameCount = g_totalFrameCount; } + + save_record.WriteArray(&header, 1); - bool success = save_record.WriteArray(tmpInput, inputOffset); + bool success; + + if (g_bReadOnly) + success = save_record.WriteArray(tmpInput, tmpLength); + else + success = save_record.WriteArray(tmpInput, inputOffset); if (success && g_bRecordingFromSaveState) { diff --git a/Source/Core/Core/Src/Movie.h b/Source/Core/Core/Src/Movie.h index 2978d0ec15..55ccf3a8da 100644 --- a/Source/Core/Core/Src/Movie.h +++ b/Source/Core/Core/Src/Movie.h @@ -87,7 +87,11 @@ struct DTMHeader { u8 audioEmulator[16]; // UTF-8 representation of the audio emulator u8 padBackend[16]; // UTF-8 representation of the input backend - u8 reserved[127]; // Make heading 256 bytes, just because we can + // only used in read-only savestates + u64 frameStart; // Offset to resume playback on + u64 totalFrameCount; // Total frames, same as normal dtm's frameCount + + u8 reserved[111]; // Make heading 256 bytes, just because we can }; #pragma pack(pop) @@ -100,11 +104,12 @@ bool IsAutoFiring(); bool IsRecordingInput(); bool IsRecordingInputFromSaveState(); bool IsPlayingInput(); +bool IsReadOnly(); bool IsUsingPad(int controller); bool IsUsingWiimote(int wiimote); void ChangePads(bool instantly = false); -void ChangeWiiPads(); +void ChangeWiiPads(bool instantly = false); void SetFrameStepping(bool bEnabled); void SetFrameStopping(bool bEnabled); diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 60f2c7d7b7..75d76a314e 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -715,6 +715,12 @@ void CFrame::OnChangeDisc(wxCommandEvent& WXUNUSED (event)) void CFrame::OnRecord(wxCommandEvent& WXUNUSED (event)) { int controllers = 0; + + if (Movie::IsReadOnly()) + { + PanicAlertT("Cannot record movies in read-only mode."); + return; + } for (int i = 0; i < 4; i++) { if (SConfig::GetInstance().m_SIDevice[i] == SI_GC_CONTROLLER)