mirror of https://github.com/stella-emu/stella.git
Optimization: rewrite DelayQueue w/o STL vectors.
This commit is contained in:
parent
145d47315e
commit
744571b1da
|
@ -742,7 +742,7 @@ bool TIADebug::vblank() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
shared_ptr<DelayQueueIterator> TIADebug::delayQueueIterator() const
|
shared_ptr<DelayQueueIterator> TIADebug::delayQueueIterator() const
|
||||||
{
|
{
|
||||||
return shared_ptr<DelayQueueIterator>(new DelayQueueIterator(myTIA.myDelayQueue));
|
return myTIA.delayQueueIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#include "DelayQueue.hxx"
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
DelayQueue::DelayQueue(uInt8 length, uInt8 size)
|
|
||||||
: myIndex(0)
|
|
||||||
{
|
|
||||||
myMembers.reserve(length);
|
|
||||||
|
|
||||||
for (uInt16 i = 0; i < length; i++)
|
|
||||||
myMembers.emplace_back(size);
|
|
||||||
|
|
||||||
memset(myIndices, 0xFF, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void DelayQueue::push(uInt8 address, uInt8 value, uInt8 delay)
|
|
||||||
{
|
|
||||||
uInt8 length = myMembers.size();
|
|
||||||
|
|
||||||
if (delay >= length)
|
|
||||||
throw runtime_error("delay exceeds queue length");
|
|
||||||
|
|
||||||
uInt8 currentIndex = myIndices[address];
|
|
||||||
|
|
||||||
if (currentIndex < 0xFF)
|
|
||||||
myMembers.at(currentIndex).remove(address);
|
|
||||||
|
|
||||||
uInt8 index = (myIndex + delay) % length;
|
|
||||||
myMembers.at(index).push(address, value);
|
|
||||||
|
|
||||||
myIndices[address] = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void DelayQueue::reset()
|
|
||||||
{
|
|
||||||
for (DelayQueueMember& member : myMembers)
|
|
||||||
member.clear();
|
|
||||||
|
|
||||||
memset(myIndices, 0xFF, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool DelayQueue::save(Serializer& out) const
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out.putInt(uInt32(myMembers.size()));
|
|
||||||
for(const DelayQueueMember& m: myMembers)
|
|
||||||
m.save(out);
|
|
||||||
|
|
||||||
out.putByte(myIndex);
|
|
||||||
out.putByteArray(myIndices, 0xFF);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_DelayQueue::save" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool DelayQueue::load(Serializer& in)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
myMembers.resize(in.getInt());
|
|
||||||
for(DelayQueueMember& m: myMembers)
|
|
||||||
m.load(in);
|
|
||||||
|
|
||||||
myIndex = in.getByte();
|
|
||||||
in.getByteArray(myIndices, 0xFF);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_DelayQueue::load" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -22,13 +22,17 @@
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "DelayQueueMember.hxx"
|
#include "DelayQueueMember.hxx"
|
||||||
|
|
||||||
|
template<int length, int capacity>
|
||||||
|
class DelayQueueIteratorImpl;
|
||||||
|
|
||||||
|
template<int length, int capacity>
|
||||||
class DelayQueue : public Serializable
|
class DelayQueue : public Serializable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class DelayQueueIterator;
|
friend DelayQueueIteratorImpl<length, capacity>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DelayQueue(uInt8 length, uInt8 size);
|
DelayQueue();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -46,12 +50,11 @@ class DelayQueue : public Serializable
|
||||||
string name() const override { return "TIA_DelayQueue"; }
|
string name() const override { return "TIA_DelayQueue"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vector<DelayQueueMember> myMembers;
|
DelayQueueMember<capacity> myMembers[length];
|
||||||
uInt8 myIndex;
|
uInt8 myIndex;
|
||||||
uInt8 myIndices[0xFF];
|
uInt8 myIndices[0xFF];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DelayQueue() = delete;
|
|
||||||
DelayQueue(const DelayQueue&) = delete;
|
DelayQueue(const DelayQueue&) = delete;
|
||||||
DelayQueue(DelayQueue&&) = delete;
|
DelayQueue(DelayQueue&&) = delete;
|
||||||
DelayQueue& operator=(const DelayQueue&) = delete;
|
DelayQueue& operator=(const DelayQueue&) = delete;
|
||||||
|
@ -62,18 +65,104 @@ class DelayQueue : public Serializable
|
||||||
// Implementation
|
// Implementation
|
||||||
// ############################################################################
|
// ############################################################################
|
||||||
|
|
||||||
template<class T> void DelayQueue::execute(T executor)
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
DelayQueue<length, capacity>::DelayQueue()
|
||||||
|
: myIndex(0)
|
||||||
{
|
{
|
||||||
DelayQueueMember& currentMember = myMembers.at(myIndex);
|
memset(myIndices, 0xFF, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto&& entry : currentMember) {
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
executor(entry.address, entry.value);
|
template<int length, int capacity>
|
||||||
myIndices[entry.address] = 0xFF;
|
void DelayQueue<length, capacity>::push(uInt8 address, uInt8 value, uInt8 delay)
|
||||||
|
{
|
||||||
|
if (delay >= length)
|
||||||
|
throw runtime_error("delay exceeds queue length");
|
||||||
|
|
||||||
|
uInt8 currentIndex = myIndices[address];
|
||||||
|
|
||||||
|
if (currentIndex < 0xFF)
|
||||||
|
myMembers[currentIndex].remove(address);
|
||||||
|
|
||||||
|
uInt8 index = (myIndex + delay) % length;
|
||||||
|
myMembers[index].push(address, value);
|
||||||
|
|
||||||
|
myIndices[address] = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
void DelayQueue<length, capacity>::reset()
|
||||||
|
{
|
||||||
|
for (uInt8 i = 0; i < length; i++)
|
||||||
|
myMembers[i].clear();
|
||||||
|
|
||||||
|
myIndex = 0;
|
||||||
|
memset(myIndices, 0xFF, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
template<class T>
|
||||||
|
void DelayQueue<length, capacity>::execute(T executor)
|
||||||
|
{
|
||||||
|
DelayQueueMember<capacity>& currentMember = myMembers[myIndex];
|
||||||
|
|
||||||
|
for (uInt8 i = 0; i < currentMember.mySize; i++) {
|
||||||
|
executor(currentMember.myEntries[i].address, currentMember.myEntries[i].value);
|
||||||
|
myIndices[currentMember.myEntries[i].address] = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentMember.clear();
|
currentMember.clear();
|
||||||
|
|
||||||
myIndex = (myIndex + 1) % myMembers.size();
|
myIndex = (myIndex + 1) % length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
bool DelayQueue<length, capacity>::save(Serializer& out) const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out.putInt(length);
|
||||||
|
|
||||||
|
for (uInt8 i = 0; i < length; i++)
|
||||||
|
myMembers[i].save(out);
|
||||||
|
|
||||||
|
out.putByte(myIndex);
|
||||||
|
out.putByteArray(myIndices, 0xFF);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: TIA_DelayQueue::save" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
bool DelayQueue<length, capacity>::load(Serializer& in)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (in.getInt() != length) throw runtime_error("delay queue length mismatch");
|
||||||
|
|
||||||
|
for (uInt8 i = 0; i < length; i++)
|
||||||
|
myMembers[i].load(in);
|
||||||
|
|
||||||
|
myIndex = in.getByte();
|
||||||
|
in.getByteArray(myIndices, 0xFF);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: TIA_DelayQueue::load" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TIA_DELAY_QUEUE
|
#endif // TIA_DELAY_QUEUE
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#include "DelayQueueIterator.hxx"
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
DelayQueueIterator::DelayQueueIterator(const DelayQueue& delayQueue)
|
|
||||||
: myDelayQueue(delayQueue),
|
|
||||||
myDelayCycle(0)
|
|
||||||
{
|
|
||||||
while (isValid()) {
|
|
||||||
const DelayQueueMember& currentMember = myDelayQueue.myMembers.at(currentIndex());
|
|
||||||
myCurrentIterator = currentMember.begin();
|
|
||||||
|
|
||||||
if (myCurrentIterator == currentMember.end())
|
|
||||||
myDelayCycle++;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool DelayQueueIterator::isValid() const
|
|
||||||
{
|
|
||||||
return myDelayCycle < myDelayQueue.myMembers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt8 DelayQueueIterator::delay() const
|
|
||||||
{
|
|
||||||
if (!isValid()) {
|
|
||||||
throw runtime_error("delay called on invalid DelayQueueInterator");
|
|
||||||
}
|
|
||||||
|
|
||||||
return myDelayCycle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt8 DelayQueueIterator::address() const
|
|
||||||
{
|
|
||||||
if (!isValid()) {
|
|
||||||
throw runtime_error("address called on invalid DelayQueueInterator");
|
|
||||||
}
|
|
||||||
|
|
||||||
return myCurrentIterator->address;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt8 DelayQueueIterator::value() const
|
|
||||||
{
|
|
||||||
if (!isValid()) {
|
|
||||||
throw runtime_error("value called on invalid DelayQueueIterator");
|
|
||||||
}
|
|
||||||
|
|
||||||
return myCurrentIterator->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool DelayQueueIterator::next()
|
|
||||||
{
|
|
||||||
if (!isValid()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++myCurrentIterator == myDelayQueue.myMembers.at(currentIndex()).end()) {
|
|
||||||
myDelayCycle++;
|
|
||||||
|
|
||||||
while (isValid()) {
|
|
||||||
const DelayQueueMember& currentMember = myDelayQueue.myMembers.at(currentIndex());
|
|
||||||
myCurrentIterator = currentMember.begin();
|
|
||||||
|
|
||||||
if (myCurrentIterator == currentMember.end())
|
|
||||||
myDelayCycle++;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid();
|
|
||||||
}
|
|
|
@ -25,28 +25,18 @@
|
||||||
class DelayQueueIterator
|
class DelayQueueIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DelayQueueIterator(const DelayQueue&);
|
virtual ~DelayQueueIterator() {}
|
||||||
|
|
||||||
bool isValid() const;
|
public:
|
||||||
|
virtual bool isValid() const = 0;
|
||||||
|
|
||||||
uInt8 delay() const;
|
virtual uInt8 delay() const = 0;
|
||||||
|
|
||||||
uInt8 address() const;
|
virtual uInt8 address() const = 0;
|
||||||
|
|
||||||
uInt8 value() const;
|
virtual uInt8 value() const = 0;
|
||||||
|
|
||||||
bool next();
|
virtual bool next() = 0;
|
||||||
|
|
||||||
private:
|
|
||||||
uInt8 currentIndex() const {
|
|
||||||
return (myDelayQueue.myIndex + myDelayCycle) % myDelayQueue.myMembers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const DelayQueue& myDelayQueue;
|
|
||||||
|
|
||||||
uInt8 myDelayCycle;
|
|
||||||
DelayQueueMember::iterator myCurrentIterator;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TIA_DELAY_QUEUE_ITERATOR
|
#endif // TIA_DELAY_QUEUE_ITERATOR
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef TIA_DELAY_QUEUE_ITERATOR_IMPL
|
||||||
|
#define TIA_DELAY_QUEUE_ITERATOR_IMPL
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
#include "DelayQueue.hxx"
|
||||||
|
#include "DelayQueueMember.hxx"
|
||||||
|
#include "DelayQueueIterator.hxx"
|
||||||
|
|
||||||
|
template<int length, int capacity>
|
||||||
|
class DelayQueueIteratorImpl : public DelayQueueIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DelayQueueIteratorImpl(const DelayQueue<length, capacity>& delayQueue);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool isValid() const override;
|
||||||
|
|
||||||
|
uInt8 delay() const override;
|
||||||
|
|
||||||
|
uInt8 address() const override;
|
||||||
|
|
||||||
|
uInt8 value() const override;
|
||||||
|
|
||||||
|
bool next() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uInt8 currentIndex() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const DelayQueue<length, capacity>& myDelayQueue;
|
||||||
|
uInt8 myDelayCycle;
|
||||||
|
uInt8 myIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ############################################################################
|
||||||
|
// Implementation
|
||||||
|
// ############################################################################
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
DelayQueueIteratorImpl<length,capacity>::DelayQueueIteratorImpl(
|
||||||
|
const DelayQueue<length, capacity>& delayQueue
|
||||||
|
)
|
||||||
|
: myDelayQueue(delayQueue),
|
||||||
|
myDelayCycle(0),
|
||||||
|
myIndex(0)
|
||||||
|
{
|
||||||
|
while (myDelayQueue.myMembers[currentIndex()].mySize == 0 && isValid())
|
||||||
|
myDelayCycle++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
bool DelayQueueIteratorImpl<length, capacity>::isValid() const
|
||||||
|
{
|
||||||
|
return myDelayCycle < length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
uInt8 DelayQueueIteratorImpl<length, capacity>::delay() const
|
||||||
|
{
|
||||||
|
if (!isValid()) {
|
||||||
|
throw runtime_error("delay called on invalid DelayQueueInterator");
|
||||||
|
}
|
||||||
|
|
||||||
|
return myDelayCycle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
uInt8 DelayQueueIteratorImpl<length, capacity>::address() const
|
||||||
|
{
|
||||||
|
if (!isValid()) {
|
||||||
|
throw runtime_error("address called on invalid DelayQueueInterator");
|
||||||
|
}
|
||||||
|
|
||||||
|
return myDelayQueue.myMembers[currentIndex()].myEntries[myIndex].address;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
uInt8 DelayQueueIteratorImpl<length, capacity>::value() const
|
||||||
|
{
|
||||||
|
if (!isValid()) {
|
||||||
|
throw runtime_error("value called on invalid DelayQueueInterator");
|
||||||
|
}
|
||||||
|
|
||||||
|
return myDelayQueue.myMembers[currentIndex()].myEntries[myIndex].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
bool DelayQueueIteratorImpl<length, capacity>::next()
|
||||||
|
{
|
||||||
|
if (!isValid()) return false;
|
||||||
|
|
||||||
|
if (++myIndex < myDelayQueue.myMembers[currentIndex()].mySize)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
myIndex = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
myDelayCycle++;
|
||||||
|
} while (myDelayQueue.myMembers[currentIndex()].mySize == 0 && isValid());
|
||||||
|
|
||||||
|
return isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int length, int capacity>
|
||||||
|
uInt8 DelayQueueIteratorImpl<length, capacity>::currentIndex() const
|
||||||
|
{
|
||||||
|
return (myDelayQueue.myIndex + myDelayCycle) % length;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TIA_DELAY_QUEUE_ITERATOR_IMPL
|
|
@ -1,93 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#include "DelayQueueMember.hxx"
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
DelayQueueMember::DelayQueueMember(uInt8 size)
|
|
||||||
: myEntries(size),
|
|
||||||
mySize(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void DelayQueueMember::push(uInt8 address, uInt8 value)
|
|
||||||
{
|
|
||||||
Entry& entry = myEntries.at(mySize++);
|
|
||||||
|
|
||||||
entry.address = address;
|
|
||||||
entry.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void DelayQueueMember::remove(uInt8 address)
|
|
||||||
{
|
|
||||||
size_t index;
|
|
||||||
|
|
||||||
for (index = 0; index < mySize; index++)
|
|
||||||
if (myEntries.at(index).address == address)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (index < mySize) {
|
|
||||||
myEntries.at(index) = myEntries.at(mySize - 1);
|
|
||||||
mySize--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool DelayQueueMember::save(Serializer& out) const
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out.putInt(mySize);
|
|
||||||
for(uInt32 i = 0; i < mySize; ++i)
|
|
||||||
{
|
|
||||||
const Entry& e = myEntries[i];
|
|
||||||
out.putByte(e.address);
|
|
||||||
out.putByte(e.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_DelayQueueMember::save" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool DelayQueueMember::load(Serializer& in)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
mySize = in.getInt();
|
|
||||||
for(uInt32 i = 0; i < mySize; ++i)
|
|
||||||
{
|
|
||||||
Entry& e = myEntries[i];
|
|
||||||
e.address = in.getByte();
|
|
||||||
e.value = in.getByte();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_DelayQueueMember::load" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -21,8 +21,9 @@
|
||||||
#include "Serializable.hxx"
|
#include "Serializable.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
class DelayQueueMember : public Serializable
|
template<int capacity>
|
||||||
{
|
class DelayQueueMember : public Serializable {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Entry {
|
struct Entry {
|
||||||
uInt8 address;
|
uInt8 address;
|
||||||
|
@ -30,47 +31,137 @@ class DelayQueueMember : public Serializable
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DelayQueueMember(uInt8 size = 0);
|
DelayQueueMember();
|
||||||
|
|
||||||
DelayQueueMember(DelayQueueMember&&) = default;
|
|
||||||
DelayQueueMember& operator=(DelayQueueMember&&) = default;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef vector<Entry>::const_iterator iterator;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
void push(uInt8 address, uInt8 value);
|
void push(uInt8 address, uInt8 value);
|
||||||
|
|
||||||
void remove(uInt8 address);
|
void remove(uInt8 address);
|
||||||
|
|
||||||
iterator begin() const {
|
void clear();
|
||||||
return myEntries.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator end() const {
|
|
||||||
return (mySize < myEntries.size()) ? (myEntries.begin() + mySize) : myEntries.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
mySize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Serializable methods (see that class for more information).
|
Serializable methods (see that class for more information).
|
||||||
*/
|
*/
|
||||||
bool save(Serializer& out) const override;
|
bool save(Serializer& out) const override;
|
||||||
bool load(Serializer& in) override;
|
bool load(Serializer& in) override;
|
||||||
string name() const override { return "TIA_DelayQueueMember"; }
|
string name() const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Entry myEntries[capacity];
|
||||||
|
uInt8 mySize;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vector<Entry> myEntries;
|
|
||||||
uInt32 mySize;
|
|
||||||
|
|
||||||
private:
|
DelayQueueMember(const DelayQueueMember<capacity>&) = delete;
|
||||||
DelayQueueMember(const DelayQueueMember&) = delete;
|
DelayQueueMember(DelayQueueMember<capacity>&&) = delete;
|
||||||
DelayQueueMember& operator=(const DelayQueueMember&) = delete;
|
DelayQueueMember<capacity>& operator=(const DelayQueueMember<capacity>&) = delete;
|
||||||
|
DelayQueueMember<capacity>& operator=(DelayQueueMember<capacity>&&) = delete;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TIA_DELAY_QUEUE_MEMBER
|
// ############################################################################
|
||||||
|
// Implementation
|
||||||
|
// ############################################################################
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int capacity>
|
||||||
|
DelayQueueMember<capacity>::DelayQueueMember()
|
||||||
|
: mySize(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int capacity>
|
||||||
|
void DelayQueueMember<capacity>::push(uInt8 address, uInt8 value)
|
||||||
|
{
|
||||||
|
if (mySize == capacity) throw runtime_error("delay queue overflow");
|
||||||
|
|
||||||
|
myEntries[mySize].address = address;
|
||||||
|
myEntries[mySize++].value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int capacity>
|
||||||
|
void DelayQueueMember<capacity>::remove(uInt8 address)
|
||||||
|
{
|
||||||
|
uInt8 index;
|
||||||
|
|
||||||
|
for (index = 0; index < mySize; index++) {
|
||||||
|
if (myEntries[index].address == address) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index < mySize) {
|
||||||
|
for (uInt8 i = index + 1; i < mySize; i++) {
|
||||||
|
myEntries[i-1] = myEntries[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
mySize--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int capacity>
|
||||||
|
void DelayQueueMember<capacity>::clear()
|
||||||
|
{
|
||||||
|
mySize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int capacity>
|
||||||
|
bool DelayQueueMember<capacity>::save(Serializer& out) const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out.putInt(mySize);
|
||||||
|
for(uInt8 i = 0; i < mySize; ++i)
|
||||||
|
{
|
||||||
|
const Entry& e = myEntries[i];
|
||||||
|
out.putByte(e.address);
|
||||||
|
out.putByte(e.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: TIA_DelayQueueMember::save" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int capacity>
|
||||||
|
bool DelayQueueMember<capacity>::load(Serializer& in)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mySize = in.getInt();
|
||||||
|
if (mySize > capacity) throw new runtime_error("invalid delay queue size");
|
||||||
|
for(uInt32 i = 0; i < mySize; ++i)
|
||||||
|
{
|
||||||
|
Entry& e = myEntries[i];
|
||||||
|
e.address = in.getByte();
|
||||||
|
e.value = in.getByte();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: TIA_DelayQueueMember::load" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
template<int capacity>
|
||||||
|
string DelayQueueMember<capacity>::name() const
|
||||||
|
{
|
||||||
|
stringstream ss;
|
||||||
|
|
||||||
|
ss << "TIA_DelayQueueMember<" << capacity << ">";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TIA_DELAY_QUEUE_MEMBER
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Console.hxx"
|
#include "Console.hxx"
|
||||||
#include "Control.hxx"
|
#include "Control.hxx"
|
||||||
#include "Paddles.hxx"
|
#include "Paddles.hxx"
|
||||||
|
#include "DelayQueueIteratorImpl.hxx"
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartDebug.hxx"
|
#include "CartDebug.hxx"
|
||||||
|
@ -66,7 +67,6 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
: myConsole(console),
|
: myConsole(console),
|
||||||
mySound(sound),
|
mySound(sound),
|
||||||
mySettings(settings),
|
mySettings(settings),
|
||||||
myDelayQueue(10, 20),
|
|
||||||
myPlayfield(~CollisionMask::playfield & 0x7FFF),
|
myPlayfield(~CollisionMask::playfield & 0x7FFF),
|
||||||
myMissile0(~CollisionMask::missile0 & 0x7FFF),
|
myMissile0(~CollisionMask::missile0 & 0x7FFF),
|
||||||
myMissile1(~CollisionMask::missile1 & 0x7FFF),
|
myMissile1(~CollisionMask::missile1 & 0x7FFF),
|
||||||
|
@ -935,6 +935,14 @@ bool TIA::toggleJitter(uInt8 mode)
|
||||||
return myFrameManager.jitterEnabled();
|
return myFrameManager.jitterEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
shared_ptr<DelayQueueIterator> TIA::delayQueueIterator() const
|
||||||
|
{
|
||||||
|
return shared_ptr<DelayQueueIterator>(
|
||||||
|
new DelayQueueIteratorImpl<delayQueueLength, delayQueueSize>(myDelayQueue)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
TIA& TIA::updateScanline()
|
TIA& TIA::updateScanline()
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "Serializer.hxx"
|
#include "Serializer.hxx"
|
||||||
#include "TIATypes.hxx"
|
#include "TIATypes.hxx"
|
||||||
#include "DelayQueue.hxx"
|
#include "DelayQueue.hxx"
|
||||||
|
#include "DelayQueueIterator.hxx"
|
||||||
#include "FrameManager.hxx"
|
#include "FrameManager.hxx"
|
||||||
#include "FrameLayout.hxx"
|
#include "FrameLayout.hxx"
|
||||||
#include "Background.hxx"
|
#include "Background.hxx"
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
#include "Ball.hxx"
|
#include "Ball.hxx"
|
||||||
#include "LatchedInput.hxx"
|
#include "LatchedInput.hxx"
|
||||||
#include "PaddleReader.hxx"
|
#include "PaddleReader.hxx"
|
||||||
|
#include "DelayQueueIterator.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class is a device that emulates the Television Interface Adaptor
|
This class is a device that emulates the Television Interface Adaptor
|
||||||
|
@ -341,6 +343,11 @@ class TIA : public Device
|
||||||
*/
|
*/
|
||||||
void flushLineCache();
|
void flushLineCache();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a new delayQueueIterator for the debugger.
|
||||||
|
*/
|
||||||
|
shared_ptr<DelayQueueIterator> delayQueueIterator() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Save the current state of this device to the given Serializer.
|
Save the current state of this device to the given Serializer.
|
||||||
|
|
||||||
|
@ -442,7 +449,10 @@ class TIA : public Device
|
||||||
Sound& mySound;
|
Sound& mySound;
|
||||||
Settings& mySettings;
|
Settings& mySettings;
|
||||||
|
|
||||||
DelayQueue myDelayQueue;
|
static constexpr int delayQueueLength = 10;
|
||||||
|
static constexpr int delayQueueSize = 20;
|
||||||
|
DelayQueue<delayQueueLength, delayQueueSize> myDelayQueue;
|
||||||
|
|
||||||
FrameManager myFrameManager;
|
FrameManager myFrameManager;
|
||||||
|
|
||||||
Background myBackground;
|
Background myBackground;
|
||||||
|
|
|
@ -2,8 +2,6 @@ MODULE := src/emucore/tia
|
||||||
|
|
||||||
MODULE_OBJS := \
|
MODULE_OBJS := \
|
||||||
src/emucore/tia/TIA.o \
|
src/emucore/tia/TIA.o \
|
||||||
src/emucore/tia/DelayQueueMember.o \
|
|
||||||
src/emucore/tia/DelayQueue.o \
|
|
||||||
src/emucore/tia/FrameManager.o \
|
src/emucore/tia/FrameManager.o \
|
||||||
src/emucore/tia/Playfield.o \
|
src/emucore/tia/Playfield.o \
|
||||||
src/emucore/tia/DrawCounterDecodes.o \
|
src/emucore/tia/DrawCounterDecodes.o \
|
||||||
|
@ -13,8 +11,7 @@ MODULE_OBJS := \
|
||||||
src/emucore/tia/Background.o \
|
src/emucore/tia/Background.o \
|
||||||
src/emucore/tia/LatchedInput.o \
|
src/emucore/tia/LatchedInput.o \
|
||||||
src/emucore/tia/PaddleReader.o \
|
src/emucore/tia/PaddleReader.o \
|
||||||
src/emucore/tia/VblankManager.o \
|
src/emucore/tia/VblankManager.o
|
||||||
src/emucore/tia/DelayQueueIterator.o
|
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
src/emucore/tia
|
src/emucore/tia
|
||||||
|
|
Loading…
Reference in New Issue