From 3f9b1b76e589ee857da8e1625952ae4be3b01f79 Mon Sep 17 00:00:00 2001 From: Bart Trzynadlowski Date: Thu, 3 May 2018 03:46:44 +0000 Subject: [PATCH] Added a stretch mode (-stretch) and modified new renderer's viewport code (hopefully correctly) to handle aspect ratio correction and widening the way the legacy one does. --- Src/Graphics/New3D/New3D.cpp | 29 +++++++++++++++++++++++++++-- Src/Graphics/New3D/New3D.h | 3 ++- Src/OSD/SDL/Main.cpp | 25 +++++++++++++++++-------- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index 1cbe630..07e33bb 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -72,6 +72,8 @@ bool CNew3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yR m_yRatio = yRes / 384.0f; m_xOffs = xOffset; m_yOffs = yOffset; + m_xRes = xRes; + m_yRes = yRes; m_totalXRes = totalXResParam; m_totalYRes = totalYResParam; @@ -1583,9 +1585,32 @@ void CNew3D::CalcViewport(Viewport* vp, float near, float far) if ((vp->vpX == 0) && (vp->vpWidth >= 495) && (vp->vpY == 0) && (vp->vpHeight >= 383)) { + /* + * Compute aspect ratio correction factor. "Window" refers to the full GL + * viewport (i.e., totalXRes x totalYRes). "Viewable area" is the effective + * Model 3 screen (xRes x yRes). In non-wide-screen, non-stretch mode, this + * is intended to replicate the 496x384 display and may in general be + * smaller than the window. The rest of the window appears to have a + * border, which is created by a scissor box. + * + * In wide-screen mode, we want to expand the frustum horizontally to fill + * the window. We want the aspect ratio to be correct. To accomplish this, + * the viewable area is set *the same* as in non-wide-screen mode (e.g., + * often smaller than the window) but glScissor() is set by the OSD layer's + * screen setup code to reveal the entire window. + * + * In stretch mode, the window and viewable area are both set the same, + * which means there will be no aspect ratio correction and the display + * will stretch to fill the entire window while keeping the view frustum + * the same as a 496x384 Model 3 display. The display will be distorted. + */ float windowAR = (float)m_totalXRes / (float)m_totalYRes; - float originalAR = 496 / 384.f; - float correction = windowAR / originalAR; // expand horizontal frustum planes + float viewableAreaAR = (float)m_xRes / (float)m_yRes; + + // Will expand horizontal frustum planes only in non-stretch mode (wide- + // screen and non-wide-screen modes have identical resolution parameters + // and only their scissor box differs) + float correction = windowAR / viewableAreaAR; vp->x = 0; vp->y = m_yOffs + (int)((384 - (vp->vpY + vp->vpHeight))*m_yRatio); diff --git a/Src/Graphics/New3D/New3D.h b/Src/Graphics/New3D/New3D.h index f6776ed..d10dadd 100644 --- a/Src/Graphics/New3D/New3D.h +++ b/Src/Graphics/New3D/New3D.h @@ -233,7 +233,8 @@ private: // Resolution and scaling factors (to support resolutions higher than 496x384) and offsets float m_xRatio, m_yRatio; unsigned m_xOffs, m_yOffs; - unsigned m_totalXRes, m_totalYRes; + unsigned m_xRes, m_yRes; // resolution of Model 3's 496x384 display area within the window + unsigned m_totalXRes, m_totalYRes; // total OpenGL window resolution // Real3D Base Matrix Pointer const float *m_matrixBasePtr; diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index b18c67c..b8b053f 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -119,7 +119,7 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned * if (yRes < (xRes/model3Ratio)) xRes = yRes*model3Ratio; if (xRes < (yRes*model3Ratio)) - yRes = xRes/model3Ratio; + yRes = xRes/model3Ratio; } // Center the visible area @@ -804,7 +804,9 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In totalXRes = xRes = s_runtime_config["XResolution"].ValueAs(); totalYRes = yRes = s_runtime_config["YResolution"].ValueAs(); sprintf(baseTitleStr, "Supermodel - %s", game.title.c_str()); - if (OKAY != CreateGLScreen(baseTitleStr, &xOffset, &yOffset ,&xRes, &yRes, &totalXRes, &totalYRes, true, s_runtime_config["FullScreen"].ValueAs())) + bool stretch = s_runtime_config["Stretch"].ValueAs(); + bool fullscreen = s_runtime_config["FullScreen"].ValueAs(); + if (OKAY != CreateGLScreen(baseTitleStr, &xOffset, &yOffset ,&xRes, &yRes, &totalXRes, &totalYRes, !stretch, fullscreen)) return 1; // Info log GL information @@ -972,12 +974,14 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In // Resize screen totalXRes = xRes = s_runtime_config["XResolution"].ValueAs(); totalYRes = yRes = s_runtime_config["YResolution"].ValueAs(); - if (OKAY != ResizeGLScreen(&xOffset,&yOffset,&xRes,&yRes,&totalXRes,&totalYRes,true,s_runtime_config["FullScreen"].ValueAs())) + bool stretch = s_runtime_config["Stretch"].ValueAs(); + bool fullscreen = s_runtime_config["FullScreen"].ValueAs(); + if (OKAY != ResizeGLScreen(&xOffset,&yOffset,&xRes,&yRes,&totalXRes,&totalYRes,!stretch,fullscreen)) goto QuitError; // Recreate renderers and attach to the emulator Render2D = new CRender2D(s_runtime_config); - Render3D = s_runtime_config["New3DEngine"].ValueAs() ? ((IRender3D *) new New3D::CNew3D(s_runtime_config, Model3->GetGame().name)) : ((IRender3D *) new Legacy3D::CLegacy3D(s_runtime_config)); + Render3D = s_runtime_config["New3DEngine"].ValueAs() ? ((IRender3D *) new New3D::CNew3D(s_runtime_config, Model3->GetGame().name)) : ((IRender3D *) new Legacy3D::CLegacy3D(s_runtime_config)); if (OKAY != Render2D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes)) goto QuitError; if (OKAY != Render3D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes)) @@ -1068,7 +1072,7 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In else if (Inputs->uiSoundVolUp->Pressed()) { // Increase sound volume by 10% - int vol = (std::min)(200, s_runtime_config["SoundVolume"].ValueAs() + 10); + int vol = (std::min)(200, s_runtime_config["SoundVolume"].ValueAs() + 10); s_runtime_config.Get("SoundVolume").SetValue(vol); printf("Sound volume: %d%%", vol); if (200 == vol) @@ -1309,6 +1313,7 @@ static Util::Config::Node DefaultConfig() config.Set("YResolution", "384"); config.Set("FullScreen", false); config.Set("WideScreen", false); + config.Set("Stretch", false); config.Set("VSync", true); config.Set("Throttle", true); config.Set("ShowFrameRate", false); @@ -1340,7 +1345,8 @@ static Util::Config::Node DefaultConfig() static void Title(void) { puts("Supermodel: A Sega Model 3 Arcade Emulator (Version " SUPERMODEL_VERSION ")"); - puts("Copyright 2011-2018 by Bart Trzynadlowski, Nik Henson, Ian Curtis, Harry Tuttle and Spindizzi\n"); + puts("Copyright 2011-2018 by Bart Trzynadlowski, Nik Henson, Ian Curtis,"); + puts(" Harry Tuttle, and Spindizzi\n"); } static void Help(void) @@ -1366,6 +1372,7 @@ static void Help(void) puts(" -window Windowed mode [Default]"); puts(" -fullscreen Full screen mode"); puts(" -wide-screen Expand 3D field of view to screen width"); + puts(" -stretch Fit viewport to resolution, ignoring aspect ratio"); puts(" -no-throttle Disable 60 Hz frame rate lock"); puts(" -vsync Lock to vertical refresh rate [Default]"); puts(" -no-vsync Do not lock to vertical refresh rate"); @@ -1465,6 +1472,8 @@ static ParsedCommandLine ParseCommandLine(int argc, char **argv) { "-fullscreen", { "FullScreen", true } }, { "-no-wide-screen", { "WideScreen", false } }, { "-wide-screen", { "WideScreen", true } }, + { "-stretch", { "Stretch", true } }, + { "-no-stretch", { "Stretch", false } }, { "-no-multi-texture", { "MultiTexture", false } }, { "-multi-texture", { "MultiTexture", true } }, { "-throttle", { "Throttle", true } }, @@ -1482,8 +1491,8 @@ static ParsedCommandLine ParseCommandLine(int argc, char **argv) { "-dsb", { "EmulateDSB", true } }, { "-no-dsb", { "EmulateDSB", false } }, #ifdef NET_BOARD - { "-net", { "EmulateNet", true } }, - { "-no-net", { "EmulateNet", false } }, + { "-net", { "EmulateNet", true } }, + { "-no-net", { "EmulateNet", false } }, #endif #ifdef SUPERMODEL_WIN32 { "-no-force-feedback", { "ForceFeedback", false } },