mirror of https://github.com/stella-emu/stella.git
savestate position in list display in message added
compressStates loop fixed and slightly optimized fixed minimal size value in Settings
This commit is contained in:
parent
47b4007bcb
commit
20eb97ce14
|
@ -72,6 +72,19 @@ class LinkedObjectPool
|
|||
*/
|
||||
T& current() const { return *myCurrent; }
|
||||
|
||||
/**
|
||||
Returns current's position in the list
|
||||
|
||||
SLOW, but only required for messages
|
||||
*/
|
||||
uInt32 currentIdx() const {
|
||||
iter it = myCurrent;
|
||||
uInt32 idx = 1;
|
||||
|
||||
while(it-- != myList.begin()) idx++;
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
Does the 'current' iterator point to a valid node in the active list?
|
||||
This must be called before 'current()' is called.
|
||||
|
|
|
@ -56,13 +56,13 @@ void RewindManager::setup()
|
|||
|
||||
// calc interval growth factor
|
||||
const double MAX_FACTOR = 1E8;
|
||||
double minFactor = 1, maxFactor = MAX_FACTOR;
|
||||
double minFactor = 0, maxFactor = MAX_FACTOR;
|
||||
|
||||
while(true)
|
||||
{
|
||||
double interval = myInterval;
|
||||
double cycleSum = interval * myUncompressed;
|
||||
// calculate next factor
|
||||
// calculate nextCycles factor
|
||||
myFactor = (minFactor + maxFactor) / 2;
|
||||
// horizon not reachable?
|
||||
if(myFactor == MAX_FACTOR)
|
||||
|
@ -91,11 +91,11 @@ void RewindManager::setup()
|
|||
bool RewindManager::addState(const string& message, bool continuous)
|
||||
{
|
||||
// only check for continuous rewind states, ignore for debugger
|
||||
if(continuous)
|
||||
if(continuous && myStateList.currentIsValid())
|
||||
{
|
||||
// check if the current state has the right interval from the last state
|
||||
RewindState& lastState = myStateList.current();
|
||||
if(myOSystem.console().tia().cycles() - lastState.cycle < myInterval)
|
||||
if(myOSystem.console().tia().cycles() - lastState.cycles < myInterval)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ bool RewindManager::addState(const string& message, bool continuous)
|
|||
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
||||
{
|
||||
state.message = message;
|
||||
state.cycle = myOSystem.console().tia().cycles();
|
||||
state.cycles = myOSystem.console().tia().cycles();
|
||||
//state.count = count++;
|
||||
//cerr << "add " << state.count << endl;
|
||||
return true;
|
||||
|
@ -157,7 +157,7 @@ bool RewindManager::unwindState()
|
|||
{
|
||||
if(!atLast())
|
||||
{
|
||||
// Set internal current iterator to next state (forward in time),
|
||||
// Set internal current iterator to nextCycles state (forward in time),
|
||||
// since we've now processed this state
|
||||
myStateList.moveToNext();
|
||||
|
||||
|
@ -181,41 +181,35 @@ bool RewindManager::unwindState()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RewindManager::compressStates()
|
||||
{
|
||||
//bool debugMode = myOSystem.eventHandler().state() == EventHandler::S_DEBUGGER;
|
||||
|
||||
uInt64 currentCycle = myOSystem.console().tia().cycles();
|
||||
uInt64 lastCycle = currentCycle;
|
||||
double expectedCycles = myInterval; // == cycles of 1 frame, TODO: use actual number of scanlines
|
||||
double maxDelta = 0;
|
||||
uInt64 currentCycles = myOSystem.console().tia().cycles();
|
||||
double expectedCycles = myInterval * (1*0 + myFactor);
|
||||
double maxError = 0;
|
||||
uInt32 removeIdx = 0;
|
||||
uInt32 idx = myStateList.size() - 2;
|
||||
|
||||
uInt32 idx = myStateList.size() - 1;
|
||||
//cerr << "idx: " << idx << endl;
|
||||
for(auto it = myStateList.last(); it != myStateList.first(); --it)
|
||||
//cerr << "idx: " << idx << endl;
|
||||
// iterate from last but one to first but one
|
||||
for(auto it = myStateList.previous(myStateList.last()); it != myStateList.first(); --it)
|
||||
{
|
||||
if(idx < mySize - myUncompressed)
|
||||
{
|
||||
//cerr << *it << endl << endl; // debug code
|
||||
expectedCycles *= myFactor;
|
||||
|
||||
double expected = expectedCycles * (1 + myFactor);
|
||||
uInt64 prev = myStateList.previous(it)->cycle;
|
||||
uInt64 next = myStateList.next(it)->cycle;
|
||||
if(next != lastCycle)
|
||||
lastCycle++;
|
||||
double delta = expected / (next - prev);
|
||||
//cerr << "prev: " << prev << ", next: " << next << ", delta: " << delta << endl;
|
||||
uInt64 prevCycles = myStateList.previous(it)->cycles;
|
||||
uInt64 nextCycles = myStateList.next(it)->cycles;
|
||||
double error = expectedCycles / (nextCycles - prevCycles);
|
||||
//cerr << "prevCycles: " << prevCycles << ", nextCycles: " << nextCycles << ", error: " << error << endl;
|
||||
|
||||
if(delta > maxDelta)
|
||||
if(error > maxError)
|
||||
{
|
||||
maxDelta = delta;
|
||||
maxError = error;
|
||||
removeIdx = idx;
|
||||
}
|
||||
}
|
||||
lastCycle = it->cycle;
|
||||
--idx;
|
||||
}
|
||||
if (maxDelta < 1)
|
||||
if (maxError < 1)
|
||||
{
|
||||
// the horizon is getting too big (can happen after changing settings)
|
||||
myStateList.remove(1); // remove oldest but one
|
||||
|
@ -231,7 +225,7 @@ void RewindManager::compressStates()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string RewindManager::getMessage(RewindState& state, RewindState& lastState)
|
||||
{
|
||||
Int64 diff = myOSystem.console().tia().cycles() - state.cycle;
|
||||
Int64 diff = myOSystem.console().tia().cycles() - state.cycles;
|
||||
stringstream message;
|
||||
|
||||
message << (diff >= 0 ? "Rewind" : "Unwind") << " " << getUnitString(diff);
|
||||
|
@ -239,6 +233,7 @@ string RewindManager::getMessage(RewindState& state, RewindState& lastState)
|
|||
// add optional message (TODO: when smart removal works, we have to do something smart with this part too)
|
||||
if(!lastState.message.empty())
|
||||
message << " (" << lastState.message << ")";
|
||||
message << " [" << myStateList.currentIdx() << "/" << myStateList.size() << "]";
|
||||
return message.str();
|
||||
}
|
||||
|
||||
|
@ -263,7 +258,7 @@ string RewindManager::getUnitString(Int64 cycles)
|
|||
|
||||
for(i = 0; i < NUM_UNITS - 1; ++i)
|
||||
{
|
||||
// use the lower unit up to twice the next unit, except for an exact match of the next unit
|
||||
// use the lower unit up to twice the nextCycles unit, except for an exact match of the nextCycles unit
|
||||
// TODO: does the latter make sense, e.g. for ROMs with changing scanlines?
|
||||
if(cycles < UNIT_CYCLES[i + 1] * 2 && cycles % UNIT_CYCLES[i + 1] != 0)
|
||||
break;
|
||||
|
|
|
@ -148,7 +148,7 @@ class RewindManager
|
|||
struct RewindState {
|
||||
Serializer data;
|
||||
string message;
|
||||
uInt64 cycle;
|
||||
uInt64 cycles;
|
||||
//int count; // TODO - remove this
|
||||
|
||||
// We do nothing on object instantiation or copy
|
||||
|
@ -158,7 +158,7 @@ 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.cycles; // << " count: " << s.count;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -320,10 +320,10 @@ void Settings::validate()
|
|||
if(i < 1 || i > 20) setInternal("dev.tv.jitter_recovery", "2");
|
||||
|
||||
int size = getInt("dev.rewind.size");
|
||||
if(size < 100 || size > 1000)
|
||||
if(size < 20 || size > 1000)
|
||||
{
|
||||
setInternal("dev.rewind.size", 100);
|
||||
size = 100;
|
||||
setInternal("dev.rewind.size", 20);
|
||||
size = 20;
|
||||
}
|
||||
|
||||
i = getInt("dev.rewind.uncompressed");
|
||||
|
@ -339,10 +339,10 @@ void Settings::validate()
|
|||
if(i < 1 || i > 20) setInternal("plr.tv.jitter_recovery", "10");
|
||||
|
||||
size = getInt("plr.rewind.size");
|
||||
if(size < 100 || size > 1000)
|
||||
if(size < 20 || size > 1000)
|
||||
{
|
||||
setInternal("plr.rewind.size", 100);
|
||||
size = 100;
|
||||
setInternal("plr.rewind.size", 20);
|
||||
size = 20;
|
||||
}
|
||||
|
||||
i = getInt("plr.rewind.uncompressed");
|
||||
|
|
Loading…
Reference in New Issue