enhanced and optimized auto-phosphor

This commit is contained in:
thrust26 2024-01-25 12:24:18 +01:00
parent 274490128f
commit 0aeffe0392
18 changed files with 256 additions and 182 deletions

View File

@ -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

View File

@ -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 &lt;always|auto|byrom&gt;</pre></td> <td><pre>-tv.phosphor &lt;byrom|always|autoon|auto&gt;</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>

View File

@ -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 },

View File

@ -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;

View File

@ -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.

View File

@ -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());
} }

View File

@ -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.

View File

@ -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));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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);
} }

View File

@ -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"

View File

@ -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];
} }
} }
} }

View File

@ -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

View File

@ -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());

View File

@ -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

View File

@ -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);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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;

View File

@ -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>