* Taseditor: fixed bug with history undo not setting "project changed" flag

* Taseditor: Greenzone invalidation actually clears irrelevant savestates
* Taseditor: fixed checkMarkersDiff, removed unused code from MARKERS_MANAGER::RestoreFromCopy
* Taseditor: when snapshots sizes differ, findFirstChange returns size instead of last frame
This commit is contained in:
ansstuff 2012-08-11 19:53:56 +00:00
parent b63ad04f84
commit 61df7ea541
8 changed files with 91 additions and 147 deletions

View File

@ -449,6 +449,7 @@ void BOOKMARKS::deploy(int slot)
bookmarks_array[slot].jumped(); bookmarks_array[slot].jumped();
} }
// jump to the target (bookmarked frame) // jump to the target (bookmarked frame)
if (greenzone.SavestateIsEmpty(jump_frame))
greenzone.WriteSavestate(jump_frame, bookmarks_array[slot].savestate); greenzone.WriteSavestate(jump_frame, bookmarks_array[slot].savestate);
playback.jump(jump_frame); playback.jump(jump_frame);
// switch current branch to this branch // switch current branch to this branch

View File

@ -47,11 +47,6 @@ void GREENZONE::init()
} }
void GREENZONE::free() void GREENZONE::free()
{ {
int size = savestates.size();
for (int i = 0; i < size; ++i)
{
ClearSavestate(i);
}
savestates.resize(0); savestates.resize(0);
greenZoneCount = 0; greenZoneCount = 0;
lag_history.resize(0); lag_history.resize(0);
@ -63,7 +58,7 @@ void GREENZONE::reset()
void GREENZONE::update() void GREENZONE::update()
{ {
// keep memorizing savestates, this function should be called at the end of every frame // keep memorizing savestates, this function should be called at the end of every frame
if (greenZoneCount <= currFrameCounter || (int)savestates.size() <= currFrameCounter || savestates[currFrameCounter].empty() || (int)lag_history.size() <= currFrameCounter) if (greenZoneCount <= currFrameCounter || (int)savestates.size() <= currFrameCounter || !savestates[currFrameCounter].size() || (int)lag_history.size() <= currFrameCounter)
CollectCurrentState(); CollectCurrentState();
// run cleaning from time to time // run cleaning from time to time
@ -83,7 +78,10 @@ void GREENZONE::CollectCurrentState()
lag_history.resize(greenZoneCount, 0); lag_history.resize(greenZoneCount, 0);
// if frame changed - log savestate // if frame changed - log savestate
storeTasSavestate(currFrameCounter); EMUFILE_MEMORY ms(&savestates[currFrameCounter]);
FCEUSS_SaveMS(&ms, Z_DEFAULT_COMPRESSION);
ms.trim();
// also log lag frames // also log lag frames
if (currFrameCounter > 0) if (currFrameCounter > 0)
{ {
@ -133,23 +131,13 @@ bool GREENZONE::loadTasSavestate(int frame)
{ {
if (frame < 0 || frame >= currMovieData.getNumRecords()) if (frame < 0 || frame >= currMovieData.getNumRecords())
return false; return false;
if ((int)savestates.size() <= frame || savestates[frame].empty()) if ((int)savestates.size() <= frame || !savestates[frame].size())
return false; return false;
EMUFILE_MEMORY ms(&savestates[frame]); EMUFILE_MEMORY ms(&savestates[frame]);
return FCEUSS_LoadFP(&ms, SSLOADPARAM_NOBACKUP); return FCEUSS_LoadFP(&ms, SSLOADPARAM_NOBACKUP);
} }
void GREENZONE::storeTasSavestate(int frame)
{
if ((int)savestates.size() <= frame)
savestates.resize(frame + 1);
EMUFILE_MEMORY ms(&savestates[frame]);
FCEUSS_SaveMS(&ms, Z_DEFAULT_COMPRESSION);
ms.trim();
}
void GREENZONE::RunGreenzoneCleaning() void GREENZONE::RunGreenzoneCleaning()
{ {
int i = currFrameCounter - taseditor_config.greenzone_capacity; int i = currFrameCounter - taseditor_config.greenzone_capacity;
@ -161,7 +149,7 @@ void GREENZONE::RunGreenzoneCleaning()
if (limit < 0) limit = 0; if (limit < 0) limit = 0;
for (; i > limit; i--) for (; i > limit; i--)
{ {
if ((i & 0x1) && !savestates[i].empty()) if ((i & 0x1) && savestates[i].size())
{ {
ClearSavestate(i); ClearSavestate(i);
changed = true; changed = true;
@ -173,7 +161,7 @@ void GREENZONE::RunGreenzoneCleaning()
if (limit < 0) limit = 0; if (limit < 0) limit = 0;
for (; i > limit; i--) for (; i > limit; i--)
{ {
if ((i & 0x3) && !savestates[i].empty()) if ((i & 0x3) && savestates[i].size())
{ {
ClearSavestate(i); ClearSavestate(i);
changed = true; changed = true;
@ -185,7 +173,7 @@ void GREENZONE::RunGreenzoneCleaning()
if (limit < 0) limit = 0; if (limit < 0) limit = 0;
for (; i > limit; i--) for (; i > limit; i--)
{ {
if ((i & 0x7) && !savestates[i].empty()) if ((i & 0x7) && savestates[i].size())
{ {
ClearSavestate(i); ClearSavestate(i);
changed = true; changed = true;
@ -197,7 +185,7 @@ void GREENZONE::RunGreenzoneCleaning()
if (limit < 0) limit = 0; if (limit < 0) limit = 0;
for (; i > limit; i--) for (; i > limit; i--)
{ {
if ((i & 0xF) && !savestates[i].empty()) if ((i & 0xF) && savestates[i].size())
{ {
ClearSavestate(i); ClearSavestate(i);
changed = true; changed = true;
@ -206,7 +194,7 @@ void GREENZONE::RunGreenzoneCleaning()
// clear all remaining // clear all remaining
for (; i > 0; i--) for (; i > 0; i--)
{ {
if (!savestates[i].empty()) if (savestates[i].size())
{ {
ClearSavestate(i); ClearSavestate(i);
changed = true; changed = true;
@ -224,23 +212,7 @@ finish:
void GREENZONE::ClearSavestate(int index) void GREENZONE::ClearSavestate(int index)
{ {
std::vector<uint8> tmp; savestates[index].resize(0);
savestates[index].swap(tmp);
}
// this function is used by Bookmark Deploy procedure
void GREENZONE::WriteSavestate(int frame, std::vector<uint8>& savestate)
{
if ((int)savestates.size() <= frame)
savestates.resize(frame + 1);
if (greenZoneCount <= frame)
{
// clear old savestates: from current end of Greenzone to new end of Greenzone
for (int i = greenZoneCount; i <= frame; ++i)
ClearSavestate(i);
greenZoneCount = frame + 1;
}
if (savestates[frame].empty())
savestates[frame] = savestate;
} }
void GREENZONE::save(EMUFILE *os, bool really_save) void GREENZONE::save(EMUFILE *os, bool really_save)
@ -274,7 +246,7 @@ void GREENZONE::save(EMUFILE *os, bool really_save)
playback.SetProgressbar(frame, greenZoneCount); playback.SetProgressbar(frame, greenZoneCount);
last_tick = frame / PROGRESSBAR_UPDATE_RATE; last_tick = frame / PROGRESSBAR_UPDATE_RATE;
} }
if (savestates[frame].empty()) continue; if (!savestates[frame].size()) continue;
write32le(frame, os); write32le(frame, os);
// write savestate // write savestate
size = savestates[frame].size(); size = savestates[frame].size();
@ -442,8 +414,16 @@ void GREENZONE::InvalidateAndCheck(int after)
{ {
if (after >= 0) if (after >= 0)
{ {
if (after >= currMovieData.getNumRecords())
after = currMovieData.getNumRecords() - 1;
if (greenZoneCount > after + 1) if (greenZoneCount > after + 1)
{ {
// clear all savestates that became irrelevant
for (int i = greenZoneCount - 1; i > after; i--)
{
if (savestates[i].size())
ClearSavestate(i);
}
greenZoneCount = after + 1; greenZoneCount = after + 1;
currMovieData.rerecordCount++; currMovieData.rerecordCount++;
// either set Playback cursor to the end of Greenzone or run seeking to restore Playback cursor position // either set Playback cursor to the end of Greenzone or run seeking to restore Playback cursor position
@ -474,8 +454,16 @@ void GREENZONE::Invalidate(int after)
{ {
if (after >= 0) if (after >= 0)
{ {
if (after >= currMovieData.getNumRecords())
after = currMovieData.getNumRecords() - 1;
if (greenZoneCount > after + 1) if (greenZoneCount > after + 1)
{ {
// clear all savestates that became irrelevant
for (int i = greenZoneCount - 1; i > after; i--)
{
if (savestates[i].size())
ClearSavestate(i);
}
greenZoneCount = after + 1; greenZoneCount = after + 1;
currMovieData.rerecordCount++; currMovieData.rerecordCount++;
} }
@ -488,11 +476,10 @@ void GREENZONE::Invalidate(int after)
int GREENZONE::FindBeginningOfGreenZone(int starting_index) int GREENZONE::FindBeginningOfGreenZone(int starting_index)
{ {
for (int i = starting_index; i < greenZoneCount; ++i) for (int i = starting_index; i < greenZoneCount; ++i)
{ if (savestates[i].size()) return i;
if (!savestates[i].empty()) return i; return -1; // error
}
return starting_index;
} }
// getters // getters
int GREENZONE::GetSize() int GREENZONE::GetSize()
{ {
@ -505,14 +492,26 @@ bool GREENZONE::GetLagHistoryAtFrame(int frame)
else else
return false; return false;
} }
// this should only be used by Bookmark Set procedure
std::vector<uint8>& GREENZONE::GetSavestate(int frame) std::vector<uint8>& GREENZONE::GetSavestate(int frame)
{ {
return savestates[frame]; return savestates[frame];
} }
// this function should only be used by Bookmark Deploy procedure
void GREENZONE::WriteSavestate(int frame, std::vector<uint8>& savestate)
{
if ((int)savestates.size() <= frame)
savestates.resize(frame + 1);
savestates[frame] = savestate;
if (greenZoneCount <= frame)
greenZoneCount = frame + 1;
}
bool GREENZONE::SavestateIsEmpty(int frame) bool GREENZONE::SavestateIsEmpty(int frame)
{ {
if (frame < greenZoneCount && frame < (int)savestates.size()) if (frame < greenZoneCount && frame < (int)savestates.size() && savestates[frame].size())
return savestates[frame].empty(); return false;
else else
return true; return true;
} }

View File

@ -28,8 +28,6 @@ public:
void RunGreenzoneCleaning(); void RunGreenzoneCleaning();
void ClearSavestate(int index); void ClearSavestate(int index);
void WriteSavestate(int frame, std::vector<uint8>& savestate);
void InvalidateAndCheck(int after); void InvalidateAndCheck(int after);
void Invalidate(int after); void Invalidate(int after);
@ -38,11 +36,11 @@ public:
int GetSize(); int GetSize();
bool GetLagHistoryAtFrame(int frame); bool GetLagHistoryAtFrame(int frame);
std::vector<uint8>& GetSavestate(int frame); std::vector<uint8>& GetSavestate(int frame);
void WriteSavestate(int frame, std::vector<uint8>& savestate);
bool SavestateIsEmpty(int frame); bool SavestateIsEmpty(int frame);
private: private:
void CollectCurrentState(); void CollectCurrentState();
void storeTasSavestate(int frame);
// saved data // saved data
int greenZoneCount; int greenZoneCount;

View File

@ -383,13 +383,14 @@ int HISTORY::JumpInTime(int new_pos)
{ {
snapshots[real_pos].toMovie(currMovieData, first_change); snapshots[real_pos].toMovie(currMovieData, first_change);
selection.must_find_current_marker = playback.must_find_current_marker = true; selection.must_find_current_marker = playback.must_find_current_marker = true;
// Piano Roll Redraw and ProjectChanged will be called by Greenzone invalidation project.SetProjectChanged();
// Piano Roll Redraw will be called by Greenzone invalidation
} else if (markers_changed) } else if (markers_changed)
{ {
markers_manager.update(); markers_manager.update();
selection.must_find_current_marker = playback.must_find_current_marker = true; selection.must_find_current_marker = playback.must_find_current_marker = true;
piano_roll.RedrawList();
project.SetProjectChanged(); project.SetProjectChanged();
piano_roll.RedrawList();
} else if (taseditor_config.enable_hot_changes) } else if (taseditor_config.enable_hot_changes)
{ {
// when using Hot Changes, Piano Roll should be always redrawn, because old changes become less hot // when using Hot Changes, Piano Roll should be always redrawn, because old changes become less hot

View File

@ -295,99 +295,45 @@ void MARKERS_MANAGER::MakeCopyTo(MARKERS& destination)
destination.notes = markers.notes; destination.notes = markers.notes;
destination.Set_already_compressed(false); destination.Set_already_compressed(false);
} }
void MARKERS_MANAGER::RestoreFromCopy(MARKERS& source, int until_frame) void MARKERS_MANAGER::RestoreFromCopy(MARKERS& source)
{ {
if (until_frame >= 0)
{
// restore Markers up to and not including the frame
if ((int)markers.markers_array.size() <= until_frame)
{
// only copy head of source
markers.markers_array = source.markers_array;
markers.markers_array.resize(until_frame);
markers.notes = source.notes;
// find last Marker
int last_marker = GetMarkerUp(until_frame-1);
// delete all notes following the note of the last Marker
markers.notes.resize(last_marker+1);
} else
{
// combine head of source and tail of destination (old Markers)
// 1 - head = part of source Markers
std::vector<int> temp_markers_array;
std::vector<std::string> temp_notes;
temp_markers_array = source.markers_array;
temp_markers_array.resize(until_frame);
temp_notes = source.notes;
// find last Marker in temp_markers_array
int last_marker, frame;
for (frame = until_frame-1; frame >= 0; frame--)
if (temp_markers_array[frame]) break;
if (frame >= 0)
last_marker = temp_markers_array[frame];
else
last_marker = 0;
// delete all temp_notes foolowing the note of the last Marker
temp_notes.resize(last_marker+1);
// 2 - tail = part of old (current) Markers
// delete all Markers (and their notes) up to and not including until_frame
//for (int i = until_frame-1; i >= 0; i--) // actually no need for that
// ClearMarker(i);
// 3 - combine head and tail (if there are actually Markers left in the tail)
int size = markers.markers_array.size();
temp_markers_array.resize(size);
for (int i = until_frame; i < size; ++i)
{
if (markers.markers_array[i])
{
last_marker++; // make new id for old Marker
temp_markers_array[i] = last_marker;
temp_notes.push_back(markers.notes[markers.markers_array[i]]); // take note from old Markers and add it to the end of the head
}
}
// 4 - save result
markers.markers_array = temp_markers_array;
markers.notes = temp_notes;
}
} else
{
// end frame was not specified, consider this as "copy all"
markers.markers_array = source.markers_array; markers.markers_array = source.markers_array;
markers.notes = source.notes; markers.notes = source.notes;
} }
}
// return true if any difference in markers_array is found, comparing to markers.markers_array // return true only when difference is found before end frame (not including end frame)
bool MARKERS_MANAGER::checkMarkersDiff(MARKERS& their_markers) bool MARKERS_MANAGER::checkMarkersDiff(MARKERS& their_markers)
{ {
if (GetMarkersSize() != their_markers.markers_array.size()) return true; int end_my = GetMarkersSize() - 1;
if (GetNotesSize() != their_markers.notes.size()) return true; int end_their = their_markers.markers_array.size() - 1;
for (int i = markers.markers_array.size()-1; i >= 0; i--) int min_end = end_my;
int i;
// 1 - check if there are any Markers after min_end
if (end_my < end_their)
{
for (i = end_their; i > min_end; i--)
if (their_markers.markers_array[i])
return true;
} else if (end_my > end_their)
{
min_end = end_their;
for (i = end_my; i > min_end; i--)
if (markers.markers_array[i])
return true;
}
// 2 - check if there's any difference before min_end
for (i = min_end; i >= 0; i--)
{ {
if (markers.markers_array[i] != their_markers.markers_array[i]) if (markers.markers_array[i] != their_markers.markers_array[i])
return true; return true;
else if (markers.markers_array[i] && markers.notes[markers.markers_array[i]].compare(their_markers.notes[their_markers.markers_array[i]])) else if (markers.markers_array[i] && // not empty
markers.notes[markers.markers_array[i]].compare(their_markers.notes[their_markers.markers_array[i]])) // notes differ
return true; return true;
} }
// also check if there's difference between 0th notes // 3 - check if there's difference between 0th Notes
if (markers.notes[0].compare(their_markers.notes[0])) if (markers.notes[0].compare(their_markers.notes[0]))
return true; return true;
return false; // no difference found
}
// return true only when difference is found before end frame (not including end frame)
bool MARKERS_MANAGER::checkMarkersDiff(MARKERS& their_markers, int end)
{
if (end < 0)
return checkMarkersDiff(their_markers);
if (markers.markers_array.size() != their_markers.markers_array.size() && ((int)markers.markers_array.size()-1 < end || (int)their_markers.markers_array.size()-1 < end)) return true;
for (int i = end-1; i >= 0; i--)
{
if (markers.markers_array[i] != their_markers.markers_array[i])
return true;
else if (markers.markers_array[i] && markers.notes[markers.markers_array[i]].compare(their_markers.notes[their_markers.markers_array[i]]))
return true;
}
return false; return false;
} }
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------

View File

@ -55,10 +55,9 @@ public:
void SetNote(int index, const char* new_text); void SetNote(int index, const char* new_text);
void MakeCopyTo(MARKERS& destination); void MakeCopyTo(MARKERS& destination);
void RestoreFromCopy(MARKERS& source, int until_frame = -1); void RestoreFromCopy(MARKERS& source);
bool checkMarkersDiff(MARKERS& their_markers); bool checkMarkersDiff(MARKERS& their_markers);
bool checkMarkersDiff(MARKERS& their_markers, int end);
void FindSimilar(); void FindSimilar();
void FindNextSimilar(); void FindNextSimilar();

View File

@ -99,13 +99,13 @@ void SNAPSHOT::init(MovieData& md, bool hotchanges, int force_input_type)
strftime(description, 10, "%H:%M:%S", timeinfo); strftime(description, 10, "%H:%M:%S", timeinfo);
} }
bool SNAPSHOT::MarkersDifferFromCurrent(int end) bool SNAPSHOT::MarkersDifferFromCurrent()
{ {
return markers_manager.checkMarkersDiff(my_markers, end); return markers_manager.checkMarkersDiff(my_markers);
} }
void SNAPSHOT::copyToMarkers(int end) void SNAPSHOT::copyToMarkers()
{ {
markers_manager.RestoreFromCopy(my_markers, end); markers_manager.RestoreFromCopy(my_markers);
} }
MARKERS& SNAPSHOT::GetMarkers() MARKERS& SNAPSHOT::GetMarkers()
{ {
@ -439,8 +439,8 @@ int SNAPSHOT::findFirstChange(SNAPSHOT& snap, int start, int end)
break; break;
} }
} }
// if current size is less then previous, return last frame (=size-1) as the frame of difference // if my_size is less then their_size, return last frame + 1 (= size) as the frame of difference
if (size < snap_end) return size-1; if (size < snap_end) return size;
// no changes were found // no changes were found
return -1; return -1;
} }
@ -485,11 +485,11 @@ int SNAPSHOT::findFirstChange(MovieData& md, int start, int end)
break; break;
} }
} }
// if sizes differ, return last frame from the lesser of them // if sizes differ, return last frame + 1 from the lesser of them
if (size < md.getNumRecords() && end >= size-1) if (size < md.getNumRecords() && end >= size-1)
return size-1; return size;
else if (size > md.getNumRecords() && end >= md.getNumRecords()-1) else if (size > md.getNumRecords() && end >= md.getNumRecords()-1)
return md.getNumRecords()-1; return md.getNumRecords();
return -1; // no changes were found return -1; // no changes were found
} }

View File

@ -20,8 +20,8 @@ public:
SNAPSHOT(); SNAPSHOT();
void init(MovieData& md, bool hotchanges, int force_input_type = -1); void init(MovieData& md, bool hotchanges, int force_input_type = -1);
bool MarkersDifferFromCurrent(int end = -1); bool MarkersDifferFromCurrent();
void copyToMarkers(int end = -1); void copyToMarkers();
MARKERS& GetMarkers(); MARKERS& GetMarkers();
void toMovie(MovieData& md, int start = 0, int end = -1); void toMovie(MovieData& md, int start = 0, int end = -1);