stella/src/emucore/tia/Playfield.cxx

284 lines
6.6 KiB
C++
Raw Normal View History

2016-11-16 00:18:44 +00:00
//============================================================================
//
// 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
2016-11-16 00:18:44 +00:00
// 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.
//============================================================================
#include "Playfield.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
Playfield::Playfield(uInt32 collisionMask)
2016-12-02 07:58:19 +00:00
: myCollisionMaskDisabled(collisionMask),
myCollisionMaskEnabled(0xFFFF),
2016-12-02 08:30:40 +00:00
myIsSuppressed(false)
2016-11-16 00:18:44 +00:00
{
reset();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::reset()
{
myPattern = 0;
myReflected = false;
myRefp = false;
myPf0 = 0;
myPf1 = 0;
myPf2 = 0;
2016-12-04 18:18:17 +00:00
myObjectColor = myDebugColor = 0;
2016-11-16 00:18:44 +00:00
myColorP0 = 0;
myColorP1 = 0;
myColorMode = ColorMode::normal;
2016-12-04 18:18:17 +00:00
myDebugEnabled = false;
2016-11-16 00:18:44 +00:00
collision = 0;
applyColors();
2016-12-02 07:58:19 +00:00
updatePattern();
2016-11-16 00:18:44 +00:00
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::pf0(uInt8 value)
{
2016-11-25 22:23:04 +00:00
myPattern = (myPattern & 0x000FFFF0) | (value >> 4);
myPf0 = value;
2016-12-02 07:58:19 +00:00
updatePattern();
2016-11-16 00:18:44 +00:00
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::pf1(uInt8 value)
{
myPattern = (myPattern & 0x000FF00F)
| ((value & 0x80) >> 3)
| ((value & 0x40) >> 1)
2016-12-04 18:18:17 +00:00
| ((value & 0x20) << 1)
| ((value & 0x10) << 3)
| ((value & 0x08) << 5)
| ((value & 0x04) << 7)
| ((value & 0x02) << 9)
| ((value & 0x01) << 11);
2016-12-02 07:58:19 +00:00
myPf1 = value;
2016-12-02 07:58:19 +00:00
updatePattern();
2016-11-16 00:18:44 +00:00
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::pf2(uInt8 value)
{
2016-11-25 22:23:04 +00:00
myPattern = (myPattern & 0x00000FFF) | (value << 12);
myPf2 = value;
2016-12-02 07:58:19 +00:00
updatePattern();
2016-11-16 00:18:44 +00:00
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::ctrlpf(uInt8 value)
{
myReflected = (value & 0x01) > 0;
myColorMode = (value & 0x06) == 0x02 ? ColorMode::score : ColorMode::normal;
applyColors();
}
2016-12-02 07:58:19 +00:00
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Playfield::toggleEnabled(bool enabled)
{
2016-12-02 08:30:40 +00:00
myIsSuppressed = !enabled;
2016-12-02 07:58:19 +00:00
updatePattern();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Playfield::toggleCollisions(bool enabled)
{
myCollisionMaskEnabled = enabled ? 0xFFFF : (0x8000 | myCollisionMaskDisabled);
2016-12-02 07:58:19 +00:00
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::setColor(uInt8 color)
{
2016-12-04 18:18:17 +00:00
myObjectColor = color;
2016-11-16 00:18:44 +00:00
applyColors();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::setColorP0(uInt8 color)
{
myColorP0 = color;
applyColors();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::setColorP1(uInt8 color)
{
myColorP1 = color;
applyColors();
}
2016-12-04 18:18:17 +00:00
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Playfield::setDebugColor(uInt8 color)
{
myDebugColor = color;
applyColors();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Playfield::enableDebugColors(bool enabled)
{
myDebugEnabled = enabled;
applyColors();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::tick(uInt32 x)
{
myX = x;
if (myX == 80 || myX == 0) myRefp = myReflected;
if (x & 0x03) return;
uInt32 currentPixel;
2016-12-02 07:58:19 +00:00
if (myEffectivePattern == 0) {
2016-11-16 00:18:44 +00:00
currentPixel = 0;
} else if (x < 80) {
2016-12-02 07:58:19 +00:00
currentPixel = myEffectivePattern & (1 << (x >> 2));
2016-11-16 00:18:44 +00:00
} else if (myRefp) {
2016-12-02 07:58:19 +00:00
currentPixel = myEffectivePattern & (1 << (39 - (x >> 2)));
2016-11-16 00:18:44 +00:00
} else {
2016-12-02 07:58:19 +00:00
currentPixel = myEffectivePattern & (1 << ((x >> 2) - 20));
2016-11-16 00:18:44 +00:00
}
2016-12-02 07:58:19 +00:00
collision = currentPixel ? myCollisionMaskEnabled : myCollisionMaskDisabled;
2016-11-16 00:18:44 +00:00
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-11-16 00:18:44 +00:00
void Playfield::applyColors()
{
2016-12-04 18:18:17 +00:00
if (myDebugEnabled)
myColorLeft = myColorRight = myDebugColor;
else
{
2016-12-04 18:18:17 +00:00
switch (myColorMode)
{
case ColorMode::normal:
myColorLeft = myColorRight = myObjectColor;
break;
case ColorMode::score:
myColorLeft = myColorP0;
myColorRight = myColorP1;
break;
}
2016-11-16 00:18:44 +00:00
}
}
2016-12-02 07:58:19 +00:00
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Playfield::updatePattern()
{
2016-12-02 08:30:40 +00:00
myEffectivePattern = myIsSuppressed ? 0 : myPattern;
2016-12-02 07:58:19 +00:00
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Playfield::save(Serializer& out) const
{
try
{
out.putString(name());
out.putInt(collision);
out.putInt(myCollisionMaskDisabled);
out.putInt(myCollisionMaskEnabled);
out.putBool(myIsSuppressed);
out.putByte(myColorLeft);
out.putByte(myColorRight);
out.putByte(myColorP0);
out.putByte(myColorP1);
out.putByte(myObjectColor);
out.putByte(myDebugColor);
out.putBool(myDebugEnabled);
out.putByte(myColorMode);
out.putInt(myPattern);
out.putInt(myEffectivePattern);
out.putBool(myRefp);
out.putBool(myReflected);
out.putByte(myPf0);
out.putByte(myPf1);
out.putByte(myPf2);
out.putInt(myX);
}
catch(...)
{
cerr << "ERROR: TIA_Playfield::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Playfield::load(Serializer& in)
{
try
{
if(in.getString() != name())
return false;
collision = in.getInt();
myCollisionMaskDisabled = in.getInt();
myCollisionMaskEnabled = in.getInt();
myIsSuppressed = in.getBool();
myColorLeft = in.getByte();
myColorRight = in.getByte();
myColorP0 = in.getByte();
myColorP1 = in.getByte();
myObjectColor = in.getByte();
myDebugColor = in.getByte();
myDebugEnabled = in.getBool();
myColorMode = (ColorMode)in.getByte();
myPattern = in.getInt();
myEffectivePattern = in.getInt();
myRefp = in.getBool();
myReflected = in.getBool();
myPf0 = in.getByte();
myPf1 = in.getByte();
myPf2 = in.getByte();
myX = in.getInt();
applyColors();
updatePattern();
}
catch(...)
{
cerr << "ERROR: TIA_Playfield::load" << endl;
return false;
}
return true;
}