bsnes/ruby/ruby.cpp
Tim Allen 434e303ffb Update to v103r12 release.
byuu says:

Changelog:

  - ruby/video: cleaned up Direct3D9 driver and fixed catastrophic
    memory leak
  - ruby/video: added fullscreen exclusive mode support to the Direct3D9
    driver¹
  - ruby/video: minor cosmetic code cleanups to various drivers
  - tomoko: added support to always allow input when in fullscreen
    exclusive mode
  - tomoko: fixed window to not remove resizability flag when exiting
    fullscreen mode

¹: I am assuming that exclusive mode will try to capture the primary
monitor. I don't know what will happen in multi-monitor setups, however,
as I don't use such a setup here.

Also, I am using `D3DPRESENT_DISCARD` instead of `D3DPRESENT_FLIP`. I'm
not sure if this will prove better or worse, but I've heard it will
waste less memory, and having a BackBufferCount of 1 should still result
in page flipping anyway. The difference is supposedly just that you
can't rely on the back buffer being a valid copy of the previous frame
like you can with FLIP.

Lastly, if you want Vsync, you can edit the configuration file to enable
that, and then turn off audio sync.

Errata: "pause emulation when focus is lost" is not working with
exclusive mode. I need to add a check to never auto-pause when in
exclusive mode. Thanks to bun for catching that one.
2017-07-09 12:23:17 +10:00

543 lines
9.8 KiB
C++

