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:
thrust26 2017-12-13 12:31:18 +01:00
parent 47b4007bcb
commit 20eb97ce14
4 changed files with 44 additions and 36 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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;
}
};

View File

@ -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");