diff --git a/filter/xbrz.cpp b/filter/xbrz.cpp index 21600fd2..9ab43618 100644 --- a/filter/xbrz.cpp +++ b/filter/xbrz.cpp @@ -16,8 +16,12 @@ #include "xbrz.h" #include #include +#ifdef unix + #include +#endif #include + namespace { template inline @@ -654,9 +658,11 @@ void blendPixel(const Kernel_3x3& ker, #define h get_h(ker) #define i get_i(ker) -#ifndef NDEBUG +#ifdef WIN32 +# ifndef NDEBUG if (breakIntoDebugger) __debugbreak(); //__asm int 3; +# endif #endif const unsigned char blend = rotateBlendInfo(blendInfo); @@ -1173,7 +1179,11 @@ void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth { switch (colFmt) { - case ColorFormat::ARGB: +#ifdef WIN32 + case ColorFormat::ARGB:// not Standard C++. +#else + case ARGB: +#endif switch (factor) { case 2: @@ -1185,9 +1195,13 @@ void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth case 5: return scaleImage(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); } - break; + break; - case ColorFormat::RGB: +#ifdef WIN32 + case ColorFormat::RGB:// not Standard C++. +#else + case RGB: +#endif switch (factor) { case 2: @@ -1199,7 +1213,7 @@ void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth case 5: return scaleImage(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); } - break; + break; } assert(false); } @@ -1209,10 +1223,18 @@ bool xbrz::equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, doub { switch (colFmt) { - case ColorFormat::ARGB: +#ifdef WIN32 + case ColorFormat::ARGB: // not Standard C++. +#else + case ARGB: +#endif return ColorDistanceARGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; - case ColorFormat::RGB: +#ifdef WIN32 + case ColorFormat::RGB:// not Standard C++. +#else + case RGB: +#endif return ColorDistanceRGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; } assert(false); diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 77296e33..fd540f1c 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -61,6 +61,14 @@ snes9x_gtk_SOURCES += \ ../filter/hq2x.h endif +if XBRZ +snes9x_gtk_SOURCES += \ + src/filter_xbrz.cpp\ + src/filter_xbrz.h\ + ../filter/xbrz.cpp \ + ../filter/xbrz.h +endif + if PORTAUDIO snes9x_gtk_SOURCES += \ src/gtk_sound_driver_portaudio.cpp \ diff --git a/gtk/configure.ac b/gtk/configure.ac index 95024a23..d2b899ec 100644 --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -104,6 +104,12 @@ AC_ARG_WITH(hq2x, [], [with_hq2x=yes]) +AC_ARG_WITH(xbrz, + [AS_HELP_STRING([--with(out)-xbrz], + [Enable support for the xBRZ filter (default: with)])], + [], + [with_xbrz=yes]) + AC_ARG_WITH(netplay, [AS_HELP_STRING([--with(out)-netplay], [Enable netplay support (default: without)])], @@ -310,6 +316,13 @@ else HQ2X=0 fi +if test yes = "$with_xbrz" ; then + XBRZ=yes + CFLAGS="$CFLAGS -DUSE_XBRZ" +else + XBRZ=0 +fi + CFLAGS="$CFLAGS $GTK_CFLAGS $GLIB_CFLAGS $LIBXML_CFLAGS $PORTAUDIO_CFLAGS $LIBPNG_CFLAGS $SDL_CFLAGS $XV_CFLAGS $XRANDR_CFLAGS $ALSA_CFLAGS $PULSEAUDIO_CFLAGS" LIBS="$LIBS $GTK_LIBS $GLIB_LIBS $LIBXML_LIBS $PORTAUDIO_LIBS $LIBPNG_LIBS $SDL_LIBS $XV_LIBS $XRANDR_LIBS $ALSA_LIBS $PULSEAUDIO_LIBS" @@ -444,6 +457,7 @@ AM_CONDITIONAL(SDL, [test yes = "$GTKJOY"]) AM_CONDITIONAL(ALSA, [test yes = "$ALSA"]) AM_CONDITIONAL(PULSEAUDIO, [test yes = "$PULSEAUDIO"]) AM_CONDITIONAL(HQ2X, [test yes = "$HQ2X"]) +AM_CONDITIONAL(XBRZ, [test yes = "$XBRZ"]) AC_SUBST(NASM) AC_SUBST(NASM_FLAGS) @@ -527,3 +541,7 @@ fi if ! test yes = "$HQ2X"; then echo "HQ2x filter compilation is disabled." fi + +if ! test yes = "$XBRZ"; then + echo "xBRZ filter compilation is disabled." +fi diff --git a/gtk/src/filter_xbrz.cpp b/gtk/src/filter_xbrz.cpp new file mode 100644 index 00000000..4b7dbe96 --- /dev/null +++ b/gtk/src/filter_xbrz.cpp @@ -0,0 +1,277 @@ + +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2011 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2011 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2011 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com/ + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. + ***********************************************************************************/ + +#include "snes9x.h" +#include "../filter/xbrz.h" +#include + +#define CONVERT_16_TO_32(pixel) \ + (((((pixel) >> 10) ) << /*RedShift+3*/ 19) | \ + ((((pixel) >> 5) & 0x1f) << /*GreenShift+3*/11) | \ + (((pixel) & 0x1f) << /*BlueShift+3*/ 3)) + +#define CONVERT_32_TO_16(pixel) \ + (((((pixel) & 0xf80000) >> 9) | \ + (((pixel) & 0xf800) >> 6) | \ + (((pixel) & 0xf8) >> 3)) & 0xffff) + +inline +void copyImage16To32(const uint16_t* src, int width, int height, int srcPitch, + uint32_t* trg, int yFirst, int yLast) +{ + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, height); + if (yFirst >= yLast || height <= 0 || width <= 0) return; + + for (int y = yFirst; y < yLast; ++y) + { + uint32_t* trgLine = trg + y * width; + const uint16_t* srcLine = reinterpret_cast(reinterpret_cast(src) + y * srcPitch); + + for (int x = 0; x < width; ++x) + trgLine[x] = CONVERT_16_TO_32(srcLine[x]); + } +} + + +//stretch image and convert from ARGB to RGB565/555 +inline +void stretchImage32To16(const uint32_t* src, int srcWidth, int srcHeight, + uint16_t* trg, int trgWidth, int trgHeight, int trgPitch, + int yFirst, int yLast) +{ + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, trgHeight); + if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return; + + for (int y = yFirst; y < yLast; ++y) + { + uint16_t* trgLine = reinterpret_cast(reinterpret_cast(trg) + y * trgPitch); + const int ySrc = srcHeight * y / trgHeight; + const uint32_t* srcLine = src + ySrc * srcWidth; + for (int x = 0; x < trgWidth; ++x) + { + const int xSrc = srcWidth * x / trgWidth; + trgLine[x] = CONVERT_32_TO_16(srcLine[xSrc]); + } + } +} + + +void xBRZ(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height, int scalingFactor) +{ + + std::vector renderBuffer; //raw image + std::vector xbrzBuffer; //scaled image + + if (width <= 0 || height <= 0) + return; + + renderBuffer.resize(width * height); + + xbrzBuffer.resize(renderBuffer.size() * scalingFactor * scalingFactor ); + + int trgWidth = width * scalingFactor; + int trgHeight = height * scalingFactor; + + copyImage16To32(reinterpret_cast(srcPtr), width, height, srcPitch, + &renderBuffer[0], 0, height); + + xbrz::scale(scalingFactor, &renderBuffer[0], &xbrzBuffer[0], width, height, xbrz::RGB, xbrz::ScalerCfg(), 0, height); + + stretchImage32To16(&xbrzBuffer[0], width * scalingFactor, height * scalingFactor, + reinterpret_cast(dstPtr), trgWidth, trgHeight, dstPitch, 0, height * scalingFactor); + +} + +void filter_2xBRZ(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + xBRZ(srcPtr, srcPitch, dstPtr, dstPitch, width, height, 2); +} + +void filter_3xBRZ(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + xBRZ(srcPtr, srcPitch, dstPtr, dstPitch, width, height, 3); +} + +void filter_4xBRZ(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + xBRZ(srcPtr, srcPitch, dstPtr, dstPitch, width, height, 4); +} + + diff --git a/gtk/src/filter_xbrz.h b/gtk/src/filter_xbrz.h new file mode 100644 index 00000000..971e7e1d --- /dev/null +++ b/gtk/src/filter_xbrz.h @@ -0,0 +1,8 @@ +#ifndef _filter_xbrz_h_ +#define _filter_xbrz_h_ + +void filter_2xBRZ (uint8 *, uint32, uint8 *, uint32, int, int); +void filter_3xBRZ (uint8 *, uint32, uint8 *, uint32, int, int); +void filter_4xBRZ (uint8 *, uint32, uint8 *, uint32, int, int); + +#endif diff --git a/gtk/src/gtk_config.cpp b/gtk/src/gtk_config.cpp index c0f3bde5..861ac646 100644 --- a/gtk/src/gtk_config.cpp +++ b/gtk/src/gtk_config.cpp @@ -484,6 +484,13 @@ Snes9xConfig::set_option (const char *name, const char *value) if (scale_method >= NUM_FILTERS - 3) scale_method = 0; #endif /* USE_HQ2X */ +#ifdef USE_XBRZ + if (scale_method >= NUM_FILTERS) + scale_method = 0; +#else + if (scale_method >= NUM_FILTERS - 3) + scale_method = 0; +#endif /* USE_XBRZ */ } else if (!strcasecmp (name, "multithreading")) { diff --git a/gtk/src/gtk_display.cpp b/gtk/src/gtk_display.cpp index fdd36e7d..be61f93c 100644 --- a/gtk/src/gtk_display.cpp +++ b/gtk/src/gtk_display.cpp @@ -985,6 +985,31 @@ get_filter_scale (int &width, int &height) break; #endif /* USE_HQ2X */ +#ifdef USE_XBRZ + case FILTER_4XBRZ: + if (((width * 4) <= S9xDisplayDriver::scaled_max_width) && + ((height * 4) <= S9xDisplayDriver::scaled_max_height)) + { + width *= 4; + height *= 4; + break; + } + + case FILTER_3XBRZ: + if (width * 3 <= S9xDisplayDriver::scaled_max_width && + height * 3 <= S9xDisplayDriver::scaled_max_height) + { + width *= 3; + height *= 3; + break; + } + + case FILTER_2XBRZ: + width *= 2; + height *= 2; + break; +#endif /* USE_XBRZ */ + case FILTER_SIMPLE4X: if (((width * 4) <= S9xDisplayDriver::scaled_max_width) && ((height * 4) <= S9xDisplayDriver::scaled_max_height)) @@ -1119,6 +1144,42 @@ internal_filter (uint8 *src_buffer, break; #endif /* USE_HQ2X */ +#ifdef USE_XBRZ + case FILTER_4XBRZ: + + filter_4xBRZ (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + + case FILTER_3XBRZ: + + filter_3xBRZ (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + + case FILTER_2XBRZ: + + filter_2xBRZ (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; +#endif /* USE_XBRZ */ + + case FILTER_SIMPLE4X: if (((width * 4) <= S9xDisplayDriver::scaled_max_width) && @@ -1778,7 +1839,6 @@ S9xInitDisplay (int argc, char **argv) #ifdef USE_HQ2X S9xBlitHQ2xFilterInit (); #endif /* USE_HQ2SX */ - S9xQueryDrivers (); S9xInitDriver (); S9xGraphicsInit (); diff --git a/gtk/src/gtk_display.h b/gtk/src/gtk_display.h index 0f30c004..d124dcfc 100644 --- a/gtk/src/gtk_display.h +++ b/gtk/src/gtk_display.h @@ -6,6 +6,9 @@ #ifdef USE_HQ2X #include "filter/hq2x.h" #endif +#ifdef USE_XBRZ +#include "filter_xbrz.h" +#endif #include "filter/epx.h" #include "filter_epx_unsafe.h" @@ -23,7 +26,10 @@ #define FILTER_HQ2X 11 #define FILTER_HQ3X 12 #define FILTER_HQ4X 13 -#define NUM_FILTERS 14 +#define FILTER_2XBRZ 14 +#define FILTER_3XBRZ 15 +#define FILTER_4XBRZ 16 +#define NUM_FILTERS 17 #define NTSC_COMPOSITE 0 #define NTSC_SVIDEO 1 diff --git a/gtk/src/gtk_preferences.cpp b/gtk/src/gtk_preferences.cpp index 3db26170..0e60c885 100644 --- a/gtk/src/gtk_preferences.cpp +++ b/gtk/src/gtk_preferences.cpp @@ -1049,6 +1049,13 @@ Snes9xPreferences::show (void) combo_box_append (GTK_COMBO_BOX (combo), _("HQ4x")); #endif +#ifdef USE_XBRZ + combo = get_widget ("scale_method_combo"); + combo_box_append (GTK_COMBO_BOX (combo), _("2xBRZ")); + combo_box_append (GTK_COMBO_BOX (combo), _("3xBRZ")); + combo_box_append (GTK_COMBO_BOX (combo), _("4xBRZ")); +#endif + combo = get_widget ("hw_accel"); combo_box_append (GTK_COMBO_BOX (combo), _("None - Use software scaler")); diff --git a/gtk/src/gtk_s9x.cpp b/gtk/src/gtk_s9x.cpp index c3324319..48195ffd 100644 --- a/gtk/src/gtk_s9x.cpp +++ b/gtk/src/gtk_s9x.cpp @@ -428,6 +428,20 @@ S9xParseArg (char **argv, int &i, int argc) gui_config->scale_method = FILTER_HQ4X; } #endif /* USE_HQ2X */ +#ifdef USE_XBRZ + else if (!strcasecmp (argv[i], "2xbrz")) + { + gui_config->scale_method = FILTER_2XBRZ; + } + else if (!strcasecmp (argv[i], "3xbrz")) + { + gui_config->scale_method = FILTER_3XBRZ; + } + else if (!strcasecmp (argv[i], "4xbrz")) + { + gui_config->scale_method = FILTER_4XBRZ; + } +#endif /* USE_XBRZ */ else if (!strcasecmp (argv[i], "epx")) { gui_config->scale_method = FILTER_EPX; @@ -765,7 +779,7 @@ S9xExtraUsage (void) printf ("GTK port options:\n" "-filter [option] Use a filter to scale the image.\n" " [option] is one of: none supereagle 2xsai\n" - " super2xsai hq2x hq3x hq4x epx ntsc\n" + " super2xsai hq2x hq3x hq4x 2xbrz 3xbrz 4xbrz epx ntsc\n" "\n" "-mutesound Disables sound output.\n"); return; diff --git a/unix/Makefile.in b/unix/Makefile.in index 58495689..dc08e075 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -7,7 +7,7 @@ OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` BUILDDIR = . -OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../statemanager.o unix.o x11.o +OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/xbrz.o ../filter/snes_ntsc.o ../statemanager.o unix.o x11.o DEFS = -DMITSHM ifdef S9XDEBUGGER