#ifdef _WIN32
#include <initguid.h>
#include <cguid.h>
#endif
#include <ruby/ruby.hpp>
using namespace nall;
using namespace ruby;
/* Shared */
#undef deprecated
#undef mkdir
#undef usleep
#if defined(DISPLAY_XORG)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#elif defined(DISPLAY_QUARTZ)
#define Boolean CocoaBoolean
#define decimal CocoaDecimal
#include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h>
#undef Boolean
#undef decimal
#elif defined(DISPLAY_WINDOWS)
#include <windows.h>
#endif
/* Video */
#if defined(VIDEO_CGL)
#include <ruby/video/cgl.cpp>
#endif
#if defined(VIDEO_DIRECT3D)
#include <ruby/video/direct3d.cpp>
#endif
#if defined(VIDEO_DIRECTDRAW)
#include <ruby/video/directdraw.cpp>
#endif
#if defined(VIDEO_GDI)
#include <ruby/video/gdi.cpp>
#endif
#if defined(VIDEO_GLX)
#include <ruby/video/glx.cpp>
#endif
#if defined(VIDEO_GLX2)
#include <ruby/video/glx2.cpp>
#endif
#if defined(VIDEO_SDL)
#include <ruby/video/sdl.cpp>
#endif
#if defined(VIDEO_WGL)
#include <ruby/video/wgl.cpp>
#endif
#if defined(VIDEO_XSHM)
#include <ruby/video/xshm.cpp>
#endif
#if defined(VIDEO_XV)
#include <ruby/video/xv.cpp>
#endif
namespace ruby {
const string Video::Exclusive = "Exclusive";
const string Video::Handle = "Handle";
const string Video::Synchronize = "Synchronize";
const string Video::Depth = "Depth";
const string Video::Filter = "Filter";
const string Video::Shader = "Shader";
const uint Video::FilterNearest = 0;
const uint Video::FilterLinear = 1;
auto Video::create(const string& driver) -> Video* {
if(!driver) return create(optimalDriver());
#if defined(VIDEO_CGL)
if(driver == "OpenGL") return new VideoCGL;
#endif
#if defined(VIDEO_DIRECT3D)
if(driver == "Direct3D") return new VideoDirect3D;
#endif
#if defined(VIDEO_DIRECTDRAW)
if(driver == "DirectDraw") return new VideoDirectDraw;
#endif
#if defined(VIDEO_GDI)
if(driver == "GDI") return new VideoGDI;
#endif
#if defined(VIDEO_GLX)
if(driver == "OpenGL") return new VideoGLX;
#endif
#if defined(VIDEO_GLX2)
if(driver == "OpenGL2") return new VideoGLX2;
#endif
#if defined(VIDEO_SDL)
if(driver == "SDL") return new VideoSDL;
#endif
#if defined(VIDEO_WGL)
if(driver == "OpenGL") return new VideoWGL;
#endif
#if defined(VIDEO_XSHM)
if(driver == "XShm") return new VideoXShm;
#endif
#if defined(VIDEO_XV)
if(driver == "X-Video") return new VideoXv;
#endif
return new Video;
}
auto Video::optimalDriver() -> string {
#if defined(VIDEO_WGL)
return "OpenGL";
#elif defined(VIDEO_DIRECT3D)
return "Direct3D";
#elif defined(VIDEO_DIRECTDRAW)
return "DirectDraw";
#elif defined(VIDEO_GDI)
return "GDI";
#elif defined(VIDEO_CGL)
return "OpenGL";
#elif defined(VIDEO_GLX)
return "OpenGL";
#elif defined(VIDEO_GLX2)
return "OpenGL2";
#elif defined(VIDEO_XV)
return "X-Video";
#elif defined(VIDEO_XSHM)
return "XShm";
#elif defined(VIDEO_SDL)
return "SDL";
#else
return "None";
#endif
}
auto Video::safestDriver() -> string {
#if defined(VIDEO_DIRECT3D)
return "Direct3D";
#elif defined(VIDEO_WGL)
return "OpenGL";
#elif defined(VIDEO_DIRECTDRAW)
return "DirectDraw";
#elif defined(VIDEO_GDI)
return "GDI";
#elif defined(VIDEO_CGL)
return "OpenGL";
#elif defined(VIDEO_XSHM)
return "XShm";
#elif defined(VIDEO_SDL)
return "SDL";
#elif defined(VIDEO_XV)
return "X-Video";
#elif defined(VIDEO_GLX2)
return "OpenGL2";
#elif defined(VIDEO_GLX)
return "OpenGL";
#else
return "None";
#endif
}
auto Video::availableDrivers() -> string_vector {
return {
#if defined(VIDEO_WGL)
"OpenGL",
#endif
#if defined(VIDEO_DIRECT3D)
"Direct3D",
#endif
#if defined(VIDEO_DIRECTDRAW)
"DirectDraw",
#endif
#if defined(VIDEO_GDI)
"GDI",
#endif
#if defined(VIDEO_CGL)
"OpenGL",
#endif
#if defined(VIDEO_GLX)
"OpenGL",
#endif
#if defined(VIDEO_GLX2)
"OpenGL2",
#endif
#if defined(VIDEO_XV)
"X-Video",
#endif
#if defined(VIDEO_XSHM)
"XShm",
#endif
#if defined(VIDEO_SDL)
"SDL",
#endif
"None"};
}
}
/* Audio */
#if defined(AUDIO_ALSA)
#include <ruby/audio/alsa.cpp>
#endif
#if defined(AUDIO_AO)
#include <ruby/audio/ao.cpp>
#endif
#if defined(AUDIO_DIRECTSOUND)
#include <ruby/audio/directsound.cpp>
#endif
#if defined(AUDIO_OPENAL)
#include <ruby/audio/openal.cpp>
#endif
#if defined(AUDIO_OSS)
#include <ruby/audio/oss.cpp>
#endif
#if defined(AUDIO_PULSEAUDIO)
#include <ruby/audio/pulseaudio.cpp>
#endif
#if defined(AUDIO_PULSEAUDIOSIMPLE)
#include <ruby/audio/pulseaudiosimple.cpp>
#endif
#if defined(AUDIO_WASAPI)
#include <ruby/audio/wasapi.cpp>
#endif
#if defined(AUDIO_XAUDIO2)
#include <ruby/audio/xaudio2.cpp>
#endif
namespace ruby {
const string Audio::Device = "Device";
const string Audio::Exclusive = "Exclusive";
const string Audio::Handle = "Handle";
const string Audio::Synchronize = "Synchronize";
const string Audio::Frequency = "Frequency";
const string Audio::Latency = "Latency";
auto Audio::create(const string& driver) -> Audio* {
if(!driver) return create(optimalDriver());
#if defined(AUDIO_ALSA)
if(driver == "ALSA") return new AudioALSA;
#endif
#if defined(AUDIO_AO)
if(driver == "libao") return new AudioAO;
#endif
#if defined(AUDIO_DIRECTSOUND)
if(driver == "DirectSound") return new AudioDS;
#endif
#if defined(AUDIO_OPENAL)
if(driver == "OpenAL") return new AudioOpenAL;
#endif
#if defined(AUDIO_OSS)
if(driver == "OSS") return new AudioOSS;
#endif
#if defined(AUDIO_PULSEAUDIO)
if(driver == "PulseAudio") return new AudioPulseAudio;
#endif
#if defined(AUDIO_PULSEAUDIOSIMPLE)
if(driver == "PulseAudioSimple") return new AudioPulseAudioSimple;
#endif
#if defined(AUDIO_WASAPI)
if(driver == "WASAPI") return new AudioWASAPI;
#endif
#if defined(AUDIO_XAUDIO2)
if(driver == "XAudio2") return new AudioXAudio2;
#endif
return new Audio;
}
auto Audio::optimalDriver() -> string {
#if defined(AUDIO_WASAPI)
return "WASAPI";
#elif defined(AUDIO_XAUDIO2)
return "XAudio2";
#elif defined(AUDIO_DIRECTSOUND)
return "DirectSound";
#elif defined(AUDIO_ALSA)
return "ALSA";
#elif defined(AUDIO_OSS)
return "OSS";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_PULSEAUDIO)
return "PulseAudio";
#elif defined(AUDIO_PULSEAUDIOSIMPLE)
return "PulseAudioSimple";
#elif defined(AUDIO_AO)
return "libao";
#else
return "None";
#endif
}
auto Audio::safestDriver() -> string {
#if defined(AUDIO_DIRECTSOUND)
return "DirectSound";
#elif defined(AUDIO_WASAPI)
return "WASAPI";
#elif defined(AUDIO_XAUDIO2)
return "XAudio2";
#elif defined(AUDIO_ALSA)
return "ALSA";
#elif defined(AUDIO_OSS)
return "OSS";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_PULSEAUDIO)
return "PulseAudio";
#elif defined(AUDIO_PULSEAUDIOSIMPLE)
return "PulseAudioSimple";
#elif defined(AUDIO_AO)
return "libao";
#else
return "None";
#endif
}
auto Audio::availableDrivers() -> string_vector {
return {
#if defined(AUDIO_WASAPI)
"WASAPI",
#endif
#if defined(AUDIO_XAUDIO2)
"XAudio2",
#endif
#if defined(AUDIO_DIRECTSOUND)
"DirectSound",
#endif
#if defined(AUDIO_ALSA)
"ALSA",
#endif
#if defined(AUDIO_OSS)
"OSS",
#endif
#if defined(AUDIO_OPENAL)
"OpenAL",
#endif
#if defined(AUDIO_PULSEAUDIO)
"PulseAudio",
#endif
#if defined(AUDIO_PULSEAUDIOSIMPLE)
"PulseAudioSimple",
#endif
#if defined(AUDIO_AO)
"libao",
#endif
"None"};
}
}
/* Input */
#if defined(INPUT_CARBON)
#include <ruby/input/carbon.cpp>
#endif
#if defined(INPUT_QUARTZ)
#include <ruby/input/quartz.cpp>
#endif
#if defined(INPUT_SDL)
#include <ruby/input/sdl.cpp>
#endif
#if defined(INPUT_UDEV)
#include <ruby/input/udev.cpp>
#endif
#if defined(INPUT_WINDOWS)
#include <ruby/input/windows.cpp>
#endif
#if defined(INPUT_XLIB)
#include <ruby/input/xlib.cpp>
#endif
namespace ruby {
const string Input::Handle = "Handle";
const string Input::KeyboardSupport = "KeyboardSupport";
const string Input::MouseSupport = "MouseSupport";
const string Input::JoypadSupport = "JoypadSupport";
const string Input::JoypadRumbleSupport = "JoypadRumbleSupport";
auto Input::create(const string& driver) -> Input* {
if(!driver) return create(optimalDriver());
#if defined(INPUT_WINDOWS)
if(driver == "Windows") return new InputWindows;
#endif
#if defined(INPUT_QUARTZ)
if(driver == "Quartz") return new InputQuartz;
#endif
#if defined(INPUT_CARBON)
if(driver == "Carbon") return new InputCarbon;
#endif
#if defined(INPUT_UDEV)
if(driver == "udev") return new InputUdev;
#endif
#if defined(INPUT_SDL)
if(driver == "SDL") return new InputSDL;
#endif
#if defined(INPUT_XLIB)
if(driver == "Xlib") return new InputXlib;
#endif
return new Input;
}
auto Input::optimalDriver() -> string {
#if defined(INPUT_WINDOWS)
return "Windows";
#elif defined(INPUT_QUARTZ)
return "Quartz";
#elif defined(INPUT_CARBON)
return "Carbon";
#elif defined(INPUT_UDEV)
return "udev";
#elif defined(INPUT_SDL)
return "SDL";
#elif defined(INPUT_XLIB)
return "Xlib";
#else
return "None";
#endif
}
auto Input::safestDriver() -> string {
#if defined(INPUT_WINDOWS)
return "Windows";
#elif defined(INPUT_QUARTZ)
return "Quartz";
#elif defined(INPUT_CARBON)
return "Carbon";
#elif defined(INPUT_UDEV)
return "udev";
#elif defined(INPUT_SDL)
return "SDL";
#elif defined(INPUT_XLIB)
return "Xlib";
#else
return "none";
#endif
}
auto Input::availableDrivers() -> string_vector {
return {
#if defined(INPUT_WINDOWS)
"Windows",
#endif
#if defined(INPUT_QUARTZ)
"Quartz",
#endif
#if defined(INPUT_CARBON)
"Carbon",
#endif
#if defined(INPUT_UDEV)
"udev",
#endif
#if defined(INPUT_SDL)
"SDL",
#endif
#if defined(INPUT_XLIB)
"Xlib",
#endif
"None"};
}
}