mirror of https://github.com/stella-emu/stella.git
Port improved line caching from 6502.ts .
This commit is contained in:
parent
38deb5b1cf
commit
24cb2417fc
|
@ -16,6 +16,7 @@
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "Background.hxx"
|
#include "Background.hxx"
|
||||||
|
#include "TIA.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Background::Background()
|
Background::Background()
|
||||||
|
@ -33,6 +34,8 @@ void Background::reset()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Background::setColor(uInt8 color)
|
void Background::setColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
if (color != myObjectColor) myTIA->flushLineCache();
|
||||||
|
|
||||||
myObjectColor = color;
|
myObjectColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -40,6 +43,7 @@ void Background::setColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Background::setDebugColor(uInt8 color)
|
void Background::setDebugColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
myDebugColor = color;
|
myDebugColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -47,6 +51,7 @@ void Background::setDebugColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Background::enableDebugColors(bool enabled)
|
void Background::enableDebugColors(bool enabled)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
myDebugEnabled = enabled;
|
myDebugEnabled = enabled;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,18 @@
|
||||||
#include "Serializable.hxx"
|
#include "Serializable.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
class TIA;
|
||||||
|
|
||||||
class Background : public Serializable
|
class Background : public Serializable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Background();
|
Background();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void setTIA(TIA* tia) {
|
||||||
|
myTIA = tia;
|
||||||
|
}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void setColor(uInt8 color);
|
void setColor(uInt8 color);
|
||||||
|
@ -50,6 +56,8 @@ class Background : public Serializable
|
||||||
uInt8 myObjectColor, myDebugColor;
|
uInt8 myObjectColor, myDebugColor;
|
||||||
bool myDebugEnabled;
|
bool myDebugEnabled;
|
||||||
|
|
||||||
|
TIA* myTIA;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Background(const Background&) = delete;
|
Background(const Background&) = delete;
|
||||||
Background(Background&&) = delete;
|
Background(Background&&) = delete;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "Ball.hxx"
|
#include "Ball.hxx"
|
||||||
|
#include "TIA.hxx"
|
||||||
|
|
||||||
enum Count: Int8 {
|
enum Count: Int8 {
|
||||||
renderCounterOffset = -4
|
renderCounterOffset = -4
|
||||||
|
@ -56,8 +57,14 @@ void Ball::reset()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Ball::enabl(uInt8 value)
|
void Ball::enabl(uInt8 value)
|
||||||
{
|
{
|
||||||
|
const auto enabledNewOldValue = myIsEnabledNew;
|
||||||
|
|
||||||
myIsEnabledNew = (value & 0x02) > 0;
|
myIsEnabledNew = (value & 0x02) > 0;
|
||||||
updateEnabled();
|
|
||||||
|
if (myIsEnabledNew != enabledNewOldValue && !myIsDelaying) {
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
updateEnabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -80,14 +87,25 @@ void Ball::ctrlpf(uInt8 value)
|
||||||
{
|
{
|
||||||
static constexpr uInt8 ourWidths[] = {1, 2, 4, 8};
|
static constexpr uInt8 ourWidths[] = {1, 2, 4, 8};
|
||||||
|
|
||||||
myWidth = ourWidths[(value & 0x30) >> 4];
|
const uInt8 newWidth = ourWidths[(value & 0x30) >> 4];
|
||||||
|
|
||||||
|
if (newWidth != myWidth) {
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
myWidth = newWidth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Ball::vdelbl(uInt8 value)
|
void Ball::vdelbl(uInt8 value)
|
||||||
{
|
{
|
||||||
|
const auto oldIsDelaying = myIsDelaying;
|
||||||
|
|
||||||
myIsDelaying = (value & 0x01) > 0;
|
myIsDelaying = (value & 0x01) > 0;
|
||||||
updateEnabled();
|
|
||||||
|
if (oldIsDelaying != myIsDelaying) {
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
updateEnabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -106,6 +124,8 @@ void Ball::toggleEnabled(bool enabled)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Ball::setColor(uInt8 color)
|
void Ball::setColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
if (color != myObjectColor && myIsEnabled) myTIA->flushLineCache();
|
||||||
|
|
||||||
myObjectColor = color;
|
myObjectColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -113,6 +133,8 @@ void Ball::setColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Ball::setDebugColor(uInt8 color)
|
void Ball::setDebugColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
myDebugColor = color;
|
myDebugColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -120,6 +142,8 @@ void Ball::setDebugColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Ball::enableDebugColors(bool enabled)
|
void Ball::enableDebugColors(bool enabled)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
myDebugEnabled = enabled;
|
myDebugEnabled = enabled;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -137,25 +161,18 @@ bool Ball::movementTick(uInt32 clock, bool apply)
|
||||||
|
|
||||||
if (clock == myHmmClocks) myIsMoving = false;
|
if (clock == myHmmClocks) myIsMoving = false;
|
||||||
|
|
||||||
if (myIsMoving && apply) {
|
if (myIsMoving && apply) tick(false);
|
||||||
render();
|
|
||||||
tick(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return myIsMoving;
|
return myIsMoving;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Ball::render()
|
void Ball::tick(bool isReceivingMclock)
|
||||||
{
|
{
|
||||||
collision = (myIsRendering && myRenderCounter >= 0 && myIsEnabled) ?
|
collision = (myIsRendering && myRenderCounter >= 0 && myIsEnabled) ?
|
||||||
myCollisionMaskEnabled :
|
myCollisionMaskEnabled :
|
||||||
myCollisionMaskDisabled;
|
myCollisionMaskDisabled;
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Ball::tick(bool isReceivingMclock)
|
|
||||||
{
|
|
||||||
bool starfieldEffect = myIsMoving && isReceivingMclock;
|
bool starfieldEffect = myIsMoving && isReceivingMclock;
|
||||||
|
|
||||||
if (myCounter == 156) {
|
if (myCounter == 156) {
|
||||||
|
@ -189,8 +206,14 @@ void Ball::tick(bool isReceivingMclock)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Ball::shuffleStatus()
|
void Ball::shuffleStatus()
|
||||||
{
|
{
|
||||||
|
const auto oldIsEnabledOld = myIsEnabledOld;
|
||||||
|
|
||||||
myIsEnabledOld = myIsEnabledNew;
|
myIsEnabledOld = myIsEnabledNew;
|
||||||
updateEnabled();
|
|
||||||
|
if (myIsEnabledOld != oldIsEnabledOld && myIsDelaying) {
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
updateEnabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -209,13 +232,15 @@ void Ball::applyColors()
|
||||||
uInt8 Ball::getPosition() const
|
uInt8 Ball::getPosition() const
|
||||||
{
|
{
|
||||||
// Mind the sign of renderCounterOffset: it's defined negative above
|
// Mind the sign of renderCounterOffset: it's defined negative above
|
||||||
return (316 - myCounter - Count::renderCounterOffset + myPlayfieldPositionProvider->getPosition()) % 160;
|
return (316 - myCounter - Count::renderCounterOffset + myTIA->getPosition()) % 160;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Ball::setPosition(uInt8 newPosition)
|
void Ball::setPosition(uInt8 newPosition)
|
||||||
{
|
{
|
||||||
myCounter = (316 - newPosition - Count::renderCounterOffset + myPlayfieldPositionProvider->getPosition()) % 160;
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
|
myCounter = (316 - newPosition - Count::renderCounterOffset + myTIA->getPosition()) % 160;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
|
|
||||||
#include "Serializable.hxx"
|
#include "Serializable.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "PlayfieldPositionProvider.hxx"
|
|
||||||
|
class TIA;
|
||||||
|
|
||||||
class Ball : public Serializable
|
class Ball : public Serializable
|
||||||
{
|
{
|
||||||
|
@ -30,8 +31,8 @@ class Ball : public Serializable
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void setPlayfieldPositionProvider(PlayfieldPositionProvider* playfieldPositionProvider) {
|
void setTIA(TIA* tia) {
|
||||||
myPlayfieldPositionProvider = playfieldPositionProvider;
|
myTIA = tia;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -59,8 +60,6 @@ class Ball : public Serializable
|
||||||
|
|
||||||
bool movementTick(uInt32 clock, bool apply);
|
bool movementTick(uInt32 clock, bool apply);
|
||||||
|
|
||||||
void render();
|
|
||||||
|
|
||||||
void tick(bool isReceivingMclock = true);
|
void tick(bool isReceivingMclock = true);
|
||||||
|
|
||||||
uInt8 getPixel(uInt8 colorIn) const {
|
uInt8 getPixel(uInt8 colorIn) const {
|
||||||
|
@ -113,7 +112,7 @@ class Ball : public Serializable
|
||||||
bool myIsRendering;
|
bool myIsRendering;
|
||||||
Int8 myRenderCounter;
|
Int8 myRenderCounter;
|
||||||
|
|
||||||
PlayfieldPositionProvider* myPlayfieldPositionProvider;
|
TIA* myTIA;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ball() = delete;
|
Ball() = delete;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "Missile.hxx"
|
#include "Missile.hxx"
|
||||||
#include "DrawCounterDecodes.hxx"
|
#include "DrawCounterDecodes.hxx"
|
||||||
|
#include "TIA.hxx"
|
||||||
|
|
||||||
enum Count: Int8 {
|
enum Count: Int8 {
|
||||||
renderCounterOffset = -4
|
renderCounterOffset = -4
|
||||||
|
@ -57,7 +58,12 @@ void Missile::reset()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Missile::enam(uInt8 value)
|
void Missile::enam(uInt8 value)
|
||||||
{
|
{
|
||||||
|
const auto oldEnam = myEnam;
|
||||||
|
|
||||||
myEnam = (value & 0x02) > 0;
|
myEnam = (value & 0x02) > 0;
|
||||||
|
|
||||||
|
if (oldEnam != myEnam) myTIA->flushLineCache();
|
||||||
|
|
||||||
updateEnabled();
|
updateEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +115,9 @@ void Missile::resmp(uInt8 value, const Player& player)
|
||||||
{
|
{
|
||||||
const uInt8 resmp = value & 0x02;
|
const uInt8 resmp = value & 0x02;
|
||||||
|
|
||||||
if (resmp == myResmp)
|
if (resmp == myResmp) return;
|
||||||
return;
|
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
myResmp = resmp;
|
myResmp = resmp;
|
||||||
|
|
||||||
|
@ -159,28 +166,21 @@ bool Missile::movementTick(uInt8 clock, uInt8 hclock, bool apply)
|
||||||
|
|
||||||
if (clock == myHmmClocks) myIsMoving = false;
|
if (clock == myHmmClocks) myIsMoving = false;
|
||||||
|
|
||||||
if (myIsMoving && apply) {
|
if (myIsMoving && apply) tick(hclock);
|
||||||
render(hclock);
|
|
||||||
tick(hclock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return myIsMoving;
|
return myIsMoving;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Missile::render(uInt8 hclock)
|
void Missile::tick(uInt8 hclock)
|
||||||
{
|
{
|
||||||
bool render =
|
const bool render =
|
||||||
myIsRendering &&
|
myIsRendering &&
|
||||||
(myRenderCounter >= 0 || (myIsMoving && myRenderCounter == -1 && myWidth < 4 && ((hclock + 1) % 4 == 3))) &&
|
(myRenderCounter >= 0 || (myIsMoving && myRenderCounter == -1 && myWidth < 4 && ((hclock + 1) % 4 == 3))) &&
|
||||||
myIsEnabled;
|
myIsEnabled;
|
||||||
|
|
||||||
collision = render ? myCollisionMaskEnabled : myCollisionMaskDisabled;
|
collision = render ? myCollisionMaskEnabled : myCollisionMaskDisabled;
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Missile::tick(uInt8 hclock)
|
|
||||||
{
|
|
||||||
if (myDecodes[myCounter] && !myResmp) {
|
if (myDecodes[myCounter] && !myResmp) {
|
||||||
myIsRendering = true;
|
myIsRendering = true;
|
||||||
myRenderCounter = Count::renderCounterOffset;
|
myRenderCounter = Count::renderCounterOffset;
|
||||||
|
@ -213,6 +213,8 @@ void Missile::tick(uInt8 hclock)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Missile::setColor(uInt8 color)
|
void Missile::setColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
if (color != myObjectColor && myIsEnabled) myTIA->flushLineCache();
|
||||||
|
|
||||||
myObjectColor = color;
|
myObjectColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -220,6 +222,7 @@ void Missile::setColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Missile::setDebugColor(uInt8 color)
|
void Missile::setDebugColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
myDebugColor = color;
|
myDebugColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -247,13 +250,14 @@ void Missile::applyColors()
|
||||||
uInt8 Missile::getPosition() const
|
uInt8 Missile::getPosition() const
|
||||||
{
|
{
|
||||||
// Mind the sign of renderCounterOffset: it's defined negative above
|
// Mind the sign of renderCounterOffset: it's defined negative above
|
||||||
return (316 - myCounter - Count::renderCounterOffset + myPlayfieldPositionProvider->getPosition()) % 160;
|
return (316 - myCounter - Count::renderCounterOffset + myTIA->getPosition()) % 160;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Missile::setPosition(uInt8 newPosition)
|
void Missile::setPosition(uInt8 newPosition)
|
||||||
{
|
{
|
||||||
myCounter = (316 - newPosition - Count::renderCounterOffset + myPlayfieldPositionProvider->getPosition()) % 160;
|
myTIA->flushLineCache();
|
||||||
|
myCounter = (316 - newPosition - Count::renderCounterOffset + myTIA->getPosition()) % 160;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
#include "Serializable.hxx"
|
#include "Serializable.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Player.hxx"
|
#include "Player.hxx"
|
||||||
#include "PlayfieldPositionProvider.hxx"
|
|
||||||
|
class TIA;
|
||||||
|
|
||||||
class Missile : public Serializable
|
class Missile : public Serializable
|
||||||
{
|
{
|
||||||
|
@ -31,8 +32,8 @@ class Missile : public Serializable
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void setPlayfieldPositionProvider(PlayfieldPositionProvider* playfieldPositionProvider) {
|
void setTIA(TIA* tia) {
|
||||||
myPlayfieldPositionProvider = playfieldPositionProvider;
|
myTIA = tia;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -51,8 +52,6 @@ class Missile : public Serializable
|
||||||
|
|
||||||
bool movementTick(uInt8 clock, uInt8 hclock, bool apply);
|
bool movementTick(uInt8 clock, uInt8 hclock, bool apply);
|
||||||
|
|
||||||
void render(uInt8 hclock);
|
|
||||||
|
|
||||||
void tick(uInt8 hclock);
|
void tick(uInt8 hclock);
|
||||||
|
|
||||||
void setColor(uInt8 color);
|
void setColor(uInt8 color);
|
||||||
|
@ -114,7 +113,7 @@ class Missile : public Serializable
|
||||||
uInt8 myObjectColor, myDebugColor;
|
uInt8 myObjectColor, myDebugColor;
|
||||||
bool myDebugEnabled;
|
bool myDebugEnabled;
|
||||||
|
|
||||||
PlayfieldPositionProvider *myPlayfieldPositionProvider;
|
TIA *myTIA;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Missile(const Missile&) = delete;
|
Missile(const Missile&) = delete;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "Player.hxx"
|
#include "Player.hxx"
|
||||||
#include "DrawCounterDecodes.hxx"
|
#include "DrawCounterDecodes.hxx"
|
||||||
|
#include "TIA.hxx"
|
||||||
|
|
||||||
enum Count: Int8 {
|
enum Count: Int8 {
|
||||||
renderCounterOffset = -5,
|
renderCounterOffset = -5,
|
||||||
|
@ -63,7 +64,10 @@ void Player::grp(uInt8 pattern)
|
||||||
|
|
||||||
myPatternNew = pattern;
|
myPatternNew = pattern;
|
||||||
|
|
||||||
if (!myIsDelaying && myPatternNew != oldPatternNew) updatePattern();
|
if (!myIsDelaying && myPatternNew != oldPatternNew) {
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
updatePattern();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -179,7 +183,10 @@ void Player::refp(uInt8 value)
|
||||||
|
|
||||||
myIsReflected = (value & 0x08) > 0;
|
myIsReflected = (value & 0x08) > 0;
|
||||||
|
|
||||||
if (oldIsReflected != myIsReflected) updatePattern();
|
if (oldIsReflected != myIsReflected) {
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
updatePattern();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -189,7 +196,10 @@ void Player::vdelp(uInt8 value)
|
||||||
|
|
||||||
myIsDelaying = (value & 0x01) > 0;
|
myIsDelaying = (value & 0x01) > 0;
|
||||||
|
|
||||||
if (oldIsDelaying != myIsDelaying) updatePattern();
|
if (oldIsDelaying != myIsDelaying) {
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
updatePattern();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -211,6 +221,8 @@ void Player::toggleCollisions(bool enabled)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Player::setColor(uInt8 color)
|
void Player::setColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
if (color != myObjectColor && myPattern) myTIA->flushLineCache();
|
||||||
|
|
||||||
myObjectColor = color;
|
myObjectColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -218,6 +230,8 @@ void Player::setColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Player::setDebugColor(uInt8 color)
|
void Player::setDebugColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
myDebugColor = color;
|
myDebugColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -225,6 +239,8 @@ void Player::setDebugColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Player::enableDebugColors(bool enabled)
|
void Player::enableDebugColors(bool enabled)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
myDebugEnabled = enabled;
|
myDebugEnabled = enabled;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -242,28 +258,19 @@ bool Player::movementTick(uInt32 clock, bool apply)
|
||||||
myIsMoving = false;
|
myIsMoving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myIsMoving && apply) {
|
if (myIsMoving && apply) tick();
|
||||||
render();
|
|
||||||
tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
return myIsMoving;
|
return myIsMoving;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Player::render()
|
|
||||||
{
|
|
||||||
if (!myIsRendering || myRenderCounter < myRenderCounterTripPoint) {
|
|
||||||
collision = myCollisionMaskDisabled;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
collision = (myPattern & (1 << mySampleCounter)) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Player::tick()
|
void Player::tick()
|
||||||
{
|
{
|
||||||
|
if (!myIsRendering || myRenderCounter < myRenderCounterTripPoint)
|
||||||
|
collision = myCollisionMaskDisabled;
|
||||||
|
else
|
||||||
|
collision = (myPattern & (1 << mySampleCounter)) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
|
||||||
|
|
||||||
if (myDecodes[myCounter]) {
|
if (myDecodes[myCounter]) {
|
||||||
myIsRendering = true;
|
myIsRendering = true;
|
||||||
mySampleCounter = 0;
|
mySampleCounter = 0;
|
||||||
|
@ -304,7 +311,10 @@ void Player::shufflePatterns()
|
||||||
|
|
||||||
myPatternOld = myPatternNew;
|
myPatternOld = myPatternNew;
|
||||||
|
|
||||||
if (myIsDelaying && myPatternOld != oldPatternOld) updatePattern();
|
if (myIsDelaying && myPatternOld != oldPatternOld) {
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
updatePattern();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -369,15 +379,17 @@ uInt8 Player::getPosition() const
|
||||||
const uInt8 shift = myDivider == 1 ? 0 : 1;
|
const uInt8 shift = myDivider == 1 ? 0 : 1;
|
||||||
|
|
||||||
// Mind the sign of renderCounterOffset: it's defined negative above
|
// Mind the sign of renderCounterOffset: it's defined negative above
|
||||||
return (316 - myCounter - Count::renderCounterOffset + shift + myPlayfieldPositionProvider->getPosition()) % 160;
|
return (316 - myCounter - Count::renderCounterOffset + shift + myTIA->getPosition()) % 160;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Player::setPosition(uInt8 newPosition)
|
void Player::setPosition(uInt8 newPosition)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
const uInt8 shift = myDivider == 1 ? 0 : 1;
|
const uInt8 shift = myDivider == 1 ? 0 : 1;
|
||||||
|
|
||||||
myCounter = (316 - newPosition - Count::renderCounterOffset + shift + myPlayfieldPositionProvider->getPosition()) % 160;
|
myCounter = (316 - newPosition - Count::renderCounterOffset + shift + myTIA->getPosition()) % 160;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Serializable.hxx"
|
#include "Serializable.hxx"
|
||||||
#include "PlayfieldPositionProvider.hxx"
|
|
||||||
|
class TIA;
|
||||||
|
|
||||||
class Player : public Serializable
|
class Player : public Serializable
|
||||||
{
|
{
|
||||||
|
@ -29,8 +30,8 @@ class Player : public Serializable
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void setPlayfieldPositionProvider(PlayfieldPositionProvider* playfieldPositionProvider) {
|
void setTIA(TIA* tia) {
|
||||||
myPlayfieldPositionProvider = playfieldPositionProvider;
|
myTIA = tia;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -60,8 +61,6 @@ class Player : public Serializable
|
||||||
|
|
||||||
bool movementTick(uInt32 clock, bool apply);
|
bool movementTick(uInt32 clock, bool apply);
|
||||||
|
|
||||||
void render();
|
|
||||||
|
|
||||||
void tick();
|
void tick();
|
||||||
uInt8 getClock() const { return myCounter; }
|
uInt8 getClock() const { return myCounter; }
|
||||||
|
|
||||||
|
@ -126,7 +125,7 @@ class Player : public Serializable
|
||||||
bool myIsReflected;
|
bool myIsReflected;
|
||||||
bool myIsDelaying;
|
bool myIsDelaying;
|
||||||
|
|
||||||
PlayfieldPositionProvider *myPlayfieldPositionProvider;
|
TIA* myTIA;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Player(const Player&) = delete;
|
Player(const Player&) = delete;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "Playfield.hxx"
|
#include "Playfield.hxx"
|
||||||
|
#include "TIA.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Playfield::Playfield(uInt32 collisionMask)
|
Playfield::Playfield(uInt32 collisionMask)
|
||||||
|
@ -52,8 +53,12 @@ void Playfield::reset()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::pf0(uInt8 value)
|
void Playfield::pf0(uInt8 value)
|
||||||
{
|
{
|
||||||
|
if (myPf0 == value >> 4) return;
|
||||||
|
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
myPattern = (myPattern & 0x000FFFF0) | (value >> 4);
|
myPattern = (myPattern & 0x000FFFF0) | (value >> 4);
|
||||||
myPf0 = value;
|
myPf0 = value >> 4;
|
||||||
|
|
||||||
updatePattern();
|
updatePattern();
|
||||||
}
|
}
|
||||||
|
@ -61,6 +66,10 @@ void Playfield::pf0(uInt8 value)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::pf1(uInt8 value)
|
void Playfield::pf1(uInt8 value)
|
||||||
{
|
{
|
||||||
|
if (myPf1 == value) return;
|
||||||
|
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
myPattern = (myPattern & 0x000FF00F)
|
myPattern = (myPattern & 0x000FF00F)
|
||||||
| ((value & 0x80) >> 3)
|
| ((value & 0x80) >> 3)
|
||||||
| ((value & 0x40) >> 1)
|
| ((value & 0x40) >> 1)
|
||||||
|
@ -78,6 +87,10 @@ void Playfield::pf1(uInt8 value)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::pf2(uInt8 value)
|
void Playfield::pf2(uInt8 value)
|
||||||
{
|
{
|
||||||
|
if (myPf2 == value) return;
|
||||||
|
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
myPattern = (myPattern & 0x00000FFF) | (value << 12);
|
myPattern = (myPattern & 0x00000FFF) | (value << 12);
|
||||||
myPf2 = value;
|
myPf2 = value;
|
||||||
|
|
||||||
|
@ -87,8 +100,15 @@ void Playfield::pf2(uInt8 value)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::ctrlpf(uInt8 value)
|
void Playfield::ctrlpf(uInt8 value)
|
||||||
{
|
{
|
||||||
myReflected = (value & 0x01) > 0;
|
const bool reflected = (value & 0x01) > 0;
|
||||||
myColorMode = (value & 0x06) == 0x02 ? ColorMode::score : ColorMode::normal;
|
const ColorMode colorMode = (value & 0x06) == 0x02 ? ColorMode::score : ColorMode::normal;
|
||||||
|
|
||||||
|
if (myReflected == reflected && myColorMode == colorMode) return;
|
||||||
|
|
||||||
|
myTIA->flushLineCache();
|
||||||
|
|
||||||
|
myReflected = reflected;
|
||||||
|
myColorMode = colorMode;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +129,8 @@ void Playfield::toggleCollisions(bool enabled)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::setColor(uInt8 color)
|
void Playfield::setColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
if (color != myObjectColor && myColorMode == ColorMode::normal) myTIA->flushLineCache();
|
||||||
|
|
||||||
myObjectColor = color;
|
myObjectColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -116,6 +138,8 @@ void Playfield::setColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::setColorP0(uInt8 color)
|
void Playfield::setColorP0(uInt8 color)
|
||||||
{
|
{
|
||||||
|
if (color != myColorP0 && myColorMode == ColorMode::score) myTIA->flushLineCache();
|
||||||
|
|
||||||
myColorP0 = color;
|
myColorP0 = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -123,6 +147,8 @@ void Playfield::setColorP0(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::setColorP1(uInt8 color)
|
void Playfield::setColorP1(uInt8 color)
|
||||||
{
|
{
|
||||||
|
if (color != myColorP1 && myColorMode == ColorMode::score) myTIA->flushLineCache();
|
||||||
|
|
||||||
myColorP1 = color;
|
myColorP1 = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -130,6 +156,7 @@ void Playfield::setColorP1(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::setDebugColor(uInt8 color)
|
void Playfield::setDebugColor(uInt8 color)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
myDebugColor = color;
|
myDebugColor = color;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
@ -137,6 +164,7 @@ void Playfield::setDebugColor(uInt8 color)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Playfield::enableDebugColors(bool enabled)
|
void Playfield::enableDebugColors(bool enabled)
|
||||||
{
|
{
|
||||||
|
myTIA->flushLineCache();
|
||||||
myDebugEnabled = enabled;
|
myDebugEnabled = enabled;
|
||||||
applyColors();
|
applyColors();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "Serializable.hxx"
|
#include "Serializable.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
class TIA;
|
||||||
|
|
||||||
class Playfield : public Serializable
|
class Playfield : public Serializable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -28,6 +30,10 @@ class Playfield : public Serializable
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
void setTIA(TIA* tia) {
|
||||||
|
myTIA = tia;
|
||||||
|
}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void pf0(uInt8 value);
|
void pf0(uInt8 value);
|
||||||
|
@ -105,6 +111,8 @@ class Playfield : public Serializable
|
||||||
|
|
||||||
uInt32 myX;
|
uInt32 myX;
|
||||||
|
|
||||||
|
TIA* myTIA;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Playfield() = delete;
|
Playfield() = delete;
|
||||||
Playfield(const Playfield&) = delete;
|
Playfield(const Playfield&) = delete;
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#ifndef TIA_PLAYFIELD_PROVIDER
|
|
||||||
#define TIA_PLAYFIELD_PROVIDER
|
|
||||||
|
|
||||||
#include "bspf.hxx"
|
|
||||||
|
|
||||||
/**
|
|
||||||
This is an abstract interface class that provides a subset of TIA
|
|
||||||
functionality for sprite positioning while avoiding circular dependencies
|
|
||||||
between TIA and sprites.
|
|
||||||
|
|
||||||
@author Christian Speckner (DirtyHairy) and Stephen Anthony
|
|
||||||
*/
|
|
||||||
class PlayfieldPositionProvider
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
Get the current x value
|
|
||||||
*/
|
|
||||||
virtual uInt8 getPosition() const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
~PlayfieldPositionProvider() = default;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // TIA_POSITIONING_PROVIDER
|
|
|
@ -95,11 +95,13 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
|
|
||||||
myTIAPinsDriven = mySettings.getBool("tiadriven");
|
myTIAPinsDriven = mySettings.getBool("tiadriven");
|
||||||
|
|
||||||
myPlayer0.setPlayfieldPositionProvider(this);
|
myBackground.setTIA(this);
|
||||||
myPlayer1.setPlayfieldPositionProvider(this);
|
myPlayfield.setTIA(this);
|
||||||
myMissile0.setPlayfieldPositionProvider(this);
|
myPlayer0.setTIA(this);
|
||||||
myMissile1.setPlayfieldPositionProvider(this);
|
myPlayer1.setTIA(this);
|
||||||
myBall.setPlayfieldPositionProvider(this);
|
myMissile0.setTIA(this);
|
||||||
|
myMissile1.setTIA(this);
|
||||||
|
myBall.setTIA(this);
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
@ -114,7 +116,6 @@ void TIA::reset()
|
||||||
myMovementClock = 0;
|
myMovementClock = 0;
|
||||||
myPriority = Priority::normal;
|
myPriority = Priority::normal;
|
||||||
myHstate = HState::blank;
|
myHstate = HState::blank;
|
||||||
myIsFreshLine = true;
|
|
||||||
myCollisionMask = 0;
|
myCollisionMask = 0;
|
||||||
myLinesSinceChange = 0;
|
myLinesSinceChange = 0;
|
||||||
myCollisionUpdateRequired = false;
|
myCollisionUpdateRequired = false;
|
||||||
|
@ -223,7 +224,6 @@ bool TIA::save(Serializer& out) const
|
||||||
out.putBool(myTIAPinsDriven);
|
out.putBool(myTIAPinsDriven);
|
||||||
|
|
||||||
out.putInt(int(myHstate));
|
out.putInt(int(myHstate));
|
||||||
out.putBool(myIsFreshLine);
|
|
||||||
|
|
||||||
out.putInt(myHblankCtr);
|
out.putInt(myHblankCtr);
|
||||||
out.putInt(myHctr);
|
out.putInt(myHctr);
|
||||||
|
@ -293,7 +293,6 @@ bool TIA::load(Serializer& in)
|
||||||
myTIAPinsDriven = in.getBool();
|
myTIAPinsDriven = in.getBool();
|
||||||
|
|
||||||
myHstate = HState(in.getInt());
|
myHstate = HState(in.getInt());
|
||||||
myIsFreshLine = in.getBool();
|
|
||||||
|
|
||||||
myHblankCtr = in.getInt();
|
myHblankCtr = in.getInt();
|
||||||
myHctr = in.getInt();
|
myHctr = in.getInt();
|
||||||
|
@ -443,6 +442,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RSYNC:
|
case RSYNC:
|
||||||
|
flushLineCache();
|
||||||
applyRsync();
|
applyRsync();
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
@ -496,13 +496,11 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COLUBK:
|
case COLUBK:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myBackground.setColor(value & 0xFE);
|
myBackground.setColor(value & 0xFE);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COLUP0:
|
case COLUP0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
value &= 0xFE;
|
value &= 0xFE;
|
||||||
myPlayfield.setColorP0(value);
|
myPlayfield.setColorP0(value);
|
||||||
myMissile0.setColor(value);
|
myMissile0.setColor(value);
|
||||||
|
@ -511,7 +509,6 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COLUP1:
|
case COLUP1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
value &= 0xFE;
|
value &= 0xFE;
|
||||||
myPlayfield.setColorP1(value);
|
myPlayfield.setColorP1(value);
|
||||||
myMissile1.setColor(value);
|
myMissile1.setColor(value);
|
||||||
|
@ -520,7 +517,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRLPF:
|
case CTRLPF:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myPriority = (value & 0x04) ? Priority::pfp :
|
myPriority = (value & 0x04) ? Priority::pfp :
|
||||||
(value & 0x02) ? Priority::score : Priority::normal;
|
(value & 0x02) ? Priority::score : Priority::normal;
|
||||||
myPlayfield.ctrlpf(value);
|
myPlayfield.ctrlpf(value);
|
||||||
|
@ -529,7 +526,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COLUPF:
|
case COLUPF:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
value &= 0xFE;
|
value &= 0xFE;
|
||||||
myPlayfield.setColor(value);
|
myPlayfield.setColor(value);
|
||||||
myBall.setColor(value);
|
myBall.setColor(value);
|
||||||
|
@ -578,38 +575,36 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESM0:
|
case RESM0:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myMissile0.resm(resxCounter(), myHstate == HState::blank);
|
myMissile0.resm(resxCounter(), myHstate == HState::blank);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESM1:
|
case RESM1:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myMissile1.resm(resxCounter(), myHstate == HState::blank);
|
myMissile1.resm(resxCounter(), myHstate == HState::blank);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESMP0:
|
case RESMP0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myMissile0.resmp(value, myPlayer0);
|
myMissile0.resmp(value, myPlayer0);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESMP1:
|
case RESMP1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myMissile1.resmp(value, myPlayer1);
|
myMissile1.resmp(value, myPlayer1);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NUSIZ0:
|
case NUSIZ0:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myMissile0.nusiz(value);
|
myMissile0.nusiz(value);
|
||||||
myPlayer0.nusiz(value, myHstate == HState::blank);
|
myPlayer0.nusiz(value, myHstate == HState::blank);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NUSIZ1:
|
case NUSIZ1:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myMissile1.nusiz(value);
|
myMissile1.nusiz(value);
|
||||||
myPlayer1.nusiz(value, myHstate == HState::blank);
|
myPlayer1.nusiz(value, myHstate == HState::blank);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
|
@ -653,13 +648,13 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
}
|
}
|
||||||
|
|
||||||
case RESP0:
|
case RESP0:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myPlayer0.resp(resxCounter());
|
myPlayer0.resp(resxCounter());
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESP1:
|
case RESP1:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myPlayer1.resp(resxCounter());
|
myPlayer1.resp(resxCounter());
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
@ -673,13 +668,11 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VDELP0:
|
case VDELP0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer0.vdelp(value);
|
myPlayer0.vdelp(value);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VDELP1:
|
case VDELP1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer1.vdelp(value);
|
myPlayer1.vdelp(value);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
@ -697,13 +690,12 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESBL:
|
case RESBL:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myBall.resbl(resxCounter());
|
myBall.resbl(resxCounter());
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VDELBL:
|
case VDELBL:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myBall.vdelbl(value);
|
myBall.vdelbl(value);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
@ -713,7 +705,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CXCLR:
|
case CXCLR:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myCollisionMask = 0;
|
myCollisionMask = 0;
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
@ -1005,18 +997,20 @@ void TIA::cycle(uInt32 colorClocks)
|
||||||
|
|
||||||
myCollisionUpdateRequired = false;
|
myCollisionUpdateRequired = false;
|
||||||
|
|
||||||
tickMovement();
|
if (myLinesSinceChange < 2) {
|
||||||
|
tickMovement();
|
||||||
|
|
||||||
if (myHstate == HState::blank)
|
if (myHstate == HState::blank)
|
||||||
tickHblank();
|
tickHblank();
|
||||||
else
|
else
|
||||||
tickHframe();
|
tickHframe();
|
||||||
|
|
||||||
|
if (myCollisionUpdateRequired) updateCollision();
|
||||||
|
}
|
||||||
|
|
||||||
if (++myHctr >= 228)
|
if (++myHctr >= 228)
|
||||||
nextLine();
|
nextLine();
|
||||||
|
|
||||||
if (myCollisionUpdateRequired) updateCollision();
|
|
||||||
|
|
||||||
myTimestamp++;
|
myTimestamp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1027,8 +1021,6 @@ void TIA::tickMovement()
|
||||||
if (!myMovementInProgress) return;
|
if (!myMovementInProgress) return;
|
||||||
|
|
||||||
if ((myHctr & 0x03) == 0) {
|
if ((myHctr & 0x03) == 0) {
|
||||||
myLinesSinceChange = 0;
|
|
||||||
|
|
||||||
const bool apply = myHstate == HState::blank;
|
const bool apply = myHstate == HState::blank;
|
||||||
bool m = false;
|
bool m = false;
|
||||||
uInt8 movementCounter = myMovementClock > 15 ? 0 : myMovementClock;
|
uInt8 movementCounter = myMovementClock > 15 ? 0 : myMovementClock;
|
||||||
|
@ -1049,9 +1041,8 @@ void TIA::tickMovement()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::tickHblank()
|
void TIA::tickHblank()
|
||||||
{
|
{
|
||||||
if (myIsFreshLine) {
|
if (myHctr == 0) {
|
||||||
myHblankCtr = 0;
|
myHblankCtr = 0;
|
||||||
myIsFreshLine = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++myHblankCtr >= 68) myHstate = HState::frame;
|
if (++myHblankCtr >= 68) myHstate = HState::frame;
|
||||||
|
@ -1061,23 +1052,11 @@ void TIA::tickHblank()
|
||||||
void TIA::tickHframe()
|
void TIA::tickHframe()
|
||||||
{
|
{
|
||||||
const uInt32 y = myFrameManager.getY();
|
const uInt32 y = myFrameManager.getY();
|
||||||
const bool lineNotCached = myLinesSinceChange < 2 || y == 0;
|
|
||||||
const uInt32 x = myHctr - 68 - myXDelta;
|
const uInt32 x = myHctr - 68 - myXDelta;
|
||||||
|
|
||||||
myCollisionUpdateRequired = lineNotCached;
|
myCollisionUpdateRequired = true;
|
||||||
|
|
||||||
myPlayfield.tick(x);
|
myPlayfield.tick(x);
|
||||||
|
|
||||||
// Render sprites
|
|
||||||
if (lineNotCached) {
|
|
||||||
myPlayer0.render();
|
|
||||||
myPlayer1.render();
|
|
||||||
myMissile0.render(myHctr);
|
|
||||||
myMissile1.render(myHctr);
|
|
||||||
myBall.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tick sprites
|
|
||||||
myMissile0.tick(myHctr);
|
myMissile0.tick(myHctr);
|
||||||
myMissile1.tick(myHctr);
|
myMissile1.tick(myHctr);
|
||||||
myPlayer0.tick();
|
myPlayer0.tick();
|
||||||
|
@ -1085,7 +1064,7 @@ void TIA::tickHframe()
|
||||||
myBall.tick();
|
myBall.tick();
|
||||||
|
|
||||||
if (myFrameManager.isRendering())
|
if (myFrameManager.isRendering())
|
||||||
renderPixel(x, y, lineNotCached);
|
renderPixel(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1097,22 +1076,39 @@ void TIA::applyRsync()
|
||||||
if (myFrameManager.isRendering())
|
if (myFrameManager.isRendering())
|
||||||
memset(myCurrentFrameBuffer.get() + myFrameManager.getY() * 160 + x, 0, 160 - x);
|
memset(myCurrentFrameBuffer.get() + myFrameManager.getY() * 160 + x, 0, 160 - x);
|
||||||
|
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myHctr = 225;
|
myHctr = 225;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::nextLine()
|
void TIA::nextLine()
|
||||||
{
|
{
|
||||||
|
if (myLinesSinceChange >= 2) {
|
||||||
|
cloneLastLine();
|
||||||
|
}
|
||||||
|
|
||||||
myHctr = 0;
|
myHctr = 0;
|
||||||
myLinesSinceChange++;
|
|
||||||
|
if (!myMovementInProgress && myLinesSinceChange < 2) myLinesSinceChange++;
|
||||||
|
|
||||||
myHstate = HState::blank;
|
myHstate = HState::blank;
|
||||||
myIsFreshLine = true;
|
|
||||||
myExtendedHblank = false;
|
myExtendedHblank = false;
|
||||||
myXDelta = 0;
|
myXDelta = 0;
|
||||||
|
|
||||||
myFrameManager.nextLine();
|
myFrameManager.nextLine();
|
||||||
|
|
||||||
|
if (myFrameManager.isRendering() && myFrameManager.getY() == 0) flushLineCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void TIA::cloneLastLine()
|
||||||
|
{
|
||||||
|
const auto y = myFrameManager.getY();
|
||||||
|
|
||||||
|
if (!myFrameManager.isRendering() || y == 0) return;
|
||||||
|
|
||||||
|
uInt8* buffer = myCurrentFrameBuffer.get();
|
||||||
|
|
||||||
|
memcpy(buffer + y * 160, buffer + (y-1) * 160, 160);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1129,58 +1125,73 @@ void TIA::updateCollision()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::renderPixel(uInt32 x, uInt32 y, bool lineNotCached)
|
void TIA::renderPixel(uInt32 x, uInt32 y)
|
||||||
{
|
{
|
||||||
if (x >= 160) return;
|
if (x >= 160) return;
|
||||||
|
|
||||||
if (lineNotCached) {
|
uInt8 color = myBackground.getColor();
|
||||||
uInt8 color = myBackground.getColor();
|
|
||||||
|
|
||||||
switch (myPriority)
|
switch (myPriority)
|
||||||
{
|
{
|
||||||
// Playfield has priority so ScoreBit isn't used
|
// Playfield has priority so ScoreBit isn't used
|
||||||
// Priority from highest to lowest:
|
// Priority from highest to lowest:
|
||||||
// BL/PF => P0/M0 => P1/M1 => BK
|
// BL/PF => P0/M0 => P1/M1 => BK
|
||||||
case Priority::pfp: // CTRLPF D2=1, D1=ignored
|
case Priority::pfp: // CTRLPF D2=1, D1=ignored
|
||||||
color = myMissile1.getPixel(color);
|
color = myMissile1.getPixel(color);
|
||||||
color = myPlayer1.getPixel(color);
|
color = myPlayer1.getPixel(color);
|
||||||
color = myMissile0.getPixel(color);
|
color = myMissile0.getPixel(color);
|
||||||
color = myPlayer0.getPixel(color);
|
color = myPlayer0.getPixel(color);
|
||||||
color = myPlayfield.getPixel(color);
|
color = myPlayfield.getPixel(color);
|
||||||
color = myBall.getPixel(color);
|
color = myBall.getPixel(color);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Priority::score: // CTRLPF D2=0, D1=1
|
case Priority::score: // CTRLPF D2=0, D1=1
|
||||||
// Formally we have (priority from highest to lowest)
|
// Formally we have (priority from highest to lowest)
|
||||||
// PF/P0/M0 => P1/M1 => BL => BK
|
// PF/P0/M0 => P1/M1 => BL => BK
|
||||||
// for the first half and
|
// for the first half and
|
||||||
// P0/M0 => PF/P1/M1 => BL => BK
|
// P0/M0 => PF/P1/M1 => BL => BK
|
||||||
// for the second half. However, the first ordering is equivalent
|
// for the second half. However, the first ordering is equivalent
|
||||||
// to the second (PF has the same color as P0/M0), so we can just
|
// to the second (PF has the same color as P0/M0), so we can just
|
||||||
// write
|
// write
|
||||||
color = myBall.getPixel(color);
|
color = myBall.getPixel(color);
|
||||||
color = myMissile1.getPixel(color);
|
color = myMissile1.getPixel(color);
|
||||||
color = myPlayer1.getPixel(color);
|
color = myPlayer1.getPixel(color);
|
||||||
color = myPlayfield.getPixel(color);
|
color = myPlayfield.getPixel(color);
|
||||||
color = myMissile0.getPixel(color);
|
color = myMissile0.getPixel(color);
|
||||||
color = myPlayer0.getPixel(color);
|
color = myPlayer0.getPixel(color);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Priority from highest to lowest:
|
// Priority from highest to lowest:
|
||||||
// P0/M0 => P1/M1 => BL/PF => BK
|
// P0/M0 => P1/M1 => BL/PF => BK
|
||||||
case Priority::normal: // CTRLPF D2=0, D1=0
|
case Priority::normal: // CTRLPF D2=0, D1=0
|
||||||
color = myPlayfield.getPixel(color);
|
color = myPlayfield.getPixel(color);
|
||||||
color = myBall.getPixel(color);
|
color = myBall.getPixel(color);
|
||||||
color = myMissile1.getPixel(color);
|
color = myMissile1.getPixel(color);
|
||||||
color = myPlayer1.getPixel(color);
|
color = myPlayer1.getPixel(color);
|
||||||
color = myMissile0.getPixel(color);
|
color = myMissile0.getPixel(color);
|
||||||
color = myPlayer0.getPixel(color);
|
color = myPlayer0.getPixel(color);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
myCurrentFrameBuffer.get()[y * 160 + x] = myFrameManager.vblank() ? 0 : color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void TIA::flushLineCache()
|
||||||
|
{
|
||||||
|
const bool wasCaching = myLinesSinceChange >= 2;
|
||||||
|
|
||||||
|
myLinesSinceChange = 0;
|
||||||
|
|
||||||
|
if (wasCaching) {
|
||||||
|
const auto rewindCycles = myHctr;
|
||||||
|
|
||||||
|
for (myHctr = 0; myHctr < rewindCycles; myHctr++) {
|
||||||
|
if (myHstate == HState::blank)
|
||||||
|
tickHblank();
|
||||||
|
else
|
||||||
|
tickHframe();
|
||||||
}
|
}
|
||||||
|
|
||||||
myCurrentFrameBuffer.get()[y * 160 + x] = myFrameManager.vblank() ? 0 : color;
|
|
||||||
} else {
|
|
||||||
myCurrentFrameBuffer.get()[y * 160 + x] = myCurrentFrameBuffer.get()[(y-1) * 160 + x];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1201,12 +1212,12 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
|
||||||
switch (address)
|
switch (address)
|
||||||
{
|
{
|
||||||
case VBLANK:
|
case VBLANK:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
myFrameManager.setVblank(value & 0x02);
|
myFrameManager.setVblank(value & 0x02);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMOVE:
|
case HMOVE:
|
||||||
myLinesSinceChange = 0;
|
flushLineCache();
|
||||||
|
|
||||||
myMovementClock = 0;
|
myMovementClock = 0;
|
||||||
myMovementInProgress = true;
|
myMovementInProgress = true;
|
||||||
|
@ -1225,32 +1236,26 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PF0:
|
case PF0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayfield.pf0(value);
|
myPlayfield.pf0(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PF1:
|
case PF1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayfield.pf1(value);
|
myPlayfield.pf1(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PF2:
|
case PF2:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayfield.pf2(value);
|
myPlayfield.pf2(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMM0:
|
case HMM0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myMissile0.hmm(value);
|
myMissile0.hmm(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMM1:
|
case HMM1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myMissile1.hmm(value);
|
myMissile1.hmm(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMCLR:
|
case HMCLR:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myMissile0.hmm(0);
|
myMissile0.hmm(0);
|
||||||
myMissile1.hmm(0);
|
myMissile1.hmm(0);
|
||||||
myPlayer0.hmp(0);
|
myPlayer0.hmp(0);
|
||||||
|
@ -1259,67 +1264,54 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GRP0:
|
case GRP0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer0.grp(value);
|
myPlayer0.grp(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GRP1:
|
case GRP1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer1.grp(value);
|
myPlayer1.grp(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DummyRegisters::shuffleP0:
|
case DummyRegisters::shuffleP0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer0.shufflePatterns();
|
myPlayer0.shufflePatterns();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DummyRegisters::shuffleP1:
|
case DummyRegisters::shuffleP1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer1.shufflePatterns();
|
myPlayer1.shufflePatterns();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DummyRegisters::shuffleBL:
|
case DummyRegisters::shuffleBL:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myBall.shuffleStatus();
|
myBall.shuffleStatus();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMP0:
|
case HMP0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer0.hmp(value);
|
myPlayer0.hmp(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMP1:
|
case HMP1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer1.hmp(value);
|
myPlayer1.hmp(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMBL:
|
case HMBL:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myBall.hmbl(value);
|
myBall.hmbl(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REFP0:
|
case REFP0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer0.refp(value);
|
myPlayer0.refp(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REFP1:
|
case REFP1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myPlayer1.refp(value);
|
myPlayer1.refp(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENABL:
|
case ENABL:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myBall.enabl(value);
|
myBall.enabl(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENAM0:
|
case ENAM0:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myMissile0.enam(value);
|
myMissile0.enam(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENAM1:
|
case ENAM1:
|
||||||
myLinesSinceChange = 0;
|
|
||||||
myMissile1.enam(value);
|
myMissile1.enam(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
#include "Ball.hxx"
|
#include "Ball.hxx"
|
||||||
#include "LatchedInput.hxx"
|
#include "LatchedInput.hxx"
|
||||||
#include "PaddleReader.hxx"
|
#include "PaddleReader.hxx"
|
||||||
#include "PlayfieldPositionProvider.hxx"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class is a device that emulates the Television Interface Adaptor
|
This class is a device that emulates the Television Interface Adaptor
|
||||||
|
@ -50,7 +49,7 @@
|
||||||
|
|
||||||
@author Christian Speckner (DirtyHairy) and Stephen Anthony
|
@author Christian Speckner (DirtyHairy) and Stephen Anthony
|
||||||
*/
|
*/
|
||||||
class TIA : public Device, public PlayfieldPositionProvider
|
class TIA : public Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class TIADebug;
|
friend class TIADebug;
|
||||||
|
@ -317,10 +316,16 @@ class TIA : public Device, public PlayfieldPositionProvider
|
||||||
/**
|
/**
|
||||||
Get the current x value
|
Get the current x value
|
||||||
*/
|
*/
|
||||||
uInt8 getPosition() const override {
|
uInt8 getPosition() const {
|
||||||
return (myHctr < 68) ? 0 : (myHctr - 68 - myXDelta);
|
return (myHctr < 68) ? 0 : (myHctr - 68 - myXDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flush the line cache after an externally triggered state change
|
||||||
|
(e.g. a register write)
|
||||||
|
*/
|
||||||
|
void flushLineCache();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Save the current state of this device to the given Serializer.
|
Save the current state of this device to the given Serializer.
|
||||||
|
|
||||||
|
@ -388,12 +393,14 @@ class TIA : public Device, public PlayfieldPositionProvider
|
||||||
|
|
||||||
void updateCollision();
|
void updateCollision();
|
||||||
|
|
||||||
void renderPixel(uInt32 x, uInt32 y, bool lineNotCached);
|
void renderPixel(uInt32 x, uInt32 y);
|
||||||
|
|
||||||
void clearHmoveComb();
|
void clearHmoveComb();
|
||||||
|
|
||||||
void nextLine();
|
void nextLine();
|
||||||
|
|
||||||
|
void cloneLastLine();
|
||||||
|
|
||||||
void delayedWrite(uInt8 address, uInt8 value);
|
void delayedWrite(uInt8 address, uInt8 value);
|
||||||
|
|
||||||
void updatePaddle(uInt8 idx);
|
void updatePaddle(uInt8 idx);
|
||||||
|
@ -442,7 +449,6 @@ class TIA : public Device, public PlayfieldPositionProvider
|
||||||
bool myTIAPinsDriven;
|
bool myTIAPinsDriven;
|
||||||
|
|
||||||
HState myHstate;
|
HState myHstate;
|
||||||
bool myIsFreshLine;
|
|
||||||
|
|
||||||
Int32 myHblankCtr;
|
Int32 myHblankCtr;
|
||||||
Int32 myHctr;
|
Int32 myHctr;
|
||||||
|
|
Loading…
Reference in New Issue