mirror of https://github.com/stella-emu/stella.git
Port main loop.
This commit is contained in:
parent
b6a2e266aa
commit
70dc29f077
|
@ -19,10 +19,10 @@
|
||||||
|
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#include "TIATypes.hxx"
|
#include "TIATypes.hxx"
|
||||||
|
#include "M6502.hxx"
|
||||||
|
|
||||||
namespace TIA6502tsCore {
|
namespace TIA6502tsCore {
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
: myConsole(console),
|
: myConsole(console),
|
||||||
mySound(sound),
|
mySound(sound),
|
||||||
|
@ -33,22 +33,60 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
[this] () {onFrameComplete();}
|
[this] () {onFrameComplete();}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
myCurrentFrameBuffer = make_ptr<uInt8[]>(160 * 320);
|
||||||
|
myPreviousFrameBuffer = make_ptr<uInt8[]>(160 * 320);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
void TIA::reset()
|
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();
|
myDelayQueue.reset();
|
||||||
|
myFrameManager.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
void TIA::systemCyclesReset()
|
void TIA::systemCyclesReset()
|
||||||
{}
|
{
|
||||||
|
uInt32 cycles = mySystem->cycles();
|
||||||
|
|
||||||
|
myLastCycle -= cycles;
|
||||||
|
mySound.adjustCycleCounter(-cycles);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
void TIA::install(System& system)
|
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
|
// TODO: stub
|
||||||
bool TIA::save(Serializer& out) const
|
bool TIA::save(Serializer& out) const
|
||||||
|
@ -74,10 +112,6 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
void TIA::installDelegate(System& system, Device& device)
|
|
||||||
{}
|
|
||||||
|
|
||||||
// TODO: stub
|
// TODO: stub
|
||||||
void TIA::frameReset()
|
void TIA::frameReset()
|
||||||
{}
|
{}
|
||||||
|
@ -98,25 +132,22 @@ bool TIA::loadDisplay(Serializer& in)
|
||||||
void TIA::update()
|
void TIA::update()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
uInt8* TIA::currentFrameBuffer() const
|
uInt8* TIA::currentFrameBuffer() const
|
||||||
{
|
{
|
||||||
return 0;
|
return myCurrentFrameBuffer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stub
|
// TODO: stub
|
||||||
uInt8* TIA::previousFrameBuffer() const
|
uInt8* TIA::previousFrameBuffer() const
|
||||||
{
|
{
|
||||||
return 0;
|
return myPreviousFrameBuffer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
uInt32 TIA::height() const
|
uInt32 TIA::height() const
|
||||||
{
|
{
|
||||||
return 0;
|
return myFrameManager.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
uInt32 TIA::ystart() const
|
uInt32 TIA::ystart() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -138,10 +169,9 @@ void TIA::enableAutoFrame(bool enabled)
|
||||||
void TIA::enableColorLoss(bool enabled)
|
void TIA::enableColorLoss(bool enabled)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// TODO: stub
|
|
||||||
bool TIA::isPAL() const
|
bool TIA::isPAL() const
|
||||||
{
|
{
|
||||||
return false;
|
return myFrameManager.tvMode() == FrameManager::TvMode::pal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stub
|
// TODO: stub
|
||||||
|
@ -159,7 +189,7 @@ uInt32 TIA::scanlines() const
|
||||||
// TODO: stub
|
// TODO: stub
|
||||||
bool TIA::partialFrame() const
|
bool TIA::partialFrame() const
|
||||||
{
|
{
|
||||||
return false;
|
return myFrameManager.isRendering();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stub
|
// TODO: stub
|
||||||
|
@ -226,9 +256,109 @@ bool TIA::toggleJitter(uInt8 mode)
|
||||||
void TIA::setJitterRecoveryFactor(Int32 f)
|
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()
|
void TIA::onFrameComplete()
|
||||||
{}
|
{
|
||||||
|
mySystem->m6502().stop();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: stub
|
// TODO: stub
|
||||||
void TIA::delayedWrite(uInt8 address, uInt8 value)
|
void TIA::delayedWrite(uInt8 address, uInt8 value)
|
||||||
|
|
|
@ -118,6 +118,26 @@ class TIA : public AbstractTIA {
|
||||||
|
|
||||||
private:
|
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 onFrameComplete();
|
||||||
|
|
||||||
void delayedWrite(uInt8 address, uInt8 value);
|
void delayedWrite(uInt8 address, uInt8 value);
|
||||||
|
@ -125,15 +145,34 @@ class TIA : public AbstractTIA {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Console& myConsole;
|
Console& myConsole;
|
||||||
|
|
||||||
Sound& mySound;
|
Sound& mySound;
|
||||||
|
|
||||||
Settings& mySettings;
|
Settings& mySettings;
|
||||||
|
|
||||||
DelayQueue myDelayQueue;
|
DelayQueue myDelayQueue;
|
||||||
|
|
||||||
FrameManager myFrameManager;
|
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:
|
private:
|
||||||
|
|
||||||
TIA() = delete;
|
TIA() = delete;
|
||||||
|
|
Loading…
Reference in New Issue