Add ball.

This commit is contained in:
Christian Speckner 2016-11-22 23:22:16 +01:00
parent 95c1d2b08c
commit d02c985a91
7 changed files with 298 additions and 5 deletions

View File

@ -0,0 +1,153 @@
//
// 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-2016 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.
//
// $Id$
//============================================================================
#include "Ball.hxx"
enum Count: Int8 {
renderCounterOffset = -4
};
namespace TIA6502tsCore {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ball::Ball(uInt32 collisionMask)
: myCollisionMask(collisionMask)
{
reset();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::reset()
{
myColor = 0;
collision = myCollisionMask;
myEnabledOld = false;
myEnabledNew = false;
myEnabled = false;
myHmmClocks = 0;
myCounter = 0;
myIsMoving = false;
myWidth = 1;
myIsRendering = false;
myRenderCounter = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::enabl(uInt8 value)
{
myEnabledNew = (value & 0x02) > 0;
updateEnabled();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::hmbl(uInt8 value)
{
myHmmClocks = (value >> 4) ^ 0x08;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::resbl(bool hblank)
{
myCounter = hblank ? 159 : 157;
if (!hblank) {
myIsRendering = true;
myRenderCounter = Count::renderCounterOffset;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::ctrlpf(uInt8 value)
{
static constexpr uInt8 ourWidths[] = {1, 2, 4, 8};
myWidth = ourWidths[(value & 0x30) >> 4];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::vdelbl(uInt8 value)
{
myIsDelaying = (value & 0x01) > 0;
updateEnabled();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::setColor(uInt8 color)
{
myColor = color;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::startMovement()
{
myIsMoving = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Ball::movementTick(uInt32 clock, bool apply)
{
if (clock == myHmmClocks) myIsMoving = false;
if (myIsMoving && apply) {
render();
tick();
}
return myIsMoving;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::render()
{
collision = (myIsRendering && myRenderCounter >= 0 && myEnabled) ? 0 : myCollisionMask;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::tick()
{
if (myCounter == 156) {
myIsRendering = true;
myRenderCounter = Count::renderCounterOffset;
}
else if (myIsRendering && ++myRenderCounter >= myWidth)
myIsRendering = false;
if (++myCounter >= 160)
myCounter = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Ball::getPixel(uInt8 colorIn) const
{
return collision > 0 ? colorIn : myColor;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::shuffleStatus()
{
myEnabledOld = myEnabledNew;
updateEnabled();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::updateEnabled()
{
myEnabled = myIsDelaying ? myEnabledOld : myEnabledNew;
}
} // namespace TIA6502tsCore

View File

@ -0,0 +1,99 @@
//============================================================================
//
// 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-2016 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.
//
// $Id$
//============================================================================
#ifndef TIA_6502TS_CORE_BALL
#define TIA_6502TS_CORE_BALL
#include "bspf.hxx"
namespace TIA6502tsCore {
class Ball
{
public:
Ball(uInt32 collisionMask);
public:
void reset();
void enabl(uInt8 value);
void hmbl(uInt8 value);
void resbl(bool hblank);
void ctrlpf(uInt8 value);
void vdelbl(uInt8 value);
void setColor(uInt8 color);
void startMovement();
bool movementTick(uInt32 clock, bool apply);
void render();
void tick();
uInt8 getPixel(uInt8 colorIn) const;
void shuffleStatus();
public:
uInt32 collision;
private:
void updateEnabled();
private:
uInt32 myCollisionMask;
uInt8 myColor;
bool myEnabledOld;
bool myEnabledNew;
bool myEnabled;
bool myIsDelaying;
uInt8 myHmmClocks;
uInt8 myCounter;
bool myIsMoving;
uInt8 myWidth;
bool myIsRendering;
Int8 myRenderCounter;
private:
Ball() = delete;
Ball(const Ball&) = delete;
Ball(Ball&&) = delete;
Ball& operator=(const Ball&) = delete;
Ball& operator=(Ball&&);
};
} // namespace TIA6502tsCore
#endif // TIA_6502TS_CORE_BALL

View File

@ -47,6 +47,7 @@ void Missile::reset()
myIsRendering = false;
myRenderCounter = 0;
myColor = 0;
collision = myCollisionMask;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -48,6 +48,7 @@ void Player::reset()
myPattern = 0;
myIsReflected = 0;
myIsDelaying = false;
collision = myCollisionMask;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -58,7 +58,8 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
myMissile0(CollisionMask::missile0),
myMissile1(CollisionMask::missile1),
myPlayer0(CollisionMask::player0),
myPlayer1(CollisionMask::player1)
myPlayer1(CollisionMask::player1),
myBall(CollisionMask::ball)
{
myFrameManager.setHandlers(
[this] () {
@ -98,6 +99,7 @@ void TIA::reset()
myMissile1.reset();
myPlayer0.reset();
myPlayer1.reset();
myBall.reset();
mySound.reset();
myDelayQueue.reset();
@ -217,11 +219,14 @@ bool TIA::poke(uInt16 address, uInt8 value)
myLinesSinceChange = 0;
myPriority = (value & 0x04) ? Priority::inverted : Priority::normal;
myPlayfield.ctrlpf(value);
myBall.ctrlpf(value);
break;
case COLUPF:
myLinesSinceChange = 0;
myPlayfield.setColor(value & 0xFE);
value &= 0xFE;
myPlayfield.setColor(value);
myBall.setColor(value);
break;
case PF0:
@ -286,8 +291,10 @@ bool TIA::poke(uInt16 address, uInt8 value)
break;
case GRP1:
myLinesSinceChange = 0;
myDelayQueue.push(GRP1, value, Delay::grp);
myDelayQueue.push(DummyRegisters::shuffleP0, 0, Delay::shufflePlayer);
myBall.shuffleStatus();
break;
case RESP0:
@ -327,6 +334,25 @@ bool TIA::poke(uInt16 address, uInt8 value)
case HMP1:
myDelayQueue.push(HMP1, value, Delay::hmp);
break;
case ENABL:
myLinesSinceChange = 0;
myBall.enabl(value);
break;
case RESBL:
myLinesSinceChange = 0;
myBall.resbl(myHstate == HState::blank);
break;
case VDELBL:
myLinesSinceChange = 0;
myBall.vdelbl(value);
break;
case HMBL:
myDelayQueue.push(HMBL, value, Delay::hmbl);
break;
}
return true;
@ -556,6 +582,7 @@ void TIA::tickMovement()
m = myMissile1.movementTick(myMovementClock, apply) || m;
m = myPlayer0.movementTick(myMovementClock, apply) || m;
m = myPlayer1.movementTick(myMovementClock, apply) || m;
m = myBall.movementTick(myMovementClock, apply) || m;
myMovementInProgress = m;
myCollisionUpdateRequired = m;
@ -605,7 +632,7 @@ void TIA::renderSprites()
myPlayer1.render();
myMissile0.render();
myMissile1.render();
myBall.render();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -615,6 +642,7 @@ void TIA::tickSprites()
myMissile1.tick();
myPlayer0.tick();
myPlayer1.tick();
myBall.tick();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -644,6 +672,7 @@ void TIA::renderPixel(uInt32 x, uInt32 y, bool lineNotCached)
if (myPriority == Priority::normal) {
color = myPlayfield.getPixel(color);
color = myBall.getPixel(color);
color = myMissile1.getPixel(color);
color = myPlayer1.getPixel(color);
color = myMissile0.getPixel(color);
@ -654,6 +683,7 @@ void TIA::renderPixel(uInt32 x, uInt32 y, bool lineNotCached)
color = myMissile0.getPixel(color);
color = myPlayer0.getPixel(color);
color = myPlayfield.getPixel(color);
color = myBall.getPixel(color);
}
myCurrentFrameBuffer.get()[y * 160 + x] = myFrameManager.vblank() ? 0 : color;
@ -690,6 +720,7 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
myMissile1.startMovement();
myPlayer0.startMovement();
myPlayer1.startMovement();
myBall.startMovement();
break;
case PF0:
@ -723,6 +754,7 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
myMissile1.hmm(0);
myPlayer0.hmp(0);
myPlayer1.hmp(0);
myBall.hmbl(0);
break;
case GRP0:
@ -754,6 +786,11 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
myLinesSinceChange = 0;
myPlayer1.hmp(value);
break;
case HMBL:
myLinesSinceChange = 0;
myBall.hmbl(value);
break;
}
}

View File

@ -30,6 +30,7 @@
#include "Playfield.hxx"
#include "Missile.hxx"
#include "Player.hxx"
#include "Ball.hxx"
class Console;
@ -192,6 +193,7 @@ class TIA : public AbstractTIA
Missile myMissile1;
Player myPlayer0;
Player myPlayer1;
Ball myBall;
private:
TIA() = delete;

View File

@ -8,8 +8,8 @@ MODULE_OBJS := \
src/emucore/tia/core_6502ts/Playfield.o \
src/emucore/tia/core_6502ts/DrawCounterDecodes.o \
src/emucore/tia/core_6502ts/Missile.o \
src/emucore/tia/core_6502ts/Player.o
src/emucore/tia/core_6502ts/Player.o \
src/emucore/tia/core_6502ts/Ball.o
MODULE_DIRS += \
src/emucore/tia/core_6502ts