Taseditor: gradual History Log autocompression when idle
This commit is contained in:
parent
d188a2def2
commit
1e2d18b747
|
@ -16,6 +16,7 @@ History - History of movie modifications
|
||||||
* implements all restoring operations: undo, redo, revert to any snapshot from the array
|
* implements all restoring operations: undo, redo, revert to any snapshot from the array
|
||||||
* also stores the state of "undo pointer"
|
* also stores the state of "undo pointer"
|
||||||
* regularly updates the state of "undo pointer"
|
* regularly updates the state of "undo pointer"
|
||||||
|
* regularly (when emulator is paused) searches for uncompressed items in the History Log and compresses first found item
|
||||||
* implements the working of History List: creating, redrawing, clicks, auto-scrolling
|
* implements the working of History List: creating, redrawing, clicks, auto-scrolling
|
||||||
* stores resources: save id, ids and names of all possible types of modification, timings of "undo pointer"
|
* stores resources: save id, ids and names of all possible types of modification, timings of "undo pointer"
|
||||||
------------------------------------------------------------------------------------ */
|
------------------------------------------------------------------------------------ */
|
||||||
|
@ -121,6 +122,8 @@ void HISTORY::init()
|
||||||
lvc.cx = 500;
|
lvc.cx = 500;
|
||||||
lvc.fmt = LVCFMT_LEFT;
|
lvc.fmt = LVCFMT_LEFT;
|
||||||
ListView_InsertColumn(hwndHistoryList, 0, &lvc);
|
ListView_InsertColumn(hwndHistoryList, 0, &lvc);
|
||||||
|
// shedule first autocompression
|
||||||
|
next_autocompress_time = clock() + TIME_BETWEEN_AUTOCOMPRESSIONS;
|
||||||
}
|
}
|
||||||
void HISTORY::free()
|
void HISTORY::free()
|
||||||
{
|
{
|
||||||
|
@ -169,6 +172,30 @@ void HISTORY::update()
|
||||||
}
|
}
|
||||||
if (old_show_undo_hint != show_undo_hint)
|
if (old_show_undo_hint != show_undo_hint)
|
||||||
piano_roll.RedrawRow(undo_hint_pos); // not changing Bookmarks List
|
piano_roll.RedrawRow(undo_hint_pos); // not changing Bookmarks List
|
||||||
|
|
||||||
|
// when cpu is idle, compress items from time to time
|
||||||
|
if (clock() > next_autocompress_time)
|
||||||
|
{
|
||||||
|
if (FCEUI_EmulationPaused())
|
||||||
|
{
|
||||||
|
// search for first occurence of an item with snapshot that is not compressed yet
|
||||||
|
int real_pos;
|
||||||
|
for (int i = history_total_items - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
real_pos = (history_start_pos + i) % history_size;
|
||||||
|
if (!snapshots[real_pos].Get_already_compressed())
|
||||||
|
{
|
||||||
|
snapshots[real_pos].compress_data();
|
||||||
|
break;
|
||||||
|
} else if (backup_bookmarks[real_pos].not_empty && backup_bookmarks[real_pos].snapshot.Get_already_compressed())
|
||||||
|
{
|
||||||
|
backup_bookmarks[real_pos].snapshot.compress_data();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next_autocompress_time = clock() + TIME_BETWEEN_AUTOCOMPRESSIONS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HISTORY::HistorySizeChanged()
|
void HISTORY::HistorySizeChanged()
|
||||||
|
@ -911,7 +938,11 @@ void HISTORY::save(EMUFILE *os, bool really_save)
|
||||||
snapshots[real_pos].save(os);
|
snapshots[real_pos].save(os);
|
||||||
backup_bookmarks[real_pos].save(os);
|
backup_bookmarks[real_pos].save(os);
|
||||||
os->fwrite(&backup_current_branch[real_pos], 1);
|
os->fwrite(&backup_current_branch[real_pos], 1);
|
||||||
playback.SetProgressbar(i, history_total_items);
|
if (i / SAVING_HISTORY_PROGRESSBAR_UPDATE_RATE > last_tick)
|
||||||
|
{
|
||||||
|
playback.SetProgressbar(i, history_total_items);
|
||||||
|
last_tick = i / PROGRESSBAR_UPDATE_RATE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#define UNDO_HINT_TIME 200
|
#define UNDO_HINT_TIME 200
|
||||||
|
|
||||||
|
#define SAVING_HISTORY_PROGRESSBAR_UPDATE_RATE 10
|
||||||
|
#define TIME_BETWEEN_AUTOCOMPRESSIONS 500 // in milliseconds
|
||||||
|
|
||||||
enum MOD_TYPES
|
enum MOD_TYPES
|
||||||
{
|
{
|
||||||
MODTYPE_INIT,
|
MODTYPE_INIT,
|
||||||
|
@ -132,18 +135,21 @@ private:
|
||||||
void AddItemToHistory(SNAPSHOT &snap, int cur_branch = 0);
|
void AddItemToHistory(SNAPSHOT &snap, int cur_branch = 0);
|
||||||
void AddItemToHistory(SNAPSHOT &snap, int cur_branch, BOOKMARK &bookm);
|
void AddItemToHistory(SNAPSHOT &snap, int cur_branch, BOOKMARK &bookm);
|
||||||
|
|
||||||
|
// saved variables
|
||||||
std::vector<SNAPSHOT> snapshots;
|
std::vector<SNAPSHOT> snapshots;
|
||||||
std::vector<BOOKMARK> backup_bookmarks;
|
std::vector<BOOKMARK> backup_bookmarks;
|
||||||
std::vector<int8> backup_current_branch;
|
std::vector<int8> backup_current_branch;
|
||||||
|
|
||||||
int history_cursor_pos;
|
int history_cursor_pos;
|
||||||
int history_start_pos;
|
|
||||||
int history_total_items;
|
int history_total_items;
|
||||||
|
|
||||||
|
// not saved variables
|
||||||
|
int history_start_pos;
|
||||||
int history_size;
|
int history_size;
|
||||||
|
|
||||||
int undo_hint_pos, old_undo_hint_pos;
|
int undo_hint_pos, old_undo_hint_pos;
|
||||||
int undo_hint_time;
|
int undo_hint_time;
|
||||||
bool old_show_undo_hint, show_undo_hint;
|
bool old_show_undo_hint, show_undo_hint;
|
||||||
|
int next_autocompress_time;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||||
Markers - Snapshot of Markers state
|
Markers - Snapshot of Markers state
|
||||||
|
|
||||||
* stores the data about Markers state: array of distributing Markers among movie frames, and array of Notes
|
* stores the data about Markers state: array of distributing Markers among movie frames, and array of Notes
|
||||||
|
* implements compression and decompression of stored data
|
||||||
* saves and loads the data from a project file. On error: sends warning to caller
|
* saves and loads the data from a project file. On error: sends warning to caller
|
||||||
* stores resources: max length of a Note
|
* stores resources: max length of a Note
|
||||||
------------------------------------------------------------------------------------ */
|
------------------------------------------------------------------------------------ */
|
||||||
|
@ -20,20 +21,20 @@ Markers - Snapshot of Markers state
|
||||||
|
|
||||||
MARKERS::MARKERS()
|
MARKERS::MARKERS()
|
||||||
{
|
{
|
||||||
|
already_compressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MARKERS::save(EMUFILE *os)
|
void MARKERS::save(EMUFILE *os)
|
||||||
{
|
{
|
||||||
// write size
|
// write size
|
||||||
int size = markers_array.size();
|
int size = markers_array.size();
|
||||||
|
int len;
|
||||||
write32le(size, os);
|
write32le(size, os);
|
||||||
// compress and write array
|
// write array
|
||||||
int len = markers_array.size() * sizeof(int);
|
if (!already_compressed)
|
||||||
uLongf comprlen = (len>>9)+12 + len;
|
compress_data();
|
||||||
std::vector<uint8> cbuf(comprlen);
|
write32le(markers_array_compressed.size(), os);
|
||||||
compress(&cbuf[0], &comprlen, (uint8*)&markers_array[0], len);
|
os->fwrite(&markers_array_compressed[0], markers_array_compressed.size());
|
||||||
write32le(comprlen, os);
|
|
||||||
os->fwrite(&cbuf[0], comprlen);
|
|
||||||
// write notes
|
// write notes
|
||||||
size = notes.size();
|
size = notes.size();
|
||||||
write32le(size, os);
|
write32le(size, os);
|
||||||
|
@ -53,13 +54,14 @@ bool MARKERS::load(EMUFILE *is)
|
||||||
{
|
{
|
||||||
markers_array.resize(size);
|
markers_array.resize(size);
|
||||||
// read and uncompress array
|
// read and uncompress array
|
||||||
|
already_compressed = true;
|
||||||
int comprlen, len;
|
int comprlen, len;
|
||||||
uLongf destlen = size * sizeof(int);
|
uLongf destlen = size * sizeof(int);
|
||||||
if (!read32le(&comprlen, is)) return true;
|
if (!read32le(&comprlen, is)) return true;
|
||||||
if (comprlen <= 0) return true;
|
if (comprlen <= 0) return true;
|
||||||
std::vector<uint8> cbuf(comprlen);
|
markers_array_compressed.resize(comprlen);
|
||||||
if (is->fread(&cbuf[0], comprlen) != comprlen) return true;
|
if (is->fread(&markers_array_compressed[0], comprlen) != comprlen) return true;
|
||||||
int e = uncompress((uint8*)&markers_array[0], &destlen, &cbuf[0], comprlen);
|
int e = uncompress((uint8*)&markers_array[0], &destlen, &markers_array_compressed[0], comprlen);
|
||||||
if (e != Z_OK && e != Z_BUF_ERROR) return true;
|
if (e != Z_OK && e != Z_BUF_ERROR) return true;
|
||||||
// read notes
|
// read notes
|
||||||
if (read32le(&size, is) && size >= 0)
|
if (read32le(&size, is) && size >= 0)
|
||||||
|
@ -101,3 +103,22 @@ bool MARKERS::skipLoad(EMUFILE *is)
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MARKERS::compress_data()
|
||||||
|
{
|
||||||
|
int len = markers_array.size() * sizeof(int);
|
||||||
|
uLongf comprlen = (len>>9)+12 + len;
|
||||||
|
markers_array_compressed.resize(comprlen);
|
||||||
|
compress(&markers_array_compressed[0], &comprlen, (uint8*)&markers_array[0], len);
|
||||||
|
markers_array_compressed.resize(comprlen);
|
||||||
|
already_compressed = true;
|
||||||
|
}
|
||||||
|
bool MARKERS::Get_already_compressed()
|
||||||
|
{
|
||||||
|
return already_compressed;
|
||||||
|
}
|
||||||
|
void MARKERS::Set_already_compressed(bool value)
|
||||||
|
{
|
||||||
|
already_compressed = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,18 @@ public:
|
||||||
bool load(EMUFILE *is);
|
bool load(EMUFILE *is);
|
||||||
bool skipLoad(EMUFILE *is);
|
bool skipLoad(EMUFILE *is);
|
||||||
|
|
||||||
std::vector<int> markers_array; // Format: 0th = marker num (id) for frame 0, 1st = marker num for frame 1, ...
|
void compress_data();
|
||||||
|
bool Get_already_compressed();
|
||||||
|
void Set_already_compressed(bool value);
|
||||||
|
|
||||||
|
// saved data
|
||||||
std::vector<std::string> notes; // Format: 0th - note for intro (Marker 0), 1st - note for Marker1, 2nd - note for Marker2, ...
|
std::vector<std::string> notes; // Format: 0th - note for intro (Marker 0), 1st - note for Marker1, 2nd - note for Marker2, ...
|
||||||
|
// not saved data
|
||||||
|
std::vector<int> markers_array; // Format: 0th = marker num (id) for frame 0, 1st = marker num for frame 1, ...
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// also saved data
|
||||||
|
std::vector<uint8> markers_array_compressed;
|
||||||
|
|
||||||
|
bool already_compressed; // to compress only once
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,6 +72,7 @@ void MARKERS_MANAGER::save(EMUFILE *os, bool really_save)
|
||||||
{
|
{
|
||||||
// write "MARKERS" string
|
// write "MARKERS" string
|
||||||
os->fwrite(markers_save_id, MARKERS_ID_LEN);
|
os->fwrite(markers_save_id, MARKERS_ID_LEN);
|
||||||
|
markers.Set_already_compressed(false); // must recompress data, because it has changed, probably
|
||||||
markers.save(os);
|
markers.save(os);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
@ -291,6 +292,7 @@ void MARKERS_MANAGER::MakeCopyTo(MARKERS& destination)
|
||||||
{
|
{
|
||||||
destination.markers_array = markers.markers_array;
|
destination.markers_array = markers.markers_array;
|
||||||
destination.notes = markers.notes;
|
destination.notes = markers.notes;
|
||||||
|
destination.Set_already_compressed(false);
|
||||||
}
|
}
|
||||||
void MARKERS_MANAGER::RestoreFromCopy(MARKERS& source, int until_frame)
|
void MARKERS_MANAGER::RestoreFromCopy(MARKERS& source, int until_frame)
|
||||||
{
|
{
|
||||||
|
|
|
@ -181,6 +181,13 @@ void SNAPSHOT::compress_data()
|
||||||
}
|
}
|
||||||
// don't recompress anymore
|
// don't recompress anymore
|
||||||
already_compressed = true;
|
already_compressed = true;
|
||||||
|
// also see if we can compress my_markers
|
||||||
|
if (!my_markers.Get_already_compressed())
|
||||||
|
my_markers.compress_data();
|
||||||
|
}
|
||||||
|
bool SNAPSHOT::Get_already_compressed()
|
||||||
|
{
|
||||||
|
return already_compressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SNAPSHOT::save(EMUFILE *os)
|
void SNAPSHOT::save(EMUFILE *os)
|
||||||
|
|
|
@ -30,6 +30,9 @@ public:
|
||||||
bool load(EMUFILE *is);
|
bool load(EMUFILE *is);
|
||||||
bool skipLoad(EMUFILE *is);
|
bool skipLoad(EMUFILE *is);
|
||||||
|
|
||||||
|
void compress_data();
|
||||||
|
bool Get_already_compressed();
|
||||||
|
|
||||||
bool checkDiff(SNAPSHOT& snap);
|
bool checkDiff(SNAPSHOT& snap);
|
||||||
void fillJoypadsDiff(SNAPSHOT& snap, int frame);
|
void fillJoypadsDiff(SNAPSHOT& snap, int frame);
|
||||||
|
|
||||||
|
@ -60,22 +63,21 @@ public:
|
||||||
// saved data
|
// saved data
|
||||||
int size; // in frames
|
int size; // in frames
|
||||||
int input_type; // theoretically TAS Editor can support any other input types
|
int input_type; // theoretically TAS Editor can support any other input types
|
||||||
std::vector<uint8> joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ...
|
|
||||||
std::vector<uint8> commands; // Format: commands-for-frame0, commands-for-frame1, ...
|
|
||||||
std::vector<uint8> hot_changes; // Format: buttons01joy0-for-frame0, buttons23joy0-for-frame0, buttons45joy0-for-frame0, buttons67joy0-for-frame0, buttons01joy1-for-frame0, ...
|
|
||||||
int jump_frame; // for jumping when making undo
|
int jump_frame; // for jumping when making undo
|
||||||
|
|
||||||
int start_frame; // for consecutive Draws
|
int start_frame; // for consecutive Draws
|
||||||
int end_frame; // for consecutive Draws
|
int end_frame; // for consecutive Draws
|
||||||
|
|
||||||
int consecutive_tag; // for consecutive Recordings and Draws
|
int consecutive_tag; // for consecutive Recordings and Draws
|
||||||
uint32 rec_joypad_diff_bits; // for consecutive Recordings
|
uint32 rec_joypad_diff_bits; // for consecutive Recordings
|
||||||
int mod_type;
|
int mod_type;
|
||||||
char description[SNAPSHOT_DESC_MAX_LENGTH];
|
char description[SNAPSHOT_DESC_MAX_LENGTH];
|
||||||
bool has_hot_changes;
|
bool has_hot_changes;
|
||||||
|
|
||||||
|
// not saved data
|
||||||
|
std::vector<uint8> joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ...
|
||||||
|
std::vector<uint8> commands; // Format: commands-for-frame0, commands-for-frame1, ...
|
||||||
|
std::vector<uint8> hot_changes; // Format: buttons01joy0-for-frame0, buttons23joy0-for-frame0, buttons45joy0-for-frame0, buttons67joy0-for-frame0, buttons01joy1-for-frame0, ...
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void compress_data();
|
|
||||||
|
|
||||||
// also saved data
|
// also saved data
|
||||||
MARKERS my_markers;
|
MARKERS my_markers;
|
||||||
|
|
Loading…
Reference in New Issue