mirror of https://github.com/stella-emu/stella.git
implement saving/loading all TM states to/from disk
This commit is contained in:
parent
ad6e6f1855
commit
67db29e826
|
@ -144,8 +144,10 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod
|
||||||
setDefaultKey(Event::ConsoleRightDiffA , KBDK_F7);
|
setDefaultKey(Event::ConsoleRightDiffA , KBDK_F7);
|
||||||
setDefaultKey(Event::ConsoleRightDiffB , KBDK_F8);
|
setDefaultKey(Event::ConsoleRightDiffB , KBDK_F8);
|
||||||
setDefaultKey(Event::SaveState , KBDK_F9);
|
setDefaultKey(Event::SaveState , KBDK_F9);
|
||||||
|
setDefaultKey(Event::SaveAllStates , KBDK_F9, KBDM_ALT);
|
||||||
setDefaultKey(Event::ChangeState , KBDK_F10);
|
setDefaultKey(Event::ChangeState , KBDK_F10);
|
||||||
setDefaultKey(Event::LoadState , KBDK_F11);
|
setDefaultKey(Event::LoadState , KBDK_F11);
|
||||||
|
setDefaultKey(Event::LoadAllStates , KBDK_F11, KBDM_ALT);
|
||||||
setDefaultKey(Event::TakeSnapshot , KBDK_F12);
|
setDefaultKey(Event::TakeSnapshot , KBDK_F12);
|
||||||
setDefaultKey(Event::Fry , KBDK_BACKSPACE);
|
setDefaultKey(Event::Fry , KBDK_BACKSPACE);
|
||||||
setDefaultKey(Event::TogglePauseMode , KBDK_PAUSE);
|
setDefaultKey(Event::TogglePauseMode , KBDK_PAUSE);
|
||||||
|
|
|
@ -36,6 +36,7 @@ RewindManager::RewindManager(OSystem& system, StateManager& statemgr)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void RewindManager::setup()
|
void RewindManager::setup()
|
||||||
{
|
{
|
||||||
|
myStateSize = 0;
|
||||||
myLastTimeMachineAdd = false;
|
myLastTimeMachineAdd = false;
|
||||||
|
|
||||||
const string& prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
|
const string& prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
|
||||||
|
@ -128,6 +129,7 @@ bool RewindManager::addState(const string& message, bool timeMachine)
|
||||||
s.rewind(); // rewind Serializer internal buffers
|
s.rewind(); // rewind Serializer internal buffers
|
||||||
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
||||||
{
|
{
|
||||||
|
myStateSize = std::max(myStateSize, uInt32(s.size()));
|
||||||
state.message = message;
|
state.message = message;
|
||||||
state.cycles = myOSystem.console().tia().cycles();
|
state.cycles = myOSystem.console().tia().cycles();
|
||||||
myLastTimeMachineAdd = timeMachine;
|
myLastTimeMachineAdd = timeMachine;
|
||||||
|
@ -218,6 +220,129 @@ uInt32 RewindManager::windStates(uInt32 numStates, bool unwind)
|
||||||
return rewindStates(numStates);
|
return rewindStates(numStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
string RewindManager::saveAllStates()
|
||||||
|
{
|
||||||
|
uInt8* buffer = NULL;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ostringstream buf;
|
||||||
|
buf << myOSystem.stateDir()
|
||||||
|
<< myOSystem.console().properties().get(PropType::Cart_Name)
|
||||||
|
<< ".sta";
|
||||||
|
|
||||||
|
// Truncate existing file to 0
|
||||||
|
FILE* fp;
|
||||||
|
errno_t err = fopen_s(&fp, buf.str().c_str(), "w");
|
||||||
|
// Make sure the file can be opened for writing
|
||||||
|
if (err != NULL)
|
||||||
|
return "Can't save to all states file";
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
Serializer out(buf.str());
|
||||||
|
|
||||||
|
int numStates = rewindStates(1000) + 1;
|
||||||
|
// Save header
|
||||||
|
buf.str("");
|
||||||
|
out.putString(STATE_HEADER);
|
||||||
|
out.putShort(numStates);
|
||||||
|
out.putInt(myStateSize);
|
||||||
|
|
||||||
|
buffer = new uInt8[myStateSize];
|
||||||
|
for (int i = 0; i < numStates; i++)
|
||||||
|
{
|
||||||
|
RewindState& state = myStateList.current();
|
||||||
|
Serializer& s = state.data;
|
||||||
|
// Rewind Serializer internal buffers
|
||||||
|
s.rewind();
|
||||||
|
// Save state
|
||||||
|
s.getByteArray(buffer, myStateSize);
|
||||||
|
out.putByteArray(buffer, myStateSize);
|
||||||
|
out.putString(state.message);
|
||||||
|
out.putLong(state.cycles);
|
||||||
|
|
||||||
|
if (i < numStates)
|
||||||
|
unwindStates(1);
|
||||||
|
}
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
buf.str("");
|
||||||
|
buf << "Saved " << numStates << " states";
|
||||||
|
return buf.str();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
if (buffer)
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
return "Error loading all states";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
string RewindManager::loadAllStates()
|
||||||
|
{
|
||||||
|
uInt8* buffer = NULL;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ostringstream buf;
|
||||||
|
buf << myOSystem.stateDir()
|
||||||
|
<< myOSystem.console().properties().get(PropType::Cart_Name)
|
||||||
|
<< ".sta";
|
||||||
|
|
||||||
|
// Make sure the file can be opened for reading
|
||||||
|
Serializer in(buf.str(), true);
|
||||||
|
if (!in)
|
||||||
|
return "Can't load from all states file";
|
||||||
|
|
||||||
|
clear();
|
||||||
|
int numStates;
|
||||||
|
|
||||||
|
// Load header
|
||||||
|
buf.str("");
|
||||||
|
// Check compatibility
|
||||||
|
if (in.getString() != STATE_HEADER)
|
||||||
|
return "Incompatible all states file";
|
||||||
|
numStates = in.getShort();
|
||||||
|
myStateSize = in.getInt();
|
||||||
|
|
||||||
|
buffer = new uInt8[myStateSize];
|
||||||
|
for (int i = 0; i < numStates; i++)
|
||||||
|
{
|
||||||
|
if (myStateList.full())
|
||||||
|
compressStates();
|
||||||
|
|
||||||
|
// Add new state at the end of the list (queue adds at end)
|
||||||
|
// This updates the 'current' iterator inside the list
|
||||||
|
myStateList.addLast();
|
||||||
|
RewindState& state = myStateList.current();
|
||||||
|
Serializer& s = state.data;
|
||||||
|
// Rewind Serializer internal buffers
|
||||||
|
s.rewind();
|
||||||
|
|
||||||
|
// Fill new state with saved values
|
||||||
|
in.getByteArray(buffer, myStateSize);
|
||||||
|
s.putByteArray(buffer, myStateSize);
|
||||||
|
state.message = in.getString();
|
||||||
|
state.cycles = in.getLong();
|
||||||
|
}
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
// initialize current state (parameters ignored)
|
||||||
|
loadState(0, 0);
|
||||||
|
|
||||||
|
buf.str("");
|
||||||
|
buf << "Loaded " << numStates << " states";
|
||||||
|
return buf.str();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
if (buffer)
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
return "Error saving all states";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void RewindManager::compressStates()
|
void RewindManager::compressStates()
|
||||||
|
|
|
@ -136,10 +136,16 @@ class RewindManager
|
||||||
*/
|
*/
|
||||||
uInt32 windStates(uInt32 numStates, bool unwind);
|
uInt32 windStates(uInt32 numStates, bool unwind);
|
||||||
|
|
||||||
|
string saveAllStates();
|
||||||
|
string loadAllStates();
|
||||||
|
|
||||||
bool atFirst() const { return myStateList.atFirst(); }
|
bool atFirst() const { return myStateList.atFirst(); }
|
||||||
bool atLast() const { return myStateList.atLast(); }
|
bool atLast() const { return myStateList.atLast(); }
|
||||||
void resize(uInt32 size) { myStateList.resize(size); }
|
void resize(uInt32 size) { myStateList.resize(size); }
|
||||||
void clear() { myStateList.clear(); }
|
void clear() {
|
||||||
|
myStateSize = 0;
|
||||||
|
myStateList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Convert the cycles into a unit string.
|
Convert the cycles into a unit string.
|
||||||
|
@ -169,6 +175,7 @@ class RewindManager
|
||||||
uInt64 myHorizon;
|
uInt64 myHorizon;
|
||||||
double myFactor;
|
double myFactor;
|
||||||
bool myLastTimeMachineAdd;
|
bool myLastTimeMachineAdd;
|
||||||
|
uInt32 myStateSize;
|
||||||
|
|
||||||
struct RewindState {
|
struct RewindState {
|
||||||
Serializer data; // actual save state
|
Serializer data; // actual save state
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
#include "StateManager.hxx"
|
#include "StateManager.hxx"
|
||||||
|
|
||||||
#define STATE_HEADER "06000003state"
|
|
||||||
// #define MOVIE_HEADER "03030000movie"
|
// #define MOVIE_HEADER "03030000movie"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#ifndef STATE_MANAGER_HXX
|
#ifndef STATE_MANAGER_HXX
|
||||||
#define STATE_MANAGER_HXX
|
#define STATE_MANAGER_HXX
|
||||||
|
|
||||||
|
#define STATE_HEADER "06000003state"
|
||||||
|
|
||||||
class OSystem;
|
class OSystem;
|
||||||
class RewindManager;
|
class RewindManager;
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ class Event
|
||||||
Rewind1Menu, Rewind10Menu, RewindAllMenu,
|
Rewind1Menu, Rewind10Menu, RewindAllMenu,
|
||||||
Unwind1Menu, Unwind10Menu, UnwindAllMenu,
|
Unwind1Menu, Unwind10Menu, UnwindAllMenu,
|
||||||
|
|
||||||
StartPauseMode,
|
StartPauseMode, SaveAllStates, LoadAllStates,
|
||||||
|
|
||||||
LastType
|
LastType
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "Settings.hxx"
|
#include "Settings.hxx"
|
||||||
#include "Sound.hxx"
|
#include "Sound.hxx"
|
||||||
#include "StateManager.hxx"
|
#include "StateManager.hxx"
|
||||||
|
#include "RewindManager.hxx"
|
||||||
#include "TimerManager.hxx"
|
#include "TimerManager.hxx"
|
||||||
#include "Switches.hxx"
|
#include "Switches.hxx"
|
||||||
#include "M6532.hxx"
|
#include "M6532.hxx"
|
||||||
|
@ -612,6 +613,11 @@ void EventHandler::handleEvent(Event::Type event, bool pressed)
|
||||||
if(pressed) myOSystem.state().saveState();
|
if(pressed) myOSystem.state().saveState();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case Event::SaveAllStates:
|
||||||
|
if (pressed)
|
||||||
|
myOSystem.frameBuffer().showMessage(myOSystem.state().rewindManager().saveAllStates());
|
||||||
|
return;
|
||||||
|
|
||||||
case Event::ChangeState:
|
case Event::ChangeState:
|
||||||
if(pressed) myOSystem.state().changeState();
|
if(pressed) myOSystem.state().changeState();
|
||||||
return;
|
return;
|
||||||
|
@ -620,6 +626,11 @@ void EventHandler::handleEvent(Event::Type event, bool pressed)
|
||||||
if(pressed) myOSystem.state().loadState();
|
if(pressed) myOSystem.state().loadState();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case Event::LoadAllStates:
|
||||||
|
if (pressed)
|
||||||
|
myOSystem.frameBuffer().showMessage(myOSystem.state().rewindManager().loadAllStates());
|
||||||
|
return;
|
||||||
|
|
||||||
case Event::Rewind:
|
case Event::Rewind:
|
||||||
if (pressed) myOSystem.state().rewindStates();
|
if (pressed) myOSystem.state().rewindStates();
|
||||||
return;
|
return;
|
||||||
|
@ -1687,6 +1698,8 @@ EventHandler::ActionList EventHandler::ourEmulActionList[EMUL_ACTIONLIST_SIZE] =
|
||||||
{ Event::Unwind1Menu, "Unwind one state & enter TM UI", "" },
|
{ Event::Unwind1Menu, "Unwind one state & enter TM UI", "" },
|
||||||
{ Event::Unwind10Menu, "Unwind 10 states & enter TM UI", "" },
|
{ Event::Unwind10Menu, "Unwind 10 states & enter TM UI", "" },
|
||||||
{ Event::UnwindAllMenu, "Unwind all states & enter TM UI", "" },
|
{ Event::UnwindAllMenu, "Unwind all states & enter TM UI", "" },
|
||||||
|
{ Event::SaveAllStates, "Save all TM states of current game", "" },
|
||||||
|
{ Event::LoadAllStates, "Load saved TM states for current game", "" },
|
||||||
|
|
||||||
{ Event::Combo1, "Combo 1", "" },
|
{ Event::Combo1, "Combo 1", "" },
|
||||||
{ Event::Combo2, "Combo 2", "" },
|
{ Event::Combo2, "Combo 2", "" },
|
||||||
|
|
|
@ -368,10 +368,11 @@ class EventHandler
|
||||||
COMBO_SIZE = 16,
|
COMBO_SIZE = 16,
|
||||||
EVENTS_PER_COMBO = 8,
|
EVENTS_PER_COMBO = 8,
|
||||||
#ifdef PNG_SUPPORT
|
#ifdef PNG_SUPPORT
|
||||||
EMUL_ACTIONLIST_SIZE = 136 + COMBO_SIZE,
|
PNG_SIZE = 2,
|
||||||
#else
|
#else
|
||||||
EMUL_ACTIONLIST_SIZE = 136 - 2 + COMBO_SIZE,
|
PNG_SIZE = 0,
|
||||||
#endif
|
#endif
|
||||||
|
EMUL_ACTIONLIST_SIZE = 136 + PNG_SIZE + COMBO_SIZE,
|
||||||
MENU_ACTIONLIST_SIZE = 18
|
MENU_ACTIONLIST_SIZE = 18
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,41 @@ static uInt32 UNWIND_ALL[BUTTON_H] =
|
||||||
0b11000011000011,
|
0b11000011000011,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
static uInt32 SAVE_ALL[BUTTON_H] =
|
||||||
|
{
|
||||||
|
0b00000111100000,
|
||||||
|
0b00000111100000,
|
||||||
|
0b00000111100000,
|
||||||
|
0b00000111100000,
|
||||||
|
0b11111111111111,
|
||||||
|
0b01111111111110,
|
||||||
|
0b00111111111100,
|
||||||
|
0b00011111111000,
|
||||||
|
0b00001111110000,
|
||||||
|
0b00000111100000,
|
||||||
|
0b00000011000000,
|
||||||
|
0b00000000000000,
|
||||||
|
0b11111111111111,
|
||||||
|
0b11111111111111,
|
||||||
|
};
|
||||||
|
static uInt32 LOAD_ALL[BUTTON_H] =
|
||||||
|
{
|
||||||
|
0b00000011000000,
|
||||||
|
0b00000111100000,
|
||||||
|
0b00001111110000,
|
||||||
|
0b00011111111000,
|
||||||
|
0b00111111111100,
|
||||||
|
0b01111111111110,
|
||||||
|
0b11111111111111,
|
||||||
|
0b00000111100000,
|
||||||
|
0b00000111100000,
|
||||||
|
0b00000111100000,
|
||||||
|
0b00000111100000,
|
||||||
|
0b00000000000000,
|
||||||
|
0b11111111111111,
|
||||||
|
0b11111111111111,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
|
TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
|
@ -232,6 +267,14 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
BUTTON_W, BUTTON_H, kUnwindAll);
|
BUTTON_W, BUTTON_H, kUnwindAll);
|
||||||
xpos = myUnwindAllWidget->getRight() + BUTTON_GAP * 4;
|
xpos = myUnwindAllWidget->getRight() + BUTTON_GAP * 4;
|
||||||
|
|
||||||
|
mySaveAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, SAVE_ALL,
|
||||||
|
BUTTON_W, BUTTON_H, kSaveAll);
|
||||||
|
xpos = mySaveAllWidget->getRight() + BUTTON_GAP;
|
||||||
|
|
||||||
|
myLoadAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, LOAD_ALL,
|
||||||
|
BUTTON_W, BUTTON_H, kLoadAll);
|
||||||
|
xpos = myLoadAllWidget->getRight() + BUTTON_GAP * 4;
|
||||||
|
|
||||||
// Add message
|
// Add message
|
||||||
myMessageWidget = new StaticTextWidget(this, font, xpos, ypos + 3, " ",
|
myMessageWidget = new StaticTextWidget(this, font, xpos, ypos + 3, " ",
|
||||||
TextAlign::Left, kBGColor);
|
TextAlign::Left, kBGColor);
|
||||||
|
@ -250,14 +293,6 @@ void TimeMachineDialog::center()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TimeMachineDialog::loadConfig()
|
void TimeMachineDialog::loadConfig()
|
||||||
{
|
{
|
||||||
RewindManager& r = instance().state().rewindManager();
|
|
||||||
IntArray cycles = r.cyclesList();
|
|
||||||
|
|
||||||
// Set range and intervals for timeline
|
|
||||||
uInt32 maxValue = cycles.size() > 1 ? uInt32(cycles.size() - 1) : 0;
|
|
||||||
myTimeline->setMaxValue(maxValue);
|
|
||||||
myTimeline->setStepValues(cycles);
|
|
||||||
|
|
||||||
// Enable blending (only once is necessary)
|
// Enable blending (only once is necessary)
|
||||||
if(!surface().attributes().blending)
|
if(!surface().attributes().blending)
|
||||||
{
|
{
|
||||||
|
@ -266,10 +301,7 @@ void TimeMachineDialog::loadConfig()
|
||||||
surface().applyAttributes();
|
surface().applyAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
myMessageWidget->setLabel("");
|
initBar();
|
||||||
handleWinds(_enterWinds);
|
|
||||||
_enterWinds = 0;
|
|
||||||
handleToggle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -355,11 +387,38 @@ void TimeMachineDialog::handleCommand(CommandSender* sender, int cmd,
|
||||||
handleWinds(1000);
|
handleWinds(1000);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kSaveAll:
|
||||||
|
instance().frameBuffer().showMessage(instance().state().rewindManager().saveAllStates());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kLoadAll:
|
||||||
|
instance().frameBuffer().showMessage(instance().state().rewindManager().loadAllStates());
|
||||||
|
initBar();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Dialog::handleCommand(sender, cmd, data, 0);
|
Dialog::handleCommand(sender, cmd, data, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void TimeMachineDialog::initBar()
|
||||||
|
{
|
||||||
|
RewindManager& r = instance().state().rewindManager();
|
||||||
|
IntArray cycles = r.cyclesList();
|
||||||
|
|
||||||
|
// Set range and intervals for timeline
|
||||||
|
uInt32 maxValue = cycles.size() > 1 ? uInt32(cycles.size() - 1) : 0;
|
||||||
|
myTimeline->setMaxValue(maxValue);
|
||||||
|
myTimeline->setStepValues(cycles);
|
||||||
|
|
||||||
|
myMessageWidget->setLabel("");
|
||||||
|
handleWinds(_enterWinds);
|
||||||
|
_enterWinds = 0;
|
||||||
|
|
||||||
|
handleToggle();
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string TimeMachineDialog::getTimeString(uInt64 cycles)
|
string TimeMachineDialog::getTimeString(uInt64 cycles)
|
||||||
{
|
{
|
||||||
|
@ -416,6 +475,7 @@ void TimeMachineDialog::handleWinds(Int32 numWinds)
|
||||||
myRewind1Widget->setEnabled(!r.atFirst());
|
myRewind1Widget->setEnabled(!r.atFirst());
|
||||||
myUnwindAllWidget->setEnabled(!r.atLast());
|
myUnwindAllWidget->setEnabled(!r.atLast());
|
||||||
myUnwind1Widget->setEnabled(!r.atLast());
|
myUnwind1Widget->setEnabled(!r.atLast());
|
||||||
|
mySaveAllWidget->setEnabled(r.getLastIdx() != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -424,4 +484,3 @@ void TimeMachineDialog::handleToggle()
|
||||||
myToggleWidget->setBitmap(instance().state().mode() == StateManager::Mode::Off ? RECORD : STOP,
|
myToggleWidget->setBitmap(instance().state().mode() == StateManager::Mode::Off ? RECORD : STOP,
|
||||||
BUTTON_W, BUTTON_H);
|
BUTTON_W, BUTTON_H);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,9 @@ class TimeMachineDialog : public Dialog
|
||||||
void handleKeyDown(StellaKey key, StellaMod mod) override;
|
void handleKeyDown(StellaKey key, StellaMod mod) override;
|
||||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||||
|
|
||||||
|
/** initialize timeline bar */
|
||||||
|
void initBar();
|
||||||
|
|
||||||
/** This dialog uses its own positioning, so we override Dialog::center() */
|
/** This dialog uses its own positioning, so we override Dialog::center() */
|
||||||
void center() override;
|
void center() override;
|
||||||
|
|
||||||
|
@ -62,6 +65,8 @@ class TimeMachineDialog : public Dialog
|
||||||
kUnwindAll = 'TMua',
|
kUnwindAll = 'TMua',
|
||||||
kUnwind10 = 'TMu1',
|
kUnwind10 = 'TMu1',
|
||||||
kUnwind1 = 'TMun',
|
kUnwind1 = 'TMun',
|
||||||
|
kSaveAll = 'TMsv',
|
||||||
|
kLoadAll = 'TMld',
|
||||||
};
|
};
|
||||||
|
|
||||||
TimeLineWidget* myTimeline;
|
TimeLineWidget* myTimeline;
|
||||||
|
@ -72,6 +77,8 @@ class TimeMachineDialog : public Dialog
|
||||||
ButtonWidget* myRewind1Widget;
|
ButtonWidget* myRewind1Widget;
|
||||||
ButtonWidget* myUnwind1Widget;
|
ButtonWidget* myUnwind1Widget;
|
||||||
ButtonWidget* myUnwindAllWidget;
|
ButtonWidget* myUnwindAllWidget;
|
||||||
|
ButtonWidget* mySaveAllWidget;
|
||||||
|
ButtonWidget* myLoadAllWidget;
|
||||||
|
|
||||||
StaticTextWidget* myCurrentTimeWidget;
|
StaticTextWidget* myCurrentTimeWidget;
|
||||||
StaticTextWidget* myLastTimeWidget;
|
StaticTextWidget* myLastTimeWidget;
|
||||||
|
|
Loading…
Reference in New Issue