mirror of https://github.com/stella-emu/stella.git
rewind buffer resize added
This commit is contained in:
parent
8034bae9de
commit
5439d185a7
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
@ -2484,11 +2484,11 @@
|
|||
<td><pre>-<plr.|dev.>rewind <1|0></pre></td>
|
||||
<td>Enables continuous rewind</td>
|
||||
</tr><tr>
|
||||
<td><pre>-<plr.|dev.>rewind.size <100 - 1000></pre></td>
|
||||
<td><pre>-<plr.|dev.>rewind.size <20 - 1000></pre></td>
|
||||
<td>Defines the rewind buffer size.</td>
|
||||
</tr><tr>
|
||||
</tr><tr>
|
||||
<td><pre>-<plr.|dev.>rewind.uncompressed <100 - 1000></pre></td>
|
||||
<td><pre>-<plr.|dev.>rewind.uncompressed <0 - 1000></pre></td>
|
||||
<td>Defines the uncompressed rewind buffer size. Must be <= rewind buffer size.</td>
|
||||
</tr><tr>
|
||||
</tr><tr>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "RewindManager.hxx"
|
||||
|
||||
static int count = 1;
|
||||
//static int count = 1;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
RewindManager::RewindManager(OSystem& system, StateManager& statemgr)
|
||||
: myOSystem(system),
|
||||
|
@ -36,18 +36,13 @@ RewindManager::RewindManager(OSystem& system, StateManager& statemgr)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RewindManager::setup()
|
||||
{
|
||||
/*static const int NUM_INTERVALS = 6;
|
||||
// TODO: check for intervals shorter than 1 frame (adjust horizon too!)
|
||||
const uInt32 INTERVAL_CYCLES[NUM_INTERVALS] = { 76, 76 * 50, 76 * 262, 76 * 262 * 10,
|
||||
76 * 262 * 60, 76 * 262 * 60 * 10 };
|
||||
static const int NUM_HORIZONS = 7;
|
||||
const uInt64 HORIZON_CYCLES[NUM_HORIZONS] = { 76 * 262, 76 * 262 * 10, 76 * 262 * 60, 76 * 262 * 60 * 10,
|
||||
76 * 262 * 60 * 60, 76 * 262 * 60 * 60 * 10, uInt64(76) * 262 * 60 * 60 * 60 };*/
|
||||
bool devSettings = myOSystem.settings().getBool("dev.settings");
|
||||
string prefix = devSettings ? "dev." : "plr.";
|
||||
string prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
|
||||
|
||||
mySize = MAX_SIZE; // myOSystem.settings().getInt(prefix + "rewind.size");
|
||||
myUncompressed = MAX_SIZE / 4; // myOSystem.settings().getInt(prefix + "rewind.uncompressed");
|
||||
mySize = myOSystem.settings().getInt(prefix + "rewind.size");
|
||||
if(mySize != myStateList.capacity())
|
||||
myStateList.resize(mySize);
|
||||
|
||||
myUncompressed = myOSystem.settings().getInt(prefix + "rewind.uncompressed");
|
||||
|
||||
myInterval = INTERVAL_CYCLES[0];
|
||||
for(int i = 0; i < NUM_INTERVALS; ++i)
|
||||
|
@ -89,7 +84,7 @@ void RewindManager::setup()
|
|||
else
|
||||
maxFactor = myFactor;
|
||||
}
|
||||
cerr << "factor " << myFactor << endl;
|
||||
//cerr << "factor " << myFactor << endl;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -122,8 +117,8 @@ bool RewindManager::addState(const string& message, bool continuous)
|
|||
{
|
||||
state.message = message;
|
||||
state.cycle = myOSystem.console().tia().cycles();
|
||||
state.count = count++;
|
||||
cerr << "add " << state.count << endl;
|
||||
//state.count = count++;
|
||||
//cerr << "add " << state.count << endl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -143,7 +138,7 @@ bool RewindManager::rewindState()
|
|||
RewindState& state = myStateList.current();
|
||||
Serializer& s = state.data;
|
||||
string message = getMessage(state, lastState);
|
||||
cerr << "rewind " << state.count << endl;
|
||||
//cerr << "rewind " << state.count << endl;
|
||||
|
||||
s.rewind(); // rewind Serializer internal buffers
|
||||
myStateManager.loadState(s);
|
||||
|
@ -169,7 +164,7 @@ bool RewindManager::unwindState()
|
|||
RewindState& state = myStateList.current();
|
||||
Serializer& s = state.data;
|
||||
string message = getMessage(state, state);
|
||||
cerr << "unwind " << state.count << endl;
|
||||
//cerr << "unwind " << state.count << endl;
|
||||
|
||||
s.rewind(); // rewind Serializer internal buffers
|
||||
myStateManager.loadState(s);
|
||||
|
@ -222,14 +217,14 @@ void RewindManager::compressStates()
|
|||
}
|
||||
if (maxDelta < 1)
|
||||
{
|
||||
// the horizon is getting too big
|
||||
// the horizon is getting too big (can happen after changing settings)
|
||||
myStateList.remove(1); // remove oldest but one
|
||||
cerr << "remove oldest + 1" << endl;
|
||||
//cerr << "remove oldest + 1" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
myStateList.remove(removeIdx); // remove
|
||||
cerr << "remove " << removeIdx << endl;
|
||||
//cerr << "remove " << removeIdx << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,8 +254,7 @@ string RewindManager::getUnitString(Int64 cycles)
|
|||
// TODO: do we need hours here? don't think so
|
||||
const Int32 NUM_UNITS = 5;
|
||||
const string UNIT_NAMES[NUM_UNITS] = { "cycle", "scanline", "frame", "second", "minute" };
|
||||
const Int64 UNIT_CYCLES[NUM_UNITS + 1] = { 1, 76, 76 * scanlines, freq,
|
||||
freq * 60, Int64(1) << 62 };
|
||||
const Int64 UNIT_CYCLES[NUM_UNITS + 1] = { 1, 76, 76 * scanlines, freq, freq * 60, Int64(1) << 62 };
|
||||
|
||||
stringstream result;
|
||||
Int32 i;
|
||||
|
@ -280,4 +274,3 @@ string RewindManager::getUnitString(Int64 cycles)
|
|||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ class RewindManager
|
|||
|
||||
private:
|
||||
// Maximum number of states to save
|
||||
static constexpr uInt32 MAX_SIZE = 20; // TODO: use a parameter here and allow user to define size in UI
|
||||
static constexpr uInt32 INITIAL_SIZE = 100;
|
||||
|
||||
OSystem& myOSystem;
|
||||
StateManager& myStateManager;
|
||||
|
@ -149,7 +149,7 @@ class RewindManager
|
|||
Serializer data;
|
||||
string message;
|
||||
uInt64 cycle;
|
||||
int count; // TODO - remove this
|
||||
//int count; // TODO - remove this
|
||||
|
||||
// We do nothing on object instantiation or copy
|
||||
// The goal of LinkedObjectPool is to not do any allocations at all
|
||||
|
@ -158,13 +158,13 @@ class RewindManager
|
|||
|
||||
// Output object info; used for debugging only
|
||||
friend ostream& operator<<(ostream& os, const RewindState& s) {
|
||||
return os << "msg: " << s.message << " cycle: " << s.cycle << " count: " << s.count;
|
||||
return os << "msg: " << s.message << " cycle: " << s.cycle; // << " count: " << s.count;
|
||||
}
|
||||
};
|
||||
|
||||
// The linked-list to store states (internally it takes care of reducing
|
||||
// frequent (de)-allocations)
|
||||
Common::LinkedObjectPool<RewindState, MAX_SIZE> myStateList;
|
||||
Common::LinkedObjectPool<RewindState, INITIAL_SIZE> myStateList;
|
||||
|
||||
void compressStates();
|
||||
|
||||
|
|
|
@ -615,8 +615,9 @@ void Debugger::setStartState()
|
|||
// Lock the bus each time the debugger is entered, so we don't disturb anything
|
||||
lockBankswitchState();
|
||||
|
||||
// Save initial state and add it to the rewind list
|
||||
saveOldState("enter debugger");
|
||||
// Save initial state and add it to the rewind list (except when in currently rewinding)
|
||||
RewindManager& r = myOSystem.state().rewindManager();
|
||||
saveOldState(r.atLast() ? "enter debugger" : "");
|
||||
|
||||
// Set the 're-disassemble' flag, but don't do it until the next scheduled time
|
||||
myDialog->rom().invalidate(false);
|
||||
|
|
|
@ -189,7 +189,8 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font)
|
|||
ypos += lineHeight + VGAP * 1;
|
||||
|
||||
// TV jitter effect
|
||||
myTVJitterWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1, "Jitter/roll effect", kTVJitter);
|
||||
myTVJitterWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
|
||||
"Jitter/roll effect", kTVJitter);
|
||||
wid.push_back(myTVJitterWidget);
|
||||
myTVJitterRecWidget = new SliderWidget(myTab, font,
|
||||
myTVJitterWidget->getRight() + fontWidth * 3, ypos - 1,
|
||||
|
@ -198,18 +199,21 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font)
|
|||
myTVJitterRecWidget->setMinValue(1); myTVJitterRecWidget->setMaxValue(20);
|
||||
wid.push_back(myTVJitterRecWidget);
|
||||
myTVJitterRecLabelWidget = new StaticTextWidget(myTab, font,
|
||||
myTVJitterRecWidget->getRight() + 4, myTVJitterRecWidget->getTop() + 2,
|
||||
myTVJitterRecWidget->getRight() + 4,
|
||||
myTVJitterRecWidget->getTop() + 2,
|
||||
5 * fontWidth, fontHeight, "", kTextAlignLeft);
|
||||
myTVJitterRecLabelWidget->setFlags(WIDGET_CLEARBG);
|
||||
wid.push_back(myTVJitterRecLabelWidget);
|
||||
ypos += lineHeight + VGAP;
|
||||
|
||||
myColorLossWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1, "PAL color-loss");
|
||||
myColorLossWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
|
||||
"PAL color-loss");
|
||||
wid.push_back(myColorLossWidget);
|
||||
ypos += lineHeight + VGAP;
|
||||
|
||||
// debug colors
|
||||
myDebugColorsWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1, "Debug colors (*)");
|
||||
myDebugColorsWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
|
||||
"Debug colors (*)");
|
||||
wid.push_back(myDebugColorsWidget);
|
||||
ypos += lineHeight + VGAP + 2;
|
||||
|
||||
|
@ -258,12 +262,12 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font)
|
|||
void DeveloperDialog::addStatesTab(const GUI::Font& font)
|
||||
{
|
||||
const string INTERVALS[NUM_INTERVALS] = {
|
||||
"1 frame",
|
||||
"3 frames",
|
||||
" 1 frame",
|
||||
" 3 frames",
|
||||
"10 frames",
|
||||
"30 frames",
|
||||
"1 second",
|
||||
"3 seconds",
|
||||
" 1 second",
|
||||
" 3 seconds",
|
||||
"10 seconds"
|
||||
};
|
||||
const string INT_SETTINGS[NUM_INTERVALS] = {
|
||||
|
@ -276,14 +280,14 @@ void DeveloperDialog::addStatesTab(const GUI::Font& font)
|
|||
"10s"
|
||||
};
|
||||
const string HORIZONS[NUM_HORIZONS] = {
|
||||
"~3 seconds",
|
||||
"~10 seconds",
|
||||
"~30 seconds",
|
||||
"~1 minute",
|
||||
"~3 minutes",
|
||||
"~10 minutes",
|
||||
"~30 minutes",
|
||||
"~60 minutes"
|
||||
" 3 seconds",
|
||||
"10 seconds",
|
||||
"30 seconds",
|
||||
" 1 minute",
|
||||
" 3 minutes",
|
||||
"10 minutes",
|
||||
"30 minutes",
|
||||
"60 minutes"
|
||||
};
|
||||
const string HOR_SETTINGS[NUM_HORIZONS] = {
|
||||
"3s",
|
||||
|
@ -325,7 +329,7 @@ void DeveloperDialog::addStatesTab(const GUI::Font& font)
|
|||
int sWidth = font.getMaxCharWidth() * 8;
|
||||
myStateSizeWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, sWidth, lineHeight,
|
||||
"Buffer size (*) ", 0, kSizeChanged);
|
||||
myStateSizeWidget->setMinValue(100);
|
||||
myStateSizeWidget->setMinValue(20);
|
||||
myStateSizeWidget->setMaxValue(1000);
|
||||
myStateSizeWidget->setStepValue(20);
|
||||
wid.push_back(myStateSizeWidget);
|
||||
|
@ -346,7 +350,7 @@ void DeveloperDialog::addStatesTab(const GUI::Font& font)
|
|||
items.clear();
|
||||
for(int i = 0; i < NUM_INTERVALS; ++i)
|
||||
VarList::push_back(items, INTERVALS[i], INT_SETTINGS[i]);
|
||||
int pwidth = font.getStringWidth("~10 seconds");
|
||||
int pwidth = font.getStringWidth("10 seconds");
|
||||
myStateIntervalWidget = new PopUpWidget(myTab, font, HBORDER + INDENT * 2, ypos, pwidth,
|
||||
lineHeight, items, "Interval ", 0, kIntervalChanged);
|
||||
wid.push_back(myStateIntervalWidget);
|
||||
|
@ -356,7 +360,7 @@ void DeveloperDialog::addStatesTab(const GUI::Font& font)
|
|||
for(int i = 0; i < NUM_HORIZONS; ++i)
|
||||
VarList::push_back(items, HORIZONS[i], HOR_SETTINGS[i]);
|
||||
myStateHorizonWidget = new PopUpWidget(myTab, font, HBORDER + INDENT * 2, ypos, pwidth,
|
||||
lineHeight, items, "Horizon ", 0, kHorizonChanged);
|
||||
lineHeight, items, "Horizon ~ ", 0, kHorizonChanged);
|
||||
wid.push_back(myStateHorizonWidget);
|
||||
|
||||
// Add message concerning usage
|
||||
|
@ -519,7 +523,6 @@ void DeveloperDialog::loadSettings(SettingsSet set)
|
|||
myUncompressed[set] = instance().settings().getInt(prefix + "rewind.uncompressed");
|
||||
myStateInterval[set] = instance().settings().getString(prefix + "rewind.interval");
|
||||
myStateHorizon[set] = instance().settings().getString(prefix + "rewind.horizon");
|
||||
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -710,9 +713,6 @@ void DeveloperDialog::saveConfig()
|
|||
instance().console().tia().setFixedColorPalette(dbgcolors))
|
||||
instance().settings().setValue("tia.dbgcolors", dbgcolors);
|
||||
|
||||
// Finally, issue a complete framebuffer re-initialization
|
||||
//instance().createFrameBuffer();
|
||||
|
||||
// update RewindManager
|
||||
instance().state().rewindManager().setup();
|
||||
instance().state().setRewindMode(myContinuousRewindWidget->getState() ?
|
||||
|
@ -967,11 +967,17 @@ void DeveloperDialog::handleSize()
|
|||
{
|
||||
uInt32 size = myStateSizeWidget->getValue();
|
||||
uInt32 uncompressed = myUncompressedWidget->getValue();
|
||||
uInt32 interval = myStateIntervalWidget->getSelected();
|
||||
uInt32 horizon = myStateHorizonWidget->getSelected();
|
||||
Int32 interval = myStateIntervalWidget->getSelected();
|
||||
Int32 horizon = myStateHorizonWidget->getSelected();
|
||||
bool found = false;
|
||||
Int32 i;
|
||||
|
||||
// handle illegal values
|
||||
if(interval == -1)
|
||||
interval = 0;
|
||||
if(horizon == -1)
|
||||
horizon = 0;
|
||||
|
||||
myStateSizeLabelWidget->setValue(size);
|
||||
// adapt horizon and interval
|
||||
do
|
||||
|
@ -1012,11 +1018,17 @@ void DeveloperDialog::handleInterval()
|
|||
{
|
||||
uInt32 size = myStateSizeWidget->getValue();
|
||||
uInt32 uncompressed = myUncompressedWidget->getValue();
|
||||
uInt32 interval = myStateIntervalWidget->getSelected();
|
||||
uInt32 horizon = myStateHorizonWidget->getSelected();
|
||||
Int32 interval = myStateIntervalWidget->getSelected();
|
||||
Int32 horizon = myStateHorizonWidget->getSelected();
|
||||
bool found = false;
|
||||
Int32 i;
|
||||
|
||||
// handle illegal values
|
||||
if(interval == -1)
|
||||
interval = 0;
|
||||
if(horizon == -1)
|
||||
horizon = 0;
|
||||
|
||||
// adapt horizon and size
|
||||
do
|
||||
{
|
||||
|
@ -1044,17 +1056,23 @@ void DeveloperDialog::handleHorizon()
|
|||
{
|
||||
uInt32 size = myStateSizeWidget->getValue();
|
||||
uInt32 uncompressed = myUncompressedWidget->getValue();
|
||||
uInt32 interval = myStateIntervalWidget->getSelected();
|
||||
uInt32 horizon = myStateHorizonWidget->getSelected();
|
||||
Int32 interval = myStateIntervalWidget->getSelected();
|
||||
Int32 horizon = myStateHorizonWidget->getSelected();
|
||||
bool found = false;
|
||||
Int32 i;
|
||||
|
||||
// handle illegal values
|
||||
if(interval == -1)
|
||||
interval = 0;
|
||||
if(horizon == -1)
|
||||
horizon = 0;
|
||||
|
||||
// adapt interval and size
|
||||
do
|
||||
{
|
||||
for(i = interval; i >= 0; --i)
|
||||
{
|
||||
if(size * instance().state().rewindManager().INTERVAL_CYCLES[i]
|
||||
if(uInt64(size) * instance().state().rewindManager().INTERVAL_CYCLES[i]
|
||||
<= instance().state().rewindManager().HORIZON_CYCLES[horizon])
|
||||
{
|
||||
found = true;
|
||||
|
|
|
@ -152,7 +152,6 @@ class DeveloperDialog : public Dialog
|
|||
bool myContinuousRewind[2];
|
||||
int myStateSize[2];
|
||||
int myUncompressed[2];
|
||||
//int myStateInterval[2];
|
||||
string myStateInterval[2];
|
||||
string myStateHorizon[2];
|
||||
|
||||
|
@ -182,8 +181,9 @@ class DeveloperDialog : public Dialog
|
|||
void handleUncompressed();
|
||||
void handleInterval();
|
||||
void handleHorizon();
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
void handleFontSize();
|
||||
#endif
|
||||
|
||||
// Following constructors and assignment operators not supported
|
||||
DeveloperDialog() = delete;
|
||||
|
|
Loading…
Reference in New Issue