GS: Add option to show vertical overscan

This commit is contained in:
refractionpcsx2 2022-06-05 18:03:13 +01:00
parent cf3cfdb2bc
commit f70c67ad7f
13 changed files with 62 additions and 29 deletions

View File

@ -104,6 +104,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.bilinearFiltering, "EmuCore/GS", "linear_present", true);
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.PCRTCOverscan, "EmuCore/GS", "pcrtc_overscan", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.DisableInterlaceOffset, "EmuCore/GS", "disable_interlace_offset", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.internalResolutionScreenshots, "EmuCore/GS", "InternalResolutionScreenshots", false);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.zoom, "EmuCore/GS", "Zoom", 100.0f);

View File

@ -271,20 +271,6 @@
</item>
<item row="7" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_5">
<item row="1" column="1">
<widget class="QCheckBox" name="internalResolutionScreenshots">
<property name="text">
<string>Internal Resolution Screenshots</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="PCRTCOffsets">
<property name="text">
<string>Screen Offsets</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="vsync">
<property name="text">
@ -292,13 +278,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="integerScaling">
<property name="text">
<string>Integer Upscaling</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="bilinearFiltering">
<property name="text">
@ -306,7 +285,35 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="internalResolutionScreenshots">
<property name="text">
<string>Internal Resolution Screenshots</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="integerScaling">
<property name="text">
<string>Integer Upscaling</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="PCRTCOverscan">
<property name="text">
<string>Show Overscan</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="PCRTCOffsets">
<property name="text">
<string>Screen Offsets</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="DisableInterlaceOffset">
<property name="toolTip">
<string>Disables interlacing offset which may reduce blurring in some situations.</string>

View File

@ -431,8 +431,9 @@ struct Pcsx2Config
struct
{
bool
DisableInterlaceOffset: 1,
DisableInterlaceOffset : 1,
PCRTCOffsets : 1,
PCRTCOverscan : 1,
IntegerScaling : 1,
LinearPresent : 1,
SyncToHostRefreshRate : 1,

View File

@ -1377,6 +1377,7 @@ void GSApp::Init()
m_default_configuration["HWDisableReadbacks"] = "0";
m_default_configuration["disable_interlace_offset"] = "0";
m_default_configuration["pcrtc_offsets"] = "0";
m_default_configuration["pcrtc_overscan"] = "0";
m_default_configuration["IntegerScaling"] = "0";
m_default_configuration["deinterlace"] = "7";
m_default_configuration["conservative_framebuffer"] = "1";

View File

@ -487,9 +487,10 @@ GSVector2i GSState::GetResolutionOffset(int i)
const auto& SMODE2 = m_regs->SMODE2;
const int res_multi = (SMODE2.INT + 1);
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
offset.x = (static_cast<int>(DISP.DX) - VideoModeOffsets[videomode].z) / (VideoModeDividers[videomode].x + 1);
offset.y = (static_cast<int>(DISP.DY) - (VideoModeOffsets[videomode].w * ((IsAnalogue() && res_multi) ? res_multi : 1))) / (VideoModeDividers[videomode].y + 1);
offset.x = (static_cast<int>(DISP.DX) - offsets.z) / (VideoModeDividers[videomode].x + 1);
offset.y = (static_cast<int>(DISP.DY) - (offsets.w * ((IsAnalogue() && res_multi) ? res_multi : 1))) / (VideoModeDividers[videomode].y + 1);
return offset;
}
@ -499,7 +500,9 @@ GSVector2i GSState::GetResolution()
const int videomode = static_cast<int>(GetVideoMode()) - 1;
const bool ignore_offset = !GSConfig.PCRTCOffsets;
GSVector2i resolution(VideoModeOffsets[videomode].x, VideoModeOffsets[videomode].y);
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
GSVector2i resolution(offsets.x, offsets.y);
// The resolution of the framebuffer is double when in FRAME mode and interlaced.
// Also we need a special check because no-interlace patches like to render in the original height, but in non-interlaced mode

View File

