devinacker / bsnes-plus

debug-oriented fork of bsnes
http://bsnes.revenant1.net
327 stars 92 forks source link

Enhancement: Any plan of adding xbrz filter support #23

Closed CarterLi closed 9 years ago

CarterLi commented 9 years ago

http://sourceforge.net/projects/xbrz/ AFAIK, Many emulators already support this high quality image upscaling filter. It should be a good idea that we add it too.

devinacker commented 9 years ago

I haven't looked at any of the existing implementations yet, but this seems like it would (ideally) require multithreading (via OpenMP) for the same reason as hq2x, which may or may not be removed from bsnes-classic later in order to reduce dependencies.

I'll leave this idea on the table for now, but it's not a high priority.

CarterLi commented 9 years ago

No, xBRZ itself has nothing to do with multithreading, doesn't use OpenMP at all. It's just thread-safe.

I've tried myself to add xBRZ support to snesfilter, but failed to make it work...

// xbrz2x.hpp
class XbrzFilter {
public:
  void size(unsigned&, unsigned&, unsigned, unsigned);
  void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
} filter_xbrz2x;
// xbrz2x.cpp
#include "xbrz.h"
#include "xbrz2x.hpp"
#include "xbrz.cpp"

void XbrzFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
  if(width > 256 || height > 240) return filter_direct.size(outwidth, outheight, width, height);

  outwidth  = 2 * width;
  outheight = 2 * height;
}

void XbrzFilter::render(uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, unsigned width, unsigned height) {
  if(width > 256 || height > 240) {
    filter_direct.render(output, outpitch, input, pitch, width, height);
    return;
  }

  xbrz::scale(2, (const uint32_t *)input, width, height, pitch, (uint32_t *)output, outpitch, xbrz::RGB);
}
diff --git a/snesfilter/snesfilter.cpp b/snesfilter/snesfilter.cpp
index 3004547..9e6dcc5 100644
--- a/snesfilter/snesfilter.cpp
+++ b/snesfilter/snesfilter.cpp
@@ -28,9 +28,10 @@ configuration *config;
 #include "lq2x/lq2x.cpp"
 #include "hq2x/hq2x.cpp"
 #include "ntsc/ntsc.cpp"
+#include "xbrz2x/xbrz2x.cpp"

 dllexport const char* snesfilter_supported() {
-  return "Pixellate2x;Scale2x;2xSaI;Super 2xSaI;Super Eagle;LQ2x;HQ2x;NTSC";
+  return "Pixellate2x;Scale2x;2xSaI;Super 2xSaI;Super Eagle;LQ2x;HQ2x;xBRZ2x;NTSC";
 }

 dllexport void snesfilter_configuration(configuration &config_) {
@@ -54,7 +55,8 @@ dllexport void snesfilter_size(unsigned filter, unsigned &outwidth, unsigned &ou
     case 5:  return filter_supereagle.size(outwidth, outheight, width, height);
     case 6:  return filter_lq2x.size(outwidth, outheight, width, height);
     case 7:  return filter_hq2x.size(outwidth, outheight, width, height);
-    case 8:  return filter_ntsc.size(outwidth, outheight, width, height);
+    case 8:  return filter_xbrz2x.size(outwidth, outheight, width, height);
+    case 9:  return filter_ntsc.size(outwidth, outheight, width, height);
   }
 }

@@ -71,13 +73,14 @@ dllexport void snesfilter_render(
     case 5:  return filter_supereagle.render(output, outpitch, input, pitch, width, height);
     case 6:  return filter_lq2x.render(output, outpitch, input, pitch, width, height);
     case 7:  return filter_hq2x.render(output, outpitch, input, pitch, width, height);
-    case 8:  return filter_ntsc.render(output, outpitch, input, pitch, width, height);
+    case 8:  return filter_xbrz2x.render(output, outpitch, input, pitch, width, height);
+    case 9:  return filter_ntsc.render(output, outpitch, input, pitch, width, height);
   }
 }

 dllexport QWidget* snesfilter_settings(unsigned filter) {
   switch(filter) {
     default: return 0;
-    case 8:  return filter_ntsc.settings();
+    case 9:  return filter_ntsc.settings();
   }
 }

Result: screenshot 2015-06-02_22-02-28

Optiroc commented 9 years ago

It seems like you need to swizzle the color channels and (obviously) put in a scaling pass somewhere. But to be honest, if filters are your "thing", more recent bsnes flavours (ie. Higan) or RetroArch are a much better fit than this specialized fork of bsnes-classic.

CarterLi commented 9 years ago

Well, I just want to play my favorite SNES games on my macbook, don't really care which emulator is used. But it seems that Higan & snes9x have dropped OSX support AFAIK. I don't know how to connect Higan owner. I have tried snes9x on my macbook too, that was awful. I found bsnes-plus one day on emucr, which says that it have OSX support. So I come here :)

I'm mainly a player, not an emulator coder. What I can do with my limited C++ skill is only imitating how xbrz filters are implemented in vbam. If you think xbrz doesn't help, feel free to close this issue.

Optiroc commented 9 years ago

For "players" OpenEmu is a pretty good choice. It supports GLSL shaders and has a much more approachable UI than RetroArch.

But then again, bsnes-plus is devinacker's work and it's obviously up to him what features to add. But I don't think I'm mistaken when I'm saying it's "not for the players". (:

CarterLi commented 9 years ago

Yes, OpenEmu has an approachable UI, but nothing else. OpenEmu lacks too many necessary features for a approachable emulator: Only one quick save supported per game; no battery save importer; no auto-hold, rapid-fire, no memory viewer, no cheat searcher. Yes it supports shaders, but doesn't support xBRZ ( both vba-m, desmume and snes9x support it ) which is my favorite. I'd rather use the original emulators than their cores with a beautiful skin.

CarterLi commented 9 years ago

As my PR has been rejected due to imcompatible licenses, this feature can't be implemented in a simple way. I'll maintain my implementation in my own fork. Closing this one