Port main loop.

This commit is contained in:
Christian Speckner 2016-11-15 19:26:23 +01:00
parent b6a2e266aa
commit 70dc29f077
2 changed files with 193 additions and 24 deletions

View File

@ -19,10 +19,10 @@
#include "TIA.hxx"
#include "TIATypes.hxx"
#include "M6502.hxx"
namespace TIA6502tsCore {
// TODO: stub
TIA::TIA(Console& console, Sound& sound, Settings& settings)
: myConsole(console),
mySound(sound),
@ -33,22 +33,60 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
[this] () {onFrameComplete();}
);
myCurrentFrameBuffer = make_ptr<uInt8[]>(160 * 320);
myPreviousFrameBuffer = make_ptr<uInt8[]>(160 * 320);
reset();
}
// TODO: stub
void TIA::reset()
{
myHblankCtr = 0;
myHctr = 0;
myMovementInProgress = false;
myExtendedHblank = false;
myMovementClock = 0;
myPriority = Priority::normal;
myHstate = HState::blank;
myIsFreshLine = true;
myCollisionMask = 0;
myLinesSinceChange = 0;
myCollisionUpdateRequired = false;
myLastCycle = 0;
mySound.reset();
myDelayQueue.reset();
myFrameManager.reset();
}
// TODO: stub
void TIA::systemCyclesReset()
{}
{
uInt32 cycles = mySystem->cycles();
myLastCycle -= cycles;
mySound.adjustCycleCounter(-cycles);
}
// TODO: stub
void TIA::install(System& system)
{}
{
installDelegate(system, *this);
}
void TIA::installDelegate(System& system, Device& device)
{
// Remember which system I'm installed in
mySystem = &system;
// All accesses are to the given device
System::PageAccess access(&device, System::PA_READWRITE);
// We're installing in a 2600 system
for(uInt32 i = 0; i < 8192; i += (1 << System::PAGE_SHIFT))
if((i & 0x1080) == 0x0000)
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
}
// TODO: stub
bool TIA::save(Serializer& out) const
@ -74,10 +112,6 @@ bool TIA::poke(uInt16 address, uInt8 value)
return false;
}
// TODO: stub
void TIA::installDelegate(System& system, Device& device)
{}
// TODO: stub
void TIA::frameReset()
{}
@ -98,25 +132,22 @@ bool TIA::loadDisplay(Serializer& in)
void TIA::update()
{}
// TODO: stub
uInt8* TIA::currentFrameBuffer() const
{
return 0;
return myCurrentFrameBuffer.get();
}
// TODO: stub
uInt8* TIA::previousFrameBuffer() const
{
return 0;
return myPreviousFrameBuffer.get();
}
// TODO: stub
uInt32 TIA::height() const
{
return 0;
return myFrameManager.height();
}
// TODO: stub
uInt32 TIA::ystart() const
{
return 0;
@ -138,10 +169,9 @@ void TIA::enableAutoFrame(bool enabled)
void TIA::enableColorLoss(bool enabled)
{}
// TODO: stub
bool TIA::isPAL() const
{
return false;
return myFrameManager.tvMode() == FrameManager::TvMode::pal;
}
// TODO: stub
@ -159,7 +189,7 @@ uInt32 TIA::scanlines() const
// TODO: stub
bool TIA::partialFrame() const
{
return false;
return myFrameManager.isRendering();
}
// TODO: stub
@ -226,9 +256,109 @@ bool TIA::toggleJitter(uInt8 mode)
void TIA::setJitterRecoveryFactor(Int32 f)
{}
// TODO: stub
void TIA::cycle(uInt32 colorClocks)
{
for (uInt32 i = 0; i < colorClocks; i++) {
myDelayQueue.execute(
[this] (uInt8 address, uInt8 value) {delayedWrite(address, value);}
);
myCollisionUpdateRequired = false;
tickMovement();
if (myHstate == HState::blank)
tickHblank();
else
tickHframe();
if (myCollisionUpdateRequired) updateCollision();
}
}
void TIA::tickMovement()
{
if (myMovementInProgress) return;
if ((myHctr & 0x03) == 0) {
myLinesSinceChange = 0;
const bool apply = myHstate == HState::blank;
bool m = false;
// TODO: propagate movement to sprites
myMovementInProgress = m;
myCollisionUpdateRequired = m;
myMovementClock++;
}
}
void TIA::tickHblank()
{
if (myIsFreshLine) {
myHblankCtr = 0;
myIsFreshLine = false;
}
if (++myHblankCtr >= 68) myHstate = HState::frame;
}
void TIA::tickHframe()
{
const uInt32 y = myFrameManager.currentLine();
const bool lineNotCached = myLinesSinceChange < 2 || y == 0;
const uInt32 x = myHctr - 68;
myCollisionUpdateRequired = lineNotCached;
// TODO: playfield tick
// TODO: render sprites
// TODO: tick sprites
if (myFrameManager.isRendering()) renderPixel(x, y, lineNotCached);
if (++myHctr >= 228) nextLine();
}
void TIA::nextLine()
{
myHctr = 0;
myLinesSinceChange++;
myHstate = HState::blank;
myIsFreshLine = true;
myExtendedHblank = false;
myFrameManager.nextLine();
}
void TIA::updateCollision()
{
// TODO: update collision mask with sprite masks
}
void TIA::renderPixel(uInt32 x, uInt32 y, bool lineNotCached)
{
if (lineNotCached) {
uInt8 color = 0;
// TODO: determine color from sprites
myCurrentFrameBuffer.get()[y * 160 + x] = myFrameManager.vblank() ? 0 : color;
} else {
myCurrentFrameBuffer.get()[y * 160 + x] = myCurrentFrameBuffer.get()[(y-1) * 160 + x];
}
}
void TIA::onFrameComplete()
{}
{
mySystem->m6502().stop();
}
// TODO: stub
void TIA::delayedWrite(uInt8 address, uInt8 value)

View File

@ -118,6 +118,26 @@ class TIA : public AbstractTIA {
private:
enum HState {blank, frame};
enum Priority {normal, inverted};
private:
void cycle(uInt32 colorClocks);
void tickMovement();
void tickHblank();
void tickHframe();
void updateCollision();
void renderPixel(uInt32 x, uInt32 y, bool lineNotCached);
void nextLine();
void onFrameComplete();
void delayedWrite(uInt8 address, uInt8 value);
@ -125,15 +145,34 @@ class TIA : public AbstractTIA {
private:
Console& myConsole;
Sound& mySound;
Settings& mySettings;
DelayQueue myDelayQueue;
FrameManager myFrameManager;
HState myHstate;
bool myIsFreshLine;
uInt32 myHblankCtr;
uInt32 myHctr;
bool myCollisionUpdateRequired;
uInt32 myCollisionMask;
uInt32 myMovementClock;
bool myMovementInProgress;
bool myExtendedHblank;
uInt32 myLinesSinceChange;
Priority myPriority;
uInt32 myLastCycle;
BytePtr myCurrentFrameBuffer;
BytePtr myPreviousFrameBuffer;
private:
TIA() = delete;