Merge pull request #5784 from leoetlino/movie-buffer

Movie: Get rid of the manual buffer management
This commit is contained in:
Jules Blok 2017-07-14 13:20:27 +02:00 committed by GitHub
commit 37e06586b8
1 changed files with 42 additions and 70 deletions

View File

@ -66,9 +66,8 @@ static PlayMode s_playMode = MODE_NONE;
static u8 s_controllers = 0;
static ControllerState s_padState;
static DTMHeader tmpHeader;
static u8* tmpInput = nullptr;
static size_t tmpInputAllocated = 0;
static u64 s_currentByte = 0, s_totalBytes = 0;
static std::vector<u8> s_temp_input;
static u64 s_currentByte = 0;
static u64 s_currentFrame = 0, s_totalFrames = 0; // VI
static u64 s_currentLagCount = 0;
static u64 s_totalLagCount = 0; // just stats
@ -105,28 +104,6 @@ static WiiManipFunction s_wii_manip_func;
static std::string s_current_file_name;
// NOTE: Host / CPU Thread
static void EnsureTmpInputSize(size_t bound)
{
if (tmpInputAllocated >= bound)
return;
// The buffer expands in powers of two of DTM_BASE_LENGTH
// (standard exponential buffer growth).
size_t newAlloc = DTM_BASE_LENGTH;
while (newAlloc < bound)
newAlloc *= 2;
u8* newTmpInput = new u8[newAlloc];
tmpInputAllocated = newAlloc;
if (tmpInput != nullptr)
{
if (s_totalBytes > 0)
memcpy(newTmpInput, tmpInput, (size_t)s_totalBytes);
delete[] tmpInput;
}
tmpInput = newTmpInput;
}
static bool IsMovieHeader(u8 magic[4])
{
return magic[0] == 'D' && magic[1] == 'T' && magic[2] == 'M' && magic[3] == 0x1A;
@ -621,9 +598,9 @@ bool BeginRecordingInput(int controllers)
s_playMode = MODE_RECORDING;
s_author = SConfig::GetInstance().m_strMovieAuthor;
EnsureTmpInputSize(1);
s_temp_input.clear();
s_currentByte = s_totalBytes = 0;
s_currentByte = 0;
if (Core::IsRunning())
Core::UpdateWantDeterminism();
@ -887,10 +864,9 @@ void RecordInput(GCPadStatus* PadStatus, int controllerID)
CheckPadStatus(PadStatus, controllerID);
EnsureTmpInputSize((size_t)(s_currentByte + sizeof(ControllerState)));
memcpy(&tmpInput[s_currentByte], &s_padState, sizeof(ControllerState));
s_temp_input.resize(s_currentByte + sizeof(ControllerState));
memcpy(&s_temp_input[s_currentByte], &s_padState, sizeof(ControllerState));
s_currentByte += sizeof(ControllerState);
s_totalBytes = s_currentByte;
}
// NOTE: CPU Thread
@ -909,11 +885,10 @@ void RecordWiimote(int wiimote, u8* data, u8 size)
return;
InputUpdate();
EnsureTmpInputSize((size_t)(s_currentByte + size + 1));
tmpInput[s_currentByte++] = size;
memcpy(&(tmpInput[s_currentByte]), data, size);
s_temp_input.resize(s_currentByte + size + 1);
s_temp_input[s_currentByte++] = size;
memcpy(&s_temp_input[s_currentByte], data, size);
s_currentByte += size;
s_totalBytes = s_currentByte;
}
// NOTE: EmuThread / Host Thread
@ -986,9 +961,8 @@ bool PlayInput(const std::string& filename)
Core::UpdateWantDeterminism();
s_totalBytes = recording_file.GetSize() - 256;
EnsureTmpInputSize((size_t)s_totalBytes);
recording_file.ReadArray(tmpInput, (size_t)s_totalBytes);
s_temp_input.resize(recording_file.GetSize() - 256);
recording_file.ReadBytes(s_temp_input.data(), s_temp_input.size());
s_currentByte = 0;
recording_file.Close();
@ -1063,38 +1037,37 @@ void LoadInput(const std::string& filename)
afterEnd = true;
}
if (!s_bReadOnly || tmpInput == nullptr)
if (!s_bReadOnly || s_temp_input.empty())
{
s_totalFrames = tmpHeader.frameCount;
s_totalLagCount = tmpHeader.lagCount;
s_totalInputCount = tmpHeader.inputCount;
s_totalTickCount = s_tickCountAtLastInput = tmpHeader.tickCount;
EnsureTmpInputSize((size_t)totalSavedBytes);
s_totalBytes = totalSavedBytes;
t_record.ReadArray(tmpInput, (size_t)s_totalBytes);
s_temp_input.resize(static_cast<size_t>(totalSavedBytes));
t_record.ReadBytes(s_temp_input.data(), s_temp_input.size());
}
else if (s_currentByte > 0)
{
if (s_currentByte > totalSavedBytes)
{
}
else if (s_currentByte > s_totalBytes)
else if (s_currentByte > s_temp_input.size())
{
afterEnd = true;
PanicAlertT("Warning: You loaded a save that's after the end of the current movie. (byte %u "
"> %u) (input %u > %u). You should load another save before continuing, or load "
"> %zu) (input %u > %u). You should load another save before continuing, or load "
"this state with read-only mode off.",
(u32)s_currentByte + 256, (u32)s_totalBytes + 256, (u32)s_currentInputCount,
(u32)s_currentByte + 256, s_temp_input.size() + 256, (u32)s_currentInputCount,
(u32)s_totalInputCount);
}
else if (s_currentByte > 0 && s_totalBytes > 0)
else if (s_currentByte > 0 && !s_temp_input.empty())
{
// verify identical from movie start to the save's current frame
std::vector<u8> movInput(s_currentByte);
t_record.ReadArray(movInput.data(), movInput.size());
const auto result = std::mismatch(movInput.begin(), movInput.end(), tmpInput);
const auto result = std::mismatch(movInput.begin(), movInput.end(), s_temp_input.begin());
if (result.first != movInput.end())
{
@ -1113,15 +1086,17 @@ void LoadInput(const std::string& filename)
"read-only mode off. Otherwise you'll probably get a desync.",
byte_offset, byte_offset);
std::copy(movInput.begin(), movInput.end(), tmpInput);
std::copy(movInput.begin(), movInput.end(), s_temp_input.begin());
}
else
{
const ptrdiff_t frame = mismatch_index / sizeof(ControllerState);
ControllerState curPadState;
memcpy(&curPadState, &tmpInput[frame * sizeof(ControllerState)], sizeof(ControllerState));
memcpy(&curPadState, &s_temp_input[frame * sizeof(ControllerState)],
sizeof(ControllerState));
ControllerState movPadState;
memcpy(&movPadState, &movInput[frame * sizeof(ControllerState)], sizeof(ControllerState));
memcpy(&movPadState, &s_temp_input[frame * sizeof(ControllerState)],
sizeof(ControllerState));
PanicAlertT(
"Warning: You loaded a save whose movie mismatches on frame %td. You should load "
"another save before continuing, or load this state with read-only mode off. "
@ -1186,7 +1161,7 @@ void LoadInput(const std::string& filename)
// NOTE: CPU Thread
static void CheckInputEnd()
{
if (s_currentByte >= s_totalBytes ||
if (s_currentByte >= s_temp_input.size() ||
(CoreTiming::GetTicks() > s_totalTickCount && !IsRecordingInputFromSaveState()))
{
EndPlayInput(!s_bReadOnly);
@ -1198,13 +1173,13 @@ void PlayController(GCPadStatus* PadStatus, int controllerID)
{
// Correct playback is entirely dependent on the emulator polling the controllers
// in the same order done during recording
if (!IsPlayingInput() || !IsUsingPad(controllerID) || tmpInput == nullptr)
if (!IsPlayingInput() || !IsUsingPad(controllerID) || s_temp_input.empty())
return;
if (s_currentByte + sizeof(ControllerState) > s_totalBytes)
if (s_currentByte + sizeof(ControllerState) > s_temp_input.size())
{
PanicAlertT("Premature movie end in PlayController. %u + %zu > %u", (u32)s_currentByte,
sizeof(ControllerState), (u32)s_totalBytes);
PanicAlertT("Premature movie end in PlayController. %u + %zu > %zu", (u32)s_currentByte,
sizeof(ControllerState), s_temp_input.size());
EndPlayInput(!s_bReadOnly);
return;
}
@ -1215,7 +1190,7 @@ void PlayController(GCPadStatus* PadStatus, int controllerID)
memset(PadStatus, 0, sizeof(GCPadStatus));
PadStatus->err = e;
memcpy(&s_padState, &tmpInput[s_currentByte], sizeof(ControllerState));
memcpy(&s_padState, &s_temp_input[s_currentByte], sizeof(ControllerState));
s_currentByte += sizeof(ControllerState);
PadStatus->triggerLeft = s_padState.TriggerL;
@ -1299,20 +1274,20 @@ void PlayController(GCPadStatus* PadStatus, int controllerID)
bool PlayWiimote(int wiimote, u8* data, const WiimoteEmu::ReportFeatures& rptf, int ext,
const wiimote_key key)
{
if (!IsPlayingInput() || !IsUsingWiimote(wiimote) || tmpInput == nullptr)
if (!IsPlayingInput() || !IsUsingWiimote(wiimote) || s_temp_input.empty())
return false;
if (s_currentByte > s_totalBytes)
if (s_currentByte > s_temp_input.size())
{
PanicAlertT("Premature movie end in PlayWiimote. %u > %u", (u32)s_currentByte,
(u32)s_totalBytes);
PanicAlertT("Premature movie end in PlayWiimote. %u > %zu", (u32)s_currentByte,
s_temp_input.size());
EndPlayInput(!s_bReadOnly);
return false;
}
u8 size = rptf.size;
u8 sizeInMovie = tmpInput[s_currentByte];
u8 sizeInMovie = s_temp_input[s_currentByte];
if (size != sizeInMovie)
{
@ -1328,15 +1303,15 @@ bool PlayWiimote(int wiimote, u8* data, const WiimoteEmu::ReportFeatures& rptf,
s_currentByte++;
if (s_currentByte + size > s_totalBytes)
if (s_currentByte + size > s_temp_input.size())
{
PanicAlertT("Premature movie end in PlayWiimote. %u + %d > %u", (u32)s_currentByte, size,
(u32)s_totalBytes);
PanicAlertT("Premature movie end in PlayWiimote. %u + %d > %zu", (u32)s_currentByte, size,
s_temp_input.size());
EndPlayInput(!s_bReadOnly);
return false;
}
memcpy(data, &(tmpInput[s_currentByte]), size);
memcpy(data, &s_temp_input[s_currentByte], size);
s_currentByte += size;
s_currentInputCount++;
@ -1440,7 +1415,7 @@ void SaveRecording(const std::string& filename)
save_record.WriteArray(&header, 1);
bool success = save_record.WriteArray(tmpInput, (size_t)s_totalBytes);
bool success = save_record.WriteBytes(s_temp_input.data(), s_temp_input.size());
if (success && s_bRecordingFromSaveState)
{
@ -1600,10 +1575,7 @@ static void GetMD5()
// NOTE: EmuThread
void Shutdown()
{
s_currentInputCount = s_totalInputCount = s_totalFrames = s_totalBytes = s_tickCountAtLastInput =
0;
delete[] tmpInput;
tmpInput = nullptr;
tmpInputAllocated = 0;
s_currentInputCount = s_totalInputCount = s_totalFrames = s_tickCountAtLastInput = 0;
s_temp_input.clear();
}
};