From 1e2d18b747f9dcb754d8a2aee7c4b858075fa198 Mon Sep 17 00:00:00 2001 From: ansstuff Date: Mon, 16 Apr 2012 20:09:16 +0000 Subject: [PATCH] Taseditor: gradual History Log autocompression when idle --- src/drivers/win/taseditor/history.cpp | 33 ++++++++++++++- src/drivers/win/taseditor/history.h | 10 ++++- src/drivers/win/taseditor/markers.cpp | 41 ++++++++++++++----- src/drivers/win/taseditor/markers.h | 11 ++++- src/drivers/win/taseditor/markers_manager.cpp | 2 + src/drivers/win/taseditor/snapshot.cpp | 7 ++++ src/drivers/win/taseditor/snapshot.h | 14 ++++--- 7 files changed, 98 insertions(+), 20 deletions(-) diff --git a/src/drivers/win/taseditor/history.cpp b/src/drivers/win/taseditor/history.cpp index aa296f7a..ebb68a52 100644 --- a/src/drivers/win/taseditor/history.cpp +++ b/src/drivers/win/taseditor/history.cpp @@ -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 { diff --git a/src/drivers/win/taseditor/history.h b/src/drivers/win/taseditor/history.h index 5476bd36..e4a938da 100644 --- a/src/drivers/win/taseditor/history.h +++ b/src/drivers/win/taseditor/history.h @@ -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 snapshots; std::vector backup_bookmarks; std::vector 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; }; diff --git a/src/drivers/win/taseditor/markers.cpp b/src/drivers/win/taseditor/markers.cpp index 1da2a267..f63eb29b 100644 --- a/src/drivers/win/taseditor/markers.cpp +++ b/src/drivers/win/taseditor/markers.cpp @@ -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 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 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; +} + diff --git a/src/drivers/win/taseditor/markers.h b/src/drivers/win/taseditor/markers.h index 066ce4eb..b713cda8 100644 --- a/src/drivers/win/taseditor/markers.h +++ b/src/drivers/win/taseditor/markers.h @@ -11,9 +11,18 @@ public: bool load(EMUFILE *is); bool skipLoad(EMUFILE *is); - std::vector 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 notes; // Format: 0th - note for intro (Marker 0), 1st - note for Marker1, 2nd - note for Marker2, ... + // not saved data + std::vector markers_array; // Format: 0th = marker num (id) for frame 0, 1st = marker num for frame 1, ... private: + // also saved data + std::vector markers_array_compressed; + bool already_compressed; // to compress only once }; diff --git a/src/drivers/win/taseditor/markers_manager.cpp b/src/drivers/win/taseditor/markers_manager.cpp index a4ac3e40..6dd25917 100644 --- a/src/drivers/win/taseditor/markers_manager.cpp +++ b/src/drivers/win/taseditor/markers_manager.cpp @@ -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) { diff --git a/src/drivers/win/taseditor/snapshot.cpp b/src/drivers/win/taseditor/snapshot.cpp index 7c6f0057..507534ac 100644 --- a/src/drivers/win/taseditor/snapshot.cpp +++ b/src/drivers/win/taseditor/snapshot.cpp @@ -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) diff --git a/src/drivers/win/taseditor/snapshot.h b/src/drivers/win/taseditor/snapshot.h index dc77a25f..ac80303a 100644 --- a/src/drivers/win/taseditor/snapshot.h +++ b/src/drivers/win/taseditor/snapshot.h @@ -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 joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ... - std::vector commands; // Format: commands-for-frame0, commands-for-frame1, ... - std::vector 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 joysticks; // Format: joy0-for-frame0, joy1-for-frame0, joy2-for-frame0, joy3-for-frame0, joy0-for-frame1, joy1-for-frame1, ... + std::vector commands; // Format: commands-for-frame0, commands-for-frame1, ... + std::vector 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;