This commit is contained in:
Christian Speckner 2016-11-13 22:56:58 +01:00
parent ea6abb0fe6
commit b6a2e266aa
4 changed files with 392 additions and 392 deletions

View File

@ -21,40 +21,40 @@
namespace TIA6502tsCore {
DelayQueue::DelayQueue(uInt8 length, uInt8 size)
: myIndex(0)
{
myMembers.reserve(length);
DelayQueue::DelayQueue(uInt8 length, uInt8 size)
: myIndex(0)
{
myMembers.reserve(length);
for (uInt16 i = 0; i < length; i++)
myMembers.emplace_back(size);
for (uInt16 i = 0; i < length; i++)
myMembers.emplace_back(size);
for (uInt8& i : myIndices)
i = 0xFF;
}
for (uInt8& i : myIndices)
i = 0xFF;
}
void DelayQueue::push(uInt8 address, uInt8 value, uInt8 delay)
{
uInt8 length = myMembers.size();
void DelayQueue::push(uInt8 address, uInt8 value, uInt8 delay)
{
uInt8 length = myMembers.size();
if (delay >= length)
throw new runtime_error("delay exceeds queue length");
if (delay >= length)
throw new runtime_error("delay exceeds queue length");
uInt8 currentIndex = myIndices[address];
uInt8 currentIndex = myIndices[address];
if (currentIndex < 0xFF)
myMembers.at(currentIndex).remove(address);
if (currentIndex < 0xFF)
myMembers.at(currentIndex).remove(address);
uInt8 index = (myIndex + delay) % length;
myMembers.at(index).push(address, value);
uInt8 index = (myIndex + delay) % length;
myMembers.at(index).push(address, value);
myIndices[address] = index;
}
myIndices[address] = index;
}
void DelayQueue::reset()
{
for (DelayQueueMember& member : myMembers)
member.clear();
}
void DelayQueue::reset()
{
for (DelayQueueMember& member : myMembers)
member.clear();
}
} // namespace TIA6502tsCore

View File

@ -21,46 +21,46 @@
namespace TIA6502tsCore {
DelayQueueMember::DelayQueueMember(uInt8 capacity)
: myEntries(capacity),
mySize(0)
{}
DelayQueueMember::DelayQueueMember(uInt8 capacity)
: myEntries(capacity),
mySize(0)
{}
void DelayQueueMember::push(uInt8 address, uInt8 value)
{
Entry& entry = myEntries.at(mySize++);
void DelayQueueMember::push(uInt8 address, uInt8 value)
{
Entry& entry = myEntries.at(mySize++);
entry.address = address;
entry.value = value;
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;
}
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--;
}
if (index < mySize) {
myEntries.at(index) = myEntries.at(mySize - 1);
mySize--;
}
}
vector<DelayQueueMember::Entry>::const_iterator DelayQueueMember::begin() const
{
return myEntries.begin();
}
vector<DelayQueueMember::Entry>::const_iterator DelayQueueMember::begin() const
{
return myEntries.begin();
}
vector<DelayQueueMember::Entry>::const_iterator DelayQueueMember::end() const
{
return myEntries.end();
}
vector<DelayQueueMember::Entry>::const_iterator DelayQueueMember::end() const
{
return myEntries.end();
}
void DelayQueueMember::clear()
{
mySize = 0;
}
void DelayQueueMember::clear()
{
mySize = 0;
}
} // namespace TIA6502tsCore

View File

@ -39,182 +39,182 @@ static constexpr uInt32
namespace TIA6502tsCore {
FrameManager::FrameManager()
{
reset();
}
FrameManager::FrameManager()
{
reset();
}
void FrameManager::setOnFrameCompleteHandler(FrameManager::frameCompletionHandler handler)
{
myOnFrameComplete = handler;
}
void FrameManager::setOnFrameCompleteHandler(FrameManager::frameCompletionHandler handler)
{
myOnFrameComplete = handler;
}
void FrameManager::reset()
{
setTvMode(TvMode::ntsc);
setState(State::waitForVsyncStart);
void FrameManager::reset()
{
setTvMode(TvMode::ntsc);
setState(State::waitForVsyncStart);
myLineInState = 0;
myLinesWithoutVsync = 0;
myWaitForVsync = true;
myVsync = false;
myVblank = false;
}
myLineInState = 0;
myLinesWithoutVsync = 0;
myWaitForVsync = true;
myVsync = false;
myVblank = false;
}
void FrameManager::nextLine()
{
myCurrentFrameTotalLines++;
myLineInState++;
void FrameManager::nextLine()
{
myCurrentFrameTotalLines++;
myLineInState++;
switch (myState) {
case State::waitForVsyncStart:
case State::waitForVsyncEnd:
if (myLinesWithoutVsync > myMaxLinesWithoutVsync) {
myWaitForVsync = false;
setState(State::waitForFrameStart);
switch (myState) {
case State::waitForVsyncStart:
case State::waitForVsyncEnd:
if (myLinesWithoutVsync > myMaxLinesWithoutVsync) {
myWaitForVsync = false;
setState(State::waitForFrameStart);
}
break;
case State::waitForFrameStart:
if (myWaitForVsync) {
if (myLineInState >= (myVblank ? myVblankLines : myVblankLines - Metrics::maxUnderscan))
setState(State::frame);
} else {
if (!myVblank) {
setState(State::frame);
}
}
break;
break;
case State::waitForFrameStart:
if (myWaitForVsync) {
if (myLineInState >= (myVblank ? myVblankLines : myVblankLines - Metrics::maxUnderscan))
setState(State::frame);
} else {
if (!myVblank) {
setState(State::frame);
}
}
case State::frame:
if (myLineInState >= myFrameLines + Metrics::visibleOverscan) {
finalizeFrame();
}
break;
break;
case State::frame:
if (myLineInState >= myFrameLines + Metrics::visibleOverscan) {
finalizeFrame();
}
case State::overscan:
if (myLineInState >= myOverscanLines - Metrics::visibleOverscan) {
setState(myWaitForVsync ? State::waitForVsyncStart : State::waitForFrameStart);
}
break;
break;
case State::overscan:
if (myLineInState >= myOverscanLines - Metrics::visibleOverscan) {
setState(myWaitForVsync ? State::waitForVsyncStart : State::waitForFrameStart);
}
default:
throw runtime_error("frame manager: invalid state");
}
}
break;
void FrameManager::setVblank(bool vblank)
{
myVblank = vblank;
}
default:
throw runtime_error("frame manager: invalid state");
}
void FrameManager::setVsync(bool vsync)
{
if (!myWaitForVsync || vsync == myVsync) return;
myVsync = vsync;
switch (myState) {
case State::waitForVsyncStart:
case State::waitForFrameStart:
case State::overscan:
if (myVsync) setState(State::waitForVsyncEnd);
break;
case State::waitForVsyncEnd:
if (!myVsync) {
setState(State::waitForFrameStart);
myLinesWithoutVsync = 0;
}
break;
case State::frame:
if (myVsync) finalizeFrame();
break;
default:
throw runtime_error("frame manager: invalid state");
}
}
bool FrameManager::isRendering() const {
return myState == State::frame;
}
FrameManager::TvMode FrameManager::tvMode() const {
return myMode;
}
bool FrameManager::vblank() const {
return myVblank;
}
uInt32 FrameManager::height() const {
return myKernelLines + Metrics::visibleOverscan;
}
uInt32 FrameManager::currentLine() const {
return myState == State::frame ? myLineInState : 0;
}
void FrameManager::setTvMode(FrameManager::TvMode mode)
{
if (mode == myMode) return;
myMode = mode;
switch (myMode) {
case TvMode::ntsc:
myVblankLines = Metrics::vblankNTSC;
myKernelLines = Metrics::kernelNTSC;
myOverscanLines = Metrics::overscanNTSC;
break;
case TvMode::pal:
myVblankLines = Metrics::vblankPAL;
myKernelLines = Metrics::kernelPAL;
myOverscanLines = Metrics::overscanPAL;
break;
default:
throw runtime_error("frame manager: invalid TV mode");
}
void FrameManager::setVblank(bool vblank)
{
myVblank = vblank;
myFrameLines = Metrics::vsync + myVblankLines + myKernelLines + myOverscanLines;
myMaxLinesWithoutVsync = myFrameLines * Metrics::maxFramesWithoutVsync;
}
void FrameManager::setState(FrameManager::State state)
{
myState = state;
myLineInState = 0;
}
void FrameManager::finalizeFrame()
{
const uInt32
deltaNTSC = abs(Int32(myCurrentFrameTotalLines) - Int32(frameLinesNTSC)),
deltaPAL = abs(Int32(myCurrentFrameTotalLines) - Int32(frameLinesPAL));
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance) {
setTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
}
void FrameManager::setVsync(bool vsync)
{
if (!myWaitForVsync || vsync == myVsync) return;
myVsync = vsync;
switch (myState) {
case State::waitForVsyncStart:
case State::waitForFrameStart:
case State::overscan:
if (myVsync) setState(State::waitForVsyncEnd);
break;
case State::waitForVsyncEnd:
if (!myVsync) {
setState(State::waitForFrameStart);
myLinesWithoutVsync = 0;
}
break;
case State::frame:
if (myVsync) finalizeFrame();
break;
default:
throw runtime_error("frame manager: invalid state");
}
if (myOnFrameComplete) {
myOnFrameComplete();
}
bool FrameManager::isRendering() const {
return myState == State::frame;
}
FrameManager::TvMode FrameManager::tvMode() const {
return myMode;
}
bool FrameManager::vblank() const {
return myVblank;
}
uInt32 FrameManager::height() const {
return myKernelLines + Metrics::visibleOverscan;
}
uInt32 FrameManager::currentLine() const {
return myState == State::frame ? myLineInState : 0;
}
void FrameManager::setTvMode(FrameManager::TvMode mode)
{
if (mode == myMode) return;
myMode = mode;
switch (myMode) {
case TvMode::ntsc:
myVblankLines = Metrics::vblankNTSC;
myKernelLines = Metrics::kernelNTSC;
myOverscanLines = Metrics::overscanNTSC;
break;
case TvMode::pal:
myVblankLines = Metrics::vblankPAL;
myKernelLines = Metrics::kernelPAL;
myOverscanLines = Metrics::overscanPAL;
break;
default:
throw runtime_error("frame manager: invalid TV mode");
}
myFrameLines = Metrics::vsync + myVblankLines + myKernelLines + myOverscanLines;
myMaxLinesWithoutVsync = myFrameLines * Metrics::maxFramesWithoutVsync;
}
void FrameManager::setState(FrameManager::State state)
{
myState = state;
myLineInState = 0;
}
void FrameManager::finalizeFrame()
{
const uInt32
deltaNTSC = abs(Int32(myCurrentFrameTotalLines) - Int32(frameLinesNTSC)),
deltaPAL = abs(Int32(myCurrentFrameTotalLines) - Int32(frameLinesPAL));
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance) {
setTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
}
if (myOnFrameComplete) {
myOnFrameComplete();
}
myCurrentFrameTotalLines = 0;
setState(State::overscan);
}
myCurrentFrameTotalLines = 0;
setState(State::overscan);
}
} // namespace TIA6502tsCore

View File

@ -22,216 +22,216 @@
namespace TIA6502tsCore {
// TODO: stub
TIA::TIA(Console& console, Sound& sound, Settings& settings)
: myConsole(console),
mySound(sound),
mySettings(settings),
myDelayQueue(10, 20)
{
myFrameManager.setOnFrameCompleteHandler(
[this] () {onFrameComplete();}
);
// TODO: stub
TIA::TIA(Console& console, Sound& sound, Settings& settings)
: myConsole(console),
mySound(sound),
mySettings(settings),
myDelayQueue(10, 20)
{
myFrameManager.setOnFrameCompleteHandler(
[this] () {onFrameComplete();}
);
reset();
}
reset();
}
// TODO: stub
void TIA::reset()
{
myDelayQueue.reset();
}
// TODO: stub
void TIA::reset()
{
myDelayQueue.reset();
}
// TODO: stub
void TIA::systemCyclesReset()
{}
// TODO: stub
void TIA::systemCyclesReset()
{}
// TODO: stub
void TIA::install(System& system)
{}
// TODO: stub
void TIA::install(System& system)
{}
// TODO: stub
bool TIA::save(Serializer& out) const
{
return true;
}
// TODO: stub
bool TIA::save(Serializer& out) const
{
return true;
}
// TODO: stub
bool TIA::load(Serializer& in)
{
return true;
}
// TODO: stub
bool TIA::load(Serializer& in)
{
return true;
}
// TODO: stub
uInt8 TIA::peek(uInt16 address)
{
return 0;
}
// TODO: stub
uInt8 TIA::peek(uInt16 address)
{
return 0;
}
// TODO: stub
bool TIA::poke(uInt16 address, uInt8 value)
{
return false;
}
// TODO: stub
bool TIA::poke(uInt16 address, uInt8 value)
{
return false;
}
// TODO: stub
void TIA::installDelegate(System& system, Device& device)
{}
// TODO: stub
void TIA::installDelegate(System& system, Device& device)
{}
// TODO: stub
void TIA::frameReset()
{}
// TODO: stub
void TIA::frameReset()
{}
// TODO: stub
bool TIA::saveDisplay(Serializer& out) const
{
return true;
}
// TODO: stub
bool TIA::saveDisplay(Serializer& out) const
{
return true;
}
// TODO: stub
bool TIA::loadDisplay(Serializer& in)
{
return true;
}
// TODO: stub
bool TIA::loadDisplay(Serializer& in)
{
return true;
}
// TODO: stub
void TIA::update()
{}
// TODO: stub
void TIA::update()
{}
// TODO: stub
uInt8* TIA::currentFrameBuffer() const
{
return 0;
}
// TODO: stub
uInt8* TIA::currentFrameBuffer() const
{
return 0;
}
// TODO: stub
uInt8* TIA::previousFrameBuffer() const
{
return 0;
}
// TODO: stub
uInt8* TIA::previousFrameBuffer() const
{
return 0;
}
// TODO: stub
uInt32 TIA::height() const
{
return 0;
}
// TODO: stub
uInt32 TIA::height() const
{
return 0;
}
// TODO: stub
uInt32 TIA::ystart() const
{
return 0;
}
// TODO: stub
uInt32 TIA::ystart() const
{
return 0;
}
// TODO: stub
void TIA::setHeight(uInt32 height)
{}
// TODO: stub
void TIA::setHeight(uInt32 height)
{}
// TODO: stub
void TIA::setYStart(uInt32 ystart)
{}
// TODO: stub
void TIA::setYStart(uInt32 ystart)
{}
// TODO: stub
void TIA::enableAutoFrame(bool enabled)
{}
// TODO: stub
void TIA::enableAutoFrame(bool enabled)
{}
// TODO: stub
void TIA::enableColorLoss(bool enabled)
{}
// TODO: stub
void TIA::enableColorLoss(bool enabled)
{}
// TODO: stub
bool TIA::isPAL() const
{
return false;
}
// TODO: stub
bool TIA::isPAL() const
{
return false;
}
// TODO: stub
uInt32 TIA::clocksThisLine() const
{
return 0;
}
// TODO: stub
uInt32 TIA::clocksThisLine() const
{
return 0;
}
// TODO: stub
uInt32 TIA::scanlines() const
{
return 0;
}
// TODO: stub
uInt32 TIA::scanlines() const
{
return 0;
}
// TODO: stub
bool TIA::partialFrame() const
{
return false;
}
// TODO: stub
bool TIA::partialFrame() const
{
return false;
}
// TODO: stub
uInt32 TIA::startScanline() const
{
return 0;
}
// TODO: stub
uInt32 TIA::startScanline() const
{
return 0;
}
// TODO: stub
bool TIA::scanlinePos(uInt16& x, uInt16& y) const
{
return 0;
}
// TODO: stub
bool TIA::scanlinePos(uInt16& x, uInt16& y) const
{
return 0;
}
// TODO: stub
bool TIA::toggleBit(TIABit b, uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::toggleBit(TIABit b, uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::toggleBits()
{
return false;
}
// TODO: stub
bool TIA::toggleBits()
{
return false;
}
// TODO: stub
bool TIA::toggleCollision(TIABit b, uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::toggleCollision(TIABit b, uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::toggleCollisions()
{
return false;
}
// TODO: stub
bool TIA::toggleCollisions()
{
return false;
}
// TODO: stub
bool TIA::toggleHMOVEBlank()
{
return false;
}
// TODO: stub
bool TIA::toggleHMOVEBlank()
{
return false;
}
// TODO: stub
bool TIA::toggleFixedColors(uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::toggleFixedColors(uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::driveUnusedPinsRandom(uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::driveUnusedPinsRandom(uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::toggleJitter(uInt8 mode)
{
return false;
}
// TODO: stub
bool TIA::toggleJitter(uInt8 mode)
{
return false;
}
// TODO: stub
void TIA::setJitterRecoveryFactor(Int32 f)
{}
// TODO: stub
void TIA::setJitterRecoveryFactor(Int32 f)
{}
// TODO: stub
void TIA::onFrameComplete()
{}
// TODO: stub
void TIA::onFrameComplete()
{}
// TODO: stub
void TIA::delayedWrite(uInt8 address, uInt8 value)
{}
// TODO: stub
void TIA::delayedWrite(uInt8 address, uInt8 value)
{}
} // namespace TIA6502tsCore