added switching to bilinear scaling if QIS makes no sense

added 5th scanline mask (aperture grille)
aligned brightness of all scanline masks
updated doc for scanline masks
This commit is contained in:
Thomas Jentzsch 2021-11-02 11:49:44 +01:00
parent 6238b5efbb
commit 6d37dc9a47
9 changed files with 90 additions and 38 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1553,6 +1553,16 @@
<td>Alt + 5</td>
<td>Cmd + 5</td>
</tr>
<tr>
<td>Switch to <i>previous</i> scanline mask</td>
<td>Shift-Alt + 6</td>
<td>Shift-Cmd + 6</td>
</tr>
<tr>
<td>Switch to <i>next</i> scanline mask</td>
<td>Alt + 6</td>
<td>Cmd + 6</td>
</tr>
<tr>
<td colspan="3"><center><font size="-1">
These settings can also be changed using <a href="#GlobalKeys"><b>Global Keys</a></font></center>
@ -2964,6 +2974,12 @@
</br>Note: No scanlines in 1x mode snapshots</td>
</tr>
<tr>
<td><pre>-tv.scanmask &lt;standard|thin|pixel|aperture|mame&gt;</pre></td>
<td>Set the scanline mask.
</br>Note: All masks (except 'standard') work better at higher zoom levels.</td>
</tr>
<tr>
<td><pre>-cheat &lt;code&gt;</pre></td>
<td>Use the specified cheatcode (see <a href="#Cheats"><b>Cheat</b></a> section for description).</td>
@ -3782,11 +3798,13 @@
(needs to be manually adjusted for your particular hardware)</td><td>-tv.phosblend</td></tr>
<tr><td>Scanline intensity</td><td>Sets scanline black-level intensity.</br>
Note: No scanlines in 1x mode snapshots</td><td>-tv.scanlines</td></tr>
<tr><td>(Scanline) Mask</td><td>Sets the scanline mask.</br>
Note: All masks (except 'standard') work better at higher zoom levels</td><td>-tv.scanmask</td></tr>
<tr><td>Clone RGB</td><td>Copy 'RGB' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone S-Video</td><td>Copy 'S-Video' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone Composite</td><td>Copy 'Composite' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone Bad adjust</td><td>Copy 'Bad Adjust' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Revert</td><td>Revert attribute sliders to saved 'Custom' TV mode settings</td><td>&nbsp;</td></tr>
<tr><td>Revert</td><td>Revert attribute sliders to previously saved 'Custom' TV mode settings</td><td>&nbsp;</td></tr>
</table>
</td>
</tr>

View File

@ -278,6 +278,10 @@ void FBSurfaceSDL2::applyAttributes()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::setScalingInterpolation(ScalingInterpolation interpolation)
{
if (interpolation == ScalingInterpolation::sharp
&& mySrcGUIR.h() >= myDstGUIR.h())
interpolation = ScalingInterpolation::blur;
if (interpolation == myInterpolationMode) return;
myInterpolationMode = interpolation;

View File

@ -147,14 +147,8 @@ void QisBlitter::recreateTexturesIfNecessary()
SDL_TextureAccess texAccess = myStaticData == nullptr ? SDL_TEXTUREACCESS_STREAMING : SDL_TEXTUREACCESS_STATIC;
if(myDstRect.w > mySrcRect.w)
myIntermediateRect.w = (myDstRect.w / mySrcRect.w) * mySrcRect.w;
else
myIntermediateRect.w = mySrcRect.w;
if(myDstRect.h > mySrcRect.h)
myIntermediateRect.h = (myDstRect.h / mySrcRect.h) * mySrcRect.h;
else
myIntermediateRect.h = mySrcRect.h;
myIntermediateRect.w = (myDstRect.w / mySrcRect.w) * mySrcRect.w;
myIntermediateRect.h = (myDstRect.h / mySrcRect.h) * mySrcRect.h;
myIntermediateRect.x = 0;
myIntermediateRect.y = 0;

View File

@ -197,6 +197,8 @@ bool GlobalKeyHandler::skipAVSetting() const
myOSystem.settings().getString("palette") == PaletteHandler::SETTING_CUSTOM;
const bool isCustomFilter =
myOSystem.settings().getInt("tv.filter") == int(NTSCFilter::Preset::CUSTOM);
const bool hasScanlines =
myOSystem.settings().getInt("tv.scanlines") > 0;
const bool isSoftwareRenderer =
myOSystem.settings().getString("video") == "software";
@ -210,6 +212,7 @@ bool GlobalKeyHandler::skipAVSetting() const
|| (mySetting >= Setting::NTSC_SHARPNESS
&& mySetting <= Setting::NTSC_BLEEDING
&& !isCustomFilter)
|| (mySetting == Setting::SCANLINE_MASK && !hasScanlines)
|| (mySetting == Setting::INTERPOLATION && isSoftwareRenderer);
}
@ -375,7 +378,7 @@ GlobalKeyHandler::SettingData GlobalKeyHandler::getSettingData(const Setting set
// Other TV effects adjustables
{Setting::PHOSPHOR, {true, std::bind(&Console::changePhosphor, &myOSystem.console(), _1)}},
{Setting::SCANLINES, {true, std::bind(&TIASurface::changeScanlineIntensity, &myOSystem.frameBuffer().tiaSurface(), _1)}},
{Setting::SCANLINE_MASK, {false, std::bind(&TIASurface::cycleScanlineMask, &myOSystem.frameBuffer().tiaSurface(), _1)}},
{Setting::SCANLINE_MASK, {false, std::bind(&TIASurface::cycleScanlineMask, &myOSystem.frameBuffer().tiaSurface(), _1)}},
{Setting::INTERPOLATION, {false, std::bind(&Console::toggleInter, &myOSystem.console(), _1)}},
// *** Input group ***
{Setting::DIGITAL_DEADZONE, {true, std::bind(&PhysicalJoystickHandler::changeDigitalDeadZone, &joyHandler(), _1)}},

View File

@ -319,9 +319,10 @@ void Settings::validate()
s = getString("tv.scanmask");
if(s != TIASurface::SETTING_STANDARD
&& s != TIASurface::SETTING_THIN
&& s != TIASurface::SETTING_PIXELS
&& s != TIASurface::SETTING_MAME)
&& s != TIASurface::SETTING_THIN
&& s != TIASurface::SETTING_PIXELS
&& s != TIASurface::SETTING_APERTURE
&& s != TIASurface::SETTING_MAME)
setValue("tv.scanmask", TIASurface::SETTING_STANDARD);
i = getInt("tv.filter");