@ -272,6 +272,15 @@ public:
GSVector4i(1920, 540, 238, 40)
};
const GSVector4i VideoModeOffsetsOverscan[6] = {
GSVector4i(640, 240, 642, 12),
GSVector4i(640, 288, 676, 18),
GSVector4i(640, 480, 276, 34),
GSVector4i(720, 480, 232, 35),
GSVector4i(1280, 720, 302, 24),
GSVector4i(1920, 540, 238, 40)
};
const GSVector4i VideoModeDividers[6] = {
GSVector4i(3, 0, 2559, 239),
GSVector4i(3, 0, 2559, 287),

View File

@ -219,7 +219,8 @@ bool GSRenderer::Merge(int field)
if (!slbg || !feedback_merge)
{
const int videomode = static_cast<int>(GetVideoMode()) - 1;
GSVector2i base_resolution(VideoModeOffsets[videomode].x, VideoModeOffsets[videomode].y);
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
GSVector2i base_resolution(offsets.x, offsets.y);
if (isinterlaced() && !m_regs->SMODE2.FFMD)
base_resolution.y *= 2;

View File

@ -57,7 +57,8 @@ void GSRendererHW::SetScaling()
{
const int videomode = static_cast<int>(GetVideoMode()) - 1;
const int display_width = (VideoModeDividers[videomode].z + 1) / GetDisplayHMagnification();
int display_height = VideoModeOffsets[videomode].y;
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
int display_height = offsets.y;
if (isinterlaced() && !m_regs->SMODE2.FFMD)
display_height *= 2;
@ -269,7 +270,8 @@ GSTexture* GSRendererHW::GetOutput(int i, int& y_offset)
TEX0.PSM = DISPFB.PSM;
const int videomode = static_cast<int>(GetVideoMode()) - 1;
const int display_height = VideoModeOffsets[videomode].y * ((isinterlaced() && !m_regs->SMODE2.FFMD) ? 2 : 1);
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
const int display_height = offsets.y * ((isinterlaced() && !m_regs->SMODE2.FFMD) ? 2 : 1);
const int display_offset = GetResolutionOffset(i).y;
int fb_height = std::min(GetFramebufferHeight(), display_height) + DISPFB.DBY;

View File

@ -145,7 +145,8 @@ GSTexture* GSRendererSW::GetOutput(int i, int& y_offset)
const int videomode = static_cast<int>(GetVideoMode()) - 1;
const int display_offset = GetResolutionOffset(i).y;
const int display_height = VideoModeOffsets[videomode].y * ((isinterlaced() && !m_regs->SMODE2.FFMD) ? 2 : 1);
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
const int display_height = offsets.y * ((isinterlaced() && !m_regs->SMODE2.FFMD) ? 2 : 1);
int h = std::min(GetFramebufferHeight(), display_height) + DISPFB.DBY;
// If there is a negative vertical offset on the picture, we need to read more.

View File

@ -93,6 +93,9 @@ const char* dialog_message(int ID, bool* updateText)
return cvtString("Enable: Takes in to account offsets in the analogue circuits.\n"
"This will use the intended aspect ratios and screen offsets, may cause odd black borders.\n"
"Used for screen positioning and screen shake in Wipeout Fusion.");
case IDC_PCRTC_OVERSCAN:
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) and Crash Nitro Kart (PAL).");
case IDC_DISABLE_INTERLACE_OFFSETS:
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"

View File

@ -43,6 +43,7 @@ enum
// Renderer
IDC_FILTER,
IDC_PCRTC_OFFSETS,
IDC_PCRTC_OVERSCAN,
IDC_DISABLE_INTERLACE_OFFSETS,
// Hardware Renderer
IDC_PRELOAD_TEXTURES,

View File

@ -322,6 +322,7 @@ RendererTab::RendererTab(wxWindow* parent)
auto* pcrtc_checks_box = new wxWrapSizer(wxHORIZONTAL);
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, "Disable Interlace Offset", "disable_interlace_offset", IDC_DISABLE_INTERLACE_OFFSETS);
general_box->Add(pcrtc_checks_box, wxSizerFlags().Center());

View File

@ -299,6 +299,7 @@ Pcsx2Config::GSOptions::GSOptions()
DisableInterlaceOffset = false;
PCRTCOffsets = false;
PCRTCOverscan = false;
IntegerScaling = false;
LinearPresent = true;
SyncToHostRefreshRate = false;
@ -516,6 +517,7 @@ void Pcsx2Config::GSOptions::ReloadIniSettings()
// using these variables, we need to use the old names. Maybe post 2.0 we can change this.
GSSettingBoolEx(DisableInterlaceOffset, "disable_interlace_offset");
GSSettingBoolEx(PCRTCOffsets, "pcrtc_offsets");
GSSettingBoolEx(PCRTCOverscan, "pcrtc_overscan");
GSSettingBool(IntegerScaling);
GSSettingBoolEx(LinearPresent, "linear_present");
GSSettingBool(UseDebugDevice);