From 4c94acf68ac04ec86bbaedcc88cb216abe03076c Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Wed, 11 Nov 2020 20:14:00 -0500 Subject: [PATCH 1/2] Added video special scaler functionality to Qt GUI. --- src/drivers/Qt/ConsoleVideoConf.cpp | 47 ++++++++++++- src/drivers/Qt/ConsoleVideoConf.h | 2 + src/drivers/Qt/ConsoleViewerGL.cpp | 64 +++++++++++++---- src/drivers/Qt/ConsoleViewerSDL.cpp | 69 ++++++++++++------ src/drivers/Qt/nes_shm.cpp | 9 ++- src/drivers/Qt/nes_shm.h | 14 ++-- src/drivers/Qt/sdl-video.cpp | 104 ++++++++++++++++++++++------ 7 files changed, 241 insertions(+), 68 deletions(-) diff --git a/src/drivers/Qt/ConsoleVideoConf.cpp b/src/drivers/Qt/ConsoleVideoConf.cpp index 086070bc..b2278421 100644 --- a/src/drivers/Qt/ConsoleVideoConf.cpp +++ b/src/drivers/Qt/ConsoleVideoConf.cpp @@ -39,6 +39,29 @@ ConsoleVideoConfDialog_t::ConsoleVideoConfDialog_t(QWidget *parent) main_vbox->addLayout( hbox1 ); + // Video Driver Select + lbl = new QLabel( tr("Scaler:") ); + + scalerSelect = new QComboBox(); + + scalerSelect->addItem( tr("None"), 0 ); + scalerSelect->addItem( tr("hq2x"), 1 ); + scalerSelect->addItem( tr("scale2x"), 2 ); + scalerSelect->addItem( tr("NTSC 2x"), 3 ); + scalerSelect->addItem( tr("hq3x"), 4 ); + scalerSelect->addItem( tr("scale3x"), 5 ); + scalerSelect->addItem( tr("Prescale 2x"), 6 ); + scalerSelect->addItem( tr("Prescale 3x"), 7 ); + scalerSelect->addItem( tr("Prescale 4x"), 8 ); + scalerSelect->addItem( tr("PAL"), 9 ); + + hbox1 = new QHBoxLayout(); + + hbox1->addWidget( lbl ); + hbox1->addWidget( scalerSelect ); + + main_vbox->addLayout( hbox1 ); + // Enable OpenGL Linear Filter Checkbox gl_LF_chkBox = new QCheckBox( tr("Enable OpenGL Linear Filter") ); @@ -59,9 +82,11 @@ ConsoleVideoConfDialog_t::ConsoleVideoConfDialog_t(QWidget *parent) setComboBoxFromProperty( regionSelect, "SDL.PAL"); setComboBoxFromProperty( driverSelect, "SDL.VideoDriver"); + setComboBoxFromProperty( scalerSelect, "SDL.SpecialFilter"); connect(regionSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(regionChanged(int)) ); connect(driverSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(driverChanged(int)) ); + connect(scalerSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(scalerChanged(int)) ); hbox1 = new QHBoxLayout(); @@ -214,8 +239,10 @@ void ConsoleVideoConfDialog_t::closeWindow(void) //---------------------------------------------------- void ConsoleVideoConfDialog_t::resetVideo(void) { + fceuWrapperLock(); KillVideo (); InitVideo (GameInfo); + fceuWrapperUnLock(); } //---------------------------------------------------- void ConsoleVideoConfDialog_t::setCheckBoxFromProperty( QCheckBox *cbx, const char *property ) @@ -348,6 +375,18 @@ void ConsoleVideoConfDialog_t::driverChanged(int index) printf("Note: A restart of the application is needed for video driver change to take effect...\n"); } //---------------------------------------------------- +void ConsoleVideoConfDialog_t::scalerChanged(int index) +{ + int scaler; + //printf("Scaler: %i : %i \n", index, scalerSelect->itemData(index).toInt() ); + + scaler = scalerSelect->itemData(index).toInt(); + + g_config->setOption ("SDL.SpecialFilter", scaler); + + g_config->save (); +} +//---------------------------------------------------- void ConsoleVideoConfDialog_t::regionChanged(int index) { int region; @@ -373,8 +412,8 @@ QSize ConsoleVideoConfDialog_t::calcNewScreenSize(void) { QSize w, v; double xscale, yscale; - int texture_width = nes_shm->ncol; - int texture_height = nes_shm->nrow; + int texture_width = nes_shm->video.ncol; + int texture_height = nes_shm->video.nrow; int l=0, r=texture_width; int t=0, b=texture_height; int dw=0, dh=0, rw, rh; @@ -395,7 +434,9 @@ QSize ConsoleVideoConfDialog_t::calcNewScreenSize(void) if ( sqrPixCbx->isChecked() ) { - yscale = xscale = xScaleBox->value(); + xscale = xScaleBox->value(); + + yscale = xscale * (double)nes_shm->video.xyRatio; } else { diff --git a/src/drivers/Qt/ConsoleVideoConf.h b/src/drivers/Qt/ConsoleVideoConf.h index 932bfe01..d65b4628 100644 --- a/src/drivers/Qt/ConsoleVideoConf.h +++ b/src/drivers/Qt/ConsoleVideoConf.h @@ -29,6 +29,7 @@ class ConsoleVideoConfDialog_t : public QDialog void closeEvent(QCloseEvent *bar); QComboBox *driverSelect; + QComboBox *scalerSelect; QComboBox *regionSelect; QCheckBox *gl_LF_chkBox; QCheckBox *new_PPU_ena; @@ -63,6 +64,7 @@ class ConsoleVideoConfDialog_t : public QDialog void showFPSChanged( int value ); void regionChanged(int index); void driverChanged(int index); + void scalerChanged(int index); void applyChanges( void ); }; diff --git a/src/drivers/Qt/ConsoleViewerGL.cpp b/src/drivers/Qt/ConsoleViewerGL.cpp index f7b38a60..92f927f5 100644 --- a/src/drivers/Qt/ConsoleViewerGL.cpp +++ b/src/drivers/Qt/ConsoleViewerGL.cpp @@ -38,7 +38,7 @@ ConsoleViewGL_t::ConsoleViewGL_t(QWidget *parent) devPixRatio = screen->devicePixelRatio(); //printf("Ratio: %f \n", screen->devicePixelRatio() ); } - localBufSize = GL_NES_WIDTH * GL_NES_HEIGHT * sizeof(uint32_t); + localBufSize = (4 * GL_NES_WIDTH) * (4 * GL_NES_HEIGHT) * sizeof(uint32_t); localBuf = (uint32_t*)malloc( localBufSize ); @@ -87,6 +87,7 @@ int ConsoleViewGL_t::init( void ) void ConsoleViewGL_t::buildTextures(void) { + int w, h; glEnable(GL_TEXTURE_RECTANGLE); if ( gltexture ) @@ -105,8 +106,11 @@ void ConsoleViewGL_t::buildTextures(void) glTexParameteri( GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + w = nes_shm->video.ncol; + h = nes_shm->video.nrow; + glTexImage2D( GL_TEXTURE_RECTANGLE, 0, - GL_RGBA8, GL_NES_WIDTH, GL_NES_HEIGHT, 0, + GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0 ); } @@ -152,46 +156,78 @@ void ConsoleViewGL_t::setLinearFilterEnable( bool ena ) void ConsoleViewGL_t::setScaleXY( double xs, double ys ) { + float xyRatio = (float)nes_shm->video.xyRatio; + xscale = xs; yscale = ys; if ( sqrPixels ) { - if (xscale < yscale ) + if ( (xscale*xyRatio) < yscale ) { - yscale = xscale; + yscale = (xscale*xyRatio); } else { - xscale = yscale; + xscale = (yscale/xyRatio); } } } void ConsoleViewGL_t::transfer2LocalBuffer(void) { - memcpy( localBuf, nes_shm->pixbuf, localBufSize ); + int i=0, hq = 0; + int numPixels = nes_shm->video.ncol * nes_shm->video.nrow; + int cpSize = numPixels * 4; + uint8_t *src, *dest; + + if ( cpSize > localBufSize ) + { + cpSize = localBufSize; + } + src = (uint8_t*)nes_shm->pixbuf; + dest = (uint8_t*)localBuf; + + hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x + + if ( hq ) + { + for (i=0; ipixbuf, cpSize ); + } } void ConsoleViewGL_t::paintGL(void) { - int texture_width = nes_shm->ncol; - int texture_height = nes_shm->nrow; + int texture_width = nes_shm->video.ncol; + int texture_height = nes_shm->video.nrow; int l=0, r=texture_width; int t=0, b=texture_height; - float xscaleTmp = (float)view_width / (float)texture_width; - float yscaleTmp = (float)view_height / (float)texture_height; + float xyRatio = (float)nes_shm->video.xyRatio; + float xscaleTmp = (float)(view_width) / (float)(texture_width); + float yscaleTmp = (float)(view_height) / (float)(texture_height); if ( sqrPixels ) { - if (xscaleTmp < yscaleTmp ) + if ( (xscaleTmp*xyRatio) < yscaleTmp ) { - yscaleTmp = xscaleTmp; + yscaleTmp = (xscaleTmp*xyRatio); } else { - xscaleTmp = yscaleTmp; + xscaleTmp = (yscaleTmp/xyRatio); } } @@ -232,7 +268,7 @@ void ConsoleViewGL_t::paintGL(void) glBindTexture(GL_TEXTURE_RECTANGLE, gltexture); glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, - 0, 0, GL_NES_WIDTH, GL_NES_HEIGHT, + 0, 0, texture_width, texture_height, GL_BGRA, GL_UNSIGNED_BYTE, localBuf ); glBegin(GL_QUADS); diff --git a/src/drivers/Qt/ConsoleViewerSDL.cpp b/src/drivers/Qt/ConsoleViewerSDL.cpp index 07f8b309..1d6c9fb1 100644 --- a/src/drivers/Qt/ConsoleViewerSDL.cpp +++ b/src/drivers/Qt/ConsoleViewerSDL.cpp @@ -43,7 +43,7 @@ ConsoleViewSDL_t::ConsoleViewSDL_t(QWidget *parent) vsyncEnabled = false; - localBufSize = GL_NES_WIDTH * GL_NES_HEIGHT * sizeof(uint32_t); + localBufSize = (4 * GL_NES_WIDTH) * (4 * GL_NES_HEIGHT) * sizeof(uint32_t); localBuf = (uint32_t*)malloc( localBufSize ); @@ -85,25 +85,56 @@ void ConsoleViewSDL_t::setLinearFilterEnable( bool ena ) void ConsoleViewSDL_t::setScaleXY( double xs, double ys ) { + float xyRatio = (float)nes_shm->video.xyRatio; + xscale = xs; yscale = ys; if ( sqrPixels ) { - if (xscale < yscale ) + if ( (xscale*xyRatio) < yscale ) { - yscale = xscale; + yscale = (xscale*xyRatio); } else { - xscale = yscale; + xscale = (yscale/xyRatio); } } } void ConsoleViewSDL_t::transfer2LocalBuffer(void) { - memcpy( localBuf, nes_shm->pixbuf, localBufSize ); + int i=0, hq = 0; + int numPixels = nes_shm->video.ncol * nes_shm->video.nrow; + int cpSize = numPixels * 4; + uint8_t *src, *dest; + + if ( cpSize > localBufSize ) + { + cpSize = localBufSize; + } + src = (uint8_t*)nes_shm->pixbuf; + dest = (uint8_t*)localBuf; + + hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x + + if ( hq ) + { + for (i=0; ipixbuf, cpSize ); + } } int ConsoleViewSDL_t::init(void) @@ -171,11 +202,11 @@ int ConsoleViewSDL_t::init(void) printf("[SDL] Renderer Output Size: %i x %i \n", sdlRendW, sdlRendH ); - sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, GL_NES_WIDTH, GL_NES_HEIGHT); + sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, nes_shm->video.ncol, nes_shm->video.nrow); if (sdlTexture == NULL) { - printf("[SDL] Failed to create texture: %i x %i", GL_NES_WIDTH, GL_NES_HEIGHT ); + printf("[SDL] Failed to create texture: %i x %i", nes_shm->video.ncol, nes_shm->video.nrow ); return -1; } @@ -201,7 +232,7 @@ void ConsoleViewSDL_t::reset(void) cleanup(); if ( init() == 0 ) { - //console->GetVideoRenderer()->RegisterRenderingDevice(this); + } else { @@ -219,23 +250,19 @@ void ConsoleViewSDL_t::resizeEvent(QResizeEvent *event) printf("SDL Resize: %i x %i \n", view_width, view_height); reset(); - - //sdlViewport.x = sdlRendW - view_width; - //sdlViewport.y = sdlRendH - view_height; - //sdlViewport.w = view_width; - //sdlViewport.h = view_height; } -//void ConsoleViewSDL_t::paintEvent( QPaintEvent *event ) void ConsoleViewSDL_t::render(void) { int nesWidth = GL_NES_WIDTH; int nesHeight = GL_NES_HEIGHT; + float xyRatio = 1.0; if ( nes_shm != NULL ) { - nesWidth = nes_shm->ncol; - nesHeight = nes_shm->nrow; + nesWidth = nes_shm->video.ncol; + nesHeight = nes_shm->video.nrow; + xyRatio = (float)nes_shm->video.xyRatio; } //printf(" %i x %i \n", nesWidth, nesHeight ); float xscaleTmp = (float)view_width / (float)nesWidth; @@ -243,13 +270,13 @@ void ConsoleViewSDL_t::render(void) if ( sqrPixels ) { - if (xscaleTmp < yscaleTmp ) + if ( (xscaleTmp*xyRatio) < yscaleTmp ) { - yscaleTmp = xscaleTmp; + yscaleTmp = (xscaleTmp*xyRatio); } else { - xscaleTmp = yscaleTmp; + xscaleTmp = (yscaleTmp/xyRatio); } } @@ -288,12 +315,10 @@ void ConsoleViewSDL_t::render(void) int rowPitch; SDL_LockTexture( sdlTexture, nullptr, (void**)&textureBuffer, &rowPitch); { - memcpy( textureBuffer, localBuf, GL_NES_HEIGHT*GL_NES_WIDTH*sizeof(uint32_t) ); + memcpy( textureBuffer, localBuf, nesWidth*nesHeight*sizeof(uint32_t) ); } SDL_UnlockTexture(sdlTexture); - //SDL_RenderSetViewport( sdlRenderer, &sdlViewport ); - SDL_Rect source = {0, 0, nesWidth, nesHeight }; SDL_Rect dest = { sx, sy, rw, rh }; SDL_RenderCopy(sdlRenderer, sdlTexture, &source, &dest); diff --git a/src/drivers/Qt/nes_shm.cpp b/src/drivers/Qt/nes_shm.cpp index 59d1e948..55f164f2 100644 --- a/src/drivers/Qt/nes_shm.cpp +++ b/src/drivers/Qt/nes_shm.cpp @@ -45,9 +45,12 @@ nes_shm_t *open_nes_shm(void) //sem_init( &vaddr->sem, 1, 1 ); - vaddr->ncol = 256; - vaddr->nrow = 256; - vaddr->pitch = 256 * 4; + vaddr->video.ncol = 256; + vaddr->video.nrow = 256; + vaddr->video.pitch = 256 * 4; + vaddr->video.scale = 1; + vaddr->video.xyRatio = 1; + vaddr->video.preScaler = 0; return vaddr; } diff --git a/src/drivers/Qt/nes_shm.h b/src/drivers/Qt/nes_shm.h index 0b63998d..2e14be81 100644 --- a/src/drivers/Qt/nes_shm.h +++ b/src/drivers/Qt/nes_shm.h @@ -20,9 +20,15 @@ struct nes_shm_t uint32_t render_count; uint32_t blit_count; - int ncol; - int nrow; - int pitch; + struct + { + int ncol; + int nrow; + int pitch; + int scale; + int xyRatio; + int preScaler; + } video; char runEmulator; char blitUpdated; @@ -57,7 +63,7 @@ struct nes_shm_t } cmd[64]; } guiEvent; - uint32_t pixbuf[65536]; // 256 x 256 + uint32_t pixbuf[1048576]; // 1024 x 1024 void clear_pixbuf(void) { diff --git a/src/drivers/Qt/sdl-video.cpp b/src/drivers/Qt/sdl-video.cpp index 17087f2e..ddcecb4e 100644 --- a/src/drivers/Qt/sdl-video.cpp +++ b/src/drivers/Qt/sdl-video.cpp @@ -96,18 +96,19 @@ KillVideo() nes_shm->clear_pixbuf(); } - //destroy_gui_video(); + // if the rest of the system has been initialized, shut it down + // shut down the system that converts from 8 to 16/32 bpp + if (initBlitToHighDone) + { + KillBlitToHigh(); + + initBlitToHighDone = 0; + } // return failure if the video system was not initialized if (s_inited == 0) return -1; - // if the rest of the system has been initialized, shut it down -// // shut down the system that converts from 8 to 16/32 bpp -// if (s_curbpp > 8) -// { -// KillBlitToHigh(); -// } // SDL Video system is not used. // shut down the SDL video sub-system @@ -154,7 +155,7 @@ int InitVideo(FCEUGI *gi) //#ifdef OPENGL // g_config->getOption("SDL.OpenGL", &s_useOpenGL); //#endif - //g_config->getOption("SDL.SpecialFilter", &s_sponge); + g_config->getOption("SDL.SpecialFilter", &s_sponge); g_config->getOption("SDL.XStretch", &xstretch); g_config->getOption("SDL.YStretch", &ystretch); //g_config->getOption("SDL.LastXRes", &xres); @@ -166,7 +167,6 @@ int InitVideo(FCEUGI *gi) //g_config->getOption("SDL.YScale", &s_eys); uint32_t rmask, gmask, bmask; - s_sponge = 0; s_exs = 1.0; s_eys = 1.0; xres = gui_draw_area_width; @@ -176,16 +176,57 @@ int InitVideo(FCEUGI *gi) FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline); s_tlines = s_erendline - s_srendline + 1; - //init_gui_video( s_useOpenGL ); + nes_shm->video.preScaler = s_sponge; + + switch ( s_sponge ) + { + case 0: // None + nes_shm->video.scale = 1; + break; + case 1: // hq2x + case 2: // Scale2x + case 3: // NTSC 2x + case 6: // Prescale2x + nes_shm->video.scale = 2; + break; + case 4: // hq3x + case 5: // Scale3x + case 7: // Prescale3x + nes_shm->video.scale = 3; + break; + case 8: // Prescale4x + nes_shm->video.scale = 4; + break; + case 9: // PAL + nes_shm->video.scale = 3; + break; + } s_inited = 1; // check to see if we are showing FPS FCEUI_SetShowFPS(show_fps); - nes_shm->ncol = NWIDTH; - nes_shm->nrow = s_tlines; - nes_shm->pitch = GL_NES_WIDTH * 4; + int iScale = nes_shm->video.scale; + if ( s_sponge == 3 ) + { + nes_shm->video.ncol = iScale*301; + } + else + { + nes_shm->video.ncol = iScale*NWIDTH; + } + if ( s_sponge == 9 ) + { + nes_shm->video.nrow = 1*s_tlines; + nes_shm->video.xyRatio = 3; + } + else + { + nes_shm->video.nrow = iScale*s_tlines; + nes_shm->video.xyRatio = 1; + } + nes_shm->video.pitch = nes_shm->video.ncol * 4; #ifdef LSB_FIRST rmask = 0x00FF0000; @@ -221,6 +262,8 @@ int InitVideo(FCEUGI *gi) initBlitToHighDone = 1; } + s_paletterefresh = 1; + return 0; } @@ -329,7 +372,7 @@ void BlitScreen(uint8 *XBuf) { uint8 *dest; - int w, h, pitch; + int w, h, pitch, iScale; // refresh the palette if required if (s_paletterefresh) @@ -341,14 +384,31 @@ BlitScreen(uint8 *XBuf) // XXX soules - not entirely sure why this is being done yet XBuf += s_srendline * 256; - dest = (uint8*)nes_shm->pixbuf; - w = GL_NES_WIDTH; - h = GL_NES_HEIGHT; - pitch = w*4; + dest = (uint8*)nes_shm->pixbuf; + iScale = nes_shm->video.scale; - nes_shm->ncol = NWIDTH; - nes_shm->nrow = s_tlines; - nes_shm->pitch = pitch; + if ( s_sponge == 3 ) + { + w = iScale*301; + } + else + { + w = iScale*NWIDTH; + } + if ( s_sponge == 9 ) + { + h = 1*s_tlines; + } + else + { + h = iScale*s_tlines; + } + pitch = w*4; + + nes_shm->video.ncol = w; + nes_shm->video.nrow = h; + nes_shm->video.pitch = pitch; + nes_shm->video.preScaler = s_sponge; if ( dest == NULL ) return; @@ -358,7 +418,7 @@ BlitScreen(uint8 *XBuf) } else { - Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, 1, 1); + Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, iScale, iScale); } nes_shm->blitUpdated = 1; From 3ca86a17485da053ede47a5ae40c86e7f8c4cb6b Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Wed, 11 Nov 2020 20:19:56 -0500 Subject: [PATCH 2/2] Added new mapper to cmakelist for SDL build. --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 862111c7..3eff0162 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -279,6 +279,7 @@ set(SRC_CORE ${CMAKE_CURRENT_SOURCE_DIR}/boards/BMW8544.cpp ${CMAKE_CURRENT_SOURCE_DIR}/boards/bonza.cpp ${CMAKE_CURRENT_SOURCE_DIR}/boards/bs-5.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/boards/bs4xxxr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/boards/cheapocabra.cpp ${CMAKE_CURRENT_SOURCE_DIR}/boards/cityfighter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/boards/coolboy.cpp