Playfield.

This commit is contained in:
Christian Speckner 2016-11-16 01:18:44 +01:00
parent 2d76b7fb98
commit cdafe8d0a4
5 changed files with 311 additions and 7 deletions

View File

@ -0,0 +1,142 @@
//============================================================================
//
// 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 "Playfield.hxx"
namespace TIA6502tsCore {
Playfield::Playfield(uInt32 collisionMask)
: myCollisionMask(collisionMask)
{
reset();
}
void Playfield::reset()
{
myPattern = 0;
myReflected = false;
myRefp = false;
myPf0 = 0;
myPf1 = 0;
myPf2 = 0;
myColor = 0;
myColorP0 = 0;
myColorP1 = 0;
myColorMode = ColorMode::normal;
collision = 0;
applyColors();
}
void Playfield::pf0(uInt8 value)
{
myPattern = (myPattern & 0x000FFFF0) | ((value & 0xF0) >> 4);
}
void Playfield::pf1(uInt8 value)
{
myPattern = (myPattern & 0x000FF00F)
| ((value & 0x80) >> 3)
| ((value & 0x40) >> 1)
| ((value & 0x20) << 1)
| ((value & 0x10) << 3)
| ((value & 0x08) << 5)
| ((value & 0x04) << 7)
| ((value & 0x02) << 9)
| ((value & 0x01) << 11);
}
void Playfield::pf2(uInt8 value)
{
myPattern = (myPattern & 0x00000FFF) | ((value & 0xFF) << 12);
}
void Playfield::ctrlpf(uInt8 value)
{
myReflected = (value & 0x01) > 0;
myColorMode = (value & 0x06) == 0x02 ? ColorMode::score : ColorMode::normal;
applyColors();
}
void Playfield::setColor(uInt8 color)
{
myColor = color;
applyColors();
}
void Playfield::setColorP0(uInt8 color)
{
myColorP0 = color;
applyColors();
}
void Playfield::setColorP1(uInt8 color)
{
myColorP1 = color;
applyColors();
}
void Playfield::tick(uInt32 x)
{
myX = x;
if (myX == 80 || myX == 0) myRefp = myReflected;
if (x & 0x03) return;
uInt32 currentPixel;
if (myPattern == 0) {
currentPixel = 0;
} else if (x < 80) {
currentPixel = myPattern & (1 << (x >> 2));
} else if (myRefp) {
currentPixel = myPattern & (1 << (39 - (x >> 2)));
} else {
currentPixel = myPattern & (1 << ((x >> 2) - 20));
}
collision = currentPixel ? 0 : myCollisionMask;
}
uInt8 Playfield::getPixel(uInt8 colorIn) const
{
if (!collision) return myX < 80 ? myColorLeft : myColorRight;
return colorIn;
}
void Playfield::applyColors()
{
switch (myColorMode) {
case ColorMode::normal:
myColorLeft = myColorRight = myColor;
break;
case ColorMode::score:
myColorLeft = myColorP0;
myColorRight = myColorP1;
break;
}
}
} // 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_PLAYFIELD
#define TIA_6502TS_CORE_PLAYFIELD
#include "bspf.hxx"
namespace TIA6502tsCore {
class Playfield {
public:
Playfield(uInt32 collisionMask);
public:
void reset();
void pf0(uInt8 value);
void pf1(uInt8 value);
void pf2(uInt8 value);
void ctrlpf(uInt8 value);
void setColor(uInt8 color);
void setColorP0(uInt8 color);
void setColorP1(uInt8 color);
void tick(uInt32 x);
uInt8 getPixel(uInt8 colorIn) const;
public:
uInt32 collision;
private:
enum ColorMode {normal, score};
private:
void applyColors();
private:
uInt8 myColorLeft;
uInt8 myColorRight;
uInt8 myColorP0;
uInt8 myColorP1;
uInt8 myColor;
ColorMode myColorMode;
uInt32 myPattern;
bool myRefp;
bool myReflected;
uInt8 myPf0;
uInt8 myPf1;
uInt8 myPf2;
uInt32 myX;
uInt32 myCollisionMask;
private:
Playfield() = delete;
Playfield(const Playfield&) = delete;
Playfield(Playfield&&) = delete;
Playfield& operator=(const Playfield&) = delete;
Playfield& operator=(Playfield&&) = delete;
};
} // namespace TIA6502tsCore
#endif // TIA_6502TS_CORE_PLAYFIELD

