mirror of https://github.com/stella-emu/stella.git
enhanced and optimized auto-phosphor
This commit is contained in:
parent
274490128f
commit
0aeffe0392
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
* Added option to start random ROM.
|
* Added option to start random ROM.
|
||||||
|
|
||||||
* Added option for automatic phosphor.
|
* Added automatically enabled phosphor modes.
|
||||||
|
|
||||||
* Enhanced Game Properties dialog for multigame ROMs.
|
* Enhanced Game Properties dialog for multigame ROMs.
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
@ -1310,7 +1310,12 @@
|
||||||
<td>Cmd + 3</td>
|
<td>Cmd + 3</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><i>Increase</i> 'phosphor' enabling mode</td>
|
<td>Select <i>previous</i> 'phosphor' enabling mode</td>
|
||||||
|
<td>-</td>
|
||||||
|
<td>-</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Select <i>next</i> 'phosphor' enabling mode</td>
|
||||||
<td>Ctrl-Alt + P</td>
|
<td>Ctrl-Alt + P</td>
|
||||||
<td>Ctrl-Cmd + P</td>
|
<td>Ctrl-Cmd + P</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1356,7 +1361,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3"><center><font size="-1">
|
<td colspan="3"><center><font size="-1">
|
||||||
Items marked as (*) will also switch to 'Custom' mode</font></center></td>
|
Items marked as (*) will also switch to 'Custom' TV effects mode</font></center></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -2926,11 +2931,13 @@
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><pre>-tv.phosphor <always|auto|byrom></pre></td>
|
<td><pre>-tv.phosphor <byrom|always|autoon|auto></pre></td>
|
||||||
<td>Determine how phosphor mode is enabled. If 'always' or 'auto', then
|
<td>Determine how phosphor mode is enabled. If 'byrom', then the ROM
|
||||||
the ROM properties entry is ignored, and phosphor mode is either always
|
properties determine whether phosphor mode is used for each ROM.
|
||||||
turned on or automatic. Otherwise, the ROM properties determine whether
|
Else the ROM properties entry is ignored. If 'always', then the
|
||||||
phosphor mode is used for each ROM.
|
phosphor mode is always enabled. If 'autoon', then the phosphor
|
||||||
|
mode is enabled automatically. If 'auto', then the phosphor mode
|
||||||
|
is enabled/disabled on automatically.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -3826,8 +3833,8 @@
|
||||||
<tr><td>TV mode</td><td>Disable TV effects, or select TV preset</td><td>-tv.filter</td></tr>
|
<tr><td>TV mode</td><td>Disable TV effects, or select TV preset</td><td>-tv.filter</td></tr>
|
||||||
<tr><td>Adjustable sliders</td><td>Set specific attribute in 'Custom' TV mode</td><td>-tv.sharpness<br/>-tv.resolution, etc.</td></tr>
|
<tr><td>Adjustable sliders</td><td>Set specific attribute in 'Custom' TV mode</td><td>-tv.sharpness<br/>-tv.resolution, etc.</td></tr>
|
||||||
<tr><td>Phosphor</td><td>Select mode for enabling phosphor</td><td>-tv.phosphor</td></tr>
|
<tr><td>Phosphor</td><td>Select mode for enabling phosphor</td><td>-tv.phosphor</td></tr>
|
||||||
<tr><td>Blend (phosphor)</td><td>Blend level to use in phosphor modes for all ROMs and automatic
|
<tr><td>Blend (phosphor)</td><td>Blend level to use in phosphor modes for all ROMs and automatic ones
|
||||||
(needs to be manually adjusted for your particular hardware)</td><td>-tv.phosblend</td></tr>
|
(level needs to be manually adjusted for your particular hardware)</td><td>-tv.phosblend</td></tr>
|
||||||
<tr><td>(Scanlines) Intensity</td><td>Sets scanlines black-level intensity.</br>
|
<tr><td>(Scanlines) Intensity</td><td>Sets scanlines black-level intensity.</br>
|
||||||
Note: No scanlines in 1x mode snapshots</td><td>-tv.scanlines</td></tr>
|
Note: No scanlines in 1x mode snapshots</td><td>-tv.scanlines</td></tr>
|
||||||
<tr><td>(Scanlines) Mask</td><td>Sets the scanlines mask.</br>
|
<tr><td>(Scanlines) Mask</td><td>Sets the scanlines mask.</br>
|
||||||
|
|
|
@ -660,7 +660,6 @@ PhysicalKeyboardHandler::DefaultCommonMapping = {
|
||||||
{ Event::PhosphorDecrease, KBDK_4, KBDM_SHIFT | MOD3 },
|
{ Event::PhosphorDecrease, KBDK_4, KBDM_SHIFT | MOD3 },
|
||||||
{ Event::PhosphorIncrease, KBDK_4, MOD3 },
|
{ Event::PhosphorIncrease, KBDK_4, MOD3 },
|
||||||
{ Event::TogglePhosphor, KBDK_P, MOD3 },
|
{ Event::TogglePhosphor, KBDK_P, MOD3 },
|
||||||
{ Event::PhosphorModeDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL | MOD3 },
|
|
||||||
{ Event::PhosphorModeIncrease, KBDK_P, KBDM_CTRL | MOD3 },
|
{ Event::PhosphorModeIncrease, KBDK_P, KBDM_CTRL | MOD3 },
|
||||||
{ Event::ScanlinesDecrease, KBDK_5, KBDM_SHIFT | MOD3 },
|
{ Event::ScanlinesDecrease, KBDK_5, KBDM_SHIFT | MOD3 },
|
||||||
{ Event::ScanlinesIncrease, KBDK_5, MOD3 },
|
{ Event::ScanlinesIncrease, KBDK_5, MOD3 },
|
||||||
|
|
|
@ -46,5 +46,30 @@ bool PhosphorHandler::initialize(bool enable, int blend)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
PhosphorHandler::PhosphorMode PhosphorHandler::toPhosphorMode(string_view name)
|
||||||
|
{
|
||||||
|
if(name == VALUE_ALWAYS)
|
||||||
|
return PhosphorMode::Always;
|
||||||
|
|
||||||
|
if(name == VALUE_AUTO_ON)
|
||||||
|
return PhosphorMode::Auto_on;
|
||||||
|
|
||||||
|
if(name == VALUE_AUTO)
|
||||||
|
return PhosphorMode::Auto;
|
||||||
|
|
||||||
|
return PhosphorMode::ByRom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
string_view PhosphorHandler::toPhosphorName(PhosphorMode type)
|
||||||
|
{
|
||||||
|
static constexpr std::array<string_view, PhosphorMode::NumTypes> SETTING_NAMES = {
|
||||||
|
VALUE_BYROM, VALUE_ALWAYS, VALUE_AUTO_ON, VALUE_AUTO
|
||||||
|
};
|
||||||
|
|
||||||
|
return SETTING_NAMES[type];
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhosphorHandler::PhosphorLUT PhosphorHandler::ourPhosphorLUT;
|
PhosphorHandler::PhosphorLUT PhosphorHandler::ourPhosphorLUT;
|
||||||
|
|
|
@ -24,12 +24,34 @@
|
||||||
class PhosphorHandler
|
class PhosphorHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Phosphor settings names
|
||||||
|
static constexpr string_view SETTING_MODE = "tv.phosphor";
|
||||||
|
static constexpr string_view SETTING_BLEND = "tv.phosblend";
|
||||||
|
// Setting values of phosphor modes
|
||||||
|
static constexpr string_view VALUE_BYROM = "byrom";
|
||||||
|
static constexpr string_view VALUE_ALWAYS = "always";
|
||||||
|
static constexpr string_view VALUE_AUTO_ON = "autoon";
|
||||||
|
static constexpr string_view VALUE_AUTO = "auto";
|
||||||
|
|
||||||
|
enum PhosphorMode {
|
||||||
|
ByRom,
|
||||||
|
Always,
|
||||||
|
Auto_on,
|
||||||
|
Auto,
|
||||||
|
NumTypes
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr string_view DEFAULT_BLEND = "50"; // align with myPhosphorPercent!
|
||||||
|
|
||||||
PhosphorHandler() = default;
|
PhosphorHandler() = default;
|
||||||
|
|
||||||
bool initialize(bool enable, int blend);
|
bool initialize(bool enable, int blend);
|
||||||
|
|
||||||
bool phosphorEnabled() const { return myUsePhosphor; }
|
bool phosphorEnabled() const { return myUsePhosphor; }
|
||||||
|
|
||||||
|
static PhosphorMode toPhosphorMode(string_view name);
|
||||||
|
static string_view toPhosphorName(PhosphorMode type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Used to calculate an averaged color pixel for the 'phosphor' effect.
|
Used to calculate an averaged color pixel for the 'phosphor' effect.
|
||||||
|
|
||||||
|
|
|
@ -534,19 +534,21 @@ void Console::setFormat(uInt32 format, bool force)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Console::toggleColorLoss(bool toggle)
|
void Console::toggleColorLoss(bool toggle)
|
||||||
{
|
{
|
||||||
const bool colorloss = !myTIA->colorLossEnabled();
|
bool colorloss = myTIA->colorLossEnabled();
|
||||||
if(myTIA->enableColorLoss(colorloss))
|
if(toggle)
|
||||||
{
|
{
|
||||||
myOSystem.settings().setValue(
|
colorloss = !colorloss;
|
||||||
myOSystem.settings().getBool("dev.settings") ? "dev.colorloss" : "plr.colorloss", colorloss);
|
if(myTIA->enableColorLoss(colorloss))
|
||||||
|
myOSystem.settings().setValue(
|
||||||
const string message = string("PAL color-loss ") +
|
myOSystem.settings().getBool("dev.settings") ? "dev.colorloss" : "plr.colorloss", colorloss);
|
||||||
(colorloss ? "enabled" : "disabled");
|
else {
|
||||||
myOSystem.frameBuffer().showTextMessage(message);
|
myOSystem.frameBuffer().showTextMessage(
|
||||||
|
"PAL color-loss not available in non PAL modes");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
const string message = string("PAL color-loss ") + (colorloss ? "enabled" : "disabled");
|
||||||
myOSystem.frameBuffer().showTextMessage(
|
myOSystem.frameBuffer().showTextMessage(message);
|
||||||
"PAL color-loss not available in non PAL modes");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -563,12 +565,14 @@ void Console::toggleInter(bool toggle)
|
||||||
bool enabled = myOSystem.settings().getBool("tia.inter");
|
bool enabled = myOSystem.settings().getBool("tia.inter");
|
||||||
|
|
||||||
if(toggle)
|
if(toggle)
|
||||||
|
{
|
||||||
enabled = !enabled;
|
enabled = !enabled;
|
||||||
|
|
||||||
myOSystem.settings().setValue("tia.inter", enabled);
|
myOSystem.settings().setValue("tia.inter", enabled);
|
||||||
|
|
||||||
// ... and apply potential setting changes to the TIA surface
|
// Apply potential setting changes to the TIA surface
|
||||||
myOSystem.frameBuffer().tiaSurface().updateSurfaceSettings();
|
myOSystem.frameBuffer().tiaSurface().updateSurfaceSettings();
|
||||||
|
}
|
||||||
ostringstream ss;
|
ostringstream ss;
|
||||||
|
|
||||||
ss << "Interpolation " << (enabled ? "enabled" : "disabled");
|
ss << "Interpolation " << (enabled ? "enabled" : "disabled");
|
||||||
|
@ -623,18 +627,22 @@ void Console::changeSpeed(int direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Console::togglePhosphor()
|
void Console::togglePhosphor(bool toggle)
|
||||||
{
|
{
|
||||||
const bool enable = !myOSystem.frameBuffer().tiaSurface().phosphorEnabled();
|
bool enable = myOSystem.frameBuffer().tiaSurface().phosphorEnabled();
|
||||||
if(!enable)
|
|
||||||
myProperties.set(PropType::Display_Phosphor, "NO");
|
|
||||||
else
|
|
||||||
myProperties.set(PropType::Display_Phosphor, "YES");
|
|
||||||
myOSystem.frameBuffer().tiaSurface().enablePhosphor(enable);
|
|
||||||
|
|
||||||
// disable auto-phosphor
|
if(toggle)
|
||||||
if(myTIA->autoPhosphorEnabled())
|
{
|
||||||
|
enable = !enable;
|
||||||
|
if(!enable)
|
||||||
|
myProperties.set(PropType::Display_Phosphor, "NO");
|
||||||
|
else
|
||||||
|
myProperties.set(PropType::Display_Phosphor, "YES");
|
||||||
|
myOSystem.frameBuffer().tiaSurface().enablePhosphor(enable);
|
||||||
|
|
||||||
|
// disable auto-phosphor
|
||||||
myTIA->enableAutoPhosphor(false);
|
myTIA->enableAutoPhosphor(false);
|
||||||
|
}
|
||||||
|
|
||||||
ostringstream msg;
|
ostringstream msg;
|
||||||
msg << "Phosphor effect " << (enable ? "enabled" : "disabled");
|
msg << "Phosphor effect " << (enable ? "enabled" : "disabled");
|
||||||
|
@ -644,42 +652,40 @@ void Console::togglePhosphor()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Console::cyclePhosphorMode(int direction)
|
void Console::cyclePhosphorMode(int direction)
|
||||||
{
|
{
|
||||||
static constexpr std::array<string_view, 3> MESSAGES = {
|
static constexpr std::array<string_view, PhosphorHandler::NumTypes> MESSAGES = {
|
||||||
"by ROM", "always on", "auto-enabled"
|
"by ROM", "always on", "auto-enabled", "auto-enabled/disabled"
|
||||||
};
|
};
|
||||||
static constexpr std::array<string_view, 3> VALUE = {
|
PhosphorHandler::PhosphorMode mode =
|
||||||
"byrom", "always", "auto"
|
PhosphorHandler::toPhosphorMode(myOSystem.settings().getString(PhosphorHandler::SETTING_MODE));
|
||||||
};
|
|
||||||
const string value = myOSystem.settings().getString("tv.phosphor");
|
|
||||||
int mode;
|
|
||||||
|
|
||||||
for(mode = 2; mode > 0; --mode)
|
|
||||||
if(value == VALUE[mode])
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(direction)
|
if(direction)
|
||||||
{
|
{
|
||||||
mode = BSPF::clampw(mode + direction, 0, 2);
|
mode = static_cast<PhosphorHandler::PhosphorMode>
|
||||||
if(mode == 0)
|
(BSPF::clampw(mode + direction, 0, static_cast<int>(PhosphorHandler::NumTypes - 1)));
|
||||||
|
switch(mode)
|
||||||
{
|
{
|
||||||
myOSystem.frameBuffer().tiaSurface().enablePhosphor(
|
case PhosphorHandler::Always:
|
||||||
myProperties.get(PropType::Display_Phosphor) == "YES",
|
myOSystem.frameBuffer().tiaSurface().enablePhosphor(
|
||||||
BSPF::stoi(myProperties.get(PropType::Display_PPBlend)));
|
true, myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND));
|
||||||
myTIA->enableAutoPhosphor(false);
|
myTIA->enableAutoPhosphor(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PhosphorHandler::Auto_on:
|
||||||
|
case PhosphorHandler::Auto:
|
||||||
|
myOSystem.frameBuffer().tiaSurface().enablePhosphor(
|
||||||
|
false, myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND));
|
||||||
|
myTIA->enableAutoPhosphor(true, mode == PhosphorHandler::Auto_on);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // PhosphorHandler::ByRom
|
||||||
|
myOSystem.frameBuffer().tiaSurface().enablePhosphor(
|
||||||
|
myProperties.get(PropType::Display_Phosphor) == "YES",
|
||||||
|
BSPF::stoi(myProperties.get(PropType::Display_PPBlend)));
|
||||||
|
myTIA->enableAutoPhosphor(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if(mode == 1)
|
myOSystem.settings().setValue(PhosphorHandler::SETTING_MODE,
|
||||||
{
|
PhosphorHandler::toPhosphorName(mode));
|
||||||
myOSystem.frameBuffer().tiaSurface().enablePhosphor(
|
|
||||||
true, myOSystem.settings().getInt("tv.phosblend"));
|
|
||||||
myTIA->enableAutoPhosphor(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
myOSystem.frameBuffer().tiaSurface().enablePhosphor(
|
|
||||||
false, myOSystem.settings().getInt("tv.phosblend"));
|
|
||||||
myTIA->enableAutoPhosphor(true);
|
|
||||||
}
|
|
||||||
myOSystem.settings().setValue("tv.phosphor", VALUE[mode]);
|
|
||||||
}
|
}
|
||||||
ostringstream msg;
|
ostringstream msg;
|
||||||
msg << "Phosphor mode " << MESSAGES[mode];
|
msg << "Phosphor mode " << MESSAGES[mode];
|
||||||
|
@ -1217,16 +1223,17 @@ void Console::changePaddleAxesRange(int direction)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Console::toggleAutoFire(bool toggle)
|
void Console::toggleAutoFire(bool toggle)
|
||||||
{
|
{
|
||||||
const bool enabled = myOSystem.settings().getBool("autofire");
|
bool enabled = myOSystem.settings().getBool("autofire");
|
||||||
|
|
||||||
if(toggle)
|
if(toggle)
|
||||||
{
|
{
|
||||||
myOSystem.settings().setValue("autofire", !enabled);
|
enabled = !enabled;
|
||||||
Controller::setAutoFire(!enabled);
|
myOSystem.settings().setValue("autofire", enabled);
|
||||||
|
Controller::setAutoFire(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream ss;
|
ostringstream ss;
|
||||||
ss << "Autofire " << (!enabled ? "enabled" : "disabled");
|
ss << "Autofire " << (enabled ? "enabled" : "disabled");
|
||||||
myOSystem.frameBuffer().showTextMessage(ss.str());
|
myOSystem.frameBuffer().showTextMessage(ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ class Console : public Serializable, public ConsoleIO
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Toggle between NTSC/PAL/SECAM (and variants) display format.
|
Switch between NTSC/PAL/SECAM (and variants) display format.
|
||||||
|
|
||||||
@param direction +1 indicates increase, -1 indicates decrease.
|
@param direction +1 indicates increase, -1 indicates decrease.
|
||||||
*/
|
*/
|
||||||
|
@ -250,7 +250,7 @@ class Console : public Serializable, public ConsoleIO
|
||||||
/**
|
/**
|
||||||
Toggles phosphor effect.
|
Toggles phosphor effect.
|
||||||
*/
|
*/
|
||||||
void togglePhosphor();
|
void togglePhosphor(bool toggle = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Toggles auto-phosphor.
|
Toggles auto-phosphor.
|
||||||
|
|
|
@ -134,7 +134,7 @@ void EventHandler::initialize()
|
||||||
|
|
||||||
// Default phosphor blend
|
// Default phosphor blend
|
||||||
Properties::setDefault(PropType::Display_PPBlend,
|
Properties::setDefault(PropType::Display_PPBlend,
|
||||||
myOSystem.settings().getString("tv.phosblend"));
|
myOSystem.settings().getString(PhosphorHandler::SETTING_BLEND));
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -326,26 +326,31 @@ FBInitStatus FrameBuffer::createDisplay(string_view title, BufferType type,
|
||||||
if(myOSystem.eventHandler().inTIAMode())
|
if(myOSystem.eventHandler().inTIAMode())
|
||||||
{
|
{
|
||||||
// Phosphor mode can be enabled either globally or per-ROM
|
// Phosphor mode can be enabled either globally or per-ROM
|
||||||
int p_blend = 0;
|
int p_blend;
|
||||||
bool enable = false;
|
bool enable;
|
||||||
const string phosphor = myOSystem.settings().getString("tv.phosphor");
|
const int phosphorMode = PhosphorHandler::toPhosphorMode(
|
||||||
|
myOSystem.settings().getString(PhosphorHandler::SETTING_MODE));
|
||||||
|
|
||||||
myOSystem.console().tia().enableAutoPhosphor(phosphor == "auto");
|
switch(phosphorMode)
|
||||||
|
{
|
||||||
|
case PhosphorHandler::Always:
|
||||||
|
enable = true;
|
||||||
|
p_blend = myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND);
|
||||||
|
myOSystem.console().tia().enableAutoPhosphor(false);
|
||||||
|
break;
|
||||||
|
|
||||||
if(phosphor == "always")
|
case PhosphorHandler::Auto_on:
|
||||||
{
|
case PhosphorHandler::Auto:
|
||||||
p_blend = myOSystem.settings().getInt("tv.phosblend");
|
enable = false;
|
||||||
enable = true;
|
p_blend = myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND);
|
||||||
}
|
myOSystem.console().tia().enableAutoPhosphor(true, phosphorMode == PhosphorHandler::Auto_on);
|
||||||
else if(phosphor == "auto")
|
break;
|
||||||
{
|
|
||||||
p_blend = myOSystem.settings().getInt("tv.phosblend");
|
default: // PhosphorHandler::ByRom
|
||||||
enable = false;
|
enable = myOSystem.console().properties().get(PropType::Display_Phosphor) == "YES";
|
||||||
}
|
p_blend = BSPF::stoi(myOSystem.console().properties().get(PropType::Display_PPBlend));
|
||||||
else
|
myOSystem.console().tia().enableAutoPhosphor(false);
|
||||||
{
|
break;
|
||||||
p_blend = BSPF::stoi(myOSystem.console().properties().get(PropType::Display_PPBlend));
|
|
||||||
enable = myOSystem.console().properties().get(PropType::Display_Phosphor) == "YES";
|
|
||||||
}
|
}
|
||||||
myTIASurface->enablePhosphor(enable, p_blend);
|
myTIASurface->enablePhosphor(enable, p_blend);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,8 +99,8 @@ Settings::Settings()
|
||||||
setPermanent("pal.gamma", "0.0");
|
setPermanent("pal.gamma", "0.0");
|
||||||
// TV filtering options
|
// TV filtering options
|
||||||
setPermanent("tv.filter", "0");
|
setPermanent("tv.filter", "0");
|
||||||
setPermanent("tv.phosphor", "byrom");
|
setPermanent(PhosphorHandler::SETTING_MODE, PhosphorHandler::VALUE_BYROM);
|
||||||
setPermanent("tv.phosblend", "50");
|
setPermanent(PhosphorHandler::SETTING_BLEND, PhosphorHandler::DEFAULT_BLEND);
|
||||||
setPermanent("tv.scanlines", "0");
|
setPermanent("tv.scanlines", "0");
|
||||||
setPermanent("tv.scanmask", TIASurface::SETTING_STANDARD);
|
setPermanent("tv.scanmask", TIASurface::SETTING_STANDARD);
|
||||||
// TV options when using 'custom' mode
|
// TV options when using 'custom' mode
|
||||||
|
@ -361,11 +361,12 @@ void Settings::validate()
|
||||||
sort(s.begin(), s.end());
|
sort(s.begin(), s.end());
|
||||||
if(s != "bgopry") setValue("tia.dbgcolors", "roygpb");
|
if(s != "bgopry") setValue("tia.dbgcolors", "roygpb");
|
||||||
|
|
||||||
s = getString("tv.phosphor");
|
if(PhosphorHandler::toPhosphorMode(getString(PhosphorHandler::SETTING_MODE)) == PhosphorHandler::ByRom)
|
||||||
if(s != "always" && s != "byrom" && s != "auto") setValue("tv.phosphor", "byrom");
|
setValue(PhosphorHandler::SETTING_MODE, PhosphorHandler::VALUE_BYROM);
|
||||||
|
|
||||||
i = getInt("tv.phosblend");
|
i = getInt(PhosphorHandler::SETTING_BLEND);
|
||||||
if(i < 0 || i > 100) setValue("tv.phosblend", "50");
|
if(i < 0 || i > 100)
|
||||||
|
setValue(PhosphorHandler::SETTING_BLEND, PhosphorHandler::DEFAULT_BLEND);
|
||||||
|
|
||||||
s = getString("tv.scanmask");
|
s = getString("tv.scanmask");
|
||||||
if(s != TIASurface::SETTING_STANDARD
|
if(s != TIASurface::SETTING_STANDARD
|
||||||
|
@ -576,8 +577,8 @@ void Settings::usage()
|
||||||
<< " -tia.correct_aspect <1|0> Enable aspect ratio correct scaling\n\n"
|
<< " -tia.correct_aspect <1|0> Enable aspect ratio correct scaling\n\n"
|
||||||
<< " -tv.filter <0-5> Set TV effects off (0) or to specified mode\n"
|
<< " -tv.filter <0-5> Set TV effects off (0) or to specified mode\n"
|
||||||
<< " (1-5)\n"
|
<< " (1-5)\n"
|
||||||
<< " -tv.phosphor <always|auto|> When to use phosphor mode\n"
|
<< " -tv.phosphor <byrom|always|> When to use phosphor mode\n"
|
||||||
<< " byrom\n"
|
<< " autoon|auto\n"
|
||||||
<< " -tv.phosblend <0-100> Set default blend level in phosphor mode\n"
|
<< " -tv.phosblend <0-100> Set default blend level in phosphor mode\n"
|
||||||
<< " -tv.scanlines <0-100> Set scanline intensity to percentage\n"
|
<< " -tv.scanlines <0-100> Set scanline intensity to percentage\n"
|
||||||
<< " (0 disables completely)\n"
|
<< " (0 disables completely)\n"
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "TIAConstants.hxx"
|
#include "TIAConstants.hxx"
|
||||||
#include "AudioQueue.hxx"
|
#include "AudioQueue.hxx"
|
||||||
#include "DispatchResult.hxx"
|
#include "DispatchResult.hxx"
|
||||||
|
#include "PhosphorHandler.hxx"
|
||||||
#include "Base.hxx"
|
#include "Base.hxx"
|
||||||
|
|
||||||
enum CollisionMask: uInt32 {
|
enum CollisionMask: uInt32 {
|
||||||
|
@ -187,11 +188,14 @@ void TIA::initialize()
|
||||||
myFrontBuffer.fill(0);
|
myFrontBuffer.fill(0);
|
||||||
myFramebuffer.fill(0);
|
myFramebuffer.fill(0);
|
||||||
|
|
||||||
|
// Prepare variables for auto-phosphor
|
||||||
memset(&myPosP0, 0, sizeof(ObjectPos));
|
memset(&myPosP0, 0, sizeof(ObjectPos));
|
||||||
memset(&myPosP1, 0, sizeof(ObjectPos));
|
memset(&myPosP1, 0, sizeof(ObjectPos));
|
||||||
memset(&myPosM0, 0, sizeof(ObjectPos));
|
memset(&myPosM0, 0, sizeof(ObjectPos));
|
||||||
memset(&myPosM1, 0, sizeof(ObjectPos));
|
memset(&myPosM1, 0, sizeof(ObjectPos));
|
||||||
memset(&myPosBL, 0, sizeof(ObjectPos));
|
memset(&myPosBL, 0, sizeof(ObjectPos));
|
||||||
|
memset(&myPatPF, 0, sizeof(ObjectGfx));
|
||||||
|
myFrameEnd = 0;
|
||||||
|
|
||||||
applyDeveloperSettings();
|
applyDeveloperSettings();
|
||||||
|
|
||||||
|
@ -200,8 +204,12 @@ void TIA::initialize()
|
||||||
setFixedColorPalette(mySettings.getString("tia.dbgcolors"));
|
setFixedColorPalette(mySettings.getString("tia.dbgcolors"));
|
||||||
enableFixedColors(
|
enableFixedColors(
|
||||||
mySettings.getBool(devSettings ? "dev.debugcolors" : "plr.debugcolors"));
|
mySettings.getBool(devSettings ? "dev.debugcolors" : "plr.debugcolors"));
|
||||||
myAutoPhosphorEnabled = mySettings.getString("tv.phosphor") == "auto";
|
// Auto-phosphor settings:
|
||||||
|
const string mode = mySettings.getString(PhosphorHandler::SETTING_MODE);
|
||||||
|
myAutoPhosphorAutoOn = mode == PhosphorHandler::VALUE_AUTO_ON;
|
||||||
|
myAutoPhosphorEnabled = myAutoPhosphorAutoOn || mode == PhosphorHandler::VALUE_AUTO;
|
||||||
myAutoPhosphorActive = false;
|
myAutoPhosphorActive = false;
|
||||||
|
myFlickerCount = 0;
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
createAccessArrays();
|
createAccessArrays();
|
||||||
|
@ -1407,6 +1415,9 @@ void TIA::onFrameComplete()
|
||||||
|
|
||||||
if(myAutoPhosphorEnabled)
|
if(myAutoPhosphorEnabled)
|
||||||
{
|
{
|
||||||
|
// Calculate difference to previous frames (with some margin).
|
||||||
|
// If difference to latest frame is larger than to older frames, and this happens for
|
||||||
|
// multiple frames, enabled phosphor mode.
|
||||||
static constexpr int MIN_FLICKER_DELTA = 6;
|
static constexpr int MIN_FLICKER_DELTA = 6;
|
||||||
static constexpr int MAX_FLICKER_DELTA = TIAConstants::H_PIXEL - MIN_FLICKER_DELTA;
|
static constexpr int MAX_FLICKER_DELTA = TIAConstants::H_PIXEL - MIN_FLICKER_DELTA;
|
||||||
static constexpr int MIN_DIFF = 4;
|
static constexpr int MIN_DIFF = 4;
|
||||||
|
@ -1414,37 +1425,34 @@ void TIA::onFrameComplete()
|
||||||
|
|
||||||
int diffCount[FLICKER_FRAMES - 1];
|
int diffCount[FLICKER_FRAMES - 1];
|
||||||
|
|
||||||
//cerr << missingScanlines << ", " << myFrontBufferScanlines << " | ";
|
//cerr << missingScanlines << ", " << myFrameEnd << " | ";
|
||||||
//cerr << myFlickerFrame << ": ";
|
//cerr << myFlickerFrame << ": ";
|
||||||
for(int frame = 0; frame < FLICKER_FRAMES - 1; ++frame)
|
for(int frame = 0; frame < FLICKER_FRAMES - 1; ++frame)
|
||||||
{
|
{
|
||||||
int otherFrame = (myFlickerFrame + frame + 1) % FLICKER_FRAMES;
|
const int otherFrame = (myFlickerFrame + frame + 1) % FLICKER_FRAMES;
|
||||||
//cerr << otherFrame << " ";
|
int count = 0;
|
||||||
// TODO:
|
for(uInt32 y = 0; y <= myFrameEnd; ++y)
|
||||||
// - differentiate fast movement and flicker
|
|
||||||
// - movement is directional
|
|
||||||
// - flicker goes back and forth
|
|
||||||
// - ignore disabled objects
|
|
||||||
diffCount[frame] = 0;
|
|
||||||
for(uInt32 y = 0; y < myFrontBufferScanlines; ++y)
|
|
||||||
{
|
{
|
||||||
int delta;
|
int delta;
|
||||||
delta = std::abs(myPosP0[y][myFlickerFrame] - myPosP0[y][otherFrame]);
|
delta = std::abs(myPosP0[y][myFlickerFrame] - myPosP0[y][otherFrame]);
|
||||||
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
||||||
++diffCount[frame];
|
++count;
|
||||||
delta = std::abs(myPosP1[y][myFlickerFrame] - myPosP1[y][otherFrame]);
|
delta = std::abs(myPosP1[y][myFlickerFrame] - myPosP1[y][otherFrame]);
|
||||||
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
||||||
++diffCount[frame];
|
++count;
|
||||||
delta = std::abs(myPosM0[y][myFlickerFrame] - myPosM0[y][otherFrame]);
|
delta = std::abs(myPosM0[y][myFlickerFrame] - myPosM0[y][otherFrame]);
|
||||||
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
||||||
++diffCount[frame];
|
++count;
|
||||||
delta = std::abs(myPosM1[y][myFlickerFrame] - myPosM1[y][otherFrame]);
|
delta = std::abs(myPosM1[y][myFlickerFrame] - myPosM1[y][otherFrame]);
|
||||||
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
||||||
++diffCount[frame];
|
++count;
|
||||||
delta = std::abs(myPosBL[y][myFlickerFrame] - myPosBL[y][otherFrame]);
|
delta = std::abs(myPosBL[y][myFlickerFrame] - myPosBL[y][otherFrame]);
|
||||||
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA)
|
||||||
++diffCount[frame];
|
++count;
|
||||||
|
if(myPatPF[y][myFlickerFrame] != myPatPF[y][otherFrame])
|
||||||
|
++count;
|
||||||
}
|
}
|
||||||
|
diffCount[frame] = count;
|
||||||
}
|
}
|
||||||
//cerr << ": ";
|
//cerr << ": ";
|
||||||
//for(int i = 0; i < FLICKER_FRAMES - 1; ++i)
|
//for(int i = 0; i < FLICKER_FRAMES - 1; ++i)
|
||||||
|
@ -1461,6 +1469,9 @@ void TIA::onFrameComplete()
|
||||||
{
|
{
|
||||||
myAutoPhosphorActive = true;
|
myAutoPhosphorActive = true;
|
||||||
myPhosphorCallback(true);
|
myPhosphorCallback(true);
|
||||||
|
// If auto-on, disable phosphor automatic (phosphor stays enabled)
|
||||||
|
if(myAutoPhosphorAutoOn)
|
||||||
|
myAutoPhosphorEnabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1481,7 +1492,6 @@ void TIA::onFrameComplete()
|
||||||
if(--myFlickerFrame < 0)
|
if(--myFlickerFrame < 0)
|
||||||
myFlickerFrame = FLICKER_FRAMES - 1;
|
myFlickerFrame = FLICKER_FRAMES - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
++myFramesSinceLastRender;
|
++myFramesSinceLastRender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1619,8 +1629,10 @@ void TIA::applyRsync()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FORCE_INLINE void TIA::nextLine()
|
FORCE_INLINE void TIA::nextLine()
|
||||||
{
|
{
|
||||||
|
bool cloned = false;
|
||||||
if (myLinesSinceChange >= 2) {
|
if (myLinesSinceChange >= 2) {
|
||||||
cloneLastLine();
|
cloneLastLine();
|
||||||
|
cloned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
myHctr = 0;
|
myHctr = 0;
|
||||||
|
@ -1642,48 +1654,43 @@ FORCE_INLINE void TIA::nextLine()
|
||||||
{
|
{
|
||||||
if(myFrameManager->getY() == 0)
|
if(myFrameManager->getY() == 0)
|
||||||
flushLineCache();
|
flushLineCache();
|
||||||
|
|
||||||
|
// Save positions of objects for auto-phosphor
|
||||||
if(myAutoPhosphorEnabled)
|
if(myAutoPhosphorEnabled)
|
||||||
{
|
{
|
||||||
// Test ROMs:
|
// Test ROMs:
|
||||||
// - missing phosphor:
|
// - missing phosphor:
|
||||||
// x Princess Rescue: Lives display (~same x-position, different y-position)
|
|
||||||
// - QB: flicker sprite for multi color (same position, different shape and color)
|
// - QB: flicker sprite for multi color (same position, different shape and color)
|
||||||
// - Star Castle Arcade: vector font flicker (same position, different shape)
|
// - Star Castle Arcade: vector font flicker (same position, different shape)
|
||||||
// - Omega Race: no phosphor enabled (flickers every 2nd frame)
|
// - Omega Race: no phosphor enabled (flickers every 2nd frame)
|
||||||
// - Riddle of the Sphinx: shots (too small to be detected)
|
// - Riddle of the Sphinx: shots (too small to be detected)
|
||||||
// - Missile Command: explosions
|
// x Yars' Revenge: shield, neutral zone (PF flicker)
|
||||||
// - Yars' Revenge: shield, neutral zone (PF flicker)
|
|
||||||
//
|
//
|
||||||
// - unneccassary phosphor:
|
// - unneccassary phosphor:
|
||||||
// - Gas Hog: before game starts (odd invisible position changes)
|
// - Gas Hog: before game starts (odd invisible sprite position changes)
|
||||||
// x Turmoil: M1 rockets (gap between RESM1 and HMOVE?)
|
// x Turmoil: M1 rockets (gap between RESM1 and HMOVE?)
|
||||||
// x Fathom: seaweed (many sprites moving vertically)
|
// x Fathom: seaweed (many sprites moving vertically)
|
||||||
// x FourPlay: game start (???)
|
// x FourPlay: game start (???)
|
||||||
// x Freeway: always (too many sprites?)
|
// x Freeway: always (too many sprites?)
|
||||||
const uInt32 y = myFrameManager->getY();
|
const uInt32 y = myFrameManager->getY();
|
||||||
//const int otherFrame = myFlickerFrame ^ 1;
|
|
||||||
//cerr << y << " ";
|
|
||||||
//if(myPlayer0.getGRPOld() != 0)
|
|
||||||
myPosP0[y][myFlickerFrame] = myPlayer0.getPosition();
|
|
||||||
//if(myPlayer1.getGRPOld() != 0)
|
|
||||||
myPosP1[y][myFlickerFrame] = myPlayer1.getPosition();
|
|
||||||
//if(myMissile0.isOn())
|
|
||||||
myPosM0[y][myFlickerFrame] = myMissile0.getPosition();
|
|
||||||
//else
|
|
||||||
// myPosM0[y][myFlickerFrame] = myPosM0[y][otherFrame];
|
|
||||||
//if(myMissile1.isOn())
|
|
||||||
myPosM1[y][myFlickerFrame] = myMissile1.getPosition();
|
|
||||||
//else
|
|
||||||
// myPosM1[y][myFlickerFrame] = myPosM1[y][otherFrame];
|
|
||||||
//if(myBall.isOn())
|
|
||||||
myPosBL[y][myFlickerFrame] = myBall.getPosition();
|
|
||||||
//else
|
|
||||||
// myPosBL[y][myFlickerFrame] = myPosBL[y][otherFrame];
|
|
||||||
|
|
||||||
//cerr << int(myPlayer0.getPosition()) << " ";
|
myPosP0[y][myFlickerFrame] = myPlayer0.getPosition();
|
||||||
|
myPosP1[y][myFlickerFrame] = myPlayer1.getPosition();
|
||||||
|
// Only use new position if missile/ball are enabled
|
||||||
|
if(myMissile0.isOn())
|
||||||
|
myPosM0[y][myFlickerFrame] = myMissile0.getPosition();
|
||||||
|
if(myMissile1.isOn())
|
||||||
|
myPosM1[y][myFlickerFrame] = myMissile1.getPosition();
|
||||||
|
if(myBall.isOn())
|
||||||
|
myPosBL[y][myFlickerFrame] = myBall.getPosition();
|
||||||
|
// Note: code checks only right side of playfield
|
||||||
|
myPatPF[y][myFlickerFrame] = (uInt32(registerValue(PF0))) << 16
|
||||||
|
| (uInt32(registerValue(PF1))) << 8 | uInt32(registerValue(PF2));
|
||||||
|
// Define end of frame for faster auto-phosphor calculation
|
||||||
|
if(!cloned)
|
||||||
|
myFrameEnd = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mySystem->m6502().clearHaltRequest();
|
mySystem->m6502().clearHaltRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1705,6 +1712,7 @@ void TIA::cloneLastLine()
|
||||||
std::copy_n(myBackBuffer.begin() + (y - 1) * TIAConstants::H_PIXEL,
|
std::copy_n(myBackBuffer.begin() + (y - 1) * TIAConstants::H_PIXEL,
|
||||||
TIAConstants::H_PIXEL, myBackBuffer.begin() + y * TIAConstants::H_PIXEL);
|
TIAConstants::H_PIXEL, myBackBuffer.begin() + y * TIAConstants::H_PIXEL);
|
||||||
|
|
||||||
|
// Save positions of objects for auto-phosphor
|
||||||
if(myAutoPhosphorEnabled)
|
if(myAutoPhosphorEnabled)
|
||||||
{
|
{
|
||||||
myPosP0[y][myFlickerFrame] = myPosP0[y - 1][myFlickerFrame];
|
myPosP0[y][myFlickerFrame] = myPosP0[y - 1][myFlickerFrame];
|
||||||
|
@ -1712,6 +1720,7 @@ void TIA::cloneLastLine()
|
||||||
myPosM0[y][myFlickerFrame] = myPosM0[y - 1][myFlickerFrame];
|
myPosM0[y][myFlickerFrame] = myPosM0[y - 1][myFlickerFrame];
|
||||||
myPosM1[y][myFlickerFrame] = myPosM1[y - 1][myFlickerFrame];
|
myPosM1[y][myFlickerFrame] = myPosM1[y - 1][myFlickerFrame];
|
||||||
myPosBL[y][myFlickerFrame] = myPosBL[y - 1][myFlickerFrame];
|
myPosBL[y][myFlickerFrame] = myPosBL[y - 1][myFlickerFrame];
|
||||||
|
myPatPF[y][myFlickerFrame] = myPatPF[y - 1][myFlickerFrame];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,29 +301,16 @@ class TIA : public Device
|
||||||
/**
|
/**
|
||||||
Enables/disables auto-phosphor.
|
Enables/disables auto-phosphor.
|
||||||
|
|
||||||
@param enabled Whether to enable or disable auto-phosphor mode
|
@param enabled Whether to use auto-phosphor mode
|
||||||
|
@param autoOn Whether to only ENABLE phosphor mode
|
||||||
*/
|
*/
|
||||||
void enableAutoPhosphor(bool enabled)
|
void enableAutoPhosphor(bool enabled, bool autoOn = false)
|
||||||
{
|
{
|
||||||
myAutoPhosphorEnabled = enabled;
|
myAutoPhosphorEnabled = enabled;
|
||||||
if(!enabled)
|
myAutoPhosphorAutoOn = autoOn;
|
||||||
myAutoPhosphorActive = false;
|
myAutoPhosphorActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Answers whether auto-phosphor is enabled.
|
|
||||||
|
|
||||||
@return Auto-phosphor is enabled
|
|
||||||
*/
|
|
||||||
bool autoPhosphorEnabled() const { return myAutoPhosphorEnabled; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Answers whether auto-phosphor is active.
|
|
||||||
|
|
||||||
@return Auto-phosphor is acitve
|
|
||||||
*/
|
|
||||||
bool autoPhosphorActive() const { return myAutoPhosphorActive; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the current color clock we've gotten to on this scanline.
|
Answers the current color clock we've gotten to on this scanline.
|
||||||
|
|
||||||
|
@ -998,13 +985,17 @@ class TIA : public Device
|
||||||
/**
|
/**
|
||||||
* Auto-phosphor detection variables.
|
* Auto-phosphor detection variables.
|
||||||
*/
|
*/
|
||||||
bool myAutoPhosphorEnabled{true};
|
|
||||||
bool myAutoPhosphorActive{true};
|
|
||||||
static constexpr int FLICKER_FRAMES = 1 + 4; // compare current frame with previous 4 frames
|
static constexpr int FLICKER_FRAMES = 1 + 4; // compare current frame with previous 4 frames
|
||||||
using ObjectPos = BSPF::array2D<uInt8, TIAConstants::frameBufferHeight, FLICKER_FRAMES>;
|
using ObjectPos = BSPF::array2D<uInt8, TIAConstants::frameBufferHeight, FLICKER_FRAMES>;
|
||||||
|
using ObjectGfx = BSPF::array2D<uInt32, TIAConstants::frameBufferHeight, FLICKER_FRAMES>;
|
||||||
|
|
||||||
|
bool myAutoPhosphorEnabled{false};
|
||||||
|
bool myAutoPhosphorAutoOn{false};
|
||||||
|
bool myAutoPhosphorActive{false};
|
||||||
ObjectPos myPosP0, myPosP1, myPosM0, myPosM1, myPosBL;
|
ObjectPos myPosP0, myPosP1, myPosM0, myPosM1, myPosBL;
|
||||||
int myFlickerFrame{0};
|
ObjectGfx myPatPF;
|
||||||
int myFlickerCount{0};
|
int myFlickerFrame{0}, myFlickerCount{0};
|
||||||
|
uInt32 myFrameEnd{0};
|
||||||
onPhosphorCallback myPhosphorCallback;
|
onPhosphorCallback myPhosphorCallback;
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
|
|
@ -160,7 +160,7 @@ void GameInfoDialog::addEmulationTab()
|
||||||
// Phosphor
|
// Phosphor
|
||||||
ypos += lineHeight + VGAP;
|
ypos += lineHeight + VGAP;
|
||||||
myPhosphor = new CheckboxWidget(myTab, _font, HBORDER, ypos + 1,
|
myPhosphor = new CheckboxWidget(myTab, _font, HBORDER, ypos + 1,
|
||||||
"Phosphor (auto-enabled for all ROMs)", kPhosphorChanged);
|
"Phosphor (auto-enabled/disabled for all ROMs)", kPhosphorChanged);
|
||||||
myPhosphor->setToolTip(Event::TogglePhosphor);
|
myPhosphor->setToolTip(Event::TogglePhosphor);
|
||||||
wid.push_back(myPhosphor);
|
wid.push_back(myPhosphor);
|
||||||
|
|
||||||
|
@ -804,13 +804,14 @@ void GameInfoDialog::loadEmulationProperties(const Properties& props)
|
||||||
myFormatDetected->setLabel("");
|
myFormatDetected->setLabel("");
|
||||||
|
|
||||||
// if phosphor is always enabled, disable game specific phosphor settings
|
// if phosphor is always enabled, disable game specific phosphor settings
|
||||||
const bool alwaysPhosphor = instance().settings().getString("tv.phosphor") == "always";
|
const string mode = instance().settings().getString(PhosphorHandler::SETTING_MODE);
|
||||||
const bool autoPhosphor = instance().settings().getString("tv.phosphor") == "auto";
|
|
||||||
const bool usePhosphor = props.get(PropType::Display_Phosphor) == "YES";
|
const bool usePhosphor = props.get(PropType::Display_Phosphor) == "YES";
|
||||||
myPhosphor->setState(usePhosphor);
|
myPhosphor->setState(usePhosphor);
|
||||||
if (alwaysPhosphor)
|
if (mode == PhosphorHandler::VALUE_ALWAYS)
|
||||||
myPhosphor->setLabel("Phosphor (enabled for all ROMs");
|
myPhosphor->setLabel("Phosphor (enabled for all ROMs");
|
||||||
else if (autoPhosphor)
|
else if (mode == PhosphorHandler::VALUE_AUTO)
|
||||||
|
myPhosphor->setLabel("Phosphor (auto-enabled/disabled for all ROMs)");
|
||||||
|
else if (mode == PhosphorHandler::VALUE_AUTO_ON)
|
||||||
myPhosphor->setLabel("Phosphor (auto-enabled for all ROMs)");
|
myPhosphor->setLabel("Phosphor (auto-enabled for all ROMs)");
|
||||||
else
|
else
|
||||||
myPhosphor->setLabel("Phosphor");
|
myPhosphor->setLabel("Phosphor");
|
||||||
|
@ -1195,7 +1196,8 @@ void GameInfoDialog::updateMultiCart()
|
||||||
myFormat->setEnabled(!isMulti);
|
myFormat->setEnabled(!isMulti);
|
||||||
|
|
||||||
// if phosphor is always enabled, disable game specific phosphor settings
|
// if phosphor is always enabled, disable game specific phosphor settings
|
||||||
const bool globalPhosphor = isMulti || instance().settings().getString("tv.phosphor") != "byrom";
|
const bool globalPhosphor = isMulti
|
||||||
|
|| instance().settings().getString(PhosphorHandler::SETTING_MODE) != PhosphorHandler::VALUE_BYROM;
|
||||||
myPhosphor->setEnabled(!globalPhosphor);
|
myPhosphor->setEnabled(!globalPhosphor);
|
||||||
myPPBlend->setEnabled(!globalPhosphor && myPhosphor->getState());
|
myPPBlend->setEnabled(!globalPhosphor && myPhosphor->getState());
|
||||||
|
|
||||||
|
|
|
@ -235,7 +235,7 @@ void StellaSettingsDialog::loadConfig()
|
||||||
myTVScanIntense->setValue(valueToLevel(settings.getInt("tv.scanlines")));
|
myTVScanIntense->setValue(valueToLevel(settings.getInt("tv.scanlines")));
|
||||||
|
|
||||||
// TV phosphor blend
|
// TV phosphor blend
|
||||||
myTVPhosLevel->setValue(valueToLevel(settings.getInt("tv.phosblend")));
|
myTVPhosLevel->setValue(valueToLevel(settings.getInt(PhosphorHandler::SETTING_BLEND)));
|
||||||
|
|
||||||
// TV overscan
|
// TV overscan
|
||||||
myTVOverscan->setValue(settings.getInt("tia.fs_overscan"));
|
myTVOverscan->setValue(settings.getInt("tia.fs_overscan"));
|
||||||
|
@ -274,10 +274,10 @@ void StellaSettingsDialog::saveConfig()
|
||||||
myTVMode->getSelectedTag().toString());
|
myTVMode->getSelectedTag().toString());
|
||||||
|
|
||||||
// TV phosphor mode
|
// TV phosphor mode
|
||||||
instance().settings().setValue("tv.phosphor",
|
instance().settings().setValue(PhosphorHandler::SETTING_MODE,
|
||||||
myTVPhosLevel->getValue() > 0 ? "always" : "byrom");
|
myTVPhosLevel->getValue() > 0 ? PhosphorHandler::VALUE_ALWAYS : PhosphorHandler::VALUE_BYROM);
|
||||||
// TV phosphor blend
|
// TV phosphor blend
|
||||||
instance().settings().setValue("tv.phosblend",
|
instance().settings().setValue(PhosphorHandler::SETTING_BLEND,
|
||||||
levelToValue(myTVPhosLevel->getValue()));
|
levelToValue(myTVPhosLevel->getValue()));
|
||||||
|
|
||||||
// TV scanline intensity and interpolation
|
// TV scanline intensity and interpolation
|
||||||
|
|
|
@ -381,11 +381,12 @@ void VideoAudioDialog::addTVEffectsTab()
|
||||||
|
|
||||||
// TV Phosphor effect
|
// TV Phosphor effect
|
||||||
items.clear();
|
items.clear();
|
||||||
VarList::push_back(items, "by ROM", "byrom");
|
VarList::push_back(items, "by ROM", PhosphorHandler::VALUE_BYROM);
|
||||||
VarList::push_back(items, "always", "always");
|
VarList::push_back(items, "always", PhosphorHandler::VALUE_ALWAYS);
|
||||||
VarList::push_back(items, "auto", "auto");
|
VarList::push_back(items, "auto on", PhosphorHandler::VALUE_AUTO_ON);
|
||||||
|
VarList::push_back(items, "auto on/off", PhosphorHandler::VALUE_AUTO);
|
||||||
myTVPhosphor = new PopUpWidget(myTab, _font, xpos, ypos,
|
myTVPhosphor = new PopUpWidget(myTab, _font, xpos, ypos,
|
||||||
_font.getStringWidth("by ROM"), lineHeight,
|
_font.getStringWidth("auto on/off"), lineHeight,
|
||||||
items, "Phosphor ", 0, kPhosphorChanged);
|
items, "Phosphor ", 0, kPhosphorChanged);
|
||||||
myTVPhosphor->setToolTip(Event::PhosphorModeDecrease, Event::PhosphorModeIncrease);
|
myTVPhosphor->setToolTip(Event::PhosphorModeDecrease, Event::PhosphorModeIncrease);
|
||||||
wid.push_back(myTVPhosphor);
|
wid.push_back(myTVPhosphor);
|
||||||
|
@ -760,8 +761,8 @@ void VideoAudioDialog::loadConfig()
|
||||||
loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
|
loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
|
||||||
|
|
||||||
// TV phosphor mode & blend
|
// TV phosphor mode & blend
|
||||||
myTVPhosphor->setSelected(settings.getString("tv.phosphor"), "byrom");
|
myTVPhosphor->setSelected(settings.getString(PhosphorHandler::SETTING_MODE), PhosphorHandler::VALUE_BYROM);
|
||||||
myTVPhosLevel->setValue(settings.getInt("tv.phosblend"));
|
myTVPhosLevel->setValue(settings.getInt(PhosphorHandler::SETTING_BLEND));
|
||||||
handlePhosphorChange();
|
handlePhosphorChange();
|
||||||
|
|
||||||
// TV scanline intensity & mask
|
// TV scanline intensity & mask
|
||||||
|
@ -895,9 +896,9 @@ void VideoAudioDialog::saveConfig()
|
||||||
NTSCFilter::saveConfig(settings);
|
NTSCFilter::saveConfig(settings);
|
||||||
|
|
||||||
// TV phosphor mode & blend
|
// TV phosphor mode & blend
|
||||||
settings.setValue("tv.phosphor", myTVPhosphor->getSelectedTag());
|
settings.setValue(PhosphorHandler::SETTING_MODE, myTVPhosphor->getSelectedTag());
|
||||||
settings.setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off"
|
settings.setValue(PhosphorHandler::SETTING_BLEND, myTVPhosLevel->getValueLabel() == "Off"
|
||||||
? "0" : myTVPhosLevel->getValueLabel());
|
? "0" : myTVPhosLevel->getValueLabel());
|
||||||
|
|
||||||
// TV scanline intensity & mask
|
// TV scanline intensity & mask
|
||||||
settings.setValue("tv.scanlines", myTVScanIntense->getValueLabel());
|
settings.setValue("tv.scanlines", myTVScanIntense->getValueLabel());
|
||||||
|
@ -1035,7 +1036,7 @@ void VideoAudioDialog::setDefaults()
|
||||||
myTVMode->setSelected("0", "0");
|
myTVMode->setSelected("0", "0");
|
||||||
|
|
||||||
// TV phosphor mode & blend
|
// TV phosphor mode & blend
|
||||||
myTVPhosphor->setSelected("byrom");
|
myTVPhosphor->setSelected(PhosphorHandler::VALUE_BYROM);
|
||||||
myTVPhosLevel->setValue(50);
|
myTVPhosLevel->setValue(50);
|
||||||
|
|
||||||
// TV scanline intensity & mask
|
// TV scanline intensity & mask
|
||||||
|
@ -1215,7 +1216,7 @@ void VideoAudioDialog::handleOverscanChange()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void VideoAudioDialog::handlePhosphorChange()
|
void VideoAudioDialog::handlePhosphorChange()
|
||||||
{
|
{
|
||||||
myTVPhosLevel->setEnabled(myTVPhosphor->getSelectedTag() != "byrom");
|
myTVPhosLevel->setEnabled(myTVPhosphor->getSelectedTag() != PhosphorHandler::VALUE_BYROM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -314,7 +314,7 @@ string Widget::getToolTip(const Common::Point& pos) const
|
||||||
const string hotkey2 = instance().eventHandler().keyHandler().getMappingDesc(
|
const string hotkey2 = instance().eventHandler().keyHandler().getMappingDesc(
|
||||||
_toolTipEvent2, _toolTipMode);
|
_toolTipEvent2, _toolTipMode);
|
||||||
|
|
||||||
if(hotkey2 != EmptyString)
|
if(hotkey != EmptyString && hotkey2 != EmptyString)
|
||||||
{
|
{
|
||||||
// Merge hotkeys if they only differ by "-Shift"
|
// Merge hotkeys if they only differ by "-Shift"
|
||||||
const string mod = "-Shift";
|
const string mod = "-Shift";
|
||||||
|
@ -333,6 +333,8 @@ string Widget::getToolTip(const Common::Point& pos) const
|
||||||
else
|
else
|
||||||
hotkey += ", " + hotkey2;
|
hotkey += ", " + hotkey2;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
hotkey += hotkey2;
|
||||||
|
|
||||||
if(hotkey == EmptyString)
|
if(hotkey == EmptyString)
|
||||||
return _toolTipText;
|
return _toolTipText;
|
||||||
|
|
|
@ -98,6 +98,7 @@
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
<EnableASAN>false</EnableASAN>
|
<EnableASAN>false</EnableASAN>
|
||||||
|
<WholeProgramOptimization>PGOptimize</WholeProgramOptimization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-Sanitize|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-Sanitize|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
@ -486,6 +487,8 @@
|
||||||
<CompileAs>CompileAsCpp</CompileAs>
|
<CompileAs>CompileAsCpp</CompileAs>
|
||||||
<AssemblerOutput>NoListing</AssemblerOutput>
|
<AssemblerOutput>NoListing</AssemblerOutput>
|
||||||
<AssemblerListingLocation>$(IntDir)asm\windows\%(RelativeDir)</AssemblerListingLocation>
|
<AssemblerListingLocation>$(IntDir)asm\windows\%(RelativeDir)</AssemblerListingLocation>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>SDL2.lib;SDL2main.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>SDL2.lib;SDL2main.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
|
Loading…
Reference in New Issue