mirror of https://github.com/PCSX2/pcsx2.git
GS-PCRTC: Add option to enable/disable Anti-Blur code.
For... accuracy? Also clean up FIELD nonsense in the merge circuit. Fixed up offset code for interlacing
This commit is contained in:
parent
c86e82039a
commit
b5807e0788
|
@ -105,6 +105,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOffsets, "EmuCore/GS", "pcrtc_offsets", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOffsets, "EmuCore/GS", "pcrtc_offsets", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOverscan, "EmuCore/GS", "pcrtc_overscan", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOverscan, "EmuCore/GS", "pcrtc_overscan", false);
|
||||||
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCAntiBlur, "EmuCore/GS", "pcrtc_antiblur", true);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.DisableInterlaceOffset, "EmuCore/GS", "disable_interlace_offset", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.DisableInterlaceOffset, "EmuCore/GS", "disable_interlace_offset", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.internalResolutionScreenshots, "EmuCore/GS", "InternalResolutionScreenshots", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.internalResolutionScreenshots, "EmuCore/GS", "InternalResolutionScreenshots", false);
|
||||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.zoom, "EmuCore/GS", "Zoom", 100.0f);
|
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.zoom, "EmuCore/GS", "Zoom", 100.0f);
|
||||||
|
|
|
@ -323,6 +323,19 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QCheckBox" name="PCRTCAntiBlur">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Enables internal Anti-Blur hacks. LEss accurate to PS2 rendering but will make a lot of games look less blurry.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Anti-Blur</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+S</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -434,6 +434,7 @@ struct Pcsx2Config
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool
|
bool
|
||||||
|
PCRTCAntiBlur : 1,
|
||||||
DisableInterlaceOffset : 1,
|
DisableInterlaceOffset : 1,
|
||||||
PCRTCOffsets : 1,
|
PCRTCOffsets : 1,
|
||||||
PCRTCOverscan : 1,
|
PCRTCOverscan : 1,
|
||||||
|
|
|
@ -1370,6 +1370,7 @@ void GSApp::Init()
|
||||||
m_default_configuration["fxaa"] = "0";
|
m_default_configuration["fxaa"] = "0";
|
||||||
m_default_configuration["GSDumpCompression"] = "0";
|
m_default_configuration["GSDumpCompression"] = "0";
|
||||||
m_default_configuration["HWDisableReadbacks"] = "0";
|
m_default_configuration["HWDisableReadbacks"] = "0";
|
||||||
|
m_default_configuration["pcrtc_antiblur"] = "1";
|
||||||
m_default_configuration["disable_interlace_offset"] = "0";
|
m_default_configuration["disable_interlace_offset"] = "0";
|
||||||
m_default_configuration["pcrtc_offsets"] = "0";
|
m_default_configuration["pcrtc_offsets"] = "0";
|
||||||
m_default_configuration["pcrtc_overscan"] = "0";
|
m_default_configuration["pcrtc_overscan"] = "0";
|
||||||
|
|
|
@ -377,7 +377,7 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
|
||||||
if (mode == 0 || mode == 2) // weave or blend
|
if (mode == 0 || mode == 2) // weave or blend
|
||||||
{
|
{
|
||||||
// weave first
|
// weave first
|
||||||
const int offset = static_cast<int>(yoffset) * (1 - field);
|
const int offset = static_cast<int>(yoffset) * field;
|
||||||
|
|
||||||
DoInterlace(m_merge, m_weavebob, field, false, GSConfig.DisableInterlaceOffset ? 0 : offset);
|
DoInterlace(m_merge, m_weavebob, field, false, GSConfig.DisableInterlaceOffset ? 0 : offset);
|
||||||
|
|
||||||
|
@ -398,7 +398,8 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
|
||||||
}
|
}
|
||||||
else if (mode == 1) // bob
|
else if (mode == 1) // bob
|
||||||
{
|
{
|
||||||
DoInterlace(m_merge, m_weavebob, 3, true, yoffset * field);
|
// Field is reversed here as we are countering the bounce.
|
||||||
|
DoInterlace(m_merge, m_weavebob, 3, true, yoffset * (1-field));
|
||||||
|
|
||||||
m_current = m_weavebob;
|
m_current = m_weavebob;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,7 @@ bool GSRenderer::Merge(int field)
|
||||||
GSVector2i frame_baseline = {INT_MAX, INT_MAX};
|
GSVector2i frame_baseline = {INT_MAX, INT_MAX};
|
||||||
GSVector2i display_combined = {0, 0};
|
GSVector2i display_combined = {0, 0};
|
||||||
bool feedback_merge = m_regs->EXTWRITE.WRITE == 1;
|
bool feedback_merge = m_regs->EXTWRITE.WRITE == 1;
|
||||||
|
bool display_offset = false;
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
|
@ -114,6 +115,7 @@ bool GSRenderer::Merge(int field)
|
||||||
frame_baseline.x = std::min(fr[i].left, frame_baseline.x);
|
frame_baseline.x = std::min(fr[i].left, frame_baseline.x);
|
||||||
frame_baseline.y = std::min(fr[i].top, frame_baseline.y);
|
frame_baseline.y = std::min(fr[i].top, frame_baseline.y);
|
||||||
|
|
||||||
|
display_offset |= std::abs(display_baseline.y - display_offsets[i].y) == 1;
|
||||||
/*DevCon.Warning("Read offset was X %d(left %d) Y %d(top %d)", display_baseline.x, dr[i].left, display_baseline.y, dr[i].top);
|
/*DevCon.Warning("Read offset was X %d(left %d) Y %d(top %d)", display_baseline.x, dr[i].left, display_baseline.y, dr[i].top);
|
||||||
DevCon.Warning("[%d]: %d %d %d %d, %d %d %d %d\n", i, fr[i].x,fr[i].y,fr[i].z,fr[i].w , dr[i].x,dr[i].y,dr[i].z,dr[i].w);
|
DevCon.Warning("[%d]: %d %d %d %d, %d %d %d %d\n", i, fr[i].x,fr[i].y,fr[i].z,fr[i].w , dr[i].x,dr[i].y,dr[i].z,dr[i].w);
|
||||||
DevCon.Warning("Offset X %d Offset Y %d", display_offsets[i].x, display_offsets[i].y);*/
|
DevCon.Warning("Offset X %d Offset Y %d", display_offsets[i].x, display_offsets[i].y);*/
|
||||||
|
@ -168,7 +170,7 @@ bool GSRenderer::Merge(int field)
|
||||||
const bool slbg = m_regs->PMODE.SLBG;
|
const bool slbg = m_regs->PMODE.SLBG;
|
||||||
|
|
||||||
GSVector2i resolution(GetResolution());
|
GSVector2i resolution(GetResolution());
|
||||||
bool scanmask_frame = true;
|
bool scanmask_frame = m_scanmask_used && !display_offset;
|
||||||
const bool ignore_offset = !GSConfig.PCRTCOffsets;
|
const bool ignore_offset = !GSConfig.PCRTCOffsets;
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
|
@ -186,18 +188,25 @@ bool GSRenderer::Merge(int field)
|
||||||
|
|
||||||
// If using scanmsk we have to keep the single line offset, regardless of upscale
|
// If using scanmsk we have to keep the single line offset, regardless of upscale
|
||||||
// so we handle this separately after the rect calculations.
|
// so we handle this separately after the rect calculations.
|
||||||
const int interlace_offset = display_diff.y & 1;
|
float interlace_offset = 0.0f;
|
||||||
|
|
||||||
if (m_scanmask_used && interlace_offset)
|
if ((!GSConfig.PCRTCAntiBlur || m_scanmask_used) && display_offset)
|
||||||
{
|
{
|
||||||
display_diff.y &= ~1;
|
interlace_offset = static_cast<float>(display_diff.y & 1);
|
||||||
scanmask_frame = false;
|
|
||||||
|
// When the displays are offset by 1 we need to adjust for upscale to handle it (reduces bounce in MGS2 when upscaling)
|
||||||
|
interlace_offset += (tex[i]->GetScale().y - 1.0f) / 2;
|
||||||
|
|
||||||
if (!ignore_offset)
|
if (!ignore_offset)
|
||||||
off.y &= ~1;
|
off.y &= ~1;
|
||||||
|
|
||||||
|
display_diff.y &= ~1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start of Anti-Blur code.
|
// Start of Anti-Blur code.
|
||||||
if (!ignore_offset)
|
if (!ignore_offset)
|
||||||
|
{
|
||||||
|
if (GSConfig.PCRTCAntiBlur)
|
||||||
{
|
{
|
||||||
if (samesrc)
|
if (samesrc)
|
||||||
{
|
{
|
||||||
|
@ -214,10 +223,22 @@ bool GSRenderer::Merge(int field)
|
||||||
off.y += 1;
|
off.y += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!slbg || !feedback_merge)
|
if (!slbg || !feedback_merge)
|
||||||
{
|
{
|
||||||
|
// If the offsets between the two displays are quite large, it's probably intended for an effect.
|
||||||
|
if (display_diff.x >= 4 || !GSConfig.PCRTCAntiBlur)
|
||||||
|
off.x = display_diff.x;
|
||||||
|
|
||||||
|
if (display_diff.y >= 4 || !GSConfig.PCRTCAntiBlur)
|
||||||
|
off.y = display_diff.y;
|
||||||
|
|
||||||
|
|
||||||
|
if (samesrc)
|
||||||
|
{
|
||||||
|
// Adjusting the screen offset when using a negative offset.
|
||||||
const int videomode = static_cast<int>(GetVideoMode()) - 1;
|
const int videomode = static_cast<int>(GetVideoMode()) - 1;
|
||||||
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
|
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
|
||||||
GSVector2i base_resolution(offsets.x, offsets.y);
|
GSVector2i base_resolution(offsets.x, offsets.y);
|
||||||
|
@ -225,16 +246,6 @@ bool GSRenderer::Merge(int field)
|
||||||
if (isinterlaced() && !m_regs->SMODE2.FFMD)
|
if (isinterlaced() && !m_regs->SMODE2.FFMD)
|
||||||
base_resolution.y *= 2;
|
base_resolution.y *= 2;
|
||||||
|
|
||||||
// If the offsets between the two displays are quite large, it's probably intended for an effect.
|
|
||||||
if (display_diff.x >= 4)
|
|
||||||
off.x = display_diff.x;
|
|
||||||
|
|
||||||
if (display_diff.y >= 4)
|
|
||||||
off.y = display_diff.y;
|
|
||||||
|
|
||||||
// Anti blur hax.
|
|
||||||
if (samesrc)
|
|
||||||
{
|
|
||||||
// Offset by DISPLAY setting
|
// Offset by DISPLAY setting
|
||||||
if (display_diff.x < 0)
|
if (display_diff.x < 0)
|
||||||
{
|
{
|
||||||
|
@ -249,17 +260,21 @@ bool GSRenderer::Merge(int field)
|
||||||
resolution.y -= display_diff.y;
|
resolution.y -= display_diff.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't do X, we only care about height, this would need to be tailored for games using X (Black does -5).
|
||||||
|
// Mainly for Hokuto no Ken which does -14 Y offset.
|
||||||
|
if (display_baseline.y < -4)
|
||||||
|
off.y += display_baseline.y;
|
||||||
|
|
||||||
|
// Anti-Blur stuff
|
||||||
|
if (GSConfig.PCRTCAntiBlur)
|
||||||
|
{
|
||||||
// Offset by DISPFB setting
|
// Offset by DISPFB setting
|
||||||
if (frame_diff.x == 1)
|
if (frame_diff.x == 1)
|
||||||
off.x += 1;
|
off.x += 1;
|
||||||
|
|
||||||
if (frame_diff.y == 1)
|
if (frame_diff.y == 1)
|
||||||
off.y += 1;
|
off.y += 1;
|
||||||
|
}
|
||||||
// Don't do X, we only care about height, this would need to be tailored for games using X (Black does -5).
|
|
||||||
// Mainly for Hokuto no Ken which does -14 Y offset.
|
|
||||||
if (display_baseline.y < -4)
|
|
||||||
off.y += display_baseline.y;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,9 +292,8 @@ bool GSRenderer::Merge(int field)
|
||||||
// src_out_rect is the resized rect for output. (Not really used)
|
// src_out_rect is the resized rect for output. (Not really used)
|
||||||
src_out_rect[i] = (GSVector4(r) * scale) / GSVector4(tex[i]->GetSize()).xyxy();
|
src_out_rect[i] = (GSVector4(r) * scale) / GSVector4(tex[i]->GetSize()).xyxy();
|
||||||
|
|
||||||
// Restore the single line offset for scanmsk.
|
// Restore manually offset "interlace" lines
|
||||||
if (m_scanmask_used && interlace_offset)
|
dst[i] += GSVector4(0.0f, interlace_offset, 0.0f, interlace_offset);
|
||||||
dst[i] += GSVector4(0.0f, 1.0f, 0.0f, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feedback_merge && tex[2])
|
if (feedback_merge && tex[2])
|
||||||
|
@ -335,24 +349,24 @@ bool GSRenderer::Merge(int field)
|
||||||
|
|
||||||
g_gs_device->Merge(tex, src_gs_read, dst, fs, m_regs->PMODE, m_regs->EXTBUF, c);
|
g_gs_device->Merge(tex, src_gs_read, dst, fs, m_regs->PMODE, m_regs->EXTBUF, c);
|
||||||
|
|
||||||
// Offset is not compatible with scanmsk, as scanmsk renders every other line, but at x7 the interlace offset will be 7 lines
|
// Use offset for bob deinterlacing, for normal deinterlacing we add an extra 1 since it's clearer, with bob that causes extra shake.
|
||||||
const int offset = (m_scanmask_used || !m_regs->SMODE2.FFMD) ? 0 : (int)(tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y);
|
const bool is_bob = GSConfig.InterlaceMode == GSInterlaceMode::BobTFF || GSConfig.InterlaceMode == GSInterlaceMode::BobBFF;
|
||||||
|
const float offset = (!m_regs->SMODE2.FFMD && !is_bob) ? 0 : ((tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y));
|
||||||
|
|
||||||
if (isReallyInterlaced() && GSConfig.InterlaceMode != GSInterlaceMode::Off)
|
if (isReallyInterlaced() && GSConfig.InterlaceMode != GSInterlaceMode::Off)
|
||||||
{
|
{
|
||||||
const bool scanmask = m_scanmask_used && scanmask_frame && GSConfig.InterlaceMode == GSInterlaceMode::Automatic;
|
// FFMD (half frames) requires blend deinterlacing, so automatically use that. Same when SCANMSK is used but not blended in the merge circuit (Alpine Racer 3)
|
||||||
|
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic && (m_regs->SMODE2.FFMD || scanmask_frame))
|
||||||
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic && (m_regs->SMODE2.FFMD)) // Auto interlace enabled / Odd frame interlace setting
|
|
||||||
{
|
{
|
||||||
constexpr int field2 = 1;
|
constexpr int field2 = 0;
|
||||||
constexpr int mode = 2;
|
constexpr int mode = 2;
|
||||||
|
|
||||||
g_gs_device->Interlace(ds, field ^ field2, mode, offset);
|
g_gs_device->Interlace(ds, field ^ field2, mode, offset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const int field2 = scanmask ? 0 : 1 - ((static_cast<int>(GSConfig.InterlaceMode) - 1) & 1);
|
const int field2 = ((static_cast<int>(GSConfig.InterlaceMode) - 1) & 1);
|
||||||
const int mode = scanmask ? 2 : ((static_cast<int>(GSConfig.InterlaceMode) - 1) >> 1);
|
const int mode = ((static_cast<int>(GSConfig.InterlaceMode) - 1) >> 1);
|
||||||
|
|
||||||
g_gs_device->Interlace(ds, field ^ field2, mode, offset);
|
g_gs_device->Interlace(ds, field ^ field2, mode, offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,9 @@ const char* dialog_message(int ID, bool* updateText)
|
||||||
return cvtString("Shows more overscan area for some games which expect there to be some.\n"
|
return cvtString("Shows more overscan area for some games which expect there to be some.\n"
|
||||||
"Used for games like Need for Speed Underground (PAL),Crash Nitro Kart (PAL) \n"
|
"Used for games like Need for Speed Underground (PAL),Crash Nitro Kart (PAL) \n"
|
||||||
"and Espgaluda (When using certain Tate modes)");
|
"and Espgaluda (When using certain Tate modes)");
|
||||||
|
case IDC_PCRTC_ANTIBLUR:
|
||||||
|
return cvtString("Enable: Adds internal anti-blur hacks on the merge ciruit.\n"
|
||||||
|
"This will likely make a lot of games look crisper but is less accurate to the PS2.");
|
||||||
case IDC_DISABLE_INTERLACE_OFFSETS:
|
case IDC_DISABLE_INTERLACE_OFFSETS:
|
||||||
return cvtString("Enable: Removes the offset for interlacing when upscaling.\n"
|
return cvtString("Enable: Removes the offset for interlacing when upscaling.\n"
|
||||||
"Can reduce blurring in some games, where the opposite is true most of the time.\n"
|
"Can reduce blurring in some games, where the opposite is true most of the time.\n"
|
||||||
|
|
|
@ -44,6 +44,7 @@ enum
|
||||||
IDC_FILTER,
|
IDC_FILTER,
|
||||||
IDC_PCRTC_OFFSETS,
|
IDC_PCRTC_OFFSETS,
|
||||||
IDC_PCRTC_OVERSCAN,
|
IDC_PCRTC_OVERSCAN,
|
||||||
|
IDC_PCRTC_ANTIBLUR,
|
||||||
IDC_DISABLE_INTERLACE_OFFSETS,
|
IDC_DISABLE_INTERLACE_OFFSETS,
|
||||||
// Hardware Renderer
|
// Hardware Renderer
|
||||||
IDC_PRELOAD_TEXTURES,
|
IDC_PRELOAD_TEXTURES,
|
||||||
|
|
|
@ -324,7 +324,7 @@ RendererTab::RendererTab(wxWindow* parent)
|
||||||
m_ui.addCheckBox(pcrtc_checks_box, "Screen Offsets", "pcrtc_offsets", IDC_PCRTC_OFFSETS);
|
m_ui.addCheckBox(pcrtc_checks_box, "Screen Offsets", "pcrtc_offsets", IDC_PCRTC_OFFSETS);
|
||||||
m_ui.addCheckBox(pcrtc_checks_box, "Show Overscan", "pcrtc_overscan", IDC_PCRTC_OVERSCAN);
|
m_ui.addCheckBox(pcrtc_checks_box, "Show Overscan", "pcrtc_overscan", IDC_PCRTC_OVERSCAN);
|
||||||
m_ui.addCheckBox(pcrtc_checks_box, "Disable Interlace Offset", "disable_interlace_offset", IDC_DISABLE_INTERLACE_OFFSETS);
|
m_ui.addCheckBox(pcrtc_checks_box, "Disable Interlace Offset", "disable_interlace_offset", IDC_DISABLE_INTERLACE_OFFSETS);
|
||||||
|
m_ui.addCheckBox(pcrtc_checks_box, "Anti-Blur", "pcrtc_antiblur", IDC_PCRTC_ANTIBLUR);
|
||||||
general_box->Add(pcrtc_checks_box, wxSizerFlags().Center());
|
general_box->Add(pcrtc_checks_box, wxSizerFlags().Center());
|
||||||
|
|
||||||
tab_box->Add(hardware_box.outer, wxSizerFlags().Expand());
|
tab_box->Add(hardware_box.outer, wxSizerFlags().Expand());
|
||||||
|
|
|
@ -300,6 +300,7 @@ Pcsx2Config::GSOptions::GSOptions()
|
||||||
{
|
{
|
||||||
bitset = 0;
|
bitset = 0;
|
||||||
|
|
||||||
|
PCRTCAntiBlur = true;
|
||||||
DisableInterlaceOffset = false;
|
DisableInterlaceOffset = false;
|
||||||
PCRTCOffsets = false;
|
PCRTCOffsets = false;
|
||||||
PCRTCOverscan = false;
|
PCRTCOverscan = false;
|
||||||
|
@ -510,6 +511,7 @@ void Pcsx2Config::GSOptions::ReloadIniSettings()
|
||||||
|
|
||||||
// Unfortunately, because code in the GS still reads the setting by key instead of
|
// Unfortunately, because code in the GS still reads the setting by key instead of
|
||||||
// using these variables, we need to use the old names. Maybe post 2.0 we can change this.
|
// using these variables, we need to use the old names. Maybe post 2.0 we can change this.
|
||||||
|
GSSettingBoolEx(PCRTCAntiBlur, "pcrtc_antiblur");
|
||||||
GSSettingBoolEx(DisableInterlaceOffset, "disable_interlace_offset");
|
GSSettingBoolEx(DisableInterlaceOffset, "disable_interlace_offset");
|
||||||
GSSettingBoolEx(PCRTCOffsets, "pcrtc_offsets");
|
GSSettingBoolEx(PCRTCOffsets, "pcrtc_offsets");
|
||||||
GSSettingBoolEx(PCRTCOverscan, "pcrtc_overscan");
|
GSSettingBoolEx(PCRTCOverscan, "pcrtc_overscan");
|
||||||
|
|
Loading…
Reference in New Issue