From ced8ca7219f91c37494f16e41cb635d1c3c23439 Mon Sep 17 00:00:00 2001 From: nitsuja Date: Mon, 26 Dec 2011 05:09:30 -0600 Subject: [PATCH] better support for RTC when recording --- Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp | 23 +++++++++++++----- Source/Core/Core/Src/Movie.cpp | 29 ++++++++++------------- Source/Core/Core/Src/Movie.h | 10 ++++---- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp b/Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp index 85bfd2428e..144270e798 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp @@ -25,6 +25,8 @@ #include "MemoryUtil.h" #include "FileUtil.h" #include "../Movie.h" +#include "../CoreTiming.h" +#include "SystemTimers.h" // We should provide an option to choose from the above, or figure out the checksum (the algo in yagcd seems wrong) // so that people can change default language. @@ -342,14 +344,23 @@ void CEXIIPL::TransferByte(u8& _uByte) u32 CEXIIPL::GetGCTime() { u64 ltime = 0; - const u32 cJanuary2000 = 0x386D4380; // Seconds between 1.1.1970 and 1.1.2000 + static const u32 cJanuary2000 = 0x386D4380; // Seconds between 1.1.1970 and 1.1.2000 - // hack in some netplay stuff - ltime = NetPlay_GetGCTime(); if (Movie::IsRecordingInput() || Movie::IsPlayingInput()) - ltime = 1234567890; // TODO: Should you be able to set a custom time in movies? - else if (0 == ltime) - ltime = Common::Timer::GetLocalTimeSinceJan1970(); + { + ltime = Movie::GetRecordingStartTime(); + + // let's keep time moving forward, regardless of what it starts at + ltime += CoreTiming::GetTicks() / SystemTimers::GetTicksPerSecond(); + } + else + { + // hack in some netplay stuff + ltime = NetPlay_GetGCTime(); + + if (0 == ltime) + ltime = Common::Timer::GetLocalTimeSinceJan1970(); + } return ((u32)ltime - cJanuary2000); diff --git a/Source/Core/Core/Src/Movie.cpp b/Source/Core/Core/Src/Movie.cpp index 07564c69a8..b478af4743 100644 --- a/Source/Core/Core/Src/Movie.cpp +++ b/Source/Core/Core/Src/Movie.cpp @@ -29,6 +29,7 @@ #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "VideoBackendBase.h" #include "State.h" +#include "Timer.h" // large enough for just over 24 hours of single-player recording #define MAX_DTM_LENGTH (40 * 1024 * 1024) @@ -53,6 +54,7 @@ u64 g_currentByte = 0, g_totalBytes = 0; 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 g_bRecordingFromSaveState = false; bool g_bPolled = false; @@ -64,6 +66,7 @@ std::string g_InputDisplay[8]; ManipFunction mfunc = NULL; + std::string GetInputDisplay() { std::string inputDisplay = ""; @@ -196,6 +199,11 @@ bool IsReadOnly() return g_bReadOnly; } +u64 GetRecordingStartTime() +{ + return g_recordingStartTime; +} + bool IsUsingPad(int controller) { return ((g_numPads & (1 << controller)) != 0); @@ -264,6 +272,7 @@ bool BeginRecordingInput(int controllers) g_currentFrame = g_totalFrames = 0; g_currentLagCount = g_totalLagCount = 0; g_currentInputCount = g_totalInputCount = 0; + g_recordingStartTime = Common::Timer::GetLocalTimeSinceJan1970(); g_rerecords = 0; g_playMode = MODE_RECORDING; @@ -532,6 +541,7 @@ bool PlayInput(const char *filename) g_totalFrames = tmpHeader.frameCount; g_totalLagCount = tmpHeader.lagCount; g_totalInputCount = tmpHeader.inputCount; + g_recordingStartTime = tmpHeader.recordingStartTime; g_currentFrame = 0; g_currentLagCount = 0; @@ -630,7 +640,7 @@ void LoadInput(const char *filename) } else if(g_currentByte > 0 && g_totalBytes > 0) { - // verify identical from movie start to thee save's current frame + // verify identical from movie start to the save's current frame u32 len = (u32)g_currentByte; u8* movInput = new u8[len]; t_record.ReadArray(movInput, (size_t)len); @@ -676,20 +686,6 @@ void LoadInput(const char *filename) g_rerecords = tmpHeader.numRerecords; - if(g_currentSaveVersion == 0) - { - // attempt support for old savestates with movies but without movie-related data in DoState. - // I'm just guessing here and the old logic was kind of broken anyway, so this probably doesn't work well. - g_totalFrames = tmpHeader.frameCount; - if(g_totalFrames < tmpHeader.deprecated_totalFrameCount) - g_totalFrames = tmpHeader.deprecated_totalFrameCount; - u64 frameStart = tmpHeader.deprecated_frameStart ? tmpHeader.deprecated_frameStart : tmpHeader.frameCount; - g_currentFrame = frameStart; - g_currentByte = frameStart * 8; - g_currentLagCount = tmpHeader.lagCount; - g_currentInputCount = tmpHeader.inputCount; - } - if (!afterEnd) { if (g_bReadOnly) @@ -817,7 +813,7 @@ bool PlayWiimote(int wiimote, u8 *data, const WiimoteEmu::ReportFeatures& rptf, if (size != sizeInMovie) { - PanicAlertT("Error in PlayWiimote. %u != %u, byte %d.\nSorry, Wii recording is temporarily broken.", sizeInMovie, size, g_currentByte); + PanicAlertT("Fatal desync. Aborting playback. (Error in PlayWiimote: %u != %u, byte %d.)%s", sizeInMovie, size, g_currentByte, (g_numPads & 0xF)?" Try re-creating the recording with all GameCube controllers disabled.":""); EndPlayInput(!g_bReadOnly); return false; } @@ -880,6 +876,7 @@ void SaveRecording(const char *filename) header.lagCount = g_totalLagCount; header.inputCount = g_totalInputCount; header.numRerecords = g_rerecords; + header.recordingStartTime = g_recordingStartTime; // TODO header.uniqueID = 0; diff --git a/Source/Core/Core/Src/Movie.h b/Source/Core/Core/Src/Movie.h index 3df376270e..9e01c48df1 100644 --- a/Source/Core/Core/Src/Movie.h +++ b/Source/Core/Core/Src/Movie.h @@ -89,7 +89,7 @@ struct DTMHeader { u64 frameCount; // Number of frames in the recording u64 inputCount; // Number of input frames in recording u64 lagCount; // Number of lag frames in the recording - u64 uniqueID; // A Unique ID comprised of: md5(time + Game ID) + u64 uniqueID; // (not implemented) A Unique ID comprised of: md5(time + Game ID) u32 numRerecords; // Number of rerecords/'cuts' of this TAS u8 author[32]; // Author's name (encoded in UTF-8) @@ -97,12 +97,9 @@ struct DTMHeader { u8 audioEmulator[16]; // UTF-8 representation of the audio emulator u8 padBackend[16]; // UTF-8 representation of the input backend - // hack, data that was only used for savestates and would more properly be stored in the savestate itself - // the hack has been removed, but these remain defined and reserved here for legacy support purposes - u64 deprecated_frameStart; // NOT USED ANYMORE (use g_currentFrame) - u64 deprecated_totalFrameCount; // NOT USED ANYMORE (use g_totalFrames or header.frameCount) + u64 recordingStartTime; // seconds since 1970 that recording started (used for RTC) - u8 reserved[111]; // Make heading 256 bytes, just because we can + u8 reserved[119]; // Make heading 256 bytes, just because we can }; #pragma pack(pop) @@ -117,6 +114,7 @@ bool IsRecordingInputFromSaveState(); bool IsJustStartingRecordingInputFromSaveState(); bool IsPlayingInput(); bool IsReadOnly(); +u64 GetRecordingStartTime(); bool IsUsingPad(int controller); bool IsUsingWiimote(int wiimote);