diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index cde3d5129e..a19194566d 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -287,17 +287,17 @@ void GLGSRender::InitVertexData() } // Scale - scaleOffsetMat[0] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4*0)] / (RSXThread::m_width / 2.0f); - scaleOffsetMat[5] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4*1)] / (RSXThread::m_height / 2.0f); + scaleOffsetMat[0] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4 * 0)] / (RSXThread::m_width / RSXThread::m_width_scale); + scaleOffsetMat[5] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4 * 1)] / (RSXThread::m_height / RSXThread::m_height_scale); scaleOffsetMat[10] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_SCALE + (0x4*2)]; // Offset - scaleOffsetMat[3] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4*0)] - (RSXThread::m_width / 2.0f); - scaleOffsetMat[7] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4*1)] - (RSXThread::m_height / 2.0f); - scaleOffsetMat[11] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4*2)] - 1/2.0f; + scaleOffsetMat[3] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 0)] - (RSXThread::m_width / RSXThread::m_width_scale); + scaleOffsetMat[7] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 1)] - (RSXThread::m_height / RSXThread::m_height_scale); + scaleOffsetMat[11] = (GLfloat&)methodRegisters[NV4097_SET_VIEWPORT_OFFSET + (0x4 * 2)]; - scaleOffsetMat[3] /= RSXThread::m_width / 2.0f; - scaleOffsetMat[7] /= RSXThread::m_height / 2.0f; + scaleOffsetMat[3] /= RSXThread::m_width / RSXThread::m_width_scale; + scaleOffsetMat[7] /= RSXThread::m_height / RSXThread::m_height_scale; l = m_program.GetLocation("scaleOffsetMat"); glUniformMatrix4fv(l, 1, false, scaleOffsetMat); @@ -598,6 +598,8 @@ void GLGSRender::OnInit() m_skip_frames = 0; RSXThread::m_width = 720; RSXThread::m_height = 576; + RSXThread::m_width_scale = 2.0f; + RSXThread::m_height_scale = 2.0f; last_width = 0; last_height = 0; diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index e2b0fe61c8..c335870cd8 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -1264,6 +1264,31 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr); m_width = re(buffers[m_gcm_current_buffer].width); m_height = re(buffers[m_gcm_current_buffer].height); + + if (Ini.GSDownscale.GetValue()) + { + if (m_width == 1280 && m_height == 720) + { + // Set scale ratio for 720p + m_width_scale = 1.125f; + m_height_scale = 1.33f; + + // Downscale 720p to 480p + m_width = 720; + m_height = 480; + } + + if (m_width == 1920 && m_height == 1080) + { + // Set scale ratio for 1080p + m_width_scale = 0.75f; + m_height_scale = 0.88f; + + // Downscale 1080p to 480p + m_width = 720; + m_height = 480; + } + } } break; diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 0424317aa0..2a5020c12e 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -137,7 +137,10 @@ public: public: uint m_draw_mode; - u32 m_width, m_height; + u32 m_width; + u32 m_height; + float m_width_scale; + float m_height_scale; u32 m_draw_array_count; u32 m_draw_array_first; diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 3dcfd9c31a..65f026e024 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -420,10 +420,11 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxCheckBox* chbox_gs_log_prog = new wxCheckBox(p_graphics, wxID_ANY, "Log vertex/fragment programs"); wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(p_graphics, wxID_ANY, "Write Depth Buffer"); wxCheckBox* chbox_gs_dump_color = new wxCheckBox(p_graphics, wxID_ANY, "Write Color Buffers"); - wxCheckBox* chbox_skip_pamf = new wxCheckBox(p_graphics, wxID_ANY, "Skip Pamf"); + wxCheckBox* chbox_skip_pamf = new wxCheckBox(p_graphics, wxID_ANY, "Skip Pamf"); + wxCheckBox* chbox_gs_downscale = new wxCheckBox(p_graphics, wxID_ANY, "480p Downscale"); wxCheckBox* chbox_gs_vsync = new wxCheckBox(p_graphics, wxID_ANY, "VSync"); wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file"); - wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit"); + wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit"); wxCheckBox* chbox_hle_logging = new wxCheckBox(p_hle, wxID_ANY, "Log all SysCalls"); wxCheckBox* chbox_hle_hook_stfunc = new wxCheckBox(p_hle, wxID_ANY, "Hook static functions"); wxCheckBox* chbox_hle_savetty = new wxCheckBox(p_hle, wxID_ANY, "Save TTY output to file"); @@ -500,9 +501,10 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) chbox_gs_dump_depth ->SetValue(Ini.GSDumpDepthBuffer.GetValue()); chbox_gs_dump_color ->SetValue(Ini.GSDumpColorBuffers.GetValue()); chbox_skip_pamf ->SetValue(Ini.SkipPamf.GetValue()); + chbox_gs_downscale ->SetValue(Ini.GSDownscale.GetValue()); chbox_gs_vsync ->SetValue(Ini.GSVSyncEnable.GetValue()); chbox_audio_dump ->SetValue(Ini.AudioDumpToFile.GetValue()); - chbox_audio_conv ->SetValue(Ini.AudioConvertToU16.GetValue()); + chbox_audio_conv ->SetValue(Ini.AudioConvertToU16.GetValue()); chbox_hle_logging ->SetValue(Ini.HLELogging.GetValue()); chbox_hle_hook_stfunc ->SetValue(Ini.HLEHookStFunc.GetValue()); chbox_hle_savetty ->SetValue(Ini.HLESaveTTY.GetValue()); @@ -561,6 +563,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) s_subpanel_graphics->Add(chbox_gs_dump_color, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_skip_pamf, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel_graphics->Add(chbox_gs_downscale, wxSizerFlags().Border(wxALL, 5).Expand()); // Input - Output s_subpanel_io->Add(s_round_io_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -609,6 +612,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) Ini.GSResolution.SetValue(ResolutionNumToId(cbox_gs_resolution->GetSelection() + 1)); Ini.GSAspectRatio.SetValue(cbox_gs_aspect->GetSelection() + 1); Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue()); + Ini.GSDownscale.SetValue(chbox_gs_downscale->GetValue()); Ini.GSLogPrograms.SetValue(chbox_gs_log_prog->GetValue()); Ini.GSDumpDepthBuffer.SetValue(chbox_gs_dump_depth->GetValue()); Ini.GSDumpColorBuffers.SetValue(chbox_gs_dump_color->GetValue()); diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index 543b8b4075..a0c17b6dc3 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -116,6 +116,7 @@ public: IniEntry GSDumpColorBuffers; IniEntry GSDumpDepthBuffer; IniEntry SkipPamf; + IniEntry GSDownscale; // Audio IniEntry AudioOutMode; @@ -184,6 +185,7 @@ public: GSDumpColorBuffers.Init("GS_DumpColorBuffers", path); GSDumpDepthBuffer.Init("GS_DumpDepthBuffer", path); SkipPamf.Init("GS_SkipPamf", path); + GSDownscale.Init("GS_Downscale", path); // Audio AudioOutMode.Init("Audio_AudioOutMode", path); @@ -248,6 +250,7 @@ public: GSDumpColorBuffers.Load(false); GSDumpDepthBuffer.Load(false); SkipPamf.Load(false); + GSDownscale.Load(false); // Audio AudioOutMode.Load(1); @@ -313,6 +316,7 @@ public: GSDumpColorBuffers.Save(); GSDumpDepthBuffer.Save(); SkipPamf.Save(); + GSDownscale.Save(); // Audio AudioOutMode.Save(); @@ -362,4 +366,4 @@ public: } }; -extern Inis Ini; \ No newline at end of file +extern Inis Ini;