mirror of https://github.com/stella-emu/stella.git
Merge branch 'master' of https://github.com/stella-emu/stella
This commit is contained in:
commit
07d2797c62
|
@ -25,8 +25,8 @@
|
||||||
* A fixed-size object-pool based doubly-linked list that makes use of
|
* A fixed-size object-pool based doubly-linked list that makes use of
|
||||||
* multiple STL lists, to reduce frequent (de)allocations.
|
* multiple STL lists, to reduce frequent (de)allocations.
|
||||||
*
|
*
|
||||||
* This structure acts like a queue (adds to end, removes from beginning),
|
* This structure can be used as either a stack or queue, but also allows
|
||||||
* but also allows for removal at any location in the queue.
|
* for removal at any location in the list.
|
||||||
*
|
*
|
||||||
* There are two internal lists; one stores active nodes, and the other
|
* There are two internal lists; one stores active nodes, and the other
|
||||||
* stores pool nodes that have been 'deleted' from the active list (note
|
* stores pool nodes that have been 'deleted' from the active list (note
|
||||||
|
@ -61,9 +61,29 @@ class LinkedObjectPool
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new node at the end of the active list, and return a reference to
|
* Return a reference to the element at the first node in the active list.
|
||||||
* that node. The reference may then be modified; ie, you're able to change
|
*/
|
||||||
* the data located at that node.
|
T& first() { return myList.front(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a reference to the element at the last node in the active list.
|
||||||
|
*/
|
||||||
|
T& last() { return myList.back(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new node at beginning of the active list, and return a reference
|
||||||
|
* to that nodes' data. The reference may then be modified; ie, you're
|
||||||
|
* able to change the data located at that node.
|
||||||
|
*/
|
||||||
|
T& addFirst() {
|
||||||
|
myList.splice(myList.begin(), myPool, myPool.begin());
|
||||||
|
return myList.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new node at the end of the active list, and return a reference
|
||||||
|
* to that nodes' data. The reference may then be modified; ie, you're
|
||||||
|
* able to change the data located at that node.
|
||||||
*/
|
*/
|
||||||
T& addLast() {
|
T& addLast() {
|
||||||
myList.splice(myList.end(), myPool, myPool.begin());
|
myList.splice(myList.end(), myPool, myPool.begin());
|
||||||
|
@ -71,13 +91,22 @@ class LinkedObjectPool
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a reference to the element at the first node.
|
* Remove the first node of the active list.
|
||||||
* The reference may not be modified.
|
|
||||||
*/
|
*/
|
||||||
const T& first() const { return myList.front(); }
|
void removeFirst() {
|
||||||
|
myPool.splice(myPool.end(), myList, myList.begin());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a single element at position of the iterator +- the offset.
|
* Remove the last node of the active list.
|
||||||
|
*/
|
||||||
|
void removeLast() {
|
||||||
|
myPool.splice(myPool.end(), myList, std::prev(myList.end(), 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to remove a single element from the active list at
|
||||||
|
* position of the iterator +- the offset.
|
||||||
*/
|
*/
|
||||||
void remove(const_iter i, Int32 offset = 0) {
|
void remove(const_iter i, Int32 offset = 0) {
|
||||||
myPool.splice(myPool.end(), myList,
|
myPool.splice(myPool.end(), myList,
|
||||||
|
@ -85,37 +114,38 @@ class LinkedObjectPool
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a single element by index, offset from the beginning of the list.
|
* Convenience method to remove a single element from the active list by
|
||||||
* (ie, '0' means first element, '1' is second, and so on).
|
* index, offset from the beginning of the list. (ie, '0' means first
|
||||||
|
* element, '1' is second, and so on).
|
||||||
*/
|
*/
|
||||||
void remove(uInt32 index) {
|
void remove(uInt32 index) {
|
||||||
myPool.splice(myPool.end(), myList, std::next(myList.begin(), index));
|
myPool.splice(myPool.end(), myList, std::next(myList.begin(), index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience method to remove the first element in the list.
|
|
||||||
*/
|
|
||||||
void removeFirst() {
|
|
||||||
myPool.splice(myPool.end(), myList, myList.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to remove a range of elements from 'index' to the
|
* Convenience method to remove a range of elements from 'index' to the
|
||||||
* end of the list.
|
* end of the active list.
|
||||||
*/
|
*/
|
||||||
void removeLast(uInt32 index) {
|
void removeLast(uInt32 index) {
|
||||||
myPool.splice(myPool.end(), myList, std::next(myList.begin(), index), myList.end());
|
myPool.splice(myPool.end(), myList, std::next(myList.begin(), index), myList.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase entire contents of active list.
|
||||||
|
*/
|
||||||
|
void clear() {
|
||||||
|
myPool.splice(myPool.end(), myList, myList.begin(), myList.end());
|
||||||
|
}
|
||||||
|
|
||||||
/** Access the list with iterators, just as you would a normal C++ STL list */
|
/** Access the list with iterators, just as you would a normal C++ STL list */
|
||||||
iter begin() { return myList.begin(); }
|
iter begin() { return myList.begin(); }
|
||||||
iter end() { return myList.end(); }
|
iter end() { return myList.end(); }
|
||||||
const_iter begin() const { return myList.cbegin(); }
|
const_iter begin() const { return myList.cbegin(); }
|
||||||
const_iter end() const { return myList.cend(); }
|
const_iter end() const { return myList.cend(); }
|
||||||
|
|
||||||
uInt32 size() const { return myList.size(); }
|
uInt32 size() const { return myList.size(); }
|
||||||
bool empty() const { return size() == 0; }
|
bool empty() const { return myList.size() == 0; }
|
||||||
bool full() const { return size() >= CAPACITY; }
|
bool full() const { return myList.size() >= CAPACITY; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<T> myList, myPool;
|
std::list<T> myList, myPool;
|
||||||
|
|
|
@ -32,16 +32,16 @@ RewindManager::RewindManager(OSystem& system, StateManager& statemgr)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool RewindManager::addState(const string& message)
|
bool RewindManager::addState(const string& message)
|
||||||
{
|
{
|
||||||
RewindPtr state = make_unique<RewindState>(); // TODO: get this from object pool
|
if(myStateList.full())
|
||||||
Serializer& s = state->data;
|
myStateList.removeLast(); // remove the oldest state file
|
||||||
|
|
||||||
|
RewindState& state = myStateList.addFirst();
|
||||||
|
Serializer& s = state.data;
|
||||||
|
|
||||||
s.reset(); // rewind Serializer internal buffers
|
s.reset(); // rewind Serializer internal buffers
|
||||||
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
||||||
{
|
{
|
||||||
state->message = "Rewind " + message;
|
state.message = "Rewind " + message;
|
||||||
|
|
||||||
// Add to the list TODO: should check against current size
|
|
||||||
myStateList.emplace_front(std::move(state));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -50,18 +50,18 @@ bool RewindManager::addState(const string& message)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool RewindManager::rewindState()
|
bool RewindManager::rewindState()
|
||||||
{
|
{
|
||||||
if(myStateList.size() > 0)
|
if(!myStateList.empty())
|
||||||
{
|
{
|
||||||
RewindPtr state = std::move(myStateList.front());
|
RewindState& state = myStateList.first();
|
||||||
myStateList.pop_front(); // TODO: add 'state' to object pool
|
Serializer& s = state.data;
|
||||||
Serializer& s = state->data;
|
|
||||||
|
|
||||||
s.reset(); // rewind Serializer internal buffers
|
s.reset(); // rewind Serializer internal buffers
|
||||||
myStateManager.loadState(s);
|
myStateManager.loadState(s);
|
||||||
myOSystem.console().tia().loadDisplay(s);
|
myOSystem.console().tia().loadDisplay(s);
|
||||||
|
|
||||||
// Show message indicating the rewind state
|
// Show message indicating the rewind state
|
||||||
myOSystem.frameBuffer().showMessage(state->message);
|
myOSystem.frameBuffer().showMessage(state.message);
|
||||||
|
myStateList.removeFirst();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,17 +21,12 @@
|
||||||
class OSystem;
|
class OSystem;
|
||||||
class StateManager;
|
class StateManager;
|
||||||
|
|
||||||
#include <list>
|
#include "LinkedObjectPool.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class is used to save (and later 'rewind') system save states.
|
This class is used to save (and later 'rewind') system save states.
|
||||||
|
|
||||||
TODO: This will eventually be converted to use object pools
|
|
||||||
Currently, it uses a C++ doubly-linked list as a stack, with
|
|
||||||
add/remove happening at the front of the list
|
|
||||||
Also, the additions are currently unbounded
|
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
*/
|
*/
|
||||||
class RewindManager
|
class RewindManager
|
||||||
|
@ -54,12 +49,12 @@ class RewindManager
|
||||||
*/
|
*/
|
||||||
bool rewindState();
|
bool rewindState();
|
||||||
|
|
||||||
bool empty() const { return myStateList.size() == 0; }
|
bool empty() const { return myStateList.empty(); }
|
||||||
void clear() { myStateList.clear(); }
|
void clear() { myStateList.clear(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Maximum number of states to save
|
// Maximum number of states to save
|
||||||
static constexpr uInt32 MAX_SIZE = 100; // FIXME: use this
|
static constexpr uInt32 MAX_SIZE = 100;
|
||||||
|
|
||||||
OSystem& myOSystem;
|
OSystem& myOSystem;
|
||||||
StateManager& myStateManager;
|
StateManager& myStateManager;
|
||||||
|
@ -67,10 +62,13 @@ class RewindManager
|
||||||
struct RewindState {
|
struct RewindState {
|
||||||
Serializer data;
|
Serializer data;
|
||||||
string message;
|
string message;
|
||||||
|
|
||||||
|
// We do nothing on object instantiation or copy
|
||||||
|
RewindState() { }
|
||||||
|
RewindState(const RewindState&) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
using RewindPtr = unique_ptr<RewindState>;
|
Common::LinkedObjectPool<RewindState, MAX_SIZE> myStateList;
|
||||||
std::list<RewindPtr> myStateList;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -407,6 +407,8 @@
|
||||||
DC9EA8880F729A36000452B5 /* KidVid.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC9EA8860F729A36000452B5 /* KidVid.hxx */; };
|
DC9EA8880F729A36000452B5 /* KidVid.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC9EA8860F729A36000452B5 /* KidVid.hxx */; };
|
||||||
DCA00FF70DBABCAD00C3823D /* RiotDebug.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCA00FF50DBABCAD00C3823D /* RiotDebug.cxx */; };
|
DCA00FF70DBABCAD00C3823D /* RiotDebug.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCA00FF50DBABCAD00C3823D /* RiotDebug.cxx */; };
|
||||||
DCA00FF80DBABCAD00C3823D /* RiotDebug.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCA00FF60DBABCAD00C3823D /* RiotDebug.hxx */; };
|
DCA00FF80DBABCAD00C3823D /* RiotDebug.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCA00FF60DBABCAD00C3823D /* RiotDebug.hxx */; };
|
||||||
|
DCA078341F8C1B04008EFEE5 /* LinkedObjectPool.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCA078321F8C1B04008EFEE5 /* LinkedObjectPool.hxx */; };
|
||||||
|
DCA078351F8C1B04008EFEE5 /* SDL_lib.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCA078331F8C1B04008EFEE5 /* SDL_lib.hxx */; };
|
||||||
DCA23AE90D75B22500F77B33 /* CartX07.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCA23AE70D75B22500F77B33 /* CartX07.cxx */; };
|
DCA23AE90D75B22500F77B33 /* CartX07.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCA23AE70D75B22500F77B33 /* CartX07.cxx */; };
|
||||||
DCA23AEA0D75B22500F77B33 /* CartX07.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCA23AE80D75B22500F77B33 /* CartX07.hxx */; };
|
DCA23AEA0D75B22500F77B33 /* CartX07.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCA23AE80D75B22500F77B33 /* CartX07.hxx */; };
|
||||||
DCAACAF6188D631500A4D282 /* Cart4KSC.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAACAEC188D631500A4D282 /* Cart4KSC.cxx */; };
|
DCAACAF6188D631500A4D282 /* Cart4KSC.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAACAEC188D631500A4D282 /* Cart4KSC.cxx */; };
|
||||||
|
@ -1041,6 +1043,8 @@
|
||||||
DC9EA8860F729A36000452B5 /* KidVid.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = KidVid.hxx; sourceTree = "<group>"; };
|
DC9EA8860F729A36000452B5 /* KidVid.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = KidVid.hxx; sourceTree = "<group>"; };
|
||||||
DCA00FF50DBABCAD00C3823D /* RiotDebug.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RiotDebug.cxx; sourceTree = "<group>"; };
|
DCA00FF50DBABCAD00C3823D /* RiotDebug.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RiotDebug.cxx; sourceTree = "<group>"; };
|
||||||
DCA00FF60DBABCAD00C3823D /* RiotDebug.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RiotDebug.hxx; sourceTree = "<group>"; };
|
DCA00FF60DBABCAD00C3823D /* RiotDebug.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RiotDebug.hxx; sourceTree = "<group>"; };
|
||||||
|
DCA078321F8C1B04008EFEE5 /* LinkedObjectPool.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LinkedObjectPool.hxx; sourceTree = "<group>"; };
|
||||||
|
DCA078331F8C1B04008EFEE5 /* SDL_lib.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SDL_lib.hxx; sourceTree = "<group>"; };
|
||||||
DCA23AE70D75B22500F77B33 /* CartX07.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CartX07.cxx; sourceTree = "<group>"; };
|
DCA23AE70D75B22500F77B33 /* CartX07.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CartX07.cxx; sourceTree = "<group>"; };
|
||||||
DCA23AE80D75B22500F77B33 /* CartX07.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = CartX07.hxx; sourceTree = "<group>"; };
|
DCA23AE80D75B22500F77B33 /* CartX07.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = CartX07.hxx; sourceTree = "<group>"; };
|
||||||
DCA43BFF10DED5890070CEFD /* Info-Stella.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Stella.plist"; sourceTree = "<group>"; };
|
DCA43BFF10DED5890070CEFD /* Info-Stella.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Stella.plist"; sourceTree = "<group>"; };
|
||||||
|
@ -1508,6 +1512,7 @@
|
||||||
DCE395EA16CB0B5F008DB1E5 /* FSNodeFactory.hxx */,
|
DCE395EA16CB0B5F008DB1E5 /* FSNodeFactory.hxx */,
|
||||||
DCE395EB16CB0B5F008DB1E5 /* FSNodeZIP.cxx */,
|
DCE395EB16CB0B5F008DB1E5 /* FSNodeZIP.cxx */,
|
||||||
DCE395EC16CB0B5F008DB1E5 /* FSNodeZIP.hxx */,
|
DCE395EC16CB0B5F008DB1E5 /* FSNodeZIP.hxx */,
|
||||||
|
DCA078321F8C1B04008EFEE5 /* LinkedObjectPool.hxx */,
|
||||||
DCB20EC61A0C506C0048F595 /* main.cxx */,
|
DCB20EC61A0C506C0048F595 /* main.cxx */,
|
||||||
DCB87E571A104C1E00BF2A3B /* MediaFactory.hxx */,
|
DCB87E571A104C1E00BF2A3B /* MediaFactory.hxx */,
|
||||||
DC56FCDC14CCCC4900A31CC3 /* MouseControl.cxx */,
|
DC56FCDC14CCCC4900A31CC3 /* MouseControl.cxx */,
|
||||||
|
@ -1516,6 +1521,7 @@
|
||||||
DCD6FC9211C28C6F005DA767 /* PNGLibrary.hxx */,
|
DCD6FC9211C28C6F005DA767 /* PNGLibrary.hxx */,
|
||||||
DCDDEAC01F5DBF0400C67366 /* RewindManager.cxx */,
|
DCDDEAC01F5DBF0400C67366 /* RewindManager.cxx */,
|
||||||
DCDDEAC11F5DBF0400C67366 /* RewindManager.hxx */,
|
DCDDEAC11F5DBF0400C67366 /* RewindManager.hxx */,
|
||||||
|
DCA078331F8C1B04008EFEE5 /* SDL_lib.hxx */,
|
||||||
DCF467B40F93993B00B25D7A /* SoundNull.hxx */,
|
DCF467B40F93993B00B25D7A /* SoundNull.hxx */,
|
||||||
DC368F5218A2FB710084199C /* SoundSDL2.cxx */,
|
DC368F5218A2FB710084199C /* SoundSDL2.cxx */,
|
||||||
DC368F5318A2FB710084199C /* SoundSDL2.hxx */,
|
DC368F5318A2FB710084199C /* SoundSDL2.hxx */,
|
||||||
|
@ -2118,10 +2124,12 @@
|
||||||
2D91745609BA90380026E9FF /* DataGridOpsWidget.hxx in Headers */,
|
2D91745609BA90380026E9FF /* DataGridOpsWidget.hxx in Headers */,
|
||||||
2D91745709BA90380026E9FF /* DataGridWidget.hxx in Headers */,
|
2D91745709BA90380026E9FF /* DataGridWidget.hxx in Headers */,
|
||||||
DCF3A6EC1DFC75E3008A8AF3 /* DelayQueue.hxx in Headers */,
|
DCF3A6EC1DFC75E3008A8AF3 /* DelayQueue.hxx in Headers */,
|
||||||
|
DCA078341F8C1B04008EFEE5 /* LinkedObjectPool.hxx in Headers */,
|
||||||
2D91745809BA90380026E9FF /* DebuggerDialog.hxx in Headers */,
|
2D91745809BA90380026E9FF /* DebuggerDialog.hxx in Headers */,
|
||||||
DCE5CDE41BA10024005CD08A /* RiotRamWidget.hxx in Headers */,
|
DCE5CDE41BA10024005CD08A /* RiotRamWidget.hxx in Headers */,
|
||||||
DCF3A6E81DFC75E3008A8AF3 /* Background.hxx in Headers */,
|
DCF3A6E81DFC75E3008A8AF3 /* Background.hxx in Headers */,
|
||||||
DCFB9FAC1ECA2609004FD69B /* DelayQueueIteratorImpl.hxx in Headers */,
|
DCFB9FAC1ECA2609004FD69B /* DelayQueueIteratorImpl.hxx in Headers */,
|
||||||
|
DCA078351F8C1B04008EFEE5 /* SDL_lib.hxx in Headers */,
|
||||||
DCDA03B11A2009BB00711920 /* CartWD.hxx in Headers */,
|
DCDA03B11A2009BB00711920 /* CartWD.hxx in Headers */,
|
||||||
2D91745909BA90380026E9FF /* PromptWidget.hxx in Headers */,
|
2D91745909BA90380026E9FF /* PromptWidget.hxx in Headers */,
|
||||||
DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */,
|
DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */,
|
||||||
|
|
Loading…
Reference in New Issue