View File

@ -21,13 +21,23 @@
#include "TIATypes.hxx"
#include "M6502.hxx"
enum CollisionMask : uInt32 {
player0 = 0b0111110000000000,
player1 = 0b0100001111000000,
missile0 = 0b0010001000111000,
missile1 = 0b0001000100100110,
ball = 0b0000100010010101,
playfield = 0b0000010001001011
};
namespace TIA6502tsCore {
TIA::TIA(Console& console, Sound& sound, Settings& settings)
: myConsole(console),
mySound(sound),
mySettings(settings),
myDelayQueue(10, 20)
myDelayQueue(10, 20),
myPlayfield(CollisionMask::playfield)
{
myFrameManager.setHandlers(
[this] () {onFrameStart();},
@ -56,6 +66,8 @@ void TIA::reset()
myLastCycle = 0;
myPlayfield.reset();
mySound.reset();
myDelayQueue.reset();
myFrameManager.reset();
@ -135,6 +147,49 @@ bool TIA::poke(uInt16 address, uInt8 value)
case AUDC1:
mySound.set(address, value, mySystem->cycles());
break;
case COLUP0:
myLinesSinceChange = 0;
myPlayfield.setColorP0(value & 0xFE);
break;
case COLUP1:
myLinesSinceChange = 0;
myPlayfield.setColorP1(value & 0xFE);
break;
case CTRLPF:
myLinesSinceChange = 0;
myPriority = (value & 0x04) ? Priority::inverted : Priority::normal;
myPlayfield.ctrlpf(value);
break;
case COLUPF:
myLinesSinceChange = 0;
myPlayfield.setColor(value & 0xFE);
break;
case PF0:
myLinesSinceChange = 0;
myPlayfield.pf0(value);
break;
case PF1:
myLinesSinceChange = 0;
myPlayfield.pf1(value);
break;
case PF2:
myLinesSinceChange = 0;
myPlayfield.pf2(value);
break;
}
return true;
@ -354,7 +409,7 @@ void TIA::tickHframe()
myCollisionUpdateRequired = lineNotCached;
// TODO: playfield tick
myPlayfield.tick(x);
// TODO: render sprites
@ -387,7 +442,11 @@ void TIA::renderPixel(uInt32 x, uInt32 y, bool lineNotCached)
if (lineNotCached) {
uInt8 color = 0;
// TODO: determine color from sprites
if (myPriority == Priority::normal) {
color = myPlayfield.getPixel(color);
} else {
color = myPlayfield.getPixel(color);
}
myCurrentFrameBuffer.get()[y * 160 + x] = myFrameManager.vblank() ? 0 : color;
} else {

View File

@ -17,8 +17,8 @@
// $Id$
//============================================================================
#ifndef TIA_6502TS_CORE
#define TIA_6502TS_CORE
#ifndef TIA_6502TS_CORE_TIA
#define TIA_6502TS_CORE_TIA
#include "bspf.hxx"
#include "AbstractTIA.hxx"
@ -27,6 +27,7 @@
#include "TIATypes.hxx"
#include "DelayQueue.hxx"
#include "FrameManager.hxx"
#include "Playfield.hxx"
class Console;
@ -177,6 +178,8 @@ class TIA : public AbstractTIA {
BytePtr myCurrentFrameBuffer;
BytePtr myPreviousFrameBuffer;
Playfield myPlayfield;
private:
TIA() = delete;
@ -189,4 +192,4 @@ class TIA : public AbstractTIA {
} // namespace TIA6502tsCore
#endif // TIA_6502TS_CORE
#endif // TIA_6502TS_CORE_TIA

View File

@ -4,7 +4,8 @@ MODULE_OBJS := \
src/emucore/tia/core_6502ts/TIA.o \
src/emucore/tia/core_6502ts/DelayQueueMember.o \
src/emucore/tia/core_6502ts/DelayQueue.o \
src/emucore/tia/core_6502ts/FrameManager.o
src/emucore/tia/core_6502ts/FrameManager.o \
src/emucore/tia/core_6502ts/Playfield.o
MODULE_DIRS += \