* Taseditor: added "Ungreenzone" item to context menu
* Taseditor: added "Config->Enable Greenzoning" * Taseditor: playback/greenzone cleanup * Taseditor: fixed bug when opening TAS Editor in MOVIE_FINISHED mode
This commit is contained in:
parent
42b35b5e23
commit
4c0f74d022
|
@ -353,6 +353,7 @@ static CFGSTRUCT fceuconfig[] = {
|
||||||
AC(taseditor_config.findnote_matchcase),
|
AC(taseditor_config.findnote_matchcase),
|
||||||
AC(taseditor_config.findnote_search_up),
|
AC(taseditor_config.findnote_search_up),
|
||||||
AC(taseditor_config.draw_input),
|
AC(taseditor_config.draw_input),
|
||||||
|
AC(taseditor_config.enable_greenzoning),
|
||||||
AC(taseditor_config.silent_autosave),
|
AC(taseditor_config.silent_autosave),
|
||||||
AC(taseditor_config.autopause_at_finish),
|
AC(taseditor_config.autopause_at_finish),
|
||||||
AC(taseditor_config.tooltips),
|
AC(taseditor_config.tooltips),
|
||||||
|
|
|
@ -276,6 +276,7 @@ BEGIN
|
||||||
MENUITEM "Set max Undo levels", ID_CONFIG_SETMAXUNDOLEVELS,MFT_STRING,MFS_ENABLED
|
MENUITEM "Set max Undo levels", ID_CONFIG_SETMAXUNDOLEVELS,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM "Set Autosave period", ID_CONFIG_SETAUTOSAVEPERIOD,MFT_STRING,MFS_ENABLED
|
MENUITEM "Set Autosave period", ID_CONFIG_SETAUTOSAVEPERIOD,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM MFT_SEPARATOR
|
MENUITEM MFT_SEPARATOR
|
||||||
|
MENUITEM "Enable Greenzoning", ID_CONFIG_ENABLEGREENZONING,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM "Silent Autosave", ID_CONFIG_SILENTAUTOSAVE,MFT_STRING,MFS_ENABLED
|
MENUITEM "Silent Autosave", ID_CONFIG_SILENTAUTOSAVE,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM "Autofire Pattern skips Lag", ID_CONFIG_PATTERNSKIPSLAG,MFT_STRING,MFS_ENABLED
|
MENUITEM "Autofire Pattern skips Lag", ID_CONFIG_PATTERNSKIPSLAG,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM "Auto-adjust Input according to Lag", ID_CONFIG_ADJUSTLAG,MFT_STRING,MFS_ENABLED
|
MENUITEM "Auto-adjust Input according to Lag", ID_CONFIG_ADJUSTLAG,MFT_STRING,MFS_ENABLED
|
||||||
|
@ -386,6 +387,8 @@ BEGIN
|
||||||
MENUITEM "Deselect", ID_SELECTED_DESELECT
|
MENUITEM "Deselect", ID_SELECTED_DESELECT
|
||||||
MENUITEM "Select between Markers\tCtrl+A", ID_SELECTED_SELECTMIDMARKERS
|
MENUITEM "Select between Markers\tCtrl+A", ID_SELECTED_SELECTMIDMARKERS
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "Ungreenzone", ID_SELECTED_UNGREENZONE
|
||||||
|
MENUITEM SEPARATOR
|
||||||
MENUITEM "Clear\tDel", ID_CONTEXT_SELECTED_CLEARFRAMES
|
MENUITEM "Clear\tDel", ID_CONTEXT_SELECTED_CLEARFRAMES
|
||||||
MENUITEM "Delete\tCtrl+Del", ID_CONTEXT_SELECTED_DELETEFRAMES
|
MENUITEM "Delete\tCtrl+Del", ID_CONTEXT_SELECTED_DELETEFRAMES
|
||||||
MENUITEM "Clone\tCtrl+Ins", ID_SELECTED_CLONE
|
MENUITEM "Clone\tCtrl+Ins", ID_SELECTED_CLONE
|
||||||
|
|
|
@ -1141,6 +1141,9 @@
|
||||||
#define ID_CONFIG_PATTERNSKIPSLAG 40568
|
#define ID_CONFIG_PATTERNSKIPSLAG 40568
|
||||||
#define CLEAR_LOG 40569
|
#define CLEAR_LOG 40569
|
||||||
#define CLOSE_LOG 40570
|
#define CLOSE_LOG 40570
|
||||||
|
#define ID_SELECTED_UNGREENZONE 40571
|
||||||
|
#define ID_SELECTED_F 40572
|
||||||
|
#define ID_CONFIG_ENABLEGREENZONING 40573
|
||||||
#define IDC_DEBUGGER_ICONTRAY 55535
|
#define IDC_DEBUGGER_ICONTRAY 55535
|
||||||
#define MW_ValueLabel2 65423
|
#define MW_ValueLabel2 65423
|
||||||
#define MW_ValueLabel1 65426
|
#define MW_ValueLabel1 65426
|
||||||
|
@ -1151,7 +1154,7 @@
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 289
|
#define _APS_NEXT_RESOURCE_VALUE 289
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40571
|
#define _APS_NEXT_COMMAND_VALUE 40574
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1282
|
#define _APS_NEXT_CONTROL_VALUE 1282
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -116,7 +116,7 @@ bool EnterTasEditor()
|
||||||
history.init();
|
history.init();
|
||||||
taseditor_lua.init();
|
taseditor_lua.init();
|
||||||
// either start new movie or use current movie
|
// either start new movie or use current movie
|
||||||
if (FCEUMOV_Mode(MOVIEMODE_INACTIVE) || currMovieData.savestate.size() != 0)
|
if (!FCEUMOV_Mode(MOVIEMODE_RECORD|MOVIEMODE_PLAY) || currMovieData.savestate.size() != 0)
|
||||||
{
|
{
|
||||||
if (currMovieData.savestate.size() != 0)
|
if (currMovieData.savestate.size() != 0)
|
||||||
FCEUD_PrintError("This version of TAS Editor doesn't work with movies starting from savestate.");
|
FCEUD_PrintError("This version of TAS Editor doesn't work with movies starting from savestate.");
|
||||||
|
@ -131,6 +131,9 @@ bool EnterTasEditor()
|
||||||
FCEUI_StopMovie();
|
FCEUI_StopMovie();
|
||||||
movieMode = MOVIEMODE_TASEDITOR;
|
movieMode = MOVIEMODE_TASEDITOR;
|
||||||
}
|
}
|
||||||
|
// if movie length is less or equal to currFrame, pad it with empty frames
|
||||||
|
if (((int)currMovieData.records.size() - 1) < currFrameCounter)
|
||||||
|
currMovieData.insertEmpty(-1, currFrameCounter - ((int)currMovieData.records.size() - 1));
|
||||||
// ensure that movie has correct set of ports/fourscore
|
// ensure that movie has correct set of ports/fourscore
|
||||||
SetInputType(currMovieData, GetInputType(currMovieData));
|
SetInputType(currMovieData, GetInputType(currMovieData));
|
||||||
// force the input configuration stored in the movie to apply to FCEUX config
|
// force the input configuration stored in the movie to apply to FCEUX config
|
||||||
|
|
|
@ -451,7 +451,7 @@ void BOOKMARKS::deploy(int slot)
|
||||||
// jump to the target (bookmarked frame)
|
// jump to the target (bookmarked frame)
|
||||||
if (greenzone.SavestateIsEmpty(keyframe))
|
if (greenzone.SavestateIsEmpty(keyframe))
|
||||||
greenzone.WriteSavestate(keyframe, bookmarks_array[slot].savestate);
|
greenzone.WriteSavestate(keyframe, bookmarks_array[slot].savestate);
|
||||||
playback.jump(keyframe);
|
playback.jump(keyframe, true);
|
||||||
// switch current branch to this branch
|
// switch current branch to this branch
|
||||||
int old_current_branch = branches.GetCurrentBranch();
|
int old_current_branch = branches.GetCurrentBranch();
|
||||||
branches.HandleBookmarkDeploy(slot);
|
branches.HandleBookmarkDeploy(slot);
|
||||||
|
|
|
@ -59,30 +59,20 @@ void GREENZONE::reset()
|
||||||
}
|
}
|
||||||
void GREENZONE::update()
|
void GREENZONE::update()
|
||||||
{
|
{
|
||||||
// keep collecting savestates, this function must be called at the end of every frame
|
// keep collecting savestates, this code must be executed at the end of every frame
|
||||||
CollectCurrentState();
|
if (taseditor_config.enable_greenzoning)
|
||||||
|
{
|
||||||
|
CollectCurrentState();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// just update Greenzone upper limit
|
||||||
|
if (greenZoneCount <= currFrameCounter)
|
||||||
|
greenZoneCount = currFrameCounter + 1;
|
||||||
|
}
|
||||||
|
|
||||||
// run cleaning from time to time
|
// run cleaning from time to time
|
||||||
if (clock() > next_cleaning_time)
|
if (clock() > next_cleaning_time)
|
||||||
RunGreenzoneCleaning();
|
RunGreenzoneCleaning();
|
||||||
}
|
|
||||||
|
|
||||||
void GREENZONE::CollectCurrentState()
|
|
||||||
{
|
|
||||||
// update Greenzone upper limit if needed
|
|
||||||
if (greenZoneCount <= currFrameCounter)
|
|
||||||
greenZoneCount = currFrameCounter + 1;
|
|
||||||
|
|
||||||
if ((int)savestates.size() < greenZoneCount)
|
|
||||||
savestates.resize(greenZoneCount);
|
|
||||||
|
|
||||||
// if frame is not saved - log savestate
|
|
||||||
if (!savestates[currFrameCounter].size())
|
|
||||||
{
|
|
||||||
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)
|
||||||
|
@ -111,21 +101,33 @@ void GREENZONE::CollectCurrentState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GREENZONE::loadTasSavestate(int frame)
|
void GREENZONE::CollectCurrentState()
|
||||||
{
|
{
|
||||||
if (frame < 0 || frame >= currMovieData.getNumRecords())
|
if ((int)savestates.size() <= currFrameCounter)
|
||||||
return false;
|
savestates.resize(currFrameCounter + 1);
|
||||||
if ((int)savestates.size() <= frame || !savestates[frame].size())
|
// if frame is not saved - log savestate
|
||||||
return false;
|
if (!savestates[currFrameCounter].size())
|
||||||
|
{
|
||||||
|
EMUFILE_MEMORY ms(&savestates[currFrameCounter]);
|
||||||
|
FCEUSS_SaveMS(&ms, Z_DEFAULT_COMPRESSION);
|
||||||
|
ms.trim();
|
||||||
|
}
|
||||||
|
if (greenZoneCount <= currFrameCounter)
|
||||||
|
greenZoneCount = currFrameCounter + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GREENZONE::LoadSavestate(unsigned int frame)
|
||||||
|
{
|
||||||
|
if (frame >= savestates.size() || !savestates[frame].size())
|
||||||
|
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::RunGreenzoneCleaning()
|
void GREENZONE::RunGreenzoneCleaning()
|
||||||
{
|
{
|
||||||
int i = currFrameCounter - taseditor_config.greenzone_capacity;
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
int i = currFrameCounter - taseditor_config.greenzone_capacity;
|
||||||
if (i <= 0) goto finish; // zeroth frame should not be cleaned
|
if (i <= 0) goto finish; // zeroth frame should not be cleaned
|
||||||
int limit;
|
int limit;
|
||||||
// 2x of 1/2
|
// 2x of 1/2
|
||||||
|
@ -133,11 +135,8 @@ 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].size())
|
if (i & 0x1)
|
||||||
{
|
changed = changed | ClearSavestateAndFreeMemory(i);
|
||||||
ClearSavestateAndFreeMemory(i);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (i < 0) goto finish;
|
if (i < 0) goto finish;
|
||||||
// 4x of 1/4
|
// 4x of 1/4
|
||||||
|
@ -145,11 +144,8 @@ 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].size())
|
if (i & 0x3)
|
||||||
{
|
changed = changed | ClearSavestateAndFreeMemory(i);
|
||||||
ClearSavestateAndFreeMemory(i);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (i < 0) goto finish;
|
if (i < 0) goto finish;
|
||||||
// 8x of 1/8
|
// 8x of 1/8
|
||||||
|
@ -157,11 +153,8 @@ 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].size())
|
if (i & 0x7)
|
||||||
{
|
changed = changed | ClearSavestateAndFreeMemory(i);
|
||||||
ClearSavestateAndFreeMemory(i);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (i < 0) goto finish;
|
if (i < 0) goto finish;
|
||||||
// 16x of 1/16
|
// 16x of 1/16
|
||||||
|
@ -169,20 +162,13 @@ 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].size())
|
if (i & 0xF)
|
||||||
{
|
changed = changed | ClearSavestateAndFreeMemory(i);
|
||||||
ClearSavestateAndFreeMemory(i);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// clear all remaining
|
// clear all remaining
|
||||||
for (; i > 0; i--)
|
for (; i > 0; i--)
|
||||||
{
|
{
|
||||||
if (savestates[i].size())
|
changed = changed | ClearSavestateAndFreeMemory(i);
|
||||||
{
|
|
||||||
ClearSavestateAndFreeMemory(i);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finish:
|
finish:
|
||||||
if (changed)
|
if (changed)
|
||||||
|
@ -194,14 +180,48 @@ finish:
|
||||||
next_cleaning_time = clock() + TIME_BETWEEN_CLEANINGS;
|
next_cleaning_time = clock() + TIME_BETWEEN_CLEANINGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GREENZONE::ClearSavestate(int index)
|
// returns true if actually cleared savestate data
|
||||||
|
bool GREENZONE::ClearSavestate(unsigned int index)
|
||||||
{
|
{
|
||||||
savestates[index].resize(0);
|
if (index < savestates.size() && savestates[index].size())
|
||||||
|
{
|
||||||
|
savestates[index].resize(0);
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GREENZONE::ClearSavestateAndFreeMemory(int index)
|
bool GREENZONE::ClearSavestateAndFreeMemory(unsigned int index)
|
||||||
{
|
{
|
||||||
savestates[index].swap(std::vector<uint8>());
|
if (index < savestates.size() && savestates[index].size())
|
||||||
|
{
|
||||||
|
savestates[index].swap(std::vector<uint8>());
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GREENZONE::UnGreenzoneSelectedFrames()
|
||||||
|
{
|
||||||
|
SelectionFrames* current_selection = selection.MakeStrobe();
|
||||||
|
if (current_selection->size() == 0) return;
|
||||||
|
bool changed = false;
|
||||||
|
int size = savestates.size();
|
||||||
|
int start_index = *current_selection->begin();
|
||||||
|
int end_index = *current_selection->rbegin();
|
||||||
|
SelectionFrames::reverse_iterator current_selection_rend = current_selection->rend();
|
||||||
|
// degreenzone frames, going backwards
|
||||||
|
for (SelectionFrames::reverse_iterator it(current_selection->rbegin()); it != current_selection_rend; it++)
|
||||||
|
changed = changed | ClearSavestateAndFreeMemory(*it);
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
piano_roll.RedrawList();
|
||||||
|
bookmarks.RedrawBookmarksList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GREENZONE::save(EMUFILE *os, bool really_save)
|
void GREENZONE::save(EMUFILE *os, bool really_save)
|
||||||
|
@ -216,10 +236,12 @@ void GREENZONE::save(EMUFILE *os, bool really_save)
|
||||||
write32le(greenZoneCount, os);
|
write32le(greenZoneCount, os);
|
||||||
// write Playback cursor position
|
// write Playback cursor position
|
||||||
write32le(currFrameCounter, os);
|
write32le(currFrameCounter, os);
|
||||||
|
CollectCurrentState();
|
||||||
// write savestates
|
// write savestates
|
||||||
int frame, size;
|
int frame, size;
|
||||||
int last_tick = 0;
|
int last_tick = 0;
|
||||||
RunGreenzoneCleaning();
|
RunGreenzoneCleaning();
|
||||||
|
if (greenZoneCount > (int)savestates.size()) greenZoneCount = savestates.size();
|
||||||
for (frame = 0; frame < greenZoneCount; ++frame)
|
for (frame = 0; frame < greenZoneCount; ++frame)
|
||||||
{
|
{
|
||||||
// update TASEditor progressbar from time to time
|
// update TASEditor progressbar from time to time
|
||||||
|
@ -248,6 +270,7 @@ void GREENZONE::save(EMUFILE *os, bool really_save)
|
||||||
if (currFrameCounter > 0)
|
if (currFrameCounter > 0)
|
||||||
{
|
{
|
||||||
// write ONE savestate for currFrameCounter
|
// write ONE savestate for currFrameCounter
|
||||||
|
CollectCurrentState();
|
||||||
int size = savestates[currFrameCounter].size();
|
int size = savestates[currFrameCounter].size();
|
||||||
write32le(size, os);
|
write32le(size, os);
|
||||||
os->fwrite(&savestates[currFrameCounter][0], size);
|
os->fwrite(&savestates[currFrameCounter][0], size);
|
||||||
|
@ -291,7 +314,7 @@ bool GREENZONE::load(EMUFILE *is, unsigned int offset)
|
||||||
savestates[frame].resize(size);
|
savestates[frame].resize(size);
|
||||||
if (is->fread(&savestates[frame][0], size) == size)
|
if (is->fread(&savestates[frame][0], size) == size)
|
||||||
{
|
{
|
||||||
if (loadTasSavestate(currFrameCounter))
|
if (LoadSavestate(currFrameCounter))
|
||||||
{
|
{
|
||||||
FCEU_printf("No Greenzone in the file\n");
|
FCEU_printf("No Greenzone in the file\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -359,12 +382,12 @@ bool GREENZONE::load(EMUFILE *is, unsigned int offset)
|
||||||
if (prev_frame+1 == greenZoneCount)
|
if (prev_frame+1 == greenZoneCount)
|
||||||
{
|
{
|
||||||
// everything went fine - load savestate at cursor position
|
// everything went fine - load savestate at cursor position
|
||||||
if (loadTasSavestate(currFrameCounter))
|
if (LoadSavestate(currFrameCounter))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// uh, okay, but maybe we managed to read at least something useful from the file
|
// uh, okay, but maybe we managed to read at least something useful from the file
|
||||||
// first see if original position of currFrameCounter was read successfully
|
// first see if original position of currFrameCounter was read successfully
|
||||||
if (loadTasSavestate(currFrameCounter))
|
if (LoadSavestate(currFrameCounter))
|
||||||
{
|
{
|
||||||
greenZoneCount = prev_frame+1; // cut greenZoneCount to last good frame
|
greenZoneCount = prev_frame+1; // cut greenZoneCount to last good frame
|
||||||
FCEU_printf("Greenzone loaded partially\n");
|
FCEU_printf("Greenzone loaded partially\n");
|
||||||
|
@ -373,7 +396,7 @@ bool GREENZONE::load(EMUFILE *is, unsigned int offset)
|
||||||
// then at least jump to some frame that was read successfully
|
// then at least jump to some frame that was read successfully
|
||||||
for (; prev_frame >= 0; prev_frame--)
|
for (; prev_frame >= 0; prev_frame--)
|
||||||
{
|
{
|
||||||
if (loadTasSavestate(prev_frame))
|
if (LoadSavestate(prev_frame))
|
||||||
{
|
{
|
||||||
currFrameCounter = prev_frame;
|
currFrameCounter = prev_frame;
|
||||||
greenZoneCount = prev_frame+1; // cut greenZoneCount to this good frame
|
greenZoneCount = prev_frame+1; // cut greenZoneCount to this good frame
|
||||||
|
@ -425,7 +448,7 @@ void GREENZONE::AdjustUp()
|
||||||
Invalidate(first_input_changes);
|
Invalidate(first_input_changes);
|
||||||
bool emu_was_paused = (FCEUI_EmulationPaused() != 0);
|
bool emu_was_paused = (FCEUI_EmulationPaused() != 0);
|
||||||
int saved_pause_frame = playback.GetPauseFrame();
|
int saved_pause_frame = playback.GetPauseFrame();
|
||||||
playback.jump(first_input_changes);
|
playback.EnsurePlaybackIsInsideGreenzone();
|
||||||
if (saved_pause_frame >= 0)
|
if (saved_pause_frame >= 0)
|
||||||
playback.SeekingStart(saved_pause_frame);
|
playback.SeekingStart(saved_pause_frame);
|
||||||
if (emu_was_paused)
|
if (emu_was_paused)
|
||||||
|
@ -462,7 +485,7 @@ void GREENZONE::AdjustDown()
|
||||||
Invalidate(first_input_chanes);
|
Invalidate(first_input_chanes);
|
||||||
bool emu_was_paused = (FCEUI_EmulationPaused() != 0);
|
bool emu_was_paused = (FCEUI_EmulationPaused() != 0);
|
||||||
int saved_pause_frame = playback.GetPauseFrame();
|
int saved_pause_frame = playback.GetPauseFrame();
|
||||||
playback.jump(first_input_chanes);
|
playback.EnsurePlaybackIsInsideGreenzone();
|
||||||
if (saved_pause_frame >= 0)
|
if (saved_pause_frame >= 0)
|
||||||
playback.SeekingStart(saved_pause_frame);
|
playback.SeekingStart(saved_pause_frame);
|
||||||
if (emu_was_paused)
|
if (emu_was_paused)
|
||||||
|
@ -483,17 +506,14 @@ void GREENZONE::InvalidateAndCheck(int after)
|
||||||
{
|
{
|
||||||
if (after >= currMovieData.getNumRecords())
|
if (after >= currMovieData.getNumRecords())
|
||||||
after = currMovieData.getNumRecords() - 1;
|
after = currMovieData.getNumRecords() - 1;
|
||||||
|
// clear all savestates that became irrelevant
|
||||||
|
for (int i = savestates.size() - 1; i > after; i--)
|
||||||
|
ClearSavestate(i);
|
||||||
if (greenZoneCount > after + 1 || currFrameCounter > after)
|
if (greenZoneCount > after + 1 || currFrameCounter > after)
|
||||||
{
|
{
|
||||||
// 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 be inside the Greenzone or run seeking to restore Playback cursor position
|
||||||
if (currFrameCounter >= greenZoneCount)
|
if (currFrameCounter >= greenZoneCount)
|
||||||
{
|
{
|
||||||
if (playback.GetPauseFrame() >= 0 && !FCEUI_EmulationPaused())
|
if (playback.GetPauseFrame() >= 0 && !FCEUI_EmulationPaused())
|
||||||
|
@ -504,10 +524,10 @@ void GREENZONE::InvalidateAndCheck(int after)
|
||||||
{
|
{
|
||||||
playback.SetLostPosition(currFrameCounter);
|
playback.SetLostPosition(currFrameCounter);
|
||||||
if (taseditor_config.restore_position)
|
if (taseditor_config.restore_position)
|
||||||
// start seeking
|
// start seeking to the green arrow
|
||||||
playback.jump(playback.GetLostPosition());
|
playback.jump(playback.GetLostPosition());
|
||||||
else
|
else
|
||||||
playback.jump(greenZoneCount - 1);
|
playback.EnsurePlaybackIsInsideGreenzone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,14 +543,11 @@ void GREENZONE::Invalidate(int after)
|
||||||
{
|
{
|
||||||
if (after >= currMovieData.getNumRecords())
|
if (after >= currMovieData.getNumRecords())
|
||||||
after = currMovieData.getNumRecords() - 1;
|
after = currMovieData.getNumRecords() - 1;
|
||||||
|
// clear all savestates that became irrelevant
|
||||||
|
for (int i = savestates.size() - 1; i > after; i--)
|
||||||
|
ClearSavestate(i);
|
||||||
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++;
|
||||||
}
|
}
|
||||||
|
@ -568,9 +585,9 @@ void GREENZONE::WriteSavestate(int frame, std::vector<uint8>& savestate)
|
||||||
greenZoneCount = frame + 1;
|
greenZoneCount = frame + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GREENZONE::SavestateIsEmpty(int frame)
|
bool GREENZONE::SavestateIsEmpty(unsigned int frame)
|
||||||
{
|
{
|
||||||
if (frame < greenZoneCount && frame < (int)savestates.size() && savestates[frame].size())
|
if ((int)frame < greenZoneCount && frame < savestates.size() && savestates[frame].size())
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -25,14 +25,11 @@ public:
|
||||||
void save(EMUFILE *os, bool really_save = true);
|
void save(EMUFILE *os, bool really_save = true);
|
||||||
bool load(EMUFILE *is, unsigned int offset);
|
bool load(EMUFILE *is, unsigned int offset);
|
||||||
|
|
||||||
void AdjustUp();
|
bool LoadSavestate(unsigned int frame);
|
||||||
void AdjustDown();
|
|
||||||
|
|
||||||
bool loadTasSavestate(int frame);
|
|
||||||
|
|
||||||
void RunGreenzoneCleaning();
|
void RunGreenzoneCleaning();
|
||||||
void ClearSavestate(int index);
|
|
||||||
void ClearSavestateAndFreeMemory(int index);
|
void UnGreenzoneSelectedFrames();
|
||||||
|
|
||||||
void InvalidateAndCheck(int after);
|
void InvalidateAndCheck(int after);
|
||||||
void Invalidate(int after);
|
void Invalidate(int after);
|
||||||
|
@ -42,13 +39,18 @@ public:
|
||||||
int GetSize();
|
int GetSize();
|
||||||
std::vector<uint8>& GetSavestate(int frame);
|
std::vector<uint8>& GetSavestate(int frame);
|
||||||
void WriteSavestate(int frame, std::vector<uint8>& savestate);
|
void WriteSavestate(int frame, std::vector<uint8>& savestate);
|
||||||
bool SavestateIsEmpty(int frame);
|
bool SavestateIsEmpty(unsigned int frame);
|
||||||
|
|
||||||
// saved data
|
// saved data
|
||||||
LAGLOG laglog;
|
LAGLOG laglog;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CollectCurrentState();
|
void CollectCurrentState();
|
||||||
|
bool ClearSavestate(unsigned int index);
|
||||||
|
bool ClearSavestateAndFreeMemory(unsigned int index);
|
||||||
|
|
||||||
|
void AdjustUp();
|
||||||
|
void AdjustDown();
|
||||||
|
|
||||||
// saved data
|
// saved data
|
||||||
int greenZoneCount;
|
int greenZoneCount;
|
||||||
|
|
|
@ -240,7 +240,7 @@ void PLAYBACK::update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// called after saving the project, because saving uses the progressbar for itself
|
// called after saving the project, because saving uses the progressbar for itself
|
||||||
void PLAYBACK::updateProgressbar()
|
void PLAYBACK::UpdateProgressbar()
|
||||||
{
|
{
|
||||||
if (pause_frame)
|
if (pause_frame)
|
||||||
{
|
{
|
||||||
|
@ -438,11 +438,10 @@ void PLAYBACK::StartFromZero()
|
||||||
currMovieData.insertEmpty(-1, 1);
|
currMovieData.insertEmpty(-1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// external interface for sending Playback cursor
|
void PLAYBACK::EnsurePlaybackIsInsideGreenzone(bool execute_lua, bool follow_cursor)
|
||||||
void PLAYBACK::jump(int frame, bool execute_lua, bool follow_cursor)
|
|
||||||
{
|
{
|
||||||
if (frame < 0) return;
|
// set the Playback cursor to the frame or at least above the frame
|
||||||
if (JumpToFrame(frame))
|
if (SetPlaybackAboveOrToFrame(greenzone.GetSize() - 1))
|
||||||
{
|
{
|
||||||
// since the game state was changed by this jump, we must update possible Lua callbacks and other tools that would normally only update in FCEUI_Emulate
|
// since the game state was changed by this jump, we must update possible Lua callbacks and other tools that would normally only update in FCEUI_Emulate
|
||||||
if (execute_lua)
|
if (execute_lua)
|
||||||
|
@ -452,44 +451,63 @@ void PLAYBACK::jump(int frame, bool execute_lua, bool follow_cursor)
|
||||||
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// internal interface
|
|
||||||
// returns true if the game state was changed (loaded)
|
// an interface for sending Playback cursor to any frame
|
||||||
bool PLAYBACK::JumpToFrame(int index)
|
void PLAYBACK::jump(int frame, bool force_reload, bool execute_lua, bool follow_cursor)
|
||||||
{
|
{
|
||||||
if (index >= greenzone.GetSize())
|
if (frame < 0) return;
|
||||||
|
|
||||||
|
// 1 - set the Playback cursor to the frame or at least above the frame
|
||||||
|
if (SetPlaybackAboveOrToFrame(frame, force_reload))
|
||||||
{
|
{
|
||||||
// make jump outside Greenzone
|
// since the game state was changed by this jump, we must update possible Lua callbacks and other tools that would normally only update in FCEUI_Emulate
|
||||||
if (currFrameCounter == greenzone.GetSize() - 1)
|
if (execute_lua)
|
||||||
|
ForceExecuteLuaFrameFunctions();
|
||||||
|
if (follow_cursor)
|
||||||
|
piano_roll.FollowPlaybackIfNeeded();
|
||||||
|
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 - seek from the current frame if we still aren't at the needed frame
|
||||||
|
if (frame > currFrameCounter)
|
||||||
|
{
|
||||||
|
SeekingStart(frame);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// the Playback is already at the needed frame
|
||||||
|
if (pause_frame) // if Playback was seeking, pause emulation right here
|
||||||
|
SeekingStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if the game state was changed (loaded)
|
||||||
|
bool PLAYBACK::SetPlaybackAboveOrToFrame(int frame, bool force_reload)
|
||||||
|
{
|
||||||
|
bool state_changed = false;
|
||||||
|
// search backwards for an earlier frame with valid savestate
|
||||||
|
int i = greenzone.GetSize() - 1;
|
||||||
|
if (i > frame)
|
||||||
|
i = frame;
|
||||||
|
for (; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (!force_reload && !state_changed && i == currFrameCounter)
|
||||||
{
|
{
|
||||||
// seek there from the end of Greenzone
|
// we can remain at current game state
|
||||||
SeekingStart(index);
|
break;
|
||||||
return false; // game state was not changed
|
} else if (!greenzone.SavestateIsEmpty(i))
|
||||||
} else if (JumpToFrame(greenzone.GetSize() - 1))
|
|
||||||
{
|
{
|
||||||
// seek there from the end of Greenzone
|
state_changed = true; // after we once tried loading a savestate, we cannot use currFrameCounter state anymore, because the game state might have been corrupted by this loading attempt
|
||||||
SeekingStart(index);
|
if (greenzone.LoadSavestate(i))
|
||||||
return true; // game state was loaded
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// make jump inside greenzone
|
|
||||||
if (greenzone.loadTasSavestate(index))
|
|
||||||
{
|
|
||||||
// successfully restored emulator state at this frame
|
|
||||||
// if Playback was seeking, pause emulation right here
|
|
||||||
if (pause_frame)
|
|
||||||
SeekingStop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// search for an earlier frame with savestate
|
|
||||||
int i = (index > 0) ? index-1 : 0;
|
|
||||||
for (; i >= 0; i--)
|
|
||||||
if (greenzone.loadTasSavestate(i)) break;
|
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
StartFromZero(); // couldn't find a savestate
|
{
|
||||||
// continue from the frame
|
// couldn't find a savestate
|
||||||
if (index != currFrameCounter)
|
StartFromZero();
|
||||||
SeekingStart(index);
|
state_changed = true;
|
||||||
return true;
|
}
|
||||||
|
return state_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PLAYBACK::SetLostPosition(int frame)
|
void PLAYBACK::SetLostPosition(int frame)
|
||||||
|
|
|
@ -16,9 +16,10 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
void jump(int frame, bool execute_lua = true, bool follow_cursor = true);
|
void EnsurePlaybackIsInsideGreenzone(bool execute_lua = true, bool follow_cursor = true);
|
||||||
|
void jump(int frame, bool force_reload = false, bool execute_lua = true, bool follow_cursor = true);
|
||||||
|
|
||||||
void updateProgressbar();
|
void UpdateProgressbar();
|
||||||
|
|
||||||
void SeekingStart(int finish_frame);
|
void SeekingStart(int finish_frame);
|
||||||
void SeekingStop();
|
void SeekingStop();
|
||||||
|
@ -55,7 +56,7 @@ public:
|
||||||
HWND hwndPlaybackMarker, hwndPlaybackMarkerEdit;
|
HWND hwndPlaybackMarker, hwndPlaybackMarkerEdit;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool JumpToFrame(int index);
|
bool SetPlaybackAboveOrToFrame(int frame, bool force_reload = false);
|
||||||
|
|
||||||
int pause_frame;
|
int pause_frame;
|
||||||
int lost_position_frame;
|
int lost_position_frame;
|
||||||
|
|
|
@ -68,6 +68,7 @@ TASEDITOR_CONFIG::TASEDITOR_CONFIG()
|
||||||
findnote_search_up = false;
|
findnote_search_up = false;
|
||||||
enable_auto_function = true;
|
enable_auto_function = true;
|
||||||
draw_input = true;
|
draw_input = true;
|
||||||
|
enable_greenzoning = true;
|
||||||
silent_autosave = true;
|
silent_autosave = true;
|
||||||
autopause_at_finish = true;
|
autopause_at_finish = true;
|
||||||
tooltips = true;
|
tooltips = true;
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
bool findnote_search_up;
|
bool findnote_search_up;
|
||||||
bool enable_auto_function;
|
bool enable_auto_function;
|
||||||
bool draw_input;
|
bool draw_input;
|
||||||
|
bool enable_greenzoning;
|
||||||
bool silent_autosave;
|
bool silent_autosave;
|
||||||
bool autopause_at_finish;
|
bool autopause_at_finish;
|
||||||
bool tooltips;
|
bool tooltips;
|
||||||
|
|
|
@ -243,7 +243,9 @@ int TASEDITOR_LUA::getplaybacktarget()
|
||||||
void TASEDITOR_LUA::setplayback(int frame)
|
void TASEDITOR_LUA::setplayback(int frame)
|
||||||
{
|
{
|
||||||
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
|
||||||
playback.jump(frame, false, true);
|
// force reload if sending to the same frame as current frame
|
||||||
|
// but don't trigger lua registered functions
|
||||||
|
playback.jump(frame, true, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// taseditor.stopseeking()
|
// taseditor.stopseeking()
|
||||||
|
|
|
@ -167,7 +167,7 @@ bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool
|
||||||
write32le(selection_offset, ofs);
|
write32le(selection_offset, ofs);
|
||||||
// finish
|
// finish
|
||||||
delete ofs;
|
delete ofs;
|
||||||
playback.updateProgressbar();
|
playback.UpdateProgressbar();
|
||||||
// also set project.changed to false, unless it was SaveCompact
|
// also set project.changed to false, unless it was SaveCompact
|
||||||
if (!different_name)
|
if (!different_name)
|
||||||
reset();
|
reset();
|
||||||
|
|
|
@ -564,6 +564,7 @@ void TASEDITOR_WINDOW::UpdateCheckedItems()
|
||||||
CheckMenuItem(hmenu, ID_VIEW_ENABLEHOTCHANGES, taseditor_config.enable_hot_changes?MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(hmenu, ID_VIEW_ENABLEHOTCHANGES, taseditor_config.enable_hot_changes?MF_CHECKED : MF_UNCHECKED);
|
||||||
CheckMenuItem(hmenu, ID_VIEW_JUMPWHENMAKINGUNDO, taseditor_config.jump_to_undo?MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(hmenu, ID_VIEW_JUMPWHENMAKINGUNDO, taseditor_config.jump_to_undo?MF_CHECKED : MF_UNCHECKED);
|
||||||
CheckMenuItem(hmenu, ID_VIEW_FOLLOWMARKERNOTECONTEXT, taseditor_config.follow_note_context?MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(hmenu, ID_VIEW_FOLLOWMARKERNOTECONTEXT, taseditor_config.follow_note_context?MF_CHECKED : MF_UNCHECKED);
|
||||||
|
CheckMenuItem(hmenu, ID_CONFIG_ENABLEGREENZONING, taseditor_config.enable_greenzoning?MF_CHECKED : MF_UNCHECKED);
|
||||||
CheckMenuItem(hmenu, ID_CONFIG_SILENTAUTOSAVE, taseditor_config.silent_autosave?MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(hmenu, ID_CONFIG_SILENTAUTOSAVE, taseditor_config.silent_autosave?MF_CHECKED : MF_UNCHECKED);
|
||||||
CheckMenuItem(hmenu, ID_CONFIG_PATTERNSKIPSLAG, taseditor_config.pattern_skips_lag?MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(hmenu, ID_CONFIG_PATTERNSKIPSLAG, taseditor_config.pattern_skips_lag?MF_CHECKED : MF_UNCHECKED);
|
||||||
CheckMenuItem(hmenu, ID_CONFIG_ADJUSTLAG, taseditor_config.adjust_input_due_to_lag?MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(hmenu, ID_CONFIG_ADJUSTLAG, taseditor_config.adjust_input_due_to_lag?MF_CHECKED : MF_UNCHECKED);
|
||||||
|
@ -923,6 +924,12 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
|
||||||
else if (piano_roll.drag_mode != DRAG_MODE_SELECTION && piano_roll.drag_mode != DRAG_MODE_DESELECTION)
|
else if (piano_roll.drag_mode != DRAG_MODE_SELECTION && piano_roll.drag_mode != DRAG_MODE_DESELECTION)
|
||||||
selection.SelectAll();
|
selection.SelectAll();
|
||||||
break;
|
break;
|
||||||
|
case ID_SELECTED_UNGREENZONE:
|
||||||
|
if (piano_roll.drag_mode != DRAG_MODE_SELECTION && piano_roll.drag_mode != DRAG_MODE_DESELECTION)
|
||||||
|
{
|
||||||
|
greenzone.UnGreenzoneSelectedFrames();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ACCEL_CTRL_X:
|
case ACCEL_CTRL_X:
|
||||||
case ID_EDIT_CUT:
|
case ID_EDIT_CUT:
|
||||||
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER)
|
||||||
|
@ -1089,6 +1096,14 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ID_CONFIG_ENABLEGREENZONING:
|
||||||
|
taseditor_config.enable_greenzoning ^= 1;
|
||||||
|
taseditor_window.UpdateCheckedItems();
|
||||||
|
break;
|
||||||
|
case ID_CONFIG_SILENTAUTOSAVE:
|
||||||
|
taseditor_config.silent_autosave ^= 1;
|
||||||
|
taseditor_window.UpdateCheckedItems();
|
||||||
|
break;
|
||||||
case ID_CONFIG_BRANCHESRESTOREFULLMOVIE:
|
case ID_CONFIG_BRANCHESRESTOREFULLMOVIE:
|
||||||
taseditor_config.branch_full_movie ^= 1;
|
taseditor_config.branch_full_movie ^= 1;
|
||||||
taseditor_window.UpdateCheckedItems();
|
taseditor_window.UpdateCheckedItems();
|
||||||
|
@ -1131,10 +1146,6 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
|
||||||
taseditor_config.draw_input ^= 1;
|
taseditor_config.draw_input ^= 1;
|
||||||
taseditor_window.UpdateCheckedItems();
|
taseditor_window.UpdateCheckedItems();
|
||||||
break;
|
break;
|
||||||
case ID_CONFIG_SILENTAUTOSAVE:
|
|
||||||
taseditor_config.silent_autosave ^= 1;
|
|
||||||
taseditor_window.UpdateCheckedItems();
|
|
||||||
break;
|
|
||||||
case ID_CONFIG_AUTOPAUSEATTHEENDOFMOVIE:
|
case ID_CONFIG_AUTOPAUSEATTHEENDOFMOVIE:
|
||||||
taseditor_config.autopause_at_finish ^= 1;
|
taseditor_config.autopause_at_finish ^= 1;
|
||||||
taseditor_window.UpdateCheckedItems();
|
taseditor_window.UpdateCheckedItems();
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//#define PUBLIC_RELEASE // uncommend this when making a public release, but comment back before committing
|
||||||
|
|
||||||
#ifndef __FCEU_VERSION
|
#ifndef __FCEU_VERSION
|
||||||
#define __FCEU_VERSION
|
#define __FCEU_VERSION
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue