From 6d76d65d8228d9497b654f825748d8eae6e3e62b Mon Sep 17 00:00:00 2001 From: Christian Speckner Date: Tue, 15 Nov 2016 21:16:36 +0100 Subject: [PATCH] Add wsync, vsync and vblank, fix bugs and connect the dots -> main loop + tv mode detection work. --- .../tia/core_6502ts/DelayQueueMember.cxx | 2 +- src/emucore/tia/core_6502ts/FrameManager.cxx | 21 +++++++-- src/emucore/tia/core_6502ts/FrameManager.hxx | 7 +-- src/emucore/tia/core_6502ts/TIA.cxx | 46 ++++++++++++++++--- src/emucore/tia/core_6502ts/TIA.hxx | 4 ++ 5 files changed, 65 insertions(+), 15 deletions(-) diff --git a/src/emucore/tia/core_6502ts/DelayQueueMember.cxx b/src/emucore/tia/core_6502ts/DelayQueueMember.cxx index a1f19736c..fba037744 100644 --- a/src/emucore/tia/core_6502ts/DelayQueueMember.cxx +++ b/src/emucore/tia/core_6502ts/DelayQueueMember.cxx @@ -55,7 +55,7 @@ vector::const_iterator DelayQueueMember::begin() const vector::const_iterator DelayQueueMember::end() const { - return myEntries.end(); + return (mySize < myEntries.size() - 1) ? (myEntries.begin() + mySize) : myEntries.end(); } void DelayQueueMember::clear() diff --git a/src/emucore/tia/core_6502ts/FrameManager.cxx b/src/emucore/tia/core_6502ts/FrameManager.cxx index 9f6d421c0..842d1bf8d 100644 --- a/src/emucore/tia/core_6502ts/FrameManager.cxx +++ b/src/emucore/tia/core_6502ts/FrameManager.cxx @@ -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() diff --git a/src/emucore/tia/core_6502ts/FrameManager.hxx b/src/emucore/tia/core_6502ts/FrameManager.hxx index 4acec6f7a..99ee3107c 100644 --- a/src/emucore/tia/core_6502ts/FrameManager.hxx +++ b/src/emucore/tia/core_6502ts/FrameManager.hxx @@ -33,7 +33,7 @@ class FrameManager { pal, ntsc }; - typedef std::function frameCompletionHandler; + typedef std::function 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; diff --git a/src/emucore/tia/core_6502ts/TIA.cxx b/src/emucore/tia/core_6502ts/TIA.cxx index a3625c05e..db20bfeb0 100644 --- a/src/emucore/tia/core_6502ts/TIA.cxx +++ b/src/emucore/tia/core_6502ts/TIA.cxx @@ -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) {} diff --git a/src/emucore/tia/core_6502ts/TIA.hxx b/src/emucore/tia/core_6502ts/TIA.hxx index 2d7f77ec1..fa8f30bb8 100644 --- a/src/emucore/tia/core_6502ts/TIA.hxx +++ b/src/emucore/tia/core_6502ts/TIA.hxx @@ -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: