mirror of https://github.com/stella-emu/stella.git
Add wsync, vsync and vblank, fix bugs and connect the dots -> main loop + tv mode detection work.
This commit is contained in:
parent
70dc29f077
commit
6d76d65d82
|
@ -55,7 +55,7 @@ vector<DelayQueueMember::Entry>::const_iterator DelayQueueMember::begin() const
|
|||
|
||||
vector<DelayQueueMember::Entry>::const_iterator DelayQueueMember::end() const
|
||||
{
|
||||
return myEntries.end();
|
||||
return (mySize < myEntries.size() - 1) ? (myEntries.begin() + mySize) : myEntries.end();
|
||||
}
|
||||
|
||||
void DelayQueueMember::clear()
|
||||
|
|
|
@ -44,16 +44,21 @@ FrameManager::FrameManager()
|
|||
reset();
|
||||
}
|
||||
|
||||
void FrameManager::setOnFrameCompleteHandler(FrameManager::frameCompletionHandler handler)
|
||||
{
|
||||
myOnFrameComplete = handler;
|
||||
void FrameManager::setHandlers(
|
||||
FrameManager::callback frameStartCallback,
|
||||
FrameManager::callback frameCompleteCallback
|
||||
) {
|
||||
myOnFrameStart = frameStartCallback;
|
||||
myOnFrameComplete = frameCompleteCallback;
|
||||
}
|
||||
|
||||
void FrameManager::reset()
|
||||
{
|
||||
myMode = TvMode::pal;
|
||||
setTvMode(TvMode::ntsc);
|
||||
setState(State::waitForVsyncStart);
|
||||
|
||||
myState = State::waitForVsyncStart;
|
||||
myCurrentFrameTotalLines = 0;
|
||||
myLineInState = 0;
|
||||
myLinesWithoutVsync = 0;
|
||||
myWaitForVsync = true;
|
||||
|
@ -89,7 +94,7 @@ void FrameManager::nextLine()
|
|||
break;
|
||||
|
||||
case State::frame:
|
||||
if (myLineInState >= myFrameLines + Metrics::visibleOverscan) {
|
||||
if (myLineInState >= myKernelLines + Metrics::visibleOverscan) {
|
||||
finalizeFrame();
|
||||
}
|
||||
|
||||
|
@ -105,6 +110,8 @@ void FrameManager::nextLine()
|
|||
default:
|
||||
throw runtime_error("frame manager: invalid state");
|
||||
}
|
||||
|
||||
if (myWaitForVsync) myLinesWithoutVsync++;
|
||||
}
|
||||
|
||||
void FrameManager::setVblank(bool vblank)
|
||||
|
@ -195,8 +202,12 @@ void FrameManager::setTvMode(FrameManager::TvMode mode)
|
|||
|
||||
void FrameManager::setState(FrameManager::State state)
|
||||
{
|
||||
if (myState == state) return;
|
||||
|
||||
myState = state;
|
||||
myLineInState = 0;
|
||||
|
||||
if (myState == State::frame && myOnFrameStart) myOnFrameStart();
|
||||
}
|
||||
|
||||
void FrameManager::finalizeFrame()
|
||||
|
|
|
@ -33,7 +33,7 @@ class FrameManager {
|
|||
pal, ntsc
|
||||
};
|
||||
|
||||
typedef std::function<void()> frameCompletionHandler;
|
||||
typedef std::function<void()> callback;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -41,7 +41,7 @@ class FrameManager {
|
|||
|
||||
public:
|
||||
|
||||
void setOnFrameCompleteHandler(frameCompletionHandler);
|
||||
void setHandlers(callback frameStartCallback, callback frameCompletionCallback);
|
||||
|
||||
void reset();
|
||||
|
||||
|
@ -81,7 +81,8 @@ class FrameManager {
|
|||
|
||||
private:
|
||||
|
||||
frameCompletionHandler myOnFrameComplete;
|
||||
callback myOnFrameStart;
|
||||
callback myOnFrameComplete;
|
||||
|
||||
TvMode myMode;
|
||||
State myState;
|
||||
|
|
|
@ -29,7 +29,8 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
|||
mySettings(settings),
|
||||
myDelayQueue(10, 20)
|
||||
{
|
||||
myFrameManager.setOnFrameCompleteHandler(
|
||||
myFrameManager.setHandlers(
|
||||
[this] () {onFrameStart();},
|
||||
[this] () {onFrameComplete();}
|
||||
);
|
||||
|
||||
|
@ -62,7 +63,7 @@ void TIA::reset()
|
|||
|
||||
void TIA::systemCyclesReset()
|
||||
{
|
||||
uInt32 cycles = mySystem->cycles();
|
||||
const uInt32 cycles = mySystem->cycles();
|
||||
|
||||
myLastCycle -= cycles;
|
||||
mySound.adjustCycleCounter(-cycles);
|
||||
|
@ -100,16 +101,32 @@ bool TIA::load(Serializer& in)
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO: stub
|
||||
uInt8 TIA::peek(uInt16 address)
|
||||
{
|
||||
updateEmulation();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: stub
|
||||
bool TIA::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
return false;
|
||||
updateEmulation();
|
||||
|
||||
switch (address & 0x3F) {
|
||||
case WSYNC:
|
||||
mySystem->incrementCycles((227 - myHctr) / 3);
|
||||
break;
|
||||
|
||||
case VSYNC:
|
||||
myFrameManager.setVsync(value & 0x02);
|
||||
break;
|
||||
|
||||
case VBLANK:
|
||||
myFrameManager.setVblank(value & 0x02);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: stub
|
||||
|
@ -130,7 +147,9 @@ bool TIA::loadDisplay(Serializer& in)
|
|||
|
||||
// TODO: stub
|
||||
void TIA::update()
|
||||
{}
|
||||
{
|
||||
mySystem->m6502().execute(25000);
|
||||
}
|
||||
|
||||
uInt8* TIA::currentFrameBuffer() const
|
||||
{
|
||||
|
@ -256,6 +275,14 @@ bool TIA::toggleJitter(uInt8 mode)
|
|||
void TIA::setJitterRecoveryFactor(Int32 f)
|
||||
{}
|
||||
|
||||
void TIA::updateEmulation() {
|
||||
const uInt32 cycles = mySystem->cycles();
|
||||
|
||||
cycle(3 * (cycles - myLastCycle));
|
||||
|
||||
myLastCycle = cycles;
|
||||
}
|
||||
|
||||
void TIA::cycle(uInt32 colorClocks)
|
||||
{
|
||||
for (uInt32 i = 0; i < colorClocks; i++) {
|
||||
|
@ -304,6 +331,8 @@ void TIA::tickHblank()
|
|||
}
|
||||
|
||||
if (++myHblankCtr >= 68) myHstate = HState::frame;
|
||||
|
||||
myHctr++;
|
||||
}
|
||||
|
||||
void TIA::tickHframe()
|
||||
|
@ -360,6 +389,11 @@ void TIA::onFrameComplete()
|
|||
mySystem->m6502().stop();
|
||||
}
|
||||
|
||||
void TIA::onFrameStart()
|
||||
{
|
||||
myCurrentFrameBuffer.swap(myPreviousFrameBuffer);
|
||||
}
|
||||
|
||||
// TODO: stub
|
||||
void TIA::delayedWrite(uInt8 address, uInt8 value)
|
||||
{}
|
||||
|
|
|
@ -124,6 +124,8 @@ class TIA : public AbstractTIA {
|
|||
|
||||
private:
|
||||
|
||||
void updateEmulation();
|
||||
|
||||
void cycle(uInt32 colorClocks);
|
||||
|
||||
void tickMovement();
|
||||
|
@ -140,6 +142,8 @@ class TIA : public AbstractTIA {
|
|||
|
||||
void onFrameComplete();
|
||||
|
||||
void onFrameStart();
|
||||
|
||||
void delayedWrite(uInt8 address, uInt8 value);
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue