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
|
|
|
|
//
|
2019-12-31 17:18:56 +00:00
|
|
|
// Copyright (c) 1995-2020 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"
|
2017-04-23 21:37:30 +00:00
|
|
|
#include "TIA.hxx"
|
2016-11-16 00:18:44 +00:00
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
Playfield::Playfield(uInt32 collisionMask)
|
2019-12-29 22:06:56 +00:00
|
|
|
: myCollisionMaskDisabled(collisionMask)
|
2016-11-16 00:18:44 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
void Playfield::reset()
|
|
|
|
{
|
|
|
|
myPattern = 0;
|
|
|
|
myReflected = false;
|
|
|
|
myRefp = false;
|
|
|
|
|
|
|
|
myPf0 = 0;
|
|
|
|
myPf1 = 0;
|
|
|
|
myPf2 = 0;
|
|
|
|
|
2018-03-24 19:28:08 +00:00
|
|
|
myX = 0;
|
|
|
|
|
2016-12-04 18:18:17 +00:00
|
|
|
myObjectColor = myDebugColor = 0;
|
2018-03-24 19:28:08 +00:00
|
|
|
myColorLeft = myColorRight = 0;
|
|
|
|
myColorP0 = myColorP1 = 0;
|
2016-11-16 00:18:44 +00:00
|
|
|
myColorMode = ColorMode::normal;
|
2016-12-04 18:18:17 +00:00
|
|
|
myDebugEnabled = false;
|
2016-11-16 00:18:44 +00:00
|
|
|
|
|
|
|
collision = 0;
|
|
|
|
|
2016-12-02 07:58:19 +00:00
|
|
|
updatePattern();
|
2016-11-16 00:18:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
void Playfield::pf0(uInt8 value)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
if (myPf0 == value >> 4) return;
|
|
|
|
|
|
|
|
myTIA->flushLineCache();
|
|
|
|
|
2016-11-25 22:23:04 +00:00
|
|
|
myPattern = (myPattern & 0x000FFFF0) | (value >> 4);
|
2017-04-23 21:37:30 +00:00
|
|
|
myPf0 = value >> 4;
|
2016-12-02 07:58:19 +00:00
|
|
|
|
|
|
|
updatePattern();
|
2016-11-16 00:18:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
void Playfield::pf1(uInt8 value)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
if (myPf1 == value) return;
|
|
|
|
|
|
|
|
myTIA->flushLineCache();
|
|
|
|
|
2016-11-16 00:18:44 +00:00
|
|
|
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
|
|
|
|
2016-12-10 20:07:47 +00:00
|
|
|
myPf1 = value;
|
2016-12-02 07:58:19 +00:00
|
|
|
updatePattern();
|
2016-11-16 00:18:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
void Playfield::pf2(uInt8 value)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
if (myPf2 == value) return;
|
|
|
|
|
|
|
|
myTIA->flushLineCache();
|
|
|
|
|
2016-11-25 22:23:04 +00:00
|
|
|
myPattern = (myPattern & 0x00000FFF) | (value << 12);
|
2016-12-10 20:07:47 +00:00
|
|
|
myPf2 = value;
|
2016-12-02 07:58:19 +00:00
|
|
|
|
|
|
|
updatePattern();
|
2016-11-16 00:18:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
void Playfield::ctrlpf(uInt8 value)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
const bool reflected = (value & 0x01) > 0;
|
|
|
|
const ColorMode colorMode = (value & 0x06) == 0x02 ? ColorMode::score : ColorMode::normal;
|
|
|
|
|
|
|
|
if (myReflected == reflected && myColorMode == colorMode) return;
|
|
|
|
|
|
|
|
myTIA->flushLineCache();
|
|
|
|
|
|
|
|
myReflected = reflected;
|
|
|
|
myColorMode = colorMode;
|
2016-11-16 00:18:44 +00:00
|
|
|
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)
|
|
|
|
{
|
2019-03-24 20:14:45 +00:00
|
|
|
// Only keep bit 15 active if collisions are disabled.
|
2016-12-02 08:05:35 +00:00
|
|
|
myCollisionMaskEnabled = enabled ? 0xFFFF : (0x8000 | myCollisionMaskDisabled);
|
2016-12-02 07:58:19 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
void Playfield::setColor(uInt8 color)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
if (color != myObjectColor && myColorMode == ColorMode::normal) myTIA->flushLineCache();
|
|
|
|
|
2016-12-04 18:18:17 +00:00
|
|
|
myObjectColor = color;
|
2016-11-16 00:18:44 +00:00
|
|
|
applyColors();
|
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
void Playfield::setColorP0(uInt8 color)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
if (color != myColorP0 && myColorMode == ColorMode::score) myTIA->flushLineCache();
|
|
|
|
|
2016-11-16 00:18:44 +00:00
|
|
|
myColorP0 = color;
|
|
|
|
applyColors();
|
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2016-11-16 00:18:44 +00:00
|
|
|
void Playfield::setColorP1(uInt8 color)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
if (color != myColorP1 && myColorMode == ColorMode::score) myTIA->flushLineCache();
|
|
|
|
|
2016-11-16 00:18:44 +00:00
|
|
|
myColorP1 = color;
|
|
|
|
applyColors();
|
|
|
|
}
|
|
|
|
|
2016-12-04 18:18:17 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Playfield::setDebugColor(uInt8 color)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
myTIA->flushLineCache();
|
2017-11-09 14:55:56 +00:00
|
|
|
// allow slight luminance variations without changing color
|
|
|
|
if((color & 0xe) == 0xe)
|
|
|
|
color -= 2;
|
|
|
|
if((color & 0xe) == 0x0)
|
|
|
|
color += 2;
|
2016-12-04 18:18:17 +00:00
|
|
|
myDebugColor = color;
|
|
|
|
applyColors();
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Playfield::enableDebugColors(bool enabled)
|
|
|
|
{
|
2017-04-23 21:37:30 +00:00
|
|
|
myTIA->flushLineCache();
|
2016-12-04 18:18:17 +00:00
|
|
|
myDebugEnabled = enabled;
|
|
|
|
applyColors();
|
|
|
|
}
|
|
|
|
|
2017-05-12 18:59:46 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Playfield::applyColorLoss()
|
|
|
|
{
|
|
|
|
myTIA->flushLineCache();
|
|
|
|
applyColors();
|
|
|
|
}
|
|
|
|
|
2018-02-08 19:53:42 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Playfield::nextLine()
|
|
|
|
{
|
|
|
|
collision = myCollisionMaskDisabled;
|
|
|
|
}
|
|
|
|
|
2016-11-22 19:14:20 +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-11-22 19:14:20 +00:00
|
|
|
{
|
2016-12-04 18:18:17 +00:00
|
|
|
switch (myColorMode)
|
|
|
|
{
|
|
|
|
case ColorMode::normal:
|
2017-05-12 18:59:46 +00:00
|
|
|
if (myTIA->colorLossActive())
|
|
|
|
myColorLeft = myColorRight = myObjectColor |= 0x01;
|
|
|
|
else
|
|
|
|
myColorLeft = myColorRight = myObjectColor &= 0xfe;
|
2016-12-04 18:18:17 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ColorMode::score:
|
2017-05-12 18:59:46 +00:00
|
|
|
if (myTIA->colorLossActive())
|
|
|
|
{
|
|
|
|
myColorLeft = myColorP0 |= 0x01;
|
|
|
|
myColorRight = myColorP1 |= 0x01;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
myColorLeft = myColorP0 &= 0xfe;
|
|
|
|
myColorRight = myColorP1 &= 0xfe;
|
|
|
|
}
|
2016-12-04 18:18:17 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-11-16 00:18:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-09 14:55:56 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
uInt8 Playfield::getColor() const
|
|
|
|
{
|
|
|
|
if (!myDebugEnabled)
|
2019-03-01 23:08:22 +00:00
|
|
|
return myX < TIAConstants::H_PIXEL / 2 ? myColorLeft : myColorRight;
|
2017-11-09 14:55:56 +00:00
|
|
|
else
|
|
|
|
{
|
2019-03-01 23:08:22 +00:00
|
|
|
if (myX < TIAConstants::H_PIXEL / 2)
|
2017-11-09 14:55:56 +00:00
|
|
|
{
|
|
|
|
// left side:
|
|
|
|
if(myX < 16)
|
|
|
|
return myDebugColor - 2; // PF0
|
|
|
|
if(myX < 48)
|
|
|
|
return myDebugColor; // PF1
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// right side:
|
|
|
|
if(!myReflected)
|
|
|
|
{
|
2019-03-01 23:08:22 +00:00
|
|
|
if(myX < TIAConstants::H_PIXEL / 2 + 16)
|
2017-11-09 14:55:56 +00:00
|
|
|
return myDebugColor - 2; // PF0
|
2019-03-01 23:08:22 +00:00
|
|
|
if(myX < TIAConstants::H_PIXEL / 2 + 48)
|
2017-11-09 14:55:56 +00:00
|
|
|
return myDebugColor; // PF1
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-03-01 23:08:22 +00:00
|
|
|
if(myX >= TIAConstants::H_PIXEL - 16)
|
2017-11-09 14:55:56 +00:00
|
|
|
return myDebugColor - 2; // PF0
|
2019-03-01 23:08:22 +00:00
|
|
|
if(myX >= TIAConstants::H_PIXEL - 48)
|
2017-11-09 14:55:56 +00:00
|
|
|
return myDebugColor; // PF1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return myDebugColor + 2; // PF2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-11-25 18:28:07 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
bool Playfield::save(Serializer& out) const
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2017-02-12 02:00:58 +00:00
|
|
|
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);
|
|
|
|
|
2018-11-19 14:38:44 +00:00
|
|
|
out.putByte(uInt8(myColorMode));
|
2017-02-12 02:00:58 +00:00
|
|
|
|
|
|
|
out.putInt(myPattern);
|
|
|
|
out.putInt(myEffectivePattern);
|
|
|
|
out.putBool(myRefp);
|
|
|
|
out.putBool(myReflected);
|
|
|
|
|
|
|
|
out.putByte(myPf0);
|
|
|
|
out.putByte(myPf1);
|
|
|
|
out.putByte(myPf2);
|
|
|
|
|
|
|
|
out.putInt(myX);
|
2016-11-25 18:28:07 +00:00
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
cerr << "ERROR: TIA_Playfield::save" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-02-21 00:35:54 +00:00
|
|
|
return true;
|
2016-11-25 18:28:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
bool Playfield::load(Serializer& in)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2017-02-12 02:00:58 +00:00
|
|
|
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();
|
|
|
|
|
2017-10-11 14:53:54 +00:00
|
|
|
myColorMode = ColorMode(in.getByte());
|
2017-02-12 02:00:58 +00:00
|
|
|
|
|
|
|
myPattern = in.getInt();
|
|
|
|
myEffectivePattern = in.getInt();
|
|
|
|
myRefp = in.getBool();
|
|
|
|
myReflected = in.getBool();
|
|
|
|
|
|
|
|
myPf0 = in.getByte();
|
|
|
|
myPf1 = in.getByte();
|
|
|
|
myPf2 = in.getByte();
|
|
|
|
|
|
|
|
myX = in.getInt();
|
2017-02-12 02:07:11 +00:00
|
|
|
|
|
|
|
applyColors();
|
|
|
|
updatePattern();
|
2016-11-25 18:28:07 +00:00
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
cerr << "ERROR: TIA_Playfield::load" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-02-21 00:35:54 +00:00
|
|
|
return true;
|
2016-11-25 18:28:07 +00:00
|
|
|
}
|