mirror of
https://github.com/libretro/stella2023.git
synced 2024-11-27 02:40:37 +00:00
fine tuning on interval factor and state compression
rewind now displayed immediately (instead of "Paused") two initial rewinds in continuous rewind mode fixed Horizon widget disabled when Uncompressed size == Buffer size fixed minimum Interval
This commit is contained in:
parent
20eb97ce14
commit
e2301dfd5e
@ -3107,9 +3107,12 @@
|
||||
<td>
|
||||
Defines the horizon of the rewind buffer. A large horizon allows
|
||||
going back further in time. To reach the horizon, save states
|
||||
will be compressed. This means that more and more intermediate
|
||||
will be compressed (*). This means that more and more intermediate
|
||||
states will be removed and the interval between save states
|
||||
becomes larger the further they are back in time.
|
||||
becomes larger the further they are back in time. The very first
|
||||
save state will not be removed.<br>
|
||||
(*) Compresion only works if 'Uncompressed size' is smaller than
|
||||
'Buffer size'.
|
||||
</td>
|
||||
<td>-plr.rewind.horizon<br>-dev.rewind.horizon</td>
|
||||
</tr>
|
||||
|
@ -36,6 +36,8 @@ RewindManager::RewindManager(OSystem& system, StateManager& statemgr)
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RewindManager::setup()
|
||||
{
|
||||
myLastContinuousAdd = false;
|
||||
|
||||
string prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
|
||||
|
||||
mySize = myOSystem.settings().getInt(prefix + "rewind.size");
|
||||
@ -55,20 +57,22 @@ void RewindManager::setup()
|
||||
myHorizon = HORIZON_CYCLES[i];
|
||||
|
||||
// calc interval growth factor
|
||||
// this factor defines the backward horizon
|
||||
const double MAX_FACTOR = 1E8;
|
||||
double minFactor = 0, maxFactor = MAX_FACTOR;
|
||||
myFactor = 1;
|
||||
|
||||
while(true)
|
||||
while(myUncompressed < mySize)
|
||||
{
|
||||
double interval = myInterval;
|
||||
double cycleSum = interval * myUncompressed;
|
||||
double cycleSum = interval * (myUncompressed + 1);
|
||||
// calculate nextCycles factor
|
||||
myFactor = (minFactor + maxFactor) / 2;
|
||||
// horizon not reachable?
|
||||
if(myFactor == MAX_FACTOR)
|
||||
break;
|
||||
// sum up interval cycles
|
||||
for(uInt32 i = myUncompressed; i < mySize; ++i)
|
||||
// sum up interval cycles (first and last state are not compressed)
|
||||
for(uInt32 i = myUncompressed + 1; i < mySize - 1; ++i)
|
||||
{
|
||||
interval *= myFactor;
|
||||
cycleSum += interval;
|
||||
@ -119,6 +123,7 @@ bool RewindManager::addState(const string& message, bool continuous)
|
||||
state.cycles = myOSystem.console().tia().cycles();
|
||||
//state.count = count++;
|
||||
//cerr << "add " << state.count << endl;
|
||||
myLastContinuousAdd = continuous;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -129,15 +134,17 @@ bool RewindManager::rewindState()
|
||||
{
|
||||
if(!atFirst())
|
||||
{
|
||||
RewindState& lastState = myStateList.current();
|
||||
|
||||
if (!myLastContinuousAdd)
|
||||
// Set internal current iterator to previous state (back in time),
|
||||
// since we will now processed this state
|
||||
myStateList.moveToPrevious();
|
||||
myStateList.moveToPrevious();
|
||||
myLastContinuousAdd = false;
|
||||
|
||||
//RewindState& lastState = myStateList.current();
|
||||
|
||||
RewindState& state = myStateList.current();
|
||||
Serializer& s = state.data;
|
||||
string message = getMessage(state, lastState);
|
||||
string message = getMessage(state);
|
||||
//cerr << "rewind " << state.count << endl;
|
||||
|
||||
s.rewind(); // rewind Serializer internal buffers
|
||||
@ -163,7 +170,7 @@ bool RewindManager::unwindState()
|
||||
|
||||
RewindState& state = myStateList.current();
|
||||
Serializer& s = state.data;
|
||||
string message = getMessage(state, state);
|
||||
string message = getMessage(state);
|
||||
//cerr << "unwind " << state.count << endl;
|
||||
|
||||
s.rewind(); // rewind Serializer internal buffers
|
||||
@ -182,8 +189,8 @@ bool RewindManager::unwindState()
|
||||
void RewindManager::compressStates()
|
||||
{
|
||||
uInt64 currentCycles = myOSystem.console().tia().cycles();
|
||||
double expectedCycles = myInterval * (1*0 + myFactor);
|
||||
double maxError = 0;
|
||||
double expectedCycles = myInterval * myFactor * (1 + myFactor);
|
||||
double maxError = 1;
|
||||
uInt32 removeIdx = 0;
|
||||
uInt32 idx = myStateList.size() - 2;
|
||||
|
||||
@ -223,17 +230,18 @@ void RewindManager::compressStates()
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string RewindManager::getMessage(RewindState& state, RewindState& lastState)
|
||||
string RewindManager::getMessage(RewindState& state)
|
||||
{
|
||||
Int64 diff = myOSystem.console().tia().cycles() - state.cycles;
|
||||
stringstream message;
|
||||
|
||||
message << (diff >= 0 ? "Rewind" : "Unwind") << " " << getUnitString(diff);
|
||||
|
||||
// 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() << "]";
|
||||
// add optional message
|
||||
if(!state.message.empty())
|
||||
message << " (" << state.message << ")";
|
||||
|
||||
return message.str();
|
||||
}
|
||||
|
||||
|
@ -144,6 +144,7 @@ class RewindManager
|
||||
uInt32 myInterval;
|
||||
uInt64 myHorizon;
|
||||
double myFactor;
|
||||
bool myLastContinuousAdd;
|
||||
|
||||
struct RewindState {
|
||||
Serializer data;
|
||||
@ -168,7 +169,7 @@ class RewindManager
|
||||
|
||||
void compressStates();
|
||||
|
||||
string getMessage(RewindState& state, RewindState& lastState);
|
||||
string getMessage(RewindState& state);
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
@ -161,7 +161,7 @@ void StateManager::update()
|
||||
switch(myActiveMode)
|
||||
{
|
||||
case Mode::Rewind:
|
||||
myRewindManager->addState("1 frame", true);
|
||||
myRewindManager->addState("continuous rewind", true);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
|
@ -299,13 +299,15 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, bool state)
|
||||
switch(key)
|
||||
{
|
||||
case KBDK_LEFT: // Alt-left rewinds states
|
||||
if(myOSystem.state().rewindState() && myState != S_PAUSE)
|
||||
setEventState(S_PAUSE);
|
||||
myOSystem.frameBuffer().resetPauseDelay();
|
||||
setEventState(S_PAUSE);
|
||||
myOSystem.state().rewindState();
|
||||
break;
|
||||
|
||||
case KBDK_RIGHT: // Alt-right unwinds states
|
||||
if(myOSystem.state().unwindState() && myState != S_PAUSE)
|
||||
setEventState(S_PAUSE);
|
||||
myOSystem.frameBuffer().resetPauseDelay();
|
||||
setEventState(S_PAUSE);
|
||||
myOSystem.state().unwindState();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -301,7 +301,7 @@ void FrameBuffer::update()
|
||||
// Show a pause message immediately and then every 7 seconds
|
||||
if (myPausedCount-- <= 0)
|
||||
{
|
||||
myPausedCount = uInt32(7 * myOSystem.frameRate());
|
||||
resetPauseDelay();
|
||||
showMessage("Paused", kMiddleCenter);
|
||||
}
|
||||
break; // S_PAUSE
|
||||
@ -471,6 +471,12 @@ inline void FrameBuffer::drawMessage()
|
||||
myMsg.enabled = false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::resetPauseDelay()
|
||||
{
|
||||
myPausedCount = uInt32(7 * myOSystem.frameRate());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
shared_ptr<FBSurface> FrameBuffer::allocateSurface(int w, int h, const uInt32* data)
|
||||
{
|
||||
|
@ -144,6 +144,11 @@ class FrameBuffer
|
||||
*/
|
||||
void enableMessages(bool enable);
|
||||
|
||||
/**
|
||||
Reset 'Paused' display delay counter
|
||||
*/
|
||||
void resetPauseDelay();
|
||||
|
||||
/**
|
||||
Allocate a new surface. The FrameBuffer class takes all responsibility
|
||||
for freeing this surface (ie, other classes must not delete it directly).
|
||||
|
@ -329,11 +329,11 @@ void Settings::validate()
|
||||
i = getInt("dev.rewind.uncompressed");
|
||||
if(i < 0 || i > size) setInternal("dev.rewind.uncompressed", size);
|
||||
|
||||
i = getInt("dev.rewind.interval");
|
||||
/*i = getInt("dev.rewind.interval");
|
||||
if(i < 0 || i > 5) setInternal("dev.rewind.interval", 0);
|
||||
|
||||
i = getInt("dev.rewind.horizon");
|
||||
if(i < 0 || i > 6) setInternal("dev.rewind.horizon", 1);
|
||||
if(i < 0 || i > 6) setInternal("dev.rewind.horizon", 1);*/
|
||||
|
||||
i = getInt("plr.tv.jitter_recovery");
|
||||
if(i < 1 || i > 20) setInternal("plr.tv.jitter_recovery", "10");
|
||||
|
@ -999,6 +999,7 @@ void DeveloperDialog::handleSize()
|
||||
myUncompressedWidget->setValue(size);
|
||||
myStateIntervalWidget->setSelectedIndex(interval);
|
||||
myStateHorizonWidget->setSelectedIndex(i);
|
||||
myStateHorizonWidget->setEnabled(size > uncompressed);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@ -1011,6 +1012,7 @@ void DeveloperDialog::handleUncompressed()
|
||||
|
||||
if(size < uncompressed)
|
||||
myStateSizeWidget->setValue(uncompressed);
|
||||
myStateHorizonWidget->setEnabled(size > uncompressed);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
Loading…
Reference in New Issue
Block a user