diff --git a/Config.h b/Config.h index c79abdf1..482579c3 100644 --- a/Config.h +++ b/Config.h @@ -13,6 +13,7 @@ struct Config u32 fullscreenWidth, fullscreenHeight, windowedWidth, windowedHeight; u32 fullscreenBits, fullscreenRefresh; u32 multisampling, verticalSync; + u32 aspect; // 0: stretch ; 1: 4/3 ; 2: 16/9 } video; struct diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp index 970e9c88..2cb5cfdd 100644 --- a/FrameBuffer.cpp +++ b/FrameBuffer.cpp @@ -363,7 +363,7 @@ void FrameBufferList::renderBuffer(u32 _address) } // glDisable(GL_SCISSOR_TEST) does not affect glBlitFramebuffer, at least on AMD - glScissor(0, 0, ogl.getWidth(), ogl.getHeight()); + glScissor(0, 0, ogl.getScreenWidth(), ogl.getScreenHeight()); glDisable(GL_SCISSOR_TEST); glBindFramebuffer(GL_READ_FRAMEBUFFER, pBuffer->m_FBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); @@ -371,9 +371,11 @@ void FrameBufferList::renderBuffer(u32 _address) float clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f}; ogl.getRender().clearColorBuffer(clearColor); const float scaleY = ogl.getScaleY(); + const float hOffset = (ogl.getScreenWidth() - ogl.getWidth()) / 2.0f; + const float vOffset = (ogl.getScreenHeight() - ogl.getHeight()) / 2.0f; glBlitFramebuffer( 0, (GLint)(srcY0*scaleY), ogl.getWidth(), (GLint)(srcY1*scaleY), - 0, ogl.getHeightOffset() + (GLint)(dstY0*scaleY), ogl.getWidth(), ogl.getHeightOffset() + (GLint)(dstY1*scaleY), + hOffset, vOffset + ogl.getHeightOffset() + (GLint)(dstY0*scaleY), hOffset + ogl.getWidth(), vOffset + ogl.getHeightOffset() + (GLint)(dstY1*scaleY), GL_COLOR_BUFFER_BIT, GL_LINEAR ); @@ -388,7 +390,7 @@ void FrameBufferList::renderBuffer(u32 _address) glBindFramebuffer(GL_READ_FRAMEBUFFER, pBuffer->m_FBO); glBlitFramebuffer( 0, (GLint)(srcY0*scaleY), ogl.getWidth(), (GLint)(srcY1*scaleY), - 0, ogl.getHeightOffset() + (GLint)(dstY0*scaleY), ogl.getWidth(), ogl.getHeightOffset() + (GLint)(dstY1*scaleY), + hOffset, vOffset + ogl.getHeightOffset() + (GLint)(dstY0*scaleY), hOffset + ogl.getWidth(), vOffset + ogl.getHeightOffset() + (GLint)(dstY1*scaleY), GL_COLOR_BUFFER_BIT, GL_LINEAR ); } diff --git a/OpenGL.cpp b/OpenGL.cpp index 7d550c7e..4ac6da97 100644 --- a/OpenGL.cpp +++ b/OpenGL.cpp @@ -173,6 +173,49 @@ void OGLVideo::updateScale() m_scaleY = m_height / (float)VI.height; } +void OGLVideo::_setBufferSize() +{ + if (m_bFullscreen && config.frameBufferEmulation.enable) { + switch (config.video.aspect) { + case 0: // stretch + m_width = m_screenWidth; + m_height = m_screenHeight; + break; + case 1: // force 4/3 + if (m_screenWidth * 3 / 4 > m_screenHeight) { + m_height = m_screenHeight; + m_width = m_screenHeight * 4 / 3; + } else if (m_screenHeight * 4 / 3 > m_screenWidth) { + m_width = m_screenWidth; + m_height = m_screenWidth * 3 / 4; + } else { + m_width = m_screenWidth; + m_height = m_screenHeight; + } + break; + case 2: // force 16/9 + if (m_screenWidth * 9 / 16 > m_screenHeight) { + m_height = m_screenHeight; + m_width = m_screenHeight * 16 / 9; + } else if (m_screenHeight * 16 / 9 > m_screenWidth) { + m_width = m_screenWidth; + m_height = m_screenWidth * 9 / 16; + } else { + m_width = m_screenWidth; + m_height = m_screenHeight; + } + break; + default: + assert(false && "Unknown aspect ratio"); + m_width = m_screenWidth; + m_height = m_screenHeight; + } + } else { + m_width = m_screenWidth; + m_height = m_screenHeight; + } +} + void OGLVideo::readScreen(void **_pDest, long *_pWidth, long *_pHeight ) { *_pWidth = m_width; @@ -635,7 +678,7 @@ void OGLRender::drawRect(int _ulx, int _uly, int _lrx, int _lry, float *_pColor) FrameBuffer* pBuffer = fbList.getCurrent(); OGLVideo & ogl = video(); if (!fbList.isFboMode()) - glViewport( 0, ogl.getHeightOffset(), ogl.getWidth(), ogl.getHeight()); + glViewport( 0, ogl.getHeightOffset(), ogl.getScreenWidth(), ogl.getScreenHeight()); else { glViewport( 0, 0, pBuffer->m_width*pBuffer->m_scaleX, pBuffer->m_height*pBuffer->m_scaleY ); } @@ -693,7 +736,7 @@ void OGLRender::drawTexturedRect(float _ulx, float _uly, float _lrx, float _lry, FrameBuffer* pBuffer = fbList.getCurrent(); OGLVideo & ogl = video(); if (!fbList.isFboMode()) - glViewport( 0, ogl.getHeightOffset(), ogl.getWidth(), ogl.getHeight()); + glViewport( 0, ogl.getHeightOffset(), ogl.getScreenWidth(), ogl.getScreenHeight()); else glViewport( 0, 0, pBuffer->m_width*pBuffer->m_scaleX, pBuffer->m_height*pBuffer->m_scaleY ); glDisable( GL_CULL_FACE ); @@ -871,7 +914,7 @@ void OGLRender::_initStates() glPolygonOffset( -3.0f, -3.0f ); OGLVideo & ogl = video(); - glViewport( 0, ogl.getHeightOffset(), ogl.getWidth(), ogl.getHeight()); + glViewport( 0, ogl.getHeightOffset(), ogl.getScreenWidth(), ogl.getScreenHeight()); glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glClear( GL_COLOR_BUFFER_BIT ); diff --git a/OpenGL.h b/OpenGL.h index 9f8ecc98..fd195dcd 100644 --- a/OpenGL.h +++ b/OpenGL.h @@ -131,6 +131,8 @@ public: f32 getScaleY() const {return m_scaleY;} u32 getWidth() const {return m_width;} u32 getHeight() const {return m_height;} + u32 getScreenWidth() const {return m_screenWidth;} + u32 getScreenHeight() const {return m_screenHeight;} u32 getHeightOffset() const {return m_heightOffset;} bool isFullscreen() const {return m_bFullscreen;} @@ -141,16 +143,21 @@ public: protected: OGLVideo() : m_bCaptureScreen(false), m_bToggleFullscreen(false), m_bResizeWindow(false), m_bFullscreen(false), - m_width(0), m_height(0), m_heightOffset(0), m_resizeWidth(0), m_resizeHeight(0), + m_width(0), m_height(0), m_heightOffset(0), + m_screenWidth(0), m_screenHeight(0), m_resizeWidth(0), m_resizeHeight(0), m_scaleX(0), m_scaleY(0), m_strScreenDirectory(NULL) {} + void _setBufferSize(); + bool m_bCaptureScreen; bool m_bToggleFullscreen; bool m_bResizeWindow; bool m_bFullscreen; - u32 m_width, m_height, m_heightOffset, m_resizeWidth, m_resizeHeight; + u32 m_width, m_height, m_heightOffset; + u32 m_screenWidth, m_screenHeight; + u32 m_resizeWidth, m_resizeHeight; f32 m_scaleX, m_scaleY; const char * m_strScreenDirectory; diff --git a/mupenplus/Config.cpp b/mupenplus/Config.cpp index be454344..f94d6b71 100644 --- a/mupenplus/Config.cpp +++ b/mupenplus/Config.cpp @@ -41,6 +41,8 @@ bool Config_SetDefault() res = ConfigSetDefaultInt(g_configVideoGliden64, "MultiSampling", 0, "Enable/Disable MultiSampling (0=off, 2,4,8,16=quality)"); assert(res == M64ERR_SUCCESS); + res = ConfigSetDefaultInt(g_configVideoGliden64, "AspectRatio", 0, "Screen aspect ratio (0=stretch, 1=force 4:3, 2=force 16:9)"); + assert(res == M64ERR_SUCCESS); //#Texture Settings res = ConfigSetDefaultBool(g_configVideoGliden64, "ForceBilinear", 0, "Force bilinear texture filter"); @@ -85,6 +87,7 @@ void Config_LoadConfig() config.video.verticalSync = ConfigGetParamBool(g_configVideoGeneral, "VerticalSync"); config.video.multisampling = ConfigGetParamInt(g_configVideoGliden64, "MultiSampling"); + config.video.aspect = ConfigGetParamInt(g_configVideoGliden64, "AspectRatio"); //#Texture Settings config.texture.forceBilinear = ConfigGetParamBool(g_configVideoGliden64, "ForceBilinear"); diff --git a/mupenplus/OpenGL_mupenplus.cpp b/mupenplus/OpenGL_mupenplus.cpp index ea170571..346ed268 100644 --- a/mupenplus/OpenGL_mupenplus.cpp +++ b/mupenplus/OpenGL_mupenplus.cpp @@ -61,13 +61,14 @@ bool OGLVideoMupenPlus::_start() _setAttributes(); m_bFullscreen = config.video.fullscreen > 0; - m_width = config.video.windowedWidth; - m_height = config.video.windowedHeight; + m_screenWidth = config.video.windowedWidth; + m_screenHeight = config.video.windowedHeight; + _setBufferSize(); - printf("(II) Setting video mode %dx%d...\n", m_width, m_height); + printf("(II) Setting video mode %dx%d...\n", m_screenWidth, m_screenHeight); const m64p_video_flags flags = M64VIDEOFLAG_SUPPORT_RESIZING; - if (CoreVideo_SetVideoMode(m_width, m_height, 0, m_bFullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, flags) != M64ERR_SUCCESS) { - printf("(EE) Error setting videomode %dx%d\n", m_width, m_height); + if (CoreVideo_SetVideoMode(m_screenWidth, m_screenHeight, 0, m_bFullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, flags) != M64ERR_SUCCESS) { + printf("(EE) Error setting videomode %dx%d\n", m_screenWidth, m_screenHeight); CoreVideo_Quit(); return false; } @@ -105,12 +106,12 @@ bool OGLVideoMupenPlus::_resizeWindow() _setAttributes(); m_bFullscreen = false; - m_width = m_resizeWidth; - m_height = m_resizeHeight; - if (CoreVideo_ResizeWindow(m_width, m_height) != M64ERR_SUCCESS) { - printf("(EE) Error setting videomode %dx%d\n", m_width, m_height); - m_width = config.video.windowedWidth; - m_height = config.video.windowedHeight; + m_width = m_screenWidth = m_resizeWidth; + m_height = m_screenHeight = m_resizeHeight; + if (CoreVideo_ResizeWindow(m_screenWidth, m_screenHeight) != M64ERR_SUCCESS) { + printf("(EE) Error setting videomode %dx%d\n", m_screenWidth, m_screenHeight); + m_width = m_screenWidth = config.video.windowedWidth; + m_height = m_screenHeight = config.video.windowedHeight; CoreVideo_Quit(); return false; } diff --git a/posix/Config.cpp b/posix/Config.cpp index 6b4db345..1e926193 100644 --- a/posix/Config.cpp +++ b/posix/Config.cpp @@ -468,6 +468,7 @@ void Config_LoadConfig() fclose( f ); + config.video.aspect = 1; // manually set frame bufer emulation options config.frameBufferEmulation.copyToRDRAM = FALSE; config.frameBufferEmulation.copyFromRDRAM = FALSE; diff --git a/posix/OpenGL_posix.cpp b/posix/OpenGL_posix.cpp index 6f41d997..49378323 100644 --- a/posix/OpenGL_posix.cpp +++ b/posix/OpenGL_posix.cpp @@ -38,12 +38,13 @@ bool OGLVideoPosix::_start() Uint32 videoFlags = 0; if (m_bFullscreen) { - m_width = config.video.fullscreenWidth; - m_height = config.video.fullscreenHeight; + m_screenWidth = config.video.fullscreenWidth; + m_screenHeight = config.video.fullscreenHeight; } else { - m_width = config.video.windowedWidth; - m_height = config.video.windowedHeight; + m_screenWidth = config.video.windowedWidth; + m_screenHeight = config.video.windowedHeight; } + _setBufferSize(); /* Initialize SDL */ printf( "[glN64]: (II) Initializing SDL video subsystem...\n" ); @@ -80,10 +81,10 @@ bool OGLVideoPosix::_start() SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );*/ SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); // 32 bit z-buffer - printf( "[glN64]: (II) Setting video mode %dx%d...\n", m_width, m_height ); - if (!(hScreen = SDL_SetVideoMode(m_width, m_height, 0, videoFlags))) + printf("[glN64]: (II) Setting video mode %dx%d...\n", m_screenWidth, m_screenHeight); + if (!(hScreen = SDL_SetVideoMode(m_screenWidth, m_screenHeight, 0, videoFlags))) { - printf( "[glN64]: (EE) Error setting videomode %dx%d: %s\n", m_width, m_height, SDL_GetError() ); + printf("[glN64]: (EE) Error setting videomode %dx%d: %s\n", m_screenWidth, m_screenHeight, SDL_GetError()); SDL_QuitSubSystem( SDL_INIT_VIDEO ); return false; } diff --git a/windows/Config.cpp b/windows/Config.cpp index 70dd1b41..2cb44b87 100644 --- a/windows/Config.cpp +++ b/windows/Config.cpp @@ -113,6 +113,7 @@ void Config_LoadConfig() config.enableHWLighting = FALSE; } + config.video.aspect = 1; // manually set frame bufer emulation options config.frameBufferEmulation.copyToRDRAM = FALSE; config.frameBufferEmulation.copyFromRDRAM = FALSE; diff --git a/windows/OpenGL_windows.cpp b/windows/OpenGL_windows.cpp index 6fa4b544..8652deed 100644 --- a/windows/OpenGL_windows.cpp +++ b/windows/OpenGL_windows.cpp @@ -233,14 +233,16 @@ bool OGLVideoWindows::_resizeWindow() RECT windowRect, statusRect, toolRect; if (m_bFullscreen) { - m_width = config.video.fullscreenWidth; - m_height = config.video.fullscreenHeight; + m_screenWidth = config.video.fullscreenWidth; + m_screenHeight = config.video.fullscreenHeight; m_heightOffset = 0; + _setBufferSize(); - return (SetWindowPos( hWnd, NULL, 0, 0, m_width, m_height, SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW ) == TRUE); + return (SetWindowPos(hWnd, NULL, 0, 0, m_screenWidth, m_screenHeight, SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW) == TRUE); } else { - m_width = config.video.windowedWidth; - m_height = config.video.windowedHeight; + m_screenWidth = m_width = config.video.windowedWidth; + m_screenHeight = config.video.windowedHeight; + _setBufferSize(); GetClientRect( hWnd, &windowRect ); GetWindowRect( hStatusBar, &statusRect );