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
|
||||
* also stores 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
|
||||
* 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.fmt = LVCFMT_LEFT;
|
||||
ListView_InsertColumn(hwndHistoryList, 0, &lvc);
|
||||
// shedule first autocompression
|
||||
next_autocompress_time = clock() + TIME_BETWEEN_AUTOCOMPRESSIONS;
|
||||
}
|
||||
void HISTORY::free()
|
||||
{
|
||||
|
@ -169,6 +172,30 @@ void HISTORY::update()
|
|||
}
|
||||
if (old_show_undo_hint != show_undo_hint)
|
||||
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()
|
||||
|
@ -911,7 +938,11 @@ void HISTORY::save(EMUFILE *os, bool really_save)
|
|||
snapshots[real_pos].save(os);
|
||||
backup_bookmarks[real_pos].save(os);
|
||||
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
|
||||
{
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#define UNDO_HINT_TIME 200
|
||||
|
||||
#define SAVING_HISTORY_PROGRESSBAR_UPDATE_RATE 10
|
||||
#define TIME_BETWEEN_AUTOCOMPRESSIONS 500 // in milliseconds
|
||||
|
||||
enum MOD_TYPES
|
||||
{
|
||||
MODTYPE_INIT,
|
||||
|
@ -132,18 +135,21 @@ private:
|
|||
void AddItemToHistory(SNAPSHOT &snap, int cur_branch = 0);
|
||||
void AddItemToHistory(SNAPSHOT &snap, int cur_branch, BOOKMARK &bookm);
|
||||
|
||||
// saved variables
|
||||
std::vector<SNAPSHOT> snapshots;
|
||||
std::vector<BOOKMARK> backup_bookmarks;
|
||||
std::vector<int8> backup_current_branch;
|
||||
|
||||
int history_cursor_pos;
|
||||
int history_start_pos;
|
||||
int history_total_items;
|
||||
|
||||
// not saved variables
|
||||
int history_start_pos;
|
||||
int history_size;
|
||||
|
||||
int undo_hint_pos, old_undo_hint_pos;
|
||||
int undo_hint_time;
|
||||
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
|
||||
|
||||
* 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
|
||||
* stores resources: max length of a Note
|
||||
------------------------------------------------------------------------------------ */
|
||||
|
@ -20,20 +21,20 @@ Markers - Snapshot of Markers state
|
|||
|
||||
MARKERS::MARKERS()
|
||||
{
|
||||
already_compressed = false;
|
||||
}
|
||||
|
||||
void MARKERS::save(EMUFILE *os)
|
||||
{
|
||||
// write size
|
||||
int size = markers_array.size();
|
||||
int len;
|
||||
write32le(size, os);
|
||||
// compress and write array
|
||||
int len = markers_array.size() * sizeof(int);
|
||||
uLongf comprlen = (len>>9)+12 + len;
|
||||
std::vector<uint8> cbuf(comprlen);
|
||||
compress(&cbuf[0], &comprlen, (uint8*)&markers_array[0], len);
|
||||
write32le(comprlen, os);
|
||||
os->fwrite(&cbuf[0], comprlen);
|
||||
// write array
|
||||
if (!already_compressed)
|
||||
compress_data();
|
||||
write32le(markers_array_compressed.size(), os);
|
||||
os->fwrite(&markers_array_compressed[0], markers_array_compressed.size());
|
||||
// write notes
|
||||
size = notes.size();
|
||||
write32le(size, os);
|
||||
|
@ -53,13 +54,14 @@ bool MARKERS::load(EMUFILE *is)
|
|||
{
|
||||
markers_array.resize(size);
|
||||
// read and uncompress array
|
||||
already_compressed = true;
|
||||
int comprlen, len;
|
||||
uLongf destlen = size * sizeof(int);
|
||||
if (!read32le(&comprlen, is)) return true;
|
||||
if (comprlen <= 0) return true;
|
||||
std::vector<uint8> cbuf(comprlen);
|
||||
if (is->fread(&cbuf[0], comprlen) != comprlen) return true;
|
||||
int e = uncompress((uint8*)&markers_array[0], &destlen, &cbuf[0], comprlen);
|
||||
markers_array_compressed.resize(comprlen);
|
||||
if (is->fread(&markers_array_compressed[0], comprlen) != comprlen) return true;
|
||||
int e = uncompress((uint8*)&markers_array[0], &destlen, &markers_array_compressed[0], comprlen);
|
||||
if (e != Z_OK && e != Z_BUF_ERROR) return true;
|
||||
// read notes
|
||||
if (read32le(&size, is) && size >= 0)
|
||||
|
@ -101,3 +103,22 @@ bool MARKERS::skipLoad(EMUFILE *is)
|
|||
}
|
||||
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 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, ...
|
||||
// not saved data
|
||||
std::vector<int> markers_array; // Format: 0th = marker num (id) for frame 0, 1st = marker num for frame 1, ...
|
||||
|
||||
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
|
||||
os->fwrite(markers_save_id, MARKERS_ID_LEN);
|
||||
markers.Set_already_compressed(false); // must recompress data, because it has changed, probably
|
||||
markers.save(os);
|
||||
} else
|
||||
{
|
||||
|
@ -291,6 +292,7 @@ void MARKERS_MANAGER::MakeCopyTo(MARKERS& destination)
|
|||
{
|
||||
destination.markers_array = markers.markers_array;
|
||||
destination.notes = markers.notes;
|
||||
destination.Set_already_compressed(false);
|
||||
}
|
||||
void MARKERS_MANAGER::RestoreFromCopy(MARKERS& source, int until_frame)
|
||||
{
|
||||
|
|
|
@ -181,6 +181,13 @@ void SNAPSHOT::compress_data()
|
|||
}
|
||||
// don't recompress anymore
|
||||
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)
|
||||
|
|
|
@ -30,6 +30,9 @@ public:
|
|||
bool load(EMUFILE *is);
|
||||
bool skipLoad(EMUFILE *is);
|
||||
|
||||
void compress_data();
|
||||
bool Get_already_compressed();
|
||||
|
||||
bool checkDiff(SNAPSHOT& snap);
|
||||
void fillJoypadsDiff(SNAPSHOT& snap, int frame);
|
||||
|
||||
|
@ -60,22 +63,21 @@ public:
|
|||
// saved data
|
||||
int size; // in frames
|
||||
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 start_frame; // for consecutive Draws
|
||||
int end_frame; // for consecutive Draws
|
||||
|
||||
int consecutive_tag; // for consecutive Recordings and Draws
|
||||
uint32 rec_joypad_diff_bits; // for consecutive Recordings
|
||||
int mod_type;
|
||||
char description[SNAPSHOT_DESC_MAX_LENGTH];
|
||||
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:
|
||||
void compress_data();
|
||||
|
||||
// also saved data
|
||||
MARKERS my_markers;
|
||||
|
|
Loading…
Reference in New Issue