View File

@ -277,6 +277,7 @@ TIASurface::ScanlineMask TIASurface::scanlineMaskType(int direction)
SETTING_STANDARD,
SETTING_THIN,
SETTING_PIXELS,
SETTING_APERTURE,
SETTING_MAME
};
int i = 0;
@ -302,10 +303,11 @@ TIASurface::ScanlineMask TIASurface::scanlineMaskType(int direction)
void TIASurface::cycleScanlineMask(int direction)
{
const string Names[int(ScanlineMask::NumMasks)] = {
"'Standard'",
"'Thin lines'",
"'Pixelated'",
"'MAME'"
"Standard",
"Thin lines",
"Pixelated",
"Aperture Grille",
"MAME"
};
int i = int(scanlineMaskType(direction));
@ -314,7 +316,7 @@ void TIASurface::cycleScanlineMask(int direction)
ostringstream msg;
msg << "Scanline pattern " << Names[i];
msg << "Scanline pattern '" << Names[i] << "'";
myOSystem.frameBuffer().showTextMessage(msg.str());
}
@ -331,6 +333,10 @@ void TIASurface::enablePhosphor(bool enable, int blend)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::createScanlineSurface()
{
// Idea: Emulate
// - Dot-Trio Shadow-Mask
// - Slot-Mask (NEC 'CromaClear')
// - Aperture-Grille (Sony 'Trinitron')
struct PatternSize
{
uInt16 width{1};
@ -345,15 +351,17 @@ void TIASurface::createScanlineSurface()
{}
};
std::array <PatternSize, int(ScanlineMask::NumMasks)> Sizes = {{
PatternSize(1, 2, 1),
PatternSize(1, 3, 1),
PatternSize(3, 3, 2),
PatternSize(3, 4, 3)
PatternSize(1, 2, 1), // standard
PatternSize(1, 3, 1), // thin
PatternSize(3, 3, 2), // pixel
PatternSize(6, 3, 1), // aperture
PatternSize(3, 4, 3), // mame
}};
// Note: With RGB = 0,0,0, the average alpha should be ~0x55 (85)
std::array<std::vector<std::vector<uInt32>>, int(ScanlineMask::NumMasks)> Pattern = {{
{ // standard
{ 0x00000000 },
{ 0xff000000 },
{ 0xaa000000 }, // 0xff decreased to 0xaa (67%) to match overall brightness of other pattern
}, { // thin lines
{ 0x00000000 },
{ 0x00000000 },
@ -367,12 +375,26 @@ void TIASurface::createScanlineSurface()
//{ 0x04ffffff, 0x80e7e7e7, 0x20ffffff },
//{ 0xff282828, 0xff282828, 0xff282828 },
// same but using RGB = 0,0,0
{ 0x08000000, 0x02000000, 0x80000000 },
{ 0x08000000, 0x80000000, 0x40000000 },
{ 0xff000000, 0xff000000, 0xff000000 },
{ 0x80000000, 0x04000000, 0x04000000 },
{ 0x04000000, 0x80000000, 0x20000000 },
{ 0xff000000, 0xff000000, 0xff000000 },
//{ 0x08000000, 0x02000000, 0x80000000 },
//{ 0x08000000, 0x80000000, 0x40000000 },
//{ 0xff000000, 0xff000000, 0xff000000 },
//{ 0x80000000, 0x04000000, 0x04000000 },
//{ 0x04000000, 0x80000000, 0x20000000 },
//{ 0xff000000, 0xff000000, 0xff000000 },
// brightened
{ 0x06000000, 0x01000000, 0x5a000000 },
{ 0x06000000, 0x5a000000, 0x3d000000 },
{ 0xb4000000, 0xb4000000, 0xb4000000 },
{ 0x5a000000, 0x03000000, 0x03000000 },
{ 0x03000000, 0x5a000000, 0x17000000 },
{ 0xb4000000, 0xb4000000, 0xb4000000 },
}, { // aperture (doubled & darkened, alpha */ 1.75)
//{ 0x2cf31d00, 0x1500ffce, 0x1c1200a4 },
//{ 0x557e0f00, 0x40005044, 0x45070067 },
//{ 0x800c0200, 0x89000606, 0x8d02000d },
{ 0x19f31d00, 0x0c00ffce, 0x101200a4, 0x19f31d00, 0x0c00ffce, 0x101200a4 },
{ 0x317e0f00, 0x25005044, 0x37070067, 0x317e0f00, 0x25005044, 0x37070067 },
{ 0xe00c0200, 0xf0000606, 0xf702000d, 0xe00c0200, 0xf0000606, 0xf702000d },
}, { // mame
// original tile data from https://wiki.arcadeotaku.com/w/MAME_CRT_Simulation
//{ 0xffb4b4b4, 0xffa5a5a5, 0xffc3c3c3 },
@ -427,6 +449,7 @@ void TIASurface::createScanlineSurface()
mySLineSurface->setSrcSize(mySLineSurface->width(), height);
mySLineSurface->setDstRect(myTiaSurface->dstRect());
updateSurfaceSettings();
enableNTSC(ntscEnabled());
}
@ -664,12 +687,13 @@ void TIASurface::renderForSnapshot()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::updateSurfaceSettings()
{
myTiaSurface->setScalingInterpolation(
interpolationModeFromSettings(myOSystem.settings())
);
mySLineSurface->setScalingInterpolation(
interpolationModeFromSettings(myOSystem.settings())
);
if(myTiaSurface != nullptr)
myTiaSurface->setScalingInterpolation(
interpolationModeFromSettings(myOSystem.settings()));
if(mySLineSurface != nullptr)
mySLineSurface->setScalingInterpolation(
interpolationModeFromSettings(myOSystem.settings()));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -49,6 +49,7 @@ class TIASurface
static constexpr const char* SETTING_STANDARD = "standard";
static constexpr const char* SETTING_THIN = "thin";
static constexpr const char* SETTING_PIXELS = "pixels";
static constexpr const char* SETTING_APERTURE = "aperture";
static constexpr const char* SETTING_MAME = "mame";
/**
@ -198,6 +199,7 @@ class TIASurface
Standard,
Thin,
Pixels,
Aperture,
Mame,
NumMasks
};

View File

@ -384,10 +384,12 @@ void VideoAudioDialog::addTVEffectsTab()
VarList::push_back(items, "Standard", TIASurface::SETTING_STANDARD);
VarList::push_back(items, "Thin lines", TIASurface::SETTING_THIN);
VarList::push_back(items, "Pixelated", TIASurface::SETTING_PIXELS);
VarList::push_back(items, "Aperture Gr.", TIASurface::SETTING_APERTURE);
VarList::push_back(items, "MAME", TIASurface::SETTING_MAME);
pwidth = _font.getStringWidth("Thin lines");
myTVScanMask = new PopUpWidget(myTab, _font, myTVScanIntense->getRight() + fontWidth * 2,
xpos = myTVScanIntense->getRight() + fontWidth * 2;
pwidth = _w - HBORDER - xpos - fontWidth * 5 - PopUpWidget::dropDownWidth(_font) - 2 * 2;
myTVScanMask = new PopUpWidget(myTab, _font, xpos,
myTVScanIntense->getTop() + 1, pwidth, lineHeight, items, "Mask ");
wid.push_back(myTVScanMask);
@ -894,7 +896,7 @@ void VideoAudioDialog::setDefaults()
myTVPhosLevel->setValue(50);
// TV scanline intensity & mask
myTVScanIntense->setValue(25);
myTVScanIntense->setValue(0);
myTVScanMask->setSelected(TIASurface::SETTING_STANDARD);
// Make sure that mutually-exclusive items are not enabled at the same time
@ -1155,9 +1157,13 @@ void VideoAudioDialog::handleCommand(CommandSender* sender, int cmd,
{
myTVScanIntense->setValueLabel("Off");
myTVScanIntense->setValueUnit("");
myTVScanMask->setEnabled(false);
}
else
{
myTVScanIntense->setValueUnit("%");
myTVScanMask->setEnabled(true);
}
break;
case kPhosphorChanged: