Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 88156cff05 | |||
| 1b7065d8b4 | |||
| 909f36017b | |||
| 631df2d903 | |||
| 789045e1b2 | |||
| 19551fb864 | |||
| 449e28f9a6 | |||
| 45db281360 | |||
| cb38303531 | |||
| 1310052bd7 | |||
| 9d786b6440 | |||
| 9734e39530 | |||
| ed4318b949 | |||
| 21a240547e | |||
| cfd83be9a1 | |||
| 620c263582 | |||
| 559bfa3112 | |||
| dff7aa5ed6 | |||
| 8d826b4f62 | |||
| f77140336d | |||
| 29cb2ddd87 | |||
| 88af328437 | |||
| 318abc4ece | |||
| d4ba991dd3 | |||
| 9ea17949ef | |||
| fc74ce36c6 | |||
| d42a27937d |
Vendored
+1
-1
@@ -10,4 +10,4 @@ env_lzo = env.Clone(
|
||||
CCFLAGS = env.filterWarnings(env['CCFLAGS']),
|
||||
CXXFLAGS = env.filterWarnings(env['CXXFLAGS']),
|
||||
)
|
||||
env_lzo.StaticLibrary(env['local_libs'] + "minilzo", files)
|
||||
env_lzo.StaticLibrary(env['local_libs'] + "lzo2", files)
|
||||
|
||||
Vendored
+1
-1
@@ -19,4 +19,4 @@ env_sfml = env.Clone(
|
||||
CXXFLAGS = env.filterWarnings(env['CXXFLAGS']),
|
||||
)
|
||||
|
||||
env_sfml.StaticLibrary(env['local_libs'] + "sfml", files)
|
||||
env_sfml.StaticLibrary(env['local_libs'] + "sfml-network", files)
|
||||
|
||||
Vendored
+1
-1
@@ -15,4 +15,4 @@ env_soil = env.Clone(
|
||||
parse_flags = ['-fPIC']
|
||||
)
|
||||
|
||||
env_soil.StaticLibrary(env['local_libs'] + "libsoil", files)
|
||||
env_soil.StaticLibrary(env['local_libs'] + "SOIL", files)
|
||||
|
||||
Vendored
+2
-4
@@ -34,15 +34,13 @@ else:
|
||||
env_wiiuse = env.Clone(
|
||||
CCFLAGS = env.filterWarnings(env['CCFLAGS']) + ' -fvisibility=default',
|
||||
CXXFLAGS = env.filterWarnings(env['CXXFLAGS']),
|
||||
parse_flags = ['-fPIC']
|
||||
)
|
||||
|
||||
libs = [
|
||||
'm',
|
||||
]
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
env_wiiuse.StaticLibrary(env['libs_dir']+"wiiuse", files, LIBS=libs)
|
||||
else:
|
||||
env_wiiuse.SharedLibrary(env['libs_dir']+"wiiuse", files, LIBS=libs)
|
||||
env_wiiuse.StaticLibrary(env['libs_dir']+"wiiuse", files, LIBS=libs)
|
||||
|
||||
env['HAVE_WIIUSE'] = 1
|
||||
|
||||
+51
-13
@@ -50,10 +50,7 @@ include_paths = [
|
||||
basedir + 'Source/Core/Core/Src',
|
||||
basedir + 'Source/Core/DebuggerWX/Src',
|
||||
basedir + 'Externals/Bochs_disasm',
|
||||
basedir + 'Externals/LZO',
|
||||
basedir + 'Externals/SOIL',
|
||||
basedir + 'Externals/Lua',
|
||||
basedir + 'Externals/SFML/include',
|
||||
basedir + 'Externals/WiiUseSrc/Src',
|
||||
basedir + 'Source/Core/VideoCommon/Src',
|
||||
basedir + 'Source/Core/InputCommon/Src',
|
||||
@@ -64,9 +61,6 @@ include_paths = [
|
||||
|
||||
dirs = [
|
||||
'Externals/Bochs_disasm',
|
||||
'Externals/LZO',
|
||||
'Externals/SOIL',
|
||||
'Externals/SFML/src',
|
||||
'Externals/Lua',
|
||||
'Externals/WiiUseSrc/Src',
|
||||
'Source/Core/Common/Src',
|
||||
@@ -83,6 +77,7 @@ dirs = [
|
||||
'Source/Plugins/Plugin_DSP_HLE/Src',
|
||||
'Source/Plugins/Plugin_DSP_LLE/Src',
|
||||
'Source/Plugins/Plugin_GCPad/Src',
|
||||
'Source/Plugins/Plugin_GCPadNew/Src',
|
||||
'Source/Plugins/Plugin_Wiimote/Src',
|
||||
'Source/Core/DolphinWX/Src',
|
||||
'Source/Core/DebuggerWX/Src',
|
||||
@@ -112,6 +107,9 @@ vars.AddVariables(
|
||||
BoolVariable('wxgl', 'Set For Building with WX GL libs (WIP)', False),
|
||||
BoolVariable('opencl', 'Build with OpenCL', False),
|
||||
BoolVariable('nojit', 'Remove entire jit cores', False),
|
||||
BoolVariable('shared_soil', 'Use system shared libSOIL', False),
|
||||
BoolVariable('shared_lzo', 'Use system shared liblzo2', False),
|
||||
BoolVariable('shared_sfml', 'Use system shared libsfml-network', False),
|
||||
PathVariable('userdir', 'Set the name of the user data directory in home', '.dolphin-emu', PathVariable.PathAccept),
|
||||
EnumVariable('install', 'Choose a local or global installation', 'local',
|
||||
allowed_values = ('local', 'global'),
|
||||
@@ -188,7 +186,7 @@ if not env['verbose']:
|
||||
env['RANLIBCOMSTR'] = "Indexing $TARGET"
|
||||
|
||||
# build flavor
|
||||
flavour = ARGUMENTS.get('flavor')
|
||||
flavour = env['flavor']
|
||||
if (flavour == 'debug'):
|
||||
compileFlags.append('-ggdb')
|
||||
cppDefines.append('_DEBUG') #enables LOGGING
|
||||
@@ -257,7 +255,7 @@ elif flavour == 'prof':
|
||||
extra = '-prof'
|
||||
|
||||
# Set up the install locations
|
||||
if (ARGUMENTS.get('install') == 'global'):
|
||||
if (env['install'] == 'global'):
|
||||
env['prefix'] = os.path.join(env['prefix'] + os.sep)
|
||||
env['binary_dir'] = env['prefix'] + 'bin/'
|
||||
env['libs_dir'] = env['prefix'] + 'lib/'
|
||||
@@ -324,6 +322,40 @@ if sys.platform != 'darwin':
|
||||
# needed for mic
|
||||
env['HAVE_PORTAUDIO'] = conf.CheckPortaudio(1890)
|
||||
|
||||
# SOIL
|
||||
env['SHARED_SOIL'] = 0;
|
||||
if env['shared_soil']:
|
||||
env['SHARED_SOIL'] = conf.CheckPKG('SOIL')
|
||||
if not env['SHARED_SOIL']:
|
||||
print "shared SOIL library not detected"
|
||||
print "falling back to the static library"
|
||||
if not env['SHARED_SOIL']:
|
||||
env['CPPPATH'] += [ basedir + 'Externals/SOIL' ]
|
||||
dirs += ['Externals/SOIL']
|
||||
|
||||
# LZO
|
||||
env['SHARED_LZO'] = 0;
|
||||
if env['shared_lzo']:
|
||||
env['SHARED_LZO'] = conf.CheckPKG('lzo2')
|
||||
if not env['SHARED_LZO']:
|
||||
print "shared LZO library not detected"
|
||||
print "falling back to the static library"
|
||||
if not env['SHARED_LZO']:
|
||||
env['CPPPATH'] += [ basedir + 'Externals/LZO' ]
|
||||
dirs += ['Externals/LZO']
|
||||
|
||||
# SFML
|
||||
env['SHARED_SFML'] = 0;
|
||||
if env['shared_sfml']:
|
||||
# TODO: Check the version of sfml. It should be at least version 1.5
|
||||
env['SHARED_SFML'] = conf.CheckPKG('sfml-network') and conf.CheckCXXHeader("SFML/Network/Ftp.hpp")
|
||||
if not env['SHARED_SFML']:
|
||||
print "shared sfml-network library not detected"
|
||||
print "falling back to the static library"
|
||||
if not env['SHARED_SFML']:
|
||||
env['CPPPATH'] += [ basedir + 'Externals/SFML/include' ]
|
||||
dirs += ['Externals/SFML/src']
|
||||
|
||||
#osx 64 specifics
|
||||
if sys.platform == 'darwin':
|
||||
if env['osx'] == '64cocoa':
|
||||
@@ -380,8 +412,11 @@ conf.Define('USE_WX', env['USE_WX'])
|
||||
conf.Define('HAVE_X11', env['HAVE_X11'])
|
||||
conf.Define('HAVE_COCOA', env['HAVE_COCOA'])
|
||||
conf.Define('HAVE_PORTAUDIO', env['HAVE_PORTAUDIO'])
|
||||
conf.Define('SHARED_SOIL', env['SHARED_SOIL'])
|
||||
conf.Define('SHARED_LZO', env['SHARED_LZO'])
|
||||
conf.Define('SHARED_SFML', env['SHARED_SFML'])
|
||||
conf.Define('USER_DIR', "\"" + env['userdir'] + "\"")
|
||||
if (ARGUMENTS.get('install') == 'global'):
|
||||
if (env['install'] == 'global'):
|
||||
conf.Define('DATA_DIR', "\"" + env['data_dir'] + "\"")
|
||||
conf.Define('LIBS_DIR', "\"" + env['libs_dir'] + "\"")
|
||||
|
||||
@@ -434,9 +469,6 @@ else:
|
||||
# add methods from utils to env
|
||||
env.AddMethod(utils.filterWarnings)
|
||||
|
||||
rev = utils.GenerateRevFile(env['flavor'],
|
||||
"Source/Core/Common/Src/svnrev_template.h",
|
||||
"Source/Core/Common/Src/svnrev.h")
|
||||
# print a nice progress indication when not compiling
|
||||
Progress(['-\r', '\\\r', '|\r', '/\r'], interval = 5)
|
||||
|
||||
@@ -481,9 +513,15 @@ else:
|
||||
env.Alias('install', env['prefix'])
|
||||
|
||||
if env['bundle']:
|
||||
# get the rev anyways, RC != RC between commits
|
||||
# copied from utils.py, could be solved better...
|
||||
try:
|
||||
rev = os.popen('svnversion .').read().strip().split(':')[0]
|
||||
except:
|
||||
rev = ""
|
||||
# Make tar ball (TODO put inside normal dir)
|
||||
tar_env = env.Clone()
|
||||
tarball = tar_env.Tar('dolphin-'+rev +'.tar.bz2', env['prefix'])
|
||||
tarball = tar_env.Tar('dolphin-2.0.tar.bz2', env['prefix'])
|
||||
tar_env.Append(TARFLAGS='-j',
|
||||
TARCOMSTR="Creating release tarball")
|
||||
|
||||
|
||||
@@ -162,7 +162,8 @@ void DSound::Clear(bool mute)
|
||||
|
||||
if (m_muted)
|
||||
{
|
||||
dsBuffer->Stop();
|
||||
if (dsBuffer != NULL)
|
||||
dsBuffer->Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
#define HAVE_WX 1
|
||||
#define HAVE_OPENAL 1
|
||||
#define HAVE_ALSA 0
|
||||
#define HAVE_PORTAUDIO 0
|
||||
|
||||
// it is VERY DANGEROUS to mix _SECURE_SCL=0 and _SECURE_SCL=1 compiled libraries.
|
||||
// You will get bizarre crash bugs whenever you use STL.
|
||||
|
||||
@@ -129,7 +129,11 @@
|
||||
// Plugin files
|
||||
#define DEFAULT_GFX_PLUGIN PLUGIN_PREFIX "Plugin_VideoOGL" PLUGIN_SUFFIX
|
||||
#define DEFAULT_DSP_PLUGIN PLUGIN_PREFIX "Plugin_DSP_HLE" PLUGIN_SUFFIX
|
||||
#if defined(_WIN32) || defined(__linux__)
|
||||
#define DEFAULT_PAD_PLUGIN PLUGIN_PREFIX "Plugin_GCPadNew" PLUGIN_SUFFIX
|
||||
#else
|
||||
#define DEFAULT_PAD_PLUGIN PLUGIN_PREFIX "Plugin_GCPad" PLUGIN_SUFFIX
|
||||
#endif
|
||||
#define DEFAULT_WIIMOTE_PLUGIN PLUGIN_PREFIX "Plugin_Wiimote" PLUGIN_SUFFIX
|
||||
|
||||
// Sys files
|
||||
|
||||
@@ -40,7 +40,7 @@ static const char* ram_temp_file = "/tmp/gc_mem.tmp";
|
||||
void MemArena::GrabLowMemSpace(size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), _T("All GC Memory"));
|
||||
hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL);
|
||||
#else
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#define SVN_REV 5163
|
||||
#define SVN_REV_STR "2.0"
|
||||
Binary file not shown.
@@ -198,7 +198,7 @@ bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
|
||||
|
||||
default:
|
||||
// PanicAlert("SetupWiiMem: Unknown country. Wii boot process will be switched to European settings.");
|
||||
filename = WII_EUR_SETTING_FILE;
|
||||
filename = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_EUR_SETTING;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,8 +85,6 @@ void SConfig::SaveSettings()
|
||||
ini.Set("Interface", "MainWindowPosY", m_LocalCoreStartupParameter.iPosY);
|
||||
ini.Set("Interface", "MainWindowWidth", m_LocalCoreStartupParameter.iWidth);
|
||||
ini.Set("Interface", "MainWindowHeight", m_LocalCoreStartupParameter.iHeight);
|
||||
ini.Set("Interface", "ShowWiimoteLeds", m_LocalCoreStartupParameter.bWiiLeds);
|
||||
ini.Set("Interface", "ShowWiimoteSpeakers", m_LocalCoreStartupParameter.bWiiSpeakers);
|
||||
ini.Set("Interface", "Language", m_InterfaceLanguage);
|
||||
ini.Set("Interface", "ShowToolbar", m_InterfaceToolbar);
|
||||
ini.Set("Interface", "ShowStatusbar", m_InterfaceStatusbar);
|
||||
@@ -197,8 +195,6 @@ void SConfig::LoadSettings()
|
||||
ini.Get("Interface", "MainWindowPosY", &m_LocalCoreStartupParameter.iPosY, 100);
|
||||
ini.Get("Interface", "MainWindowWidth", &m_LocalCoreStartupParameter.iWidth, 800);
|
||||
ini.Get("Interface", "MainWindowHeight", &m_LocalCoreStartupParameter.iHeight, 600);
|
||||
ini.Get("Interface", "ShowWiimoteLeds", &m_LocalCoreStartupParameter.bWiiLeds, false);
|
||||
ini.Get("Interface", "ShowWiimoteSpeakers", &m_LocalCoreStartupParameter.bWiiSpeakers, false);
|
||||
ini.Get("Interface", "Language", (int*)&m_InterfaceLanguage, 0);
|
||||
ini.Get("Interface", "ShowToolbar", &m_InterfaceToolbar, true);
|
||||
ini.Get("Interface", "ShowStatusbar", &m_InterfaceStatusbar, true);
|
||||
|
||||
@@ -29,11 +29,6 @@
|
||||
#include "MathUtil.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#endif
|
||||
|
||||
#include "Console.h"
|
||||
#include "Core.h"
|
||||
#include "CPUDetect.h"
|
||||
@@ -252,45 +247,6 @@ void Stop() // - Hammertime!
|
||||
g_EmuThread = 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
void ProcessXEvents(void)
|
||||
{
|
||||
if (GetState() == CORE_PAUSE)
|
||||
{
|
||||
Display *dpy = (Display *)g_pWindowHandle;
|
||||
XEvent event;
|
||||
KeySym key;
|
||||
int num_events;
|
||||
for (num_events = XPending(dpy);num_events > 0;num_events--)
|
||||
{
|
||||
XNextEvent(dpy, &event);
|
||||
switch(event.type) {
|
||||
case KeyPress:
|
||||
key = XLookupKeysym((XKeyEvent*)&event, 0);
|
||||
if (key == XK_Escape)
|
||||
Host_Message(WM_USER_PAUSE);
|
||||
case ClientMessage:
|
||||
if ((ulong) event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False))
|
||||
Host_Message(WM_USER_STOP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
THREAD_RETURN XEventThread(void *pArg)
|
||||
{
|
||||
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
|
||||
{
|
||||
ProcessXEvents();
|
||||
Common::SleepCurrentThread(200);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create the CPU thread. which would be a CPU + Video thread in Single Core mode.
|
||||
|
||||
THREAD_RETURN CpuThread(void *pArg)
|
||||
@@ -366,6 +322,9 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
VideoInitialize.pScheduleEvent_Threadsafe = CoreTiming::ScheduleEvent_Threadsafe;
|
||||
// This is first the m_Panel handle, then it is updated to have the new window handle
|
||||
VideoInitialize.pWindowHandle = _CoreParameter.hMainWindow;
|
||||
#if defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2
|
||||
VideoInitialize.pPanel = _CoreParameter.hMainWindow;
|
||||
#endif
|
||||
VideoInitialize.pLog = Callback_VideoLog;
|
||||
VideoInitialize.pSysMessage = Host_SysMessage;
|
||||
VideoInitialize.pRequestWindowSize = NULL; //Callback_VideoRequestWindowSize;
|
||||
@@ -386,7 +345,7 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
// Under linux, this is an X11 Display, not a HWND!
|
||||
g_pWindowHandle = (HWND)VideoInitialize.pWindowHandle;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
g_pXWindow = (Window *)VideoInitialize.pXWindow;
|
||||
g_pXWindow = (void *)VideoInitialize.pXWindow;
|
||||
#endif
|
||||
Callback_PeekMessages = VideoInitialize.pPeekMessages;
|
||||
g_pUpdateFPSDisplay = VideoInitialize.pUpdateFPSDisplay;
|
||||
@@ -415,6 +374,9 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
PADInitialize.hWnd = g_pWindowHandle;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
PADInitialize.pXWindow = g_pXWindow;
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2
|
||||
PADInitialize.pPanel = VideoInitialize.pPanel;
|
||||
#endif
|
||||
#endif
|
||||
PADInitialize.pLog = Callback_PADLog;
|
||||
// This is may be needed to avoid a SDL problem
|
||||
@@ -427,6 +389,9 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
SWiimoteInitialize WiimoteInitialize;
|
||||
WiimoteInitialize.hWnd = g_pWindowHandle;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2
|
||||
WiimoteInitialize.pPanel = VideoInitialize.pPanel;
|
||||
#endif
|
||||
WiimoteInitialize.pXWindow = g_pXWindow;
|
||||
#endif
|
||||
WiimoteInitialize.ISOId = Ascii2Hex(_CoreParameter.m_strUniqueID);
|
||||
@@ -457,10 +422,6 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
|
||||
// Spawn the CPU thread
|
||||
Common::Thread *cpuThread = NULL;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
Common::Thread *xEventThread = NULL;
|
||||
#endif
|
||||
|
||||
// ENTER THE VIDEO THREAD LOOP
|
||||
if (_CoreParameter.bCPUThread)
|
||||
{
|
||||
@@ -469,9 +430,6 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
|
||||
Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent
|
||||
cpuThread = new Common::Thread(CpuThread, pArg);
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
xEventThread = new Common::Thread(XEventThread, pArg);
|
||||
#endif
|
||||
Common::SetCurrentThreadName("Video thread");
|
||||
|
||||
if (g_pUpdateFPSDisplay != NULL)
|
||||
@@ -506,9 +464,6 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
{
|
||||
if (Callback_PeekMessages)
|
||||
Callback_PeekMessages();
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
ProcessXEvents();
|
||||
#endif
|
||||
Common::SleepCurrentThread(20);
|
||||
}
|
||||
|
||||
@@ -815,11 +770,15 @@ void Callback_KeyPress(int key, bool shift, bool control)
|
||||
State_UndoLoadState();
|
||||
}
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
if (key == 0)
|
||||
Host_Message(WM_USER_CREATE);
|
||||
// 0x1b == VK_ESCAPE
|
||||
if (key == 0x1b)
|
||||
Host_Message(WM_USER_STOP);
|
||||
if (key == 0x1c)
|
||||
Host_Message(WM_USER_PAUSE);
|
||||
if (key == 0x1d)
|
||||
Host_Message(TOGGLE_FULLSCREEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ SCoreStartupParameter::SCoreStartupParameter()
|
||||
bEnableCheats(false), bEnableIsoCache(false),
|
||||
bRunCompareServer(false), bRunCompareClient(false),
|
||||
iTLBHack(0), SelectedLanguage(0),
|
||||
bWii(false), bWiiLeds(false), bWiiSpeakers(false),
|
||||
bWii(false),
|
||||
bConfirmStop(false), bHideCursor(false),
|
||||
bAutoHideCursor(false), bUsePanicHandlers(true),
|
||||
iTheme(0),
|
||||
@@ -91,7 +91,6 @@ void SCoreStartupParameter::LoadDefaults()
|
||||
// These work fine in 32bit OSX
|
||||
// Since the reason why 64bit OSX fails out is due to casting (u32)(u64)
|
||||
// Since all 64bit applications are above the 32bit memory boundary
|
||||
bJITLoadStoreOff = true;
|
||||
bJITLoadStorePairedOff = true;
|
||||
#endif
|
||||
//#elif defined(__linux__)
|
||||
|
||||
@@ -73,8 +73,7 @@ struct SCoreStartupParameter
|
||||
|
||||
int SelectedLanguage;
|
||||
|
||||
// Wii settings
|
||||
bool bWii, bWiiLeds, bWiiSpeakers;
|
||||
bool bWii;
|
||||
|
||||
// Interface settings
|
||||
bool bConfirmStop, bHideCursor, bAutoHideCursor, bUsePanicHandlers;
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
bool MicButton = false;
|
||||
bool IsOpen;
|
||||
|
||||
//#define HAVE_PORTAUDIO
|
||||
#if !defined(HAVE_PORTAUDIO) || !HAVE_PORTAUDIO
|
||||
// Unfortunately this must be enabled in Common.h for windows users. Scons should enable it otherwise7
|
||||
#if !HAVE_PORTAUDIO
|
||||
|
||||
void SetMic(bool Value){}
|
||||
|
||||
|
||||
@@ -53,8 +53,4 @@ void Host_UpdateStatusBar(const char* _pText, int Filed = 0);
|
||||
void Host_SysMessage(const char *fmt, ...);
|
||||
void Host_SetWiiMoteConnectionState(int _State);
|
||||
|
||||
void Host_UpdateLeds(int bits);
|
||||
void Host_UpdateSpeakerStatus(int index, int bits);
|
||||
void Host_UpdateStatus();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -146,75 +146,10 @@ bool CWII_IPC_HLE_WiiMote::LinkChannel()
|
||||
}
|
||||
|
||||
m_Connected = 3;
|
||||
UpdateStatus();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===================================================
|
||||
/* Send a status report to the status bar. */
|
||||
// ----------------
|
||||
void CWII_IPC_HLE_WiiMote::ShowStatus(const void* _pData)
|
||||
{
|
||||
// Check if it's enabled
|
||||
SCoreStartupParameter& StartUp = SConfig::GetInstance().m_LocalCoreStartupParameter;
|
||||
bool LedsOn = StartUp.bWiiLeds;
|
||||
bool SpeakersOn = StartUp.bWiiSpeakers;
|
||||
|
||||
const u8* data = (const u8*)_pData;
|
||||
|
||||
// Get the last four bits with LED info
|
||||
if (LedsOn)
|
||||
{
|
||||
if (data[1] == 0x11)
|
||||
{
|
||||
int led_bits = (data[2] >> 4);
|
||||
Host_UpdateLeds(led_bits);
|
||||
}
|
||||
}
|
||||
|
||||
int speaker_bits = 0;
|
||||
|
||||
if (SpeakersOn)
|
||||
{
|
||||
u8 Bits = 0;
|
||||
switch (data[1])
|
||||
{
|
||||
case 0x14: // Enable and disable speakers
|
||||
if (data[2] == 0x02) // Off
|
||||
Bits = 0;
|
||||
else if (data[2] == 0x06) // On
|
||||
Bits = 1;
|
||||
Host_UpdateSpeakerStatus(0, Bits);
|
||||
break;
|
||||
|
||||
case 0x19: // Mute and unmute
|
||||
// Get the value
|
||||
if (data[2] == 0x02) // Unmute
|
||||
Bits = 1;
|
||||
else if (data[2] == 0x06) // Mute
|
||||
Bits = 0;
|
||||
Host_UpdateSpeakerStatus(1, Bits);
|
||||
break;
|
||||
// Write to speaker registry, or write sound
|
||||
case 0x16:
|
||||
case 0x18:
|
||||
// Turn on the activity light
|
||||
Host_UpdateSpeakerStatus(2, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Turn off the activity icon again
|
||||
void CWII_IPC_HLE_WiiMote::UpdateStatus()
|
||||
{
|
||||
// Check if it's enabled
|
||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiSpeakers)
|
||||
return;
|
||||
Host_UpdateStatus();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -335,13 +270,10 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size)
|
||||
|
||||
case HID_CONTROL_CHANNEL:
|
||||
mote->Wiimote_ControlChannel(m_ConnectionHandle & 0xFF, pHeader->CID, pData, DataSize);
|
||||
// Call Wiimote Plugin
|
||||
break;
|
||||
|
||||
case HID_INTERRUPT_CHANNEL:
|
||||
ShowStatus(pData);
|
||||
mote->Wiimote_InterruptChannel(m_ConnectionHandle & 0xFF, pHeader->CID, pData, DataSize);
|
||||
// Call Wiimote Plugin
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -130,66 +130,33 @@ struct SL2CAP_CommandDisconnectionResponse // 0x07
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
class CBigEndianBuffer
|
||||
{
|
||||
public:
|
||||
CBigEndianBuffer(u8* pBuffer)
|
||||
: m_pBuffer(pBuffer)
|
||||
{
|
||||
}
|
||||
CBigEndianBuffer(u8* pBuffer) : m_pBuffer(pBuffer) {}
|
||||
|
||||
u8 Read8(u32 offset)
|
||||
{
|
||||
return m_pBuffer[offset];
|
||||
}
|
||||
u8 Read8(u32 offset) { return m_pBuffer[offset]; }
|
||||
u16 Read16(u32 offset) { return Common::swap16(*(u16*)&m_pBuffer[offset]); }
|
||||
u32 Read32(u32 offset) { return Common::swap32(*(u32*)&m_pBuffer[offset]); }
|
||||
|
||||
u16 Read16(u32 offset)
|
||||
{
|
||||
return Common::swap16(*(u16*)&m_pBuffer[offset]);
|
||||
}
|
||||
void Write8(u32 offset, u8 data) { m_pBuffer[offset] = data; }
|
||||
void Write16(u32 offset, u16 data) { *(u16*)&m_pBuffer[offset] = Common::swap16(data); }
|
||||
void Write32(u32 offset, u32 data) { *(u32*)&m_pBuffer[offset] = Common::swap32(data); }
|
||||
|
||||
u32 Read32(u32 offset)
|
||||
{
|
||||
return Common::swap32(*(u32*)&m_pBuffer[offset]);
|
||||
}
|
||||
|
||||
void Write8(u32 offset, u8 data)
|
||||
{
|
||||
m_pBuffer[offset] = data;
|
||||
}
|
||||
|
||||
void Write16(u32 offset, u16 data)
|
||||
{
|
||||
*(u16*)&m_pBuffer[offset] = Common::swap16(data);
|
||||
}
|
||||
|
||||
void Write32(u32 offset, u32 data)
|
||||
{
|
||||
*(u32*)&m_pBuffer[offset] = Common::swap32(data);
|
||||
}
|
||||
|
||||
u8* GetPointer(u32 offset)
|
||||
{
|
||||
return &m_pBuffer[offset];
|
||||
}
|
||||
u8* GetPointer(u32 offset) { return &m_pBuffer[offset]; }
|
||||
|
||||
private:
|
||||
|
||||
u8* m_pBuffer;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class CWII_IPC_HLE_WiiMote
|
||||
{
|
||||
public:
|
||||
|
||||
CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* _pHost, int _Number, bool ready = false);
|
||||
|
||||
virtual ~CWII_IPC_HLE_WiiMote()
|
||||
{}
|
||||
virtual ~CWII_IPC_HLE_WiiMote() {}
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
@@ -200,8 +167,6 @@ public:
|
||||
bool LinkChannel();
|
||||
void ResetChannels();
|
||||
void Activate(bool ready);
|
||||
void ShowStatus(const void* _pData); // Show status
|
||||
void UpdateStatus(); // Update status
|
||||
void ExecuteL2capCmd(u8* _pData, u32 _Size); // From CPU
|
||||
void ReceiveL2capData(u16 scid, const void* _pData, u32 _Size); // From wiimote
|
||||
|
||||
@@ -220,7 +185,6 @@ public:
|
||||
const u8* GetLinkKey() const { return m_LinkKey; }
|
||||
|
||||
private:
|
||||
|
||||
// -1: inactive, 0: ready, 1: connecting 2: linking 3: connected & linked
|
||||
int m_Connected;
|
||||
|
||||
@@ -277,9 +241,7 @@ private:
|
||||
void ReceiveConfigurationResponse(u8 _Ident, u8* _pData, u32 _Size);
|
||||
|
||||
// some new ugly stuff
|
||||
//
|
||||
// should be inside the plugin
|
||||
//
|
||||
void HandleSDP(u16 _SCID, u8* _pData, u32 _Size);
|
||||
void SDPSendServiceSearchResponse(u16 _SCID, u16 _TransactionID, u8* _pServiceSearchPattern, u16 _MaximumServiceRecordCount);
|
||||
|
||||
|
||||
@@ -477,9 +477,13 @@ void divwx(UGeckoInstruction _inst)
|
||||
s32 b = m_GPR[_inst.RB];
|
||||
if (b == 0 || ((u32)a == 0x80000000 && b == -1))
|
||||
{
|
||||
if (_inst.OE)
|
||||
if (_inst.OE)
|
||||
// should set OV
|
||||
PanicAlert("OE: divwx");
|
||||
//else PanicAlert("Div by zero", "divwux");
|
||||
if (((u32)a & 0x80000000) && b == 0)
|
||||
m_GPR[_inst.RD] = -1;
|
||||
else
|
||||
m_GPR[_inst.RD] = 0;
|
||||
}
|
||||
else
|
||||
m_GPR[_inst.RD] = (u32)(a / b);
|
||||
@@ -493,17 +497,17 @@ void divwux(UGeckoInstruction _inst)
|
||||
u32 a = m_GPR[_inst.RA];
|
||||
u32 b = m_GPR[_inst.RB];
|
||||
|
||||
if (b == 0) // || (a == 0x80000000 && b == 0xFFFFFFFF))
|
||||
if (b == 0)
|
||||
{
|
||||
if (_inst.OE)
|
||||
if (_inst.OE)
|
||||
// should set OV
|
||||
PanicAlert("OE: divwux");
|
||||
//else PanicAlert("Div by zero", "divwux");
|
||||
m_GPR[_inst.RD] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_GPR[_inst.RD] = a / b;
|
||||
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
|
||||
}
|
||||
|
||||
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
|
||||
}
|
||||
|
||||
void mulhwx(UGeckoInstruction _inst)
|
||||
@@ -572,7 +576,7 @@ void subfex(UGeckoInstruction _inst)
|
||||
m_GPR[_inst.RD] = (~a) + b + carry;
|
||||
SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry));
|
||||
|
||||
if (_inst.OE) PanicAlert("OE: subfcx");
|
||||
if (_inst.OE) PanicAlert("OE: subfex");
|
||||
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
|
||||
}
|
||||
|
||||
|
||||
@@ -388,34 +388,77 @@ void Jit64::subfic(UGeckoInstruction inst)
|
||||
void Jit64::subfcx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START;
|
||||
Default(inst);
|
||||
return;
|
||||
/*
|
||||
u32 a = m_GPR[_inst.RA];
|
||||
u32 b = m_GPR[_inst.RB];
|
||||
m_GPR[_inst.RD] = b - a;
|
||||
SetCarry(a == 0 || Helper_Carry(b, 0-a));
|
||||
JITDISABLE(Integer)
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
gpr.Lock(a, b, d);
|
||||
if(d != a && d != b)
|
||||
gpr.LoadToX64(d, false, true);
|
||||
else
|
||||
gpr.LoadToX64(d, true, true);
|
||||
|
||||
if (_inst.OE) PanicAlert("OE: subfcx");
|
||||
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
|
||||
*/
|
||||
// For some reason, I could not get the jit versions of sub*
|
||||
// working with x86 sub...so we use the ~a + b + 1 method
|
||||
JitClearCA();
|
||||
MOV(32, R(EAX), gpr.R(a));
|
||||
NOT(32, R(EAX));
|
||||
ADD(32, R(EAX), gpr.R(b));
|
||||
FixupBranch carry1 = J_CC(CC_NC);
|
||||
JitSetCA();
|
||||
SetJumpTarget(carry1);
|
||||
ADD(32, R(EAX), Imm32(1));
|
||||
FixupBranch carry2 = J_CC(CC_NC);
|
||||
JitSetCA();
|
||||
SetJumpTarget(carry2);
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
|
||||
gpr.UnlockAll();
|
||||
if (inst.OE) PanicAlert("OE: subfcx");
|
||||
if (inst.Rc) {
|
||||
CALL((u8*)asm_routines.computeRc);
|
||||
}
|
||||
}
|
||||
|
||||
void Jit64::subfex(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START;
|
||||
Default(inst);
|
||||
return;
|
||||
/*
|
||||
u32 a = m_GPR[_inst.RA];
|
||||
u32 b = m_GPR[_inst.RB];
|
||||
int carry = GetCarry();
|
||||
m_GPR[_inst.RD] = (~a) + b + carry;
|
||||
SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry));
|
||||
JITDISABLE(Integer)
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
gpr.FlushLockX(ECX);
|
||||
gpr.Lock(a, b, d);
|
||||
if(d != a && d != b)
|
||||
gpr.LoadToX64(d, false, true);
|
||||
else
|
||||
gpr.LoadToX64(d, true, true);
|
||||
|
||||
if (_inst.OE) PanicAlert("OE: subfcx");
|
||||
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
|
||||
*/
|
||||
// Get CA
|
||||
MOV(32, R(ECX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||
SHR(32, R(ECX), Imm8(29));
|
||||
AND(32, R(ECX), Imm32(1));
|
||||
// Don't need it anymore
|
||||
JitClearCA();
|
||||
|
||||
// ~a + b
|
||||
MOV(32, R(EAX), gpr.R(a));
|
||||
NOT(32, R(EAX));
|
||||
ADD(32, R(EAX), gpr.R(b));
|
||||
FixupBranch carry1 = J_CC(CC_NC);
|
||||
JitSetCA();
|
||||
SetJumpTarget(carry1);
|
||||
|
||||
// + CA
|
||||
ADD(32, R(EAX), R(ECX));
|
||||
FixupBranch carry2 = J_CC(CC_NC);
|
||||
JitSetCA();
|
||||
SetJumpTarget(carry2);
|
||||
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
if (inst.OE) PanicAlert("OE: subfex");
|
||||
if (inst.Rc) {
|
||||
CALL((u8*)asm_routines.computeRc);
|
||||
}
|
||||
}
|
||||
|
||||
void Jit64::subfx(UGeckoInstruction inst)
|
||||
@@ -503,10 +546,10 @@ void Jit64::mulhwux(UGeckoInstruction inst)
|
||||
}
|
||||
}
|
||||
|
||||
// skipped some of the special handling in here - if we get crashes, let the interpreter handle this op
|
||||
void Jit64::divwux(UGeckoInstruction inst) {
|
||||
Default(inst); return;
|
||||
|
||||
void Jit64::divwux(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(Integer)
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
gpr.FlushLockX(EDX);
|
||||
gpr.Lock(a, b, d);
|
||||
@@ -518,8 +561,16 @@ void Jit64::divwux(UGeckoInstruction inst) {
|
||||
MOV(32, R(EAX), gpr.R(a));
|
||||
XOR(32, R(EDX), R(EDX));
|
||||
gpr.KillImmediate(b);
|
||||
CMP(32, gpr.R(b), Imm32(0));
|
||||
// doesn't handle if OE is set, but int doesn't either...
|
||||
FixupBranch not_div_by_zero = J_CC(CC_NZ);
|
||||
MOV(32, gpr.R(d), R(EDX));
|
||||
MOV(32, R(EAX), gpr.R(d));
|
||||
FixupBranch end = J();
|
||||
SetJumpTarget(not_div_by_zero);
|
||||
DIV(32, gpr.R(b));
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
SetJumpTarget(end);
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
if (inst.Rc) {
|
||||
@@ -575,6 +626,31 @@ void Jit64::addx(UGeckoInstruction inst)
|
||||
}
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
else if( a == b && b == d && a == d)
|
||||
{
|
||||
gpr.Lock(d);
|
||||
gpr.LoadToX64(d, true);
|
||||
ADD(32, gpr.R(d), gpr.R(d));
|
||||
if (inst.Rc)
|
||||
{
|
||||
MOV(32, R(EAX), gpr.R(d));
|
||||
CALL((u8*)asm_routines.computeRc);
|
||||
}
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
else if( a == b && b != d)
|
||||
{
|
||||
gpr.Lock(a, d);
|
||||
gpr.LoadToX64(d, false);
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
ADD(32, gpr.R(d), gpr.R(d));
|
||||
if (inst.Rc)
|
||||
{
|
||||
MOV(32, R(EAX), gpr.R(d));
|
||||
CALL((u8*)asm_routines.computeRc);
|
||||
}
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
Default(inst); return;
|
||||
|
||||
@@ -317,7 +317,9 @@ void Jit64::stX(UGeckoInstruction inst)
|
||||
case 38: accessSize = 8; break; //stb
|
||||
default: _assert_msg_(DYNA_REC, 0, "AWETKLJASDLKF"); return;
|
||||
}
|
||||
|
||||
|
||||
#ifndef __APPLE__ && _M_X64
|
||||
//(Sonicadvance1) This code path fails in OSX, not 100% sure why
|
||||
if (gpr.R(a).IsImm())
|
||||
{
|
||||
// If we already know the address through constant folding, we can do some
|
||||
@@ -353,6 +355,7 @@ void Jit64::stX(UGeckoInstruction inst)
|
||||
}
|
||||
// Other IO not worth the trouble.
|
||||
}
|
||||
#endif
|
||||
|
||||
// Optimized stack access?
|
||||
if (accessSize == 32 && !gpr.R(a).IsImm() && a == 1 && js.st.isFirstBlockOfFunction && jo.optimizeStack)
|
||||
|
||||
@@ -37,6 +37,60 @@ using namespace Gen;
|
||||
|
||||
static int temp32;
|
||||
|
||||
#ifdef __APPLE__ && _M_X64
|
||||
void CommonAsmRoutines::GenFifoWrite(int size)
|
||||
{
|
||||
// Assume value in ABI_PARAM1
|
||||
PUSH(RSI);
|
||||
if (size != 32)
|
||||
PUSH(EDX);
|
||||
BSWAP(size, ABI_PARAM1);
|
||||
MOV(32, R(EAX), Imm32((u64)GPFifo::m_gatherPipe));
|
||||
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
|
||||
if (size != 32) {
|
||||
MOV(32, R(EDX), R(ABI_PARAM1));
|
||||
MOV(size, MComplex(RAX, RSI, 1, 0), R(EDX));
|
||||
} else {
|
||||
MOV(size, MComplex(RAX, RSI, 1, 0), R(ABI_PARAM1));
|
||||
}
|
||||
ADD(64, R(RSI), Imm8(size >> 3));
|
||||
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
|
||||
if (size != 32)
|
||||
POP(EDX);
|
||||
POP(RSI);
|
||||
RET();
|
||||
}
|
||||
void CommonAsmRoutines::GenFifoFloatWrite()
|
||||
{
|
||||
// Assume value in XMM0
|
||||
PUSH(RSI);
|
||||
PUSH(EDX);
|
||||
MOVSS(M(&temp32), XMM0);
|
||||
MOV(32, R(EDX), M(&temp32));
|
||||
BSWAP(32, EDX);
|
||||
MOV(64, R(RAX), Imm64((u64)GPFifo::m_gatherPipe));
|
||||
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
|
||||
MOV(32, MComplex(RAX, RSI, 1, 0), R(EDX));
|
||||
ADD(64, R(RSI), Imm8(4));
|
||||
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
|
||||
POP(EDX);
|
||||
POP(RSI);
|
||||
RET();
|
||||
}
|
||||
|
||||
void CommonAsmRoutines::GenFifoXmm64Write()
|
||||
{
|
||||
// Assume value in XMM0. Assume pre-byteswapped (unlike the others here!)
|
||||
PUSH(RSI);
|
||||
MOV(64, R(RAX), Imm32((u64)GPFifo::m_gatherPipe));
|
||||
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
|
||||
MOVQ_xmm(MComplex(RAX, RSI, 1, 0), XMM0);
|
||||
ADD(64, R(RSI), Imm8(8));
|
||||
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
|
||||
POP(RSI);
|
||||
RET();
|
||||
}
|
||||
#else
|
||||
void CommonAsmRoutines::GenFifoWrite(int size)
|
||||
{
|
||||
// Assume value in ABI_PARAM1
|
||||
@@ -59,7 +113,6 @@ void CommonAsmRoutines::GenFifoWrite(int size)
|
||||
POP(ESI);
|
||||
RET();
|
||||
}
|
||||
|
||||
void CommonAsmRoutines::GenFifoFloatWrite()
|
||||
{
|
||||
// Assume value in XMM0
|
||||
@@ -77,7 +130,6 @@ void CommonAsmRoutines::GenFifoFloatWrite()
|
||||
POP(ESI);
|
||||
RET();
|
||||
}
|
||||
|
||||
void CommonAsmRoutines::GenFifoXmm64Write()
|
||||
{
|
||||
// Assume value in XMM0. Assume pre-byteswapped (unlike the others here!)
|
||||
@@ -86,10 +138,11 @@ void CommonAsmRoutines::GenFifoXmm64Write()
|
||||
MOV(32, R(ESI), M(&GPFifo::m_gatherPipeCount));
|
||||
MOVQ_xmm(MComplex(RAX, RSI, 1, 0), XMM0);
|
||||
ADD(32, R(ESI), Imm8(8));
|
||||
MOV(32, M(&GPFifo::m_gatherPipeCount), R(ESI));
|
||||
POP(ESI);
|
||||
RET();
|
||||
MOV(32, M(&GPFifo::m_gatherPipeCount), R(ESI));
|
||||
POP(ESI);
|
||||
RET();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Safe + Fast Quantizers, originally from JITIL by magumagu
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ libs = [
|
||||
'bdisasm',
|
||||
'inputcommon',
|
||||
'lua',
|
||||
'sfml'
|
||||
'sfml-network'
|
||||
]
|
||||
|
||||
env_core = env.Clone();
|
||||
|
||||
@@ -31,7 +31,11 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(SHARED_LZO) && SHARED_LZO
|
||||
#include <lzo/lzo1x.h>
|
||||
#else
|
||||
#include "minilzo.h"
|
||||
#endif
|
||||
|
||||
// TODO: Move to namespace
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ DriveReader::DriveReader(const char *drive)
|
||||
0, &dwNotUsed, NULL);
|
||||
#endif
|
||||
#else
|
||||
SectorReader::SetSectorSize(2048);
|
||||
file_ = fopen(drive, "rb");
|
||||
if (file_)
|
||||
{
|
||||
@@ -83,7 +84,8 @@ DriveReader::~DriveReader()
|
||||
hDisc = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#else
|
||||
fclose(file_);
|
||||
if (file_)
|
||||
fclose(file_);
|
||||
file_ = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Version="9.00"
|
||||
Name="Dolphin"
|
||||
ProjectGUID="{A72606EF-C5C1-4954-90AD-F0F93A8D97D9}"
|
||||
RootNamespace="DolphinWX"
|
||||
@@ -31,7 +31,7 @@
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""$(ProjectDir)..\Common\SubWCRev.exe" "$(SolutionDir)\." "$(ProjectDir)..\Common\src\svnrev_template.h" "$(ProjectDir)..\Common\src\svnrev.h""
|
||||
ExcludedFromBuild="false"
|
||||
ExcludedFromBuild="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
@@ -147,7 +147,7 @@
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""$(ProjectDir)..\Common\SubWCRev.exe" "$(SolutionDir)\." "$(ProjectDir)..\Common\src\svnrev_template.h" "$(ProjectDir)..\Common\src\svnrev.h""
|
||||
ExcludedFromBuild="false"
|
||||
ExcludedFromBuild="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
@@ -263,7 +263,7 @@
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""$(ProjectDir)..\Common\SubWCRev.exe" "$(SolutionDir)\." "$(ProjectDir)..\Common\src\svnrev_template.h" "$(ProjectDir)..\Common\src\svnrev.h""
|
||||
ExcludedFromBuild="false"
|
||||
ExcludedFromBuild="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
@@ -374,7 +374,7 @@
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""$(ProjectDir)..\Common\SubWCRev.exe" "$(SolutionDir)\." "$(ProjectDir)..\Common\src\svnrev_template.h" "$(ProjectDir)..\Common\src\svnrev.h""
|
||||
ExcludedFromBuild="false"
|
||||
ExcludedFromBuild="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
@@ -485,7 +485,7 @@
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""$(ProjectDir)..\Common\SubWCRev.exe" "$(SolutionDir)\." "$(ProjectDir)..\Common\src\svnrev_template.h" "$(ProjectDir)..\Common\src\svnrev.h""
|
||||
ExcludedFromBuild="false"
|
||||
ExcludedFromBuild="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
@@ -600,7 +600,7 @@
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""$(ProjectDir)..\Common\SubWCRev.exe" "$(SolutionDir)\." "$(ProjectDir)..\Common\src\svnrev_template.h" "$(ProjectDir)..\Common\src\svnrev.h""
|
||||
ExcludedFromBuild="false"
|
||||
ExcludedFromBuild="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
@@ -855,10 +855,6 @@
|
||||
RelativePath=".\Src\FrameTools.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\FrameWiimote.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\GameListCtrl.cpp"
|
||||
>
|
||||
|
||||
@@ -46,7 +46,7 @@ void AboutDolphin::CreateGUIControls()
|
||||
DolphinLogo = new wxBitmap(iDolphinLogo);
|
||||
sbDolphinLogo = new wxStaticBitmap(this, ID_LOGO, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
|
||||
sbDolphinLogo->SetBitmap(*DolphinLogo);
|
||||
std::string Text = std::string("Dolphin SVN revision ") + SVN_REV_STR +"\n" "Copyright (c) 2003-2010+ Dolphin Team\n"
|
||||
std::string Text = std::string("Dolphin ") + SVN_REV_STR +"\n" "Copyright (c) 2003-2010+ Dolphin Team\n"
|
||||
"Dolphin is a Gamecube/Wii emulator, which was originally written by F|RES and ector.\n"
|
||||
"Today Dolphin is an open source project with many contributors, too many to list.\n"
|
||||
"If interested, just go check out the project page at http://code.google.com/p/dolphin-emu.\n\n"
|
||||
|
||||
@@ -120,7 +120,7 @@ bool BootCore(const std::string& _rFilename)
|
||||
if (unique_id.size() == 6 && game_ini.Load(StartUp.m_strGameIni.c_str()))
|
||||
{
|
||||
// General settings
|
||||
game_ini.Get("Core", "CPUOnThread", &StartUp.bCPUThread, StartUp.bCPUThread);
|
||||
game_ini.Get("Core", "CPUThread", &StartUp.bCPUThread, StartUp.bCPUThread);
|
||||
game_ini.Get("Core", "SkipIdle", &StartUp.bSkipIdle, StartUp.bSkipIdle);
|
||||
game_ini.Get("Core", "EnableFPRF", &StartUp.bEnableFPRF, StartUp.bEnableFPRF);
|
||||
game_ini.Get("Core", "TLBHack", &StartUp.iTLBHack, StartUp.iTLBHack);
|
||||
@@ -139,9 +139,6 @@ bool BootCore(const std::string& _rFilename)
|
||||
{
|
||||
// Save the window handle of the eventual parent to the rendering window
|
||||
StartUp.hMainWindow = main_frame->GetRenderHandle();
|
||||
|
||||
// Now that we know if we have a Wii game we can run this
|
||||
main_frame->ModifyStatusBar();
|
||||
}
|
||||
#endif
|
||||
// Init the core
|
||||
|
||||
@@ -56,8 +56,6 @@ EVT_CHECKBOX(ID_INTERFACE_HIDECURSOR, CConfigMain::CoreSettingsChanged)
|
||||
EVT_CHECKBOX(ID_INTERFACE_AUTOHIDECURSOR, CConfigMain::CoreSettingsChanged)
|
||||
#endif
|
||||
EVT_RADIOBOX(ID_INTERFACE_THEME, CConfigMain::CoreSettingsChanged)
|
||||
EVT_CHECKBOX(ID_INTERFACE_WIIMOTE_LEDS, CConfigMain::CoreSettingsChanged)
|
||||
EVT_CHECKBOX(ID_INTERFACE_WIIMOTE_SPEAKERS, CConfigMain::CoreSettingsChanged)
|
||||
EVT_CHOICE(ID_INTERFACE_LANG, CConfigMain::CoreSettingsChanged)
|
||||
|
||||
EVT_CHECKBOX(ID_ALWAYS_HLE_BS2, CConfigMain::CoreSettingsChanged)
|
||||
@@ -229,8 +227,6 @@ void CConfigMain::InitializeGUIValues()
|
||||
AutoHideCursor->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bAutoHideCursor);
|
||||
HideCursor->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor);
|
||||
#endif
|
||||
WiimoteStatusLEDs->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiLeds);
|
||||
WiimoteStatusSpeakers->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiSpeakers);
|
||||
Theme->SetSelection(SConfig::GetInstance().m_LocalCoreStartupParameter.iTheme);
|
||||
// need redesign
|
||||
InterfaceLang->SetSelection(SConfig::GetInstance().m_InterfaceLanguage);
|
||||
@@ -289,8 +285,6 @@ void CConfigMain::InitializeGUITooltips()
|
||||
HideCursor->SetToolTip(wxT("This will always hide the cursor when it's over the rendering window.")
|
||||
wxT("\nIt can be convenient in a Wii game that already has a cursor."));
|
||||
#endif
|
||||
WiimoteStatusLEDs->SetToolTip(wxT("Show which wiimotes are connected in the statusbar."));
|
||||
WiimoteStatusSpeakers->SetToolTip(wxT("Show wiimote speaker status in the statusbar."));
|
||||
InterfaceLang->SetToolTip(wxT("For the time being this will only change the text shown in")
|
||||
wxT("\nthe game list of PAL GC games."));
|
||||
// Themes: Copyright notice
|
||||
@@ -352,11 +346,6 @@ void CConfigMain::CreateGUIControls()
|
||||
AutoHideCursor = new wxCheckBox(GeneralPage, ID_INTERFACE_AUTOHIDECURSOR, wxT("Auto"));
|
||||
HideCursor = new wxCheckBox(GeneralPage, ID_INTERFACE_HIDECURSOR, wxT("Always"));
|
||||
#endif
|
||||
// Wiimote status in statusbar
|
||||
wxStaticText *WiimoteStatusText = new wxStaticText(GeneralPage, ID_INTERFACE_WIIMOTE_TEXT, wxT("Show wiimote status:"), wxDefaultPosition, wxDefaultSize);
|
||||
WiimoteStatusLEDs = new wxCheckBox(GeneralPage, ID_INTERFACE_WIIMOTE_LEDS, wxT("LEDs"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
WiimoteStatusSpeakers = new wxCheckBox(GeneralPage, ID_INTERFACE_WIIMOTE_SPEAKERS, wxT("Speakers"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
|
||||
// Interface Language
|
||||
// At the moment this only changes the language displayed in m_gamelistctrl
|
||||
// If someone wants to control the whole GUI's language, it should be set here too
|
||||
@@ -396,11 +385,6 @@ void CConfigMain::CreateGUIControls()
|
||||
sHideCursor->Add(HideCursor, 0, wxLEFT, 5);
|
||||
sbInterface->Add(sHideCursor, 0, wxALL, 5);
|
||||
#endif
|
||||
wxBoxSizer *sWiimoteStatus = new wxBoxSizer(wxHORIZONTAL);
|
||||
sWiimoteStatus->Add(WiimoteStatusText);
|
||||
sWiimoteStatus->Add(WiimoteStatusLEDs, 0, wxLEFT, 5);
|
||||
sWiimoteStatus->Add(WiimoteStatusSpeakers, 0, wxLEFT, 5);
|
||||
sbInterface->Add(sWiimoteStatus, 0, wxALL, 5);
|
||||
sbInterface->Add(Theme, 0, wxEXPAND | wxALL, 5);
|
||||
wxBoxSizer *sInterfaceLanguage = new wxBoxSizer(wxHORIZONTAL);
|
||||
sInterfaceLanguage->Add(InterfaceLangText, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
@@ -430,7 +414,11 @@ void CConfigMain::CreateGUIControls()
|
||||
GCEXIDeviceText[1] = new wxStaticText(GamecubePage, ID_GC_EXIDEVICE_SLOTB_TEXT, wxT("Slot B"), wxDefaultPosition, wxDefaultSize);
|
||||
GCEXIDeviceText[2] = new wxStaticText(GamecubePage, ID_GC_EXIDEVICE_SP1_TEXT, wxT("SP1 "), wxDefaultPosition, wxDefaultSize);
|
||||
GCEXIDeviceText[2]->SetToolTip(wxT("Serial Port 1 - This is the port which devices such as the net adapter use"));
|
||||
const wxString SlotDevices[] = {wxT(DEV_NONE_STR),wxT(DEV_DUMMY_STR),wxT(EXIDEV_MEMCARD_STR), wxT(EXIDEV_MIC_STR)};
|
||||
const wxString SlotDevices[] = {wxT(DEV_NONE_STR),wxT(DEV_DUMMY_STR),wxT(EXIDEV_MEMCARD_STR)
|
||||
#if HAVE_PORTAUDIO
|
||||
, wxT(EXIDEV_MIC_STR)
|
||||
#endif
|
||||
};
|
||||
static const int numSlotDevices = sizeof(SlotDevices)/sizeof(wxString);
|
||||
const wxString SP1Devices[] = {wxT(DEV_NONE_STR),wxT(DEV_DUMMY_STR),wxT(EXIDEV_BBA_STR),wxT(EXIDEV_AM_BB_STR)};
|
||||
static const int numSP1Devices = sizeof(SP1Devices)/sizeof(wxString);
|
||||
@@ -475,9 +463,11 @@ void CConfigMain::CreateGUIControls()
|
||||
GCSIDeviceText[1] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 2"), wxDefaultPosition, wxDefaultSize);
|
||||
GCSIDeviceText[2] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 3"), wxDefaultPosition, wxDefaultSize);
|
||||
GCSIDeviceText[3] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 4"), wxDefaultPosition, wxDefaultSize);
|
||||
const wxString SIDevices[] = {wxT(DEV_NONE_STR),wxT(SIDEV_STDCONT_STR),wxT(SIDEV_GBA_STR),wxT(SIDEV_AM_BB_STR)};
|
||||
const wxString SIPort1Devices[] = {wxT(DEV_NONE_STR),wxT(SIDEV_STDCONT_STR),wxT(SIDEV_GBA_STR),wxT(SIDEV_AM_BB_STR)};
|
||||
static const int numSIPort1Devices = sizeof(SIPort1Devices)/sizeof(wxString);
|
||||
const wxString SIDevices[] = {wxT(DEV_NONE_STR),wxT(SIDEV_STDCONT_STR),wxT(SIDEV_GBA_STR)};
|
||||
static const int numSIDevices = sizeof(SIDevices)/sizeof(wxString);
|
||||
GCSIDevice[0] = new wxChoice(GamecubePage, ID_GC_SIDEVICE0, wxDefaultPosition, wxDefaultSize, numSIDevices, SIDevices, 0, wxDefaultValidator);
|
||||
GCSIDevice[0] = new wxChoice(GamecubePage, ID_GC_SIDEVICE0, wxDefaultPosition, wxDefaultSize, numSIPort1Devices, SIPort1Devices, 0, wxDefaultValidator);
|
||||
GCSIDevice[1] = new wxChoice(GamecubePage, ID_GC_SIDEVICE1, wxDefaultPosition, wxDefaultSize, numSIDevices, SIDevices, 0, wxDefaultValidator);
|
||||
GCSIDevice[2] = new wxChoice(GamecubePage, ID_GC_SIDEVICE2, wxDefaultPosition, wxDefaultSize, numSIDevices, SIDevices, 0, wxDefaultValidator);
|
||||
GCSIDevice[3] = new wxChoice(GamecubePage, ID_GC_SIDEVICE3, wxDefaultPosition, wxDefaultSize, numSIDevices, SIDevices, 0, wxDefaultValidator);
|
||||
@@ -725,12 +715,6 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event)
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.iTheme = Theme->GetSelection();
|
||||
main_frame->InitBitmaps();
|
||||
break;
|
||||
case ID_INTERFACE_WIIMOTE_LEDS:
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiLeds = WiimoteStatusLEDs->IsChecked();
|
||||
break;
|
||||
case ID_INTERFACE_WIIMOTE_SPEAKERS:
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiSpeakers = WiimoteStatusSpeakers->IsChecked();
|
||||
break;
|
||||
case ID_INTERFACE_LANG:
|
||||
SConfig::GetInstance().m_InterfaceLanguage = (INTERFACE_LANGUAGE)InterfaceLang->GetSelection();
|
||||
bRefreshList = true;
|
||||
|
||||
@@ -52,7 +52,6 @@ private:
|
||||
#if wxUSE_TIMER && defined _WIN32
|
||||
wxCheckBox* HideCursor, *AutoHideCursor;
|
||||
#endif
|
||||
wxCheckBox* WiimoteStatusLEDs, * WiimoteStatusSpeakers;
|
||||
wxChoice* InterfaceLang;
|
||||
wxChoice* Framelimit;
|
||||
wxRadioBox* Theme;
|
||||
@@ -175,7 +174,6 @@ private:
|
||||
#if wxUSE_TIMER && defined _WIN32
|
||||
ID_INTERFACE_HIDECURSOR_TEXT, ID_INTERFACE_HIDECURSOR, ID_INTERFACE_AUTOHIDECURSOR,
|
||||
#endif
|
||||
ID_INTERFACE_WIIMOTE_TEXT, ID_INTERFACE_WIIMOTE_LEDS, ID_INTERFACE_WIIMOTE_SPEAKERS,
|
||||
ID_INTERFACE_LANG_TEXT, ID_INTERFACE_LANG,
|
||||
ID_INTERFACE_THEME,
|
||||
ID_FRAMELIMIT_TEXT, ID_FRAMELIMIT,
|
||||
|
||||
@@ -173,7 +173,7 @@ CPanel::CPanel(
|
||||
main_frame->bNoWiimoteMsg = false;
|
||||
else
|
||||
{
|
||||
// The Wiimote has been disconnect, we offer reconnect here
|
||||
// The Wiimote has been disconnected, we offer reconnect here
|
||||
wxMessageDialog *dlg = new wxMessageDialog(
|
||||
this,
|
||||
wxString::Format(wxT("Wiimote %i has been disconnected by system.\n")
|
||||
@@ -321,7 +321,6 @@ CFrame::CFrame(wxFrame* parent,
|
||||
, g_pCodeWindow(NULL)
|
||||
, m_MenuBar(NULL)
|
||||
, bRenderToMain(false), bNoWiimoteMsg(false)
|
||||
, HaveLeds(false), HaveSpeakers(false)
|
||||
, m_ToolBar(NULL), m_ToolBarDebug(NULL), m_ToolBarAui(NULL)
|
||||
, bFloatLogWindow(false), bFloatConsoleWindow(false)
|
||||
, m_pStatusBar(NULL), m_GameListCtrl(NULL), m_Panel(NULL)
|
||||
@@ -523,10 +522,54 @@ void CFrame::OnQuit(wxCommandEvent& WXUNUSED (event))
|
||||
Close(true);
|
||||
}
|
||||
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
void CFrame::X11_SendClientEvent(const char *message)
|
||||
{
|
||||
XEvent event;
|
||||
Display *dpy = (Display *)Core::GetWindowHandle();
|
||||
Window win = *(Window *)Core::GetXWindow();
|
||||
|
||||
// Init X event structure for client message
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.data.l[0] = XInternAtom(dpy, message, False);
|
||||
|
||||
// Send the event
|
||||
if (!XSendEvent(dpy, win, False, False, &event))
|
||||
ERROR_LOG(VIDEO, "Failed to send message %s to the emulator window.\n", message);
|
||||
}
|
||||
|
||||
void X11_SendKeyEvent(int key)
|
||||
{
|
||||
XEvent event;
|
||||
Display *dpy = (Display *)Core::GetWindowHandle();
|
||||
Window win = *(Window *)Core::GetXWindow();
|
||||
|
||||
// Init X event structure for key press event
|
||||
event.xkey.type = KeyPress;
|
||||
// WARNING: This works for '3' to '7'. If in the future other keys are needed
|
||||
// convert with InputCommon::wxCharCodeWXToX from X11InputBase.cpp.
|
||||
event.xkey.keycode = XKeysymToKeycode(dpy, key);
|
||||
|
||||
// Send the event
|
||||
if (!XSendEvent(dpy, win, False, False, &event))
|
||||
ERROR_LOG(VIDEO, "Failed to send key press event to the emulator window.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// --------
|
||||
// Events
|
||||
void CFrame::OnActive(wxActivateEvent& event)
|
||||
{
|
||||
#if defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE)
|
||||
{
|
||||
if (event.GetActive())
|
||||
X11_SendClientEvent("FOCUSIN");
|
||||
else
|
||||
X11_SendClientEvent("FOCUSOUT");
|
||||
}
|
||||
#endif
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -582,18 +625,21 @@ void CFrame::OnMove(wxMoveEvent& event)
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.iPosX = GetPosition().x;
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.iPosY = GetPosition().y;
|
||||
}
|
||||
|
||||
void CFrame::OnResize(wxSizeEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.iWidth = GetSize().GetWidth();
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.iHeight = GetSize().GetHeight();
|
||||
|
||||
DoMoveIcons(); // In FrameWiimote.cpp
|
||||
}
|
||||
void CFrame::OnResizeAll(wxSizeEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
#if defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE)
|
||||
X11_SendClientEvent("RESIZE");
|
||||
#endif
|
||||
//wxWindow * Win = (wxWindow*)event.GetEventObject();
|
||||
//NOTICE_LOG(CONSOLE, "OnResizeAll: %i", (HWND)Win->GetHWND());
|
||||
}
|
||||
@@ -649,11 +695,17 @@ void CFrame::OnHostMessage(wxCommandEvent& event)
|
||||
}
|
||||
break;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
case WM_USER_CREATE:
|
||||
bRenderToMain = true;
|
||||
break;
|
||||
case TOGGLE_FULLSCREEN:
|
||||
DoFullscreen(!IsFullScreen());
|
||||
break;
|
||||
case WM_USER_STOP:
|
||||
main_frame->DoStop();
|
||||
DoStop();
|
||||
break;
|
||||
case WM_USER_PAUSE:
|
||||
main_frame->OnPlay(event);
|
||||
DoPause();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -740,32 +792,36 @@ void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event))
|
||||
|
||||
void CFrame::OnKeyDown(wxKeyEvent& event)
|
||||
{
|
||||
// Toggle fullscreen
|
||||
if (event.GetKeyCode() == WXK_RETURN && event.GetModifiers() == wxMOD_ALT)
|
||||
{
|
||||
DoFullscreen(!IsFullScreen());
|
||||
|
||||
// We do that to avoid the event to be double processed (which would cause the window to be stuck in fullscreen)
|
||||
event.StopPropagation();
|
||||
}
|
||||
else if(event.GetKeyCode() == WXK_ESCAPE)
|
||||
{
|
||||
main_frame->DoPause();
|
||||
}
|
||||
// event.Skip() allows the event to propagate to the gamelist for example
|
||||
else if (! (Core::GetState() == Core::CORE_RUN && bRenderToMain && event.GetEventObject() == this))
|
||||
event.Skip();
|
||||
|
||||
#ifdef _WIN32
|
||||
if(event.GetKeyCode() == 'M', '3', '4', '5', '6', '7') // Send this to the video plugin WndProc
|
||||
{
|
||||
PostMessage((HWND)Core::GetWindowHandle(), WM_USER, WM_USER_KEYDOWN, event.GetKeyCode());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Send the keyboard status to the Input plugin
|
||||
if(Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||
CPluginManager::GetInstance().GetPad(0)->PAD_Input(event.GetKeyCode(), 1); // 1 = Down
|
||||
{
|
||||
// Toggle fullscreen
|
||||
if (event.GetKeyCode() == WXK_RETURN && event.GetModifiers() == wxMOD_ALT)
|
||||
{
|
||||
DoFullscreen(!IsFullScreen());
|
||||
|
||||
// We do that to avoid the event to be double processed (which would cause the window to be stuck in fullscreen)
|
||||
event.StopPropagation();
|
||||
}
|
||||
else if(event.GetKeyCode() == WXK_ESCAPE)
|
||||
{
|
||||
main_frame->DoPause();
|
||||
}
|
||||
// event.Skip() allows the event to propagate to the gamelist for example
|
||||
else if (! (Core::GetState() == Core::CORE_RUN && bRenderToMain && event.GetEventObject() == this))
|
||||
event.Skip();
|
||||
|
||||
if (event.GetKeyCode() >= '3' && event.GetKeyCode() <= '7') // Send this to the video plugin
|
||||
{
|
||||
#ifdef _WIN32
|
||||
PostMessage((HWND)Core::GetWindowHandle(), WM_USER, WM_USER_KEYDOWN, event.GetKeyCode());
|
||||
#elif defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
X11_SendKeyEvent(event.GetKeyCode());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Send the keyboard status to the Input plugin
|
||||
CPluginManager::GetInstance().GetPad(0)->PAD_Input(event.GetKeyCode(), 1); // 1 = Down
|
||||
}
|
||||
}
|
||||
|
||||
void CFrame::OnKeyUp(wxKeyEvent& event)
|
||||
@@ -910,66 +966,48 @@ wxAuiNotebook* CFrame::CreateEmptyNotebook()
|
||||
return NB;
|
||||
}
|
||||
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
void X11_ShowFullScreen(bool bF)
|
||||
{
|
||||
XEvent event;
|
||||
Display *dpy = (Display *)Core::GetWindowHandle();
|
||||
Window win = *(Window *)Core::GetXWindow();
|
||||
|
||||
// Init X event structure for TOGGLE_FULLSCREEN client message
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.data.l[0] = XInternAtom(dpy, "TOGGLE_FULLSCREEN", False);;
|
||||
|
||||
// Send the event
|
||||
if (!XSendEvent(dpy, win, False, False, &event))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Failed to switch fullscreen/windowed mode.\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void CFrame::DoFullscreen(bool bF)
|
||||
{
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
if ((Core::GetState() == Core::CORE_RUN))
|
||||
X11_ShowFullScreen(bF);
|
||||
#endif
|
||||
// Only switch this to fullscreen if we're rendering to main AND if we're running a game
|
||||
// plus if a modal dialog is open, this will still process the keyboard events, and may cause
|
||||
// the main window to become unresponsive, so we have to avoid that.
|
||||
if ((bRenderToMain && Core::GetState() == Core::CORE_RUN))
|
||||
if ((Core::GetState() == Core::CORE_RUN) || (Core::GetState() == Core::CORE_PAUSE))
|
||||
{
|
||||
ShowFullScreen(bF);
|
||||
if (bRenderToMain)
|
||||
{
|
||||
ShowFullScreen(bF);
|
||||
|
||||
if (bF)
|
||||
{
|
||||
// Save the current mode before going to fullscreen
|
||||
AuiCurrent = m_Mgr->SavePerspective();
|
||||
m_Mgr->LoadPerspective(AuiFullscreen, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore saved perspective
|
||||
m_Mgr->LoadPerspective(AuiCurrent, true);
|
||||
}
|
||||
if (bF)
|
||||
{
|
||||
// Save the current mode before going to fullscreen
|
||||
AuiCurrent = m_Mgr->SavePerspective();
|
||||
m_Mgr->LoadPerspective(AuiFullscreen, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore saved perspective
|
||||
m_Mgr->LoadPerspective(AuiCurrent, true);
|
||||
}
|
||||
|
||||
// Show the cursor again, in case it was hidden
|
||||
if (IsFullScreen())
|
||||
{
|
||||
#ifdef _WIN32
|
||||
MSWSetCursor(true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
else // Post the message to the separate rendering window which will then handle it.
|
||||
{
|
||||
BringWindowToTop((HWND)Core::GetWindowHandle());
|
||||
PostMessage((HWND)Core::GetWindowHandle(), WM_USER, TOGGLE_FULLSCREEN, 0);
|
||||
}
|
||||
// Show the cursor again, in case it was hidden
|
||||
if (IsFullScreen())
|
||||
{
|
||||
MSWSetCursor(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef _WIN32
|
||||
else // Post the message to the separate rendering window which will then handle it.
|
||||
{
|
||||
BringWindowToTop((HWND)Core::GetWindowHandle());
|
||||
PostMessage((HWND)Core::GetWindowHandle(), WM_USER, TOGGLE_FULLSCREEN, 0);
|
||||
}
|
||||
#elif defined HAVE_X11 && HAVE_X11
|
||||
else // Send the event to the separate rendering window which will then handle it.
|
||||
X11_SendClientEvent("TOGGLE_FULLSCREEN");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Debugging, show loose windows
|
||||
@@ -1060,4 +1098,4 @@ void CFrame::ListTopWindows()
|
||||
j++;
|
||||
}
|
||||
NOTICE_LOG(CONSOLE, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ class CFrame : public wxFrame
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return(m_Panel->GetHandle());
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
return m_Panel;
|
||||
#else
|
||||
return this;
|
||||
#endif
|
||||
@@ -91,23 +93,6 @@ class CFrame : public wxFrame
|
||||
void OnCustomHostMessage(int Id);
|
||||
void StartGame(const std::string& filename);
|
||||
|
||||
// ---------------------------------------
|
||||
// Wiimote leds
|
||||
// --------------------
|
||||
void ModifyStatusBar();
|
||||
void CreateDestroy(int Case);
|
||||
void CreateLeds(); void CreateSpeakers();
|
||||
void UpdateLeds(); void UpdateSpeakers();
|
||||
wxBitmap CreateBitmapForLeds(bool On);
|
||||
wxBitmap CreateBitmapForSpeakers(int BitmapType, bool On);
|
||||
void DoMoveIcons(); void MoveLeds(); void MoveSpeakers();
|
||||
bool HaveLeds; bool HaveSpeakers;
|
||||
|
||||
wxStaticBitmap *m_StatBmp[7];
|
||||
u8 g_Leds[4]; u8 g_Leds_[4];
|
||||
u8 g_Speakers[3]; u8 g_Speakers_[3];
|
||||
// ---------------
|
||||
|
||||
// AUI
|
||||
wxAuiManager *m_Mgr;
|
||||
wxAuiToolBar *m_ToolBar, *m_ToolBarDebug, *m_ToolBarAui;
|
||||
@@ -233,14 +218,6 @@ class CFrame : public wxFrame
|
||||
THEMES_MAX
|
||||
};
|
||||
|
||||
enum WiimoteBitmaps // Wiimote speaker bitmaps
|
||||
{
|
||||
CREATELEDS,
|
||||
DESTROYLEDS,
|
||||
CREATESPEAKERS,
|
||||
DESTROYSPEAKERS
|
||||
};
|
||||
|
||||
wxBitmap m_Bitmaps[EToolbar_Max];
|
||||
wxBitmap m_BitmapsMenu[EToolbar_Max];
|
||||
|
||||
@@ -326,6 +303,9 @@ class CFrame : public wxFrame
|
||||
|
||||
void OnGameListCtrl_ItemActivated(wxListEvent& event);
|
||||
void DoFullscreen(bool _F);
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
void X11_SendClientEvent(const char *message);
|
||||
#endif
|
||||
|
||||
// MenuBar
|
||||
// File - Drive
|
||||
|
||||
@@ -470,6 +470,7 @@ bool game_loading = false;
|
||||
// 3. Boot last selected game
|
||||
void CFrame::BootGame(const std::string& filename)
|
||||
{
|
||||
bool success = false;
|
||||
SCoreStartupParameter& StartUp = SConfig::GetInstance().m_LocalCoreStartupParameter;
|
||||
|
||||
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||
@@ -479,23 +480,23 @@ void CFrame::BootGame(const std::string& filename)
|
||||
// Start the selected ISO, or try one of the saved paths.
|
||||
// If all that fails, ask to add a dir and don't boot
|
||||
if (!filename.empty())
|
||||
BootManager::BootCore(filename);
|
||||
success = BootManager::BootCore(filename);
|
||||
else if (m_GameListCtrl->GetSelectedISO() != NULL)
|
||||
{
|
||||
if (m_GameListCtrl->GetSelectedISO()->IsValid())
|
||||
BootManager::BootCore(m_GameListCtrl->GetSelectedISO()->GetFileName());
|
||||
success = BootManager::BootCore(m_GameListCtrl->GetSelectedISO()->GetFileName());
|
||||
}
|
||||
else if (!StartUp.m_strDefaultGCM.empty()
|
||||
&& wxFileExists(wxString(StartUp.m_strDefaultGCM.c_str(), wxConvUTF8)))
|
||||
{
|
||||
BootManager::BootCore(StartUp.m_strDefaultGCM);
|
||||
success = BootManager::BootCore(StartUp.m_strDefaultGCM);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!SConfig::GetInstance().m_LastFilename.empty()
|
||||
&& wxFileExists(wxString(SConfig::GetInstance().m_LastFilename.c_str(), wxConvUTF8)))
|
||||
{
|
||||
BootManager::BootCore(SConfig::GetInstance().m_LastFilename);
|
||||
success = BootManager::BootCore(SConfig::GetInstance().m_LastFilename);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -506,6 +507,12 @@ void CFrame::BootGame(const std::string& filename)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
game_loading = false;
|
||||
m_GameListCtrl->Enable();
|
||||
m_GameListCtrl->Show();
|
||||
}
|
||||
}
|
||||
|
||||
// Open file to boot
|
||||
@@ -546,13 +553,7 @@ void CFrame::DoOpen(bool Boot)
|
||||
{
|
||||
if (!fileChosen)
|
||||
return;
|
||||
BootManager::BootCore(std::string(path.mb_str()));
|
||||
// Game has been started, hide the game list
|
||||
if (m_GameListCtrl->IsShown())
|
||||
{
|
||||
m_GameListCtrl->Disable();
|
||||
m_GameListCtrl->Hide();
|
||||
}
|
||||
StartGame(std::string(path.mb_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -629,16 +630,11 @@ void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event))
|
||||
wxThread::Sleep(20);
|
||||
g_pCodeWindow->JumpToAddress(PC);
|
||||
g_pCodeWindow->Update();
|
||||
// Update toolbar with Play/Pause status
|
||||
UpdateGUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Core::GetState() == Core::CORE_RUN)
|
||||
Core::SetState(Core::CORE_PAUSE);
|
||||
else
|
||||
Core::SetState(Core::CORE_RUN);
|
||||
}
|
||||
// Update toolbar with Play/Pause status
|
||||
UpdateGUI();
|
||||
DoPause();
|
||||
}
|
||||
else
|
||||
// Core is uninitialized, start the game
|
||||
@@ -666,7 +662,7 @@ void CFrame::StartGame(const std::string& filename)
|
||||
|
||||
void CFrame::OnBootDrive(wxCommandEvent& event)
|
||||
{
|
||||
BootManager::BootCore(drives[event.GetId()-IDM_DRIVE1].c_str());
|
||||
StartGame(drives[event.GetId()-IDM_DRIVE1]);
|
||||
}
|
||||
|
||||
|
||||
@@ -691,7 +687,20 @@ void CFrame::OnScreenshot(wxCommandEvent& WXUNUSED (event))
|
||||
// Pause the emulation
|
||||
void CFrame::DoPause()
|
||||
{
|
||||
Core::SetState(Core::CORE_PAUSE);
|
||||
if (Core::GetState() == Core::CORE_RUN)
|
||||
{
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
X11_SendClientEvent("PAUSE");
|
||||
#endif
|
||||
Core::SetState(Core::CORE_PAUSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
X11_SendClientEvent("RESUME");
|
||||
#endif
|
||||
Core::SetState(Core::CORE_RUN);
|
||||
}
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,485 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
||||
// Include
|
||||
// -------------
|
||||
#include "Globals.h"
|
||||
#include "Frame.h"
|
||||
#include "FileUtil.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
#include "GameListCtrl.h"
|
||||
#include "BootManager.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Setup.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "Core.h"
|
||||
#include "State.h"
|
||||
#include "ConfigMain.h"
|
||||
#include "PluginManager.h"
|
||||
#include "MemcardManager.h"
|
||||
#include "CheatsWindow.h"
|
||||
#include "AboutDolphin.h"
|
||||
|
||||
#include <wx/statusbr.h>
|
||||
|
||||
|
||||
|
||||
namespace WiimoteLeds
|
||||
{
|
||||
int LED_SIZE_X = 8;
|
||||
int LED_SIZE_Y = 8;
|
||||
int SPEAKER_SIZE_X = 8;
|
||||
int SPEAKER_SIZE_Y = 8;
|
||||
|
||||
int ConnectionStatusWidth = 103; // These widths need to be revised, for vista at least
|
||||
int ConnectionStatusOnlyAdj = 7;
|
||||
int RightmostMargin = 6;
|
||||
int SpIconMargin = 11;
|
||||
int LedIconMargin = 11;
|
||||
|
||||
// The necessary recording status width, allow Frame to be at last of the form 100,000
|
||||
#ifdef RERECORDING
|
||||
static const int RerecordingStatusWidth = 340;
|
||||
#endif
|
||||
|
||||
// Leds only
|
||||
static const int LdWidthsOn[] =
|
||||
{
|
||||
-1,
|
||||
#ifdef RERECORDING
|
||||
RerecordingStatusWidth,
|
||||
#endif
|
||||
ConnectionStatusWidth,
|
||||
(LedIconMargin + LED_SIZE_X) * 4 + RightmostMargin
|
||||
};
|
||||
static const int StylesFieldOn[] = { wxSB_NORMAL, wxSB_NORMAL, wxSB_NORMAL };
|
||||
|
||||
// Speakers only
|
||||
static const int SpWidthsOn[] =
|
||||
{
|
||||
-1,
|
||||
#ifdef RERECORDING
|
||||
RerecordingStatusWidth,
|
||||
#endif
|
||||
ConnectionStatusWidth,
|
||||
( SpIconMargin + SPEAKER_SIZE_X ) * 3 + RightmostMargin
|
||||
};
|
||||
static const int SpStylesFieldOn[] = { wxSB_NORMAL,
|
||||
#ifdef RERECORDING
|
||||
wxSB_NORMAL,
|
||||
#endif
|
||||
wxSB_NORMAL, wxSB_NORMAL };
|
||||
|
||||
// Both
|
||||
static const int LdSpWidthsOn[] =
|
||||
{
|
||||
-1,
|
||||
#ifdef RERECORDING
|
||||
RerecordingStatusWidth,
|
||||
#endif
|
||||
ConnectionStatusWidth,
|
||||
(SpIconMargin + SPEAKER_SIZE_X) * 3,
|
||||
(LedIconMargin + LED_SIZE_X) * 4 + RightmostMargin
|
||||
};
|
||||
static const int LdSpStylesFieldOn[] = { wxSB_NORMAL,
|
||||
#ifdef RERECORDING
|
||||
wxSB_NORMAL,
|
||||
#endif
|
||||
wxSB_NORMAL, wxSB_NORMAL };
|
||||
|
||||
// Only the Wiimote connection Status
|
||||
static const int WidthsOff[] =
|
||||
{
|
||||
-1,
|
||||
#ifdef RERECORDING
|
||||
RerecordingStatusWidth,
|
||||
#endif
|
||||
ConnectionStatusWidth + ConnectionStatusOnlyAdj + RightmostMargin
|
||||
};
|
||||
static const int StylesFieldOff[] = { wxSB_NORMAL,
|
||||
#ifdef RERECORDING
|
||||
wxSB_NORMAL,
|
||||
#endif
|
||||
wxSB_NORMAL };
|
||||
|
||||
// GC mode
|
||||
static const int WidthsOffGC[] = { -1
|
||||
#ifdef RERECORDING
|
||||
, RerecordingStatusWidth
|
||||
#endif
|
||||
};
|
||||
static const int StylesFieldOffGC[] = { wxSB_NORMAL
|
||||
#ifdef RERECORDING
|
||||
, wxSB_NORMAL
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
// =======================================================
|
||||
// Modify status bar
|
||||
// -------------
|
||||
void CFrame::ModifyStatusBar()
|
||||
{
|
||||
// Get settings
|
||||
bool LedsOn = SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiLeds;
|
||||
bool SpeakersOn = SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiSpeakers;
|
||||
|
||||
// Don't use this for GC games, or before a game is loaded
|
||||
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
{ LedsOn = false; SpeakersOn = false; }
|
||||
|
||||
// Declarations
|
||||
int Fields = 0;
|
||||
int *Widths = 0;
|
||||
int *StylesFields = 0;
|
||||
|
||||
// ---------------------------------------
|
||||
// Leds only
|
||||
// -------------
|
||||
if(LedsOn && !SpeakersOn)
|
||||
{
|
||||
Fields = 3;
|
||||
Widths = (int*)WiimoteLeds::LdWidthsOn;
|
||||
StylesFields = (int*)WiimoteLeds::StylesFieldOn;
|
||||
}
|
||||
// ---------------------------------------
|
||||
// Speaker only
|
||||
// -------------
|
||||
else if(!LedsOn && SpeakersOn)
|
||||
{
|
||||
Fields = 3;
|
||||
Widths = (int*)WiimoteLeds::SpWidthsOn;
|
||||
StylesFields = (int*)WiimoteLeds::SpStylesFieldOn;
|
||||
}
|
||||
// ---------------------------------------
|
||||
// Both on
|
||||
// -------------
|
||||
else if(LedsOn && SpeakersOn)
|
||||
{
|
||||
Fields = 4;
|
||||
Widths = (int*)WiimoteLeds::LdSpWidthsOn;
|
||||
StylesFields = (int*)WiimoteLeds::LdSpStylesFieldOn;
|
||||
}
|
||||
// ---------------------------------------
|
||||
// Both off
|
||||
// -------------
|
||||
else if(!LedsOn && !SpeakersOn)
|
||||
{
|
||||
Fields = 2;
|
||||
Widths = (int*)WiimoteLeds::WidthsOff;
|
||||
StylesFields = (int*)WiimoteLeds::StylesFieldOff;
|
||||
|
||||
// Maybe we should even go down to one field
|
||||
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
{
|
||||
Fields = 1;
|
||||
Widths = (int*)WiimoteLeds::WidthsOffGC;
|
||||
StylesFields = (int*)WiimoteLeds::StylesFieldOffGC;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a filed for the rerecording status
|
||||
#ifdef RERECORDING
|
||||
Fields++;
|
||||
#endif
|
||||
|
||||
// Update the settings
|
||||
m_pStatusBar->SetFieldsCount(Fields);
|
||||
m_pStatusBar->SetStatusWidths(Fields, Widths);
|
||||
m_pStatusBar->SetStatusStyles(Fields, StylesFields);
|
||||
|
||||
/* Destroy and create all, and check for HaveLeds and HaveSpeakers in case we have
|
||||
gotten a confirmed on or off setting, in which case we don't do anything */
|
||||
if(!LedsOn && HaveLeds) CreateDestroy(DESTROYLEDS);
|
||||
if(!SpeakersOn && HaveSpeakers) CreateDestroy(DESTROYSPEAKERS);
|
||||
if(LedsOn && !HaveLeds) CreateDestroy(CREATELEDS);
|
||||
if(SpeakersOn && !HaveSpeakers) CreateDestroy(CREATESPEAKERS);
|
||||
|
||||
DoMoveIcons();
|
||||
m_pStatusBar->Refresh(); // avoid small glitches that can occur
|
||||
}
|
||||
|
||||
|
||||
// =======================================================
|
||||
// Create and destroy leds and speakers icons
|
||||
// -------------
|
||||
void CFrame::CreateDestroy(int Case)
|
||||
{
|
||||
switch(Case)
|
||||
{
|
||||
case CREATELEDS:
|
||||
{
|
||||
CreateLeds();
|
||||
UpdateLeds();
|
||||
HaveLeds = true;
|
||||
break;
|
||||
}
|
||||
case DESTROYLEDS:
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
m_StatBmp[i]->Destroy();
|
||||
}
|
||||
HaveLeds = false;
|
||||
break;
|
||||
}
|
||||
case CREATESPEAKERS:
|
||||
{
|
||||
CreateSpeakers();
|
||||
HaveSpeakers = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case DESTROYSPEAKERS:
|
||||
{
|
||||
for(int i = 4; i < 7; i++)
|
||||
{
|
||||
m_StatBmp[i]->Destroy();
|
||||
}
|
||||
HaveSpeakers = false;
|
||||
break;
|
||||
}
|
||||
} // end of switch
|
||||
|
||||
DoMoveIcons();
|
||||
}
|
||||
// =============
|
||||
|
||||
|
||||
// =======================================================
|
||||
// Create and update leds
|
||||
// -------------
|
||||
void CFrame::CreateLeds()
|
||||
{
|
||||
// Begin with blank ones
|
||||
memset(&g_Leds, 0, sizeof(g_Leds));
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
m_StatBmp[i] = new wxStaticBitmap(m_pStatusBar, wxID_ANY,
|
||||
CreateBitmapForLeds(g_Leds[i] == 1));
|
||||
}
|
||||
}
|
||||
// Update leds
|
||||
void CFrame::UpdateLeds()
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
m_StatBmp[i]->SetBitmap(CreateBitmapForLeds(g_Leds[i] != 0));
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================
|
||||
// Create and speaker icons
|
||||
// -------------
|
||||
void CFrame::CreateSpeakers()
|
||||
{
|
||||
// Begin with blank ones
|
||||
memset(&g_Speakers, 0, sizeof(g_Speakers));
|
||||
memset(&g_Speakers_, 0, sizeof(g_Speakers_));
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
m_StatBmp[i+4] = new wxStaticBitmap(m_pStatusBar, wxID_ANY,
|
||||
CreateBitmapForSpeakers(i, g_Speakers[i] != 0));
|
||||
}
|
||||
}
|
||||
// Update icons
|
||||
void CFrame::UpdateSpeakers()
|
||||
{
|
||||
/*if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC)
|
||||
{ PanicAlert("Not NTSC");}
|
||||
|
||||
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
{ PanicAlert("Not Wii");}*/
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
m_StatBmp[i+4]->SetBitmap(CreateBitmapForSpeakers(i, g_Speakers[i] != 0));
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================
|
||||
// Create the Leds bitmap
|
||||
// -------------
|
||||
wxBitmap CFrame::CreateBitmapForLeds(bool On)
|
||||
{
|
||||
wxBitmap bitmap(WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
|
||||
// Set outline and fill colors
|
||||
wxBrush LightBlueBrush(_T("#0383f0"));
|
||||
wxPen LightBluePen(_T("#80c5fd"));
|
||||
wxPen LightGrayPen(_T("#909090"));
|
||||
dc.SetPen(On ? LightBluePen : LightGrayPen);
|
||||
dc.SetBrush(On ? LightBlueBrush : *wxWHITE_BRUSH);
|
||||
|
||||
dc.Clear();
|
||||
dc.DrawRectangle(0, 0, WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
// =======================================================
|
||||
// Create the Speaker bitmap
|
||||
// -------------
|
||||
wxBitmap CFrame::CreateBitmapForSpeakers(int BitmapType, bool On)
|
||||
{
|
||||
wxBitmap bitmap(WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
wxBrush BackgroundGrayBrush(_T("#ece9d8")); // the right color in windows
|
||||
|
||||
switch(BitmapType)
|
||||
{
|
||||
case 0: // Speaker on
|
||||
{
|
||||
// Set outline and fill colors
|
||||
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
|
||||
dc.SetBrush(On ? *wxGREEN_BRUSH : *wxWHITE_BRUSH);
|
||||
dc.SetBackground(BackgroundGrayBrush);
|
||||
dc.Clear();
|
||||
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
return bitmap;
|
||||
}
|
||||
case 1: // Speaker unmuted
|
||||
{
|
||||
// Set outline and fill colors
|
||||
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
|
||||
dc.SetBrush(On ? *wxBLUE_BRUSH : *wxWHITE_BRUSH);
|
||||
dc.SetBackground(BackgroundGrayBrush);
|
||||
dc.Clear();
|
||||
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
return bitmap;
|
||||
}
|
||||
case 2: // Speaker activity
|
||||
{
|
||||
// Set outline and fill colors
|
||||
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
|
||||
dc.SetBrush(On ? *wxGREEN_BRUSH : *wxWHITE_BRUSH);
|
||||
dc.SetBackground(BackgroundGrayBrush);
|
||||
dc.Clear();
|
||||
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
// =======================================================
|
||||
// Move the bitmaps
|
||||
// -------------
|
||||
void CFrame::DoMoveIcons()
|
||||
{
|
||||
if (!m_pStatusBar) return;
|
||||
|
||||
if(HaveLeds) MoveLeds();
|
||||
if(HaveSpeakers) MoveSpeakers();
|
||||
|
||||
// If there is not room for the led icons hide them
|
||||
if(m_pStatusBar->GetFieldsCount() >= 2 && HaveLeds)
|
||||
{
|
||||
wxRect Rect;
|
||||
#ifdef RERECORDING
|
||||
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 4 : 3, Rect);
|
||||
#else
|
||||
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 3 : 2, Rect);
|
||||
#endif
|
||||
if(Rect.GetWidth() < 20)
|
||||
for (int i = 0; i < 4; i++) m_StatBmp[i]->Hide();
|
||||
else // if(!m_StatBmp[0]->IsShown())
|
||||
for (int i = 0; i < 4; i++) m_StatBmp[i]->Show();
|
||||
//INFO_LOG(CONSOLE, "LED: %i ", Rect.GetWidth());
|
||||
}
|
||||
|
||||
// If there is not room for the speaker icons hide them
|
||||
if(m_pStatusBar->GetFieldsCount() >= 2 && HaveSpeakers)
|
||||
{
|
||||
wxRect Rect;
|
||||
#ifdef RERECORDING
|
||||
m_pStatusBar->GetFieldRect(3, Rect);
|
||||
#else
|
||||
m_pStatusBar->GetFieldRect(2, Rect);
|
||||
#endif
|
||||
if(Rect.GetWidth() < 20)
|
||||
for(int i = 0; i < 3; i++) m_StatBmp[i + 4]->Hide();
|
||||
else // if(!m_StatBmp[4]->IsShown())
|
||||
for (int i = 0; i < 3; i++) m_StatBmp[i + 4]->Show();
|
||||
//INFO_LOG(CONSOLE, "Speaker: %i\n", Rect.GetWidth());
|
||||
}
|
||||
}
|
||||
|
||||
void CFrame::MoveLeds()
|
||||
{
|
||||
wxRect Rect;
|
||||
// Get the bitmap field coordinates
|
||||
#ifdef RERECORDING
|
||||
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 4 : 3, Rect);
|
||||
#else
|
||||
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 3 : 2, Rect);
|
||||
#endif
|
||||
wxSize Size = m_StatBmp[0]->GetSize(); // Get the bitmap size
|
||||
|
||||
//wxMessageBox(wxString::Format("%i", Rect.x));
|
||||
int x = Rect.x + 10;
|
||||
int Dist = WiimoteLeds::LED_SIZE_X + 7;
|
||||
int y = Rect.y + (Rect.height - Size.y) / 2;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
if(i > 0) x = m_StatBmp[i-1]->GetPosition().x + Dist;
|
||||
m_StatBmp[i]->Move(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void CFrame::MoveSpeakers()
|
||||
{
|
||||
wxRect Rect;
|
||||
// Get the bitmap field coordinates
|
||||
#ifdef RERECORDING
|
||||
m_pStatusBar->GetFieldRect(3, Rect);
|
||||
#else
|
||||
m_pStatusBar->GetFieldRect(2, Rect);
|
||||
#endif
|
||||
|
||||
// Get the actual bitmap size, currently it's the same as SPEAKER_SIZE_Y
|
||||
wxSize Size = m_StatBmp[4]->GetSize();
|
||||
|
||||
//wxMessageBox(wxString::Format("%i", Rect.x));
|
||||
int x = Rect.x + 9;
|
||||
int Dist = WiimoteLeds::SPEAKER_SIZE_X + 7;
|
||||
int y = Rect.y + (Rect.height - Size.y) / 2;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if(i > 0) x = m_StatBmp[i-1+4]->GetPosition().x + Dist;
|
||||
m_StatBmp[i + 4]->Move(x, y);
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
@@ -418,7 +418,7 @@ bool DolphinApp::OnInit()
|
||||
#ifdef DEBUGFAST
|
||||
const char *title = "Dolphin Debugfast SVN R " SVN_REV_STR;
|
||||
#else
|
||||
const char *title = "Dolphin SVN R " SVN_REV_STR;
|
||||
const char *title = "Dolphin " SVN_REV_STR;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -533,6 +533,8 @@ void Host_Message(int Id)
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
switch(Id)
|
||||
{
|
||||
case WM_USER_CREATE:
|
||||
case TOGGLE_FULLSCREEN:
|
||||
case WM_USER_STOP:
|
||||
case WM_USER_PAUSE:
|
||||
{
|
||||
@@ -613,55 +615,12 @@ void Host_UpdateBreakPointView()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Update Wiimote status bar
|
||||
|
||||
void Host_UpdateLeds(int led_bits)
|
||||
{
|
||||
// Convert it to a simpler byte format
|
||||
main_frame->g_Leds[0] = led_bits >> 0;
|
||||
main_frame->g_Leds[1] = led_bits >> 1;
|
||||
main_frame->g_Leds[2] = led_bits >> 2;
|
||||
main_frame->g_Leds[3] = led_bits >> 3;
|
||||
|
||||
main_frame->UpdateLeds();
|
||||
}
|
||||
|
||||
void Host_UpdateSpeakerStatus(int index, int speaker_bits)
|
||||
{
|
||||
main_frame->g_Speakers[index] = speaker_bits;
|
||||
main_frame->UpdateSpeakers();
|
||||
}
|
||||
|
||||
void Host_UpdateStatus()
|
||||
{
|
||||
// Debugging
|
||||
//std::string Tmp = ArrayToString(main_frame->g_Speakers, sizeof(main_frame->g_Speakers));
|
||||
//std::string Tmp2 = ArrayToString(main_frame->g_Speakers_, sizeof(main_frame->g_Speakers_));
|
||||
//LOGV(CONSOLE, 0, "Tmp: %s", Tmp.c_str());
|
||||
//LOGV(CONSOLE, 0, "Tmp2: %s", Tmp2.c_str());
|
||||
// Don't do a lot of CreateBitmap() if we don't need to
|
||||
if(memcmp(main_frame->g_Speakers_, main_frame->g_Speakers,
|
||||
sizeof(main_frame->g_Speakers)))
|
||||
{
|
||||
// Turn off the activity light again
|
||||
main_frame->g_Speakers[2] = 0;
|
||||
main_frame->UpdateSpeakers();
|
||||
memcpy(main_frame->g_Speakers_, main_frame->g_Speakers, sizeof(main_frame->g_Speakers));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Host_UpdateMemoryView()
|
||||
{}
|
||||
|
||||
|
||||
void Host_SetDebugMode(bool)
|
||||
{}
|
||||
|
||||
|
||||
void Host_SetWaitCursor(bool enable)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_COCOA) && HAVE_COCOA
|
||||
#import "cocoaApp.h"
|
||||
#endif
|
||||
@@ -54,7 +58,48 @@ void Host_NotifyMapLoaded(){}
|
||||
|
||||
void Host_ShowJitResults(unsigned int address){}
|
||||
|
||||
void Host_Message(int Id){}
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
void X11_SendClientEvent(const char *message)
|
||||
{
|
||||
XEvent event;
|
||||
Display *dpy = (Display *)Core::GetWindowHandle();
|
||||
Window win = *(Window *)Core::GetXWindow();
|
||||
|
||||
// Init X event structure for client message
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.data.l[0] = XInternAtom(dpy, message, False);
|
||||
|
||||
// Send the event
|
||||
if (!XSendEvent(dpy, win, False, False, &event))
|
||||
ERROR_LOG(VIDEO, "Failed to send message %s to the emulator window.\n", message);
|
||||
}
|
||||
#endif
|
||||
|
||||
Common::Event updateMainFrameEvent;
|
||||
void Host_Message(int Id)
|
||||
{
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
switch (Id)
|
||||
{
|
||||
case WM_USER_STOP:
|
||||
updateMainFrameEvent.Set();
|
||||
break;
|
||||
case WM_USER_PAUSE:
|
||||
if (Core::GetState() == Core::CORE_RUN)
|
||||
{
|
||||
X11_SendClientEvent("PAUSE");
|
||||
Core::SetState(Core::CORE_PAUSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
X11_SendClientEvent("RESUME");
|
||||
Core::SetState(Core::CORE_RUN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Host_UpdateLogDisplay(){}
|
||||
|
||||
@@ -62,7 +107,6 @@ void Host_UpdateLogDisplay(){}
|
||||
void Host_UpdateDisasmDialog(){}
|
||||
|
||||
|
||||
Common::Event updateMainFrameEvent;
|
||||
void Host_UpdateMainFrame()
|
||||
{
|
||||
updateMainFrameEvent.Set();
|
||||
@@ -99,16 +143,6 @@ void Host_SysMessage(const char *fmt, ...)
|
||||
fprintf(stderr, "%s", msg);
|
||||
}
|
||||
|
||||
void Host_UpdateLeds(int led_bits)
|
||||
{
|
||||
}
|
||||
void Host_UpdateSpeakerStatus(int index, int speaker_bits)
|
||||
{
|
||||
}
|
||||
void Host_UpdateStatus()
|
||||
{
|
||||
}
|
||||
|
||||
void Host_SetWiiMoteConnectionState(int _State) {}
|
||||
|
||||
|
||||
@@ -230,7 +264,6 @@ int main(int argc, char* argv[])
|
||||
std::string bootFile(args_info.inputs[0]);
|
||||
|
||||
updateMainFrameEvent.Init();
|
||||
cpu_info.Detect();
|
||||
|
||||
LogManager::Init();
|
||||
EventHandler::Init();
|
||||
@@ -239,13 +272,23 @@ int main(int argc, char* argv[])
|
||||
|
||||
CPluginManager::GetInstance().ScanForPlugins();
|
||||
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
XInitThreads();
|
||||
#endif
|
||||
|
||||
if (BootManager::BootCore(bootFile)) //no use running the loop when booting fails
|
||||
{
|
||||
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
|
||||
{
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
while (Core::GetState() == Core::CORE_UNINITIALIZED)
|
||||
updateMainFrameEvent.Wait();
|
||||
}
|
||||
updateMainFrameEvent.Wait();
|
||||
Core::Stop();
|
||||
#else
|
||||
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
|
||||
updateMainFrameEvent.Wait();
|
||||
#endif
|
||||
}
|
||||
updateMainFrameEvent.Shutdown();
|
||||
|
||||
CPluginManager::Shutdown();
|
||||
SConfig::Shutdown();
|
||||
|
||||
@@ -11,8 +11,8 @@ files = [
|
||||
]
|
||||
|
||||
libs = [
|
||||
'core', 'minilzo', 'discio', 'bdisasm', 'videocommon',
|
||||
'inputcommon', 'common', 'lua', 'z', 'sfml'
|
||||
'core', 'lzo2', 'discio', 'bdisasm', 'videocommon',
|
||||
'inputcommon', 'common', 'lua', 'z', 'sfml-network'
|
||||
]
|
||||
|
||||
if wxenv['HAVE_WX']:
|
||||
@@ -23,7 +23,6 @@ if wxenv['HAVE_WX']:
|
||||
'Frame.cpp',
|
||||
'FrameAui.cpp',
|
||||
'FrameTools.cpp',
|
||||
'FrameWiimote.cpp',
|
||||
'LuaWindow.cpp',
|
||||
'LogWindow.cpp',
|
||||
'GameListCtrl.cpp',
|
||||
|
||||
@@ -121,9 +121,24 @@ KeySym wxCharCodeWXToX(int id)
|
||||
void XKeyToString(unsigned int keycode, char *keyStr) {
|
||||
switch (keycode) {
|
||||
|
||||
case XK_Insert:
|
||||
sprintf(keyStr, "INSERT");
|
||||
break;
|
||||
case XK_Delete:
|
||||
sprintf(keyStr, "DELETE");
|
||||
break;
|
||||
case XK_Home:
|
||||
sprintf(keyStr, "HOME");
|
||||
break;
|
||||
case XK_End:
|
||||
sprintf(keyStr, "END");
|
||||
break;
|
||||
case XK_Prior:
|
||||
sprintf(keyStr, "PAGEUP");
|
||||
break;
|
||||
case XK_Next:
|
||||
sprintf(keyStr, "PAGEDOWN");
|
||||
break;
|
||||
case XK_Left:
|
||||
sprintf(keyStr, "LEFT");
|
||||
break;
|
||||
@@ -139,6 +154,18 @@ void XKeyToString(unsigned int keycode, char *keyStr) {
|
||||
case XK_Return:
|
||||
sprintf(keyStr, "RETURN");
|
||||
break;
|
||||
case XK_Escape:
|
||||
sprintf(keyStr, "ESCAPE");
|
||||
break;
|
||||
case XK_Caps_Lock:
|
||||
sprintf(keyStr, "CAPSLOCK");
|
||||
break;
|
||||
case XK_BackSpace:
|
||||
sprintf(keyStr, "BACKSPACE");
|
||||
break;
|
||||
case XK_Tab:
|
||||
sprintf(keyStr, "TAB");
|
||||
break;
|
||||
case XK_KP_Enter:
|
||||
sprintf(keyStr, "KP ENTER");
|
||||
break;
|
||||
@@ -154,12 +181,114 @@ void XKeyToString(unsigned int keycode, char *keyStr) {
|
||||
case XK_KP_Down:
|
||||
sprintf(keyStr, "KP DOWN");
|
||||
break;
|
||||
case XK_KP_Insert:
|
||||
sprintf(keyStr, "KP Insert");
|
||||
break;
|
||||
case XK_KP_Delete:
|
||||
sprintf(keyStr, "KP Delete");
|
||||
break;
|
||||
case XK_KP_Page_Down:
|
||||
sprintf(keyStr, "KP Page Down");
|
||||
break;
|
||||
case XK_KP_Page_Up:
|
||||
sprintf(keyStr, "KP Page Up");
|
||||
break;
|
||||
case XK_KP_Separator:
|
||||
sprintf(keyStr, "KP Separator");
|
||||
break;
|
||||
case XK_KP_Home:
|
||||
sprintf(keyStr, "KP Home");
|
||||
break;
|
||||
case XK_KP_End:
|
||||
sprintf(keyStr, "KP End");
|
||||
break;
|
||||
case XK_KP_Subtract:
|
||||
sprintf(keyStr, "KP -");
|
||||
break;
|
||||
case XK_KP_Add:
|
||||
sprintf(keyStr, "KP +");
|
||||
break;
|
||||
case XK_KP_Multiply:
|
||||
sprintf(keyStr, "KP *");
|
||||
break;
|
||||
case XK_KP_Divide:
|
||||
sprintf(keyStr, "KP /");
|
||||
break;
|
||||
case XK_KP_Decimal:
|
||||
sprintf(keyStr, "KP .");
|
||||
break;
|
||||
case XK_KP_0:
|
||||
sprintf(keyStr, "KP 0");
|
||||
break;
|
||||
case XK_KP_1:
|
||||
sprintf(keyStr, "KP 1");
|
||||
break;
|
||||
case XK_KP_2:
|
||||
sprintf(keyStr, "KP 2");
|
||||
break;
|
||||
case XK_KP_3:
|
||||
sprintf(keyStr, "KP 3");
|
||||
break;
|
||||
case XK_KP_4:
|
||||
sprintf(keyStr, "KP 4");
|
||||
break;
|
||||
case XK_KP_5:
|
||||
sprintf(keyStr, "KP 5");
|
||||
break;
|
||||
case XK_KP_6:
|
||||
sprintf(keyStr, "KP 6");
|
||||
break;
|
||||
case XK_KP_7:
|
||||
sprintf(keyStr, "KP 7");
|
||||
break;
|
||||
case XK_KP_8:
|
||||
sprintf(keyStr, "KP 8");
|
||||
break;
|
||||
case XK_KP_9:
|
||||
sprintf(keyStr, "KP 9");
|
||||
break;
|
||||
case XK_Shift_L:
|
||||
sprintf(keyStr, "LShift");
|
||||
break;
|
||||
case XK_Control_L:
|
||||
sprintf(keyStr, "LControl");
|
||||
break;
|
||||
case XK_F1:
|
||||
sprintf(keyStr, "F1");
|
||||
break;
|
||||
case XK_F2:
|
||||
sprintf(keyStr, "F2");
|
||||
break;
|
||||
case XK_F3:
|
||||
sprintf(keyStr, "F3");
|
||||
break;
|
||||
case XK_F4:
|
||||
sprintf(keyStr, "F4");
|
||||
break;
|
||||
case XK_F5:
|
||||
sprintf(keyStr, "F5");
|
||||
break;
|
||||
case XK_F6:
|
||||
sprintf(keyStr, "F6");
|
||||
break;
|
||||
case XK_F7:
|
||||
sprintf(keyStr, "F7");
|
||||
break;
|
||||
case XK_F8:
|
||||
sprintf(keyStr, "F8");
|
||||
break;
|
||||
case XK_F9:
|
||||
sprintf(keyStr, "F9");
|
||||
break;
|
||||
case XK_F10:
|
||||
sprintf(keyStr, "F10");
|
||||
break;
|
||||
case XK_F11:
|
||||
sprintf(keyStr, "F11");
|
||||
break;
|
||||
case XK_F12:
|
||||
sprintf(keyStr, "F12");
|
||||
break;
|
||||
default:
|
||||
sprintf(keyStr, "%c", toupper(keycode));
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#if defined(SHARED_SOIL) && SHARED_SOIL
|
||||
#include <SOIL/SOIL.h>
|
||||
#else
|
||||
#include "SOIL.h"
|
||||
#endif
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
#include "FileSearch.h"
|
||||
|
||||
@@ -59,6 +59,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dolphin", "Core\DolphinWX\D
|
||||
{823DDC98-42D5-4A38-88CF-9DC06C788AE4} = {823DDC98-42D5-4A38-88CF-9DC06C788AE4}
|
||||
{3D8156A9-64D1-4C8E-ADBE-1B319030E4A4} = {3D8156A9-64D1-4C8E-ADBE-1B319030E4A4}
|
||||
{0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} = {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E}
|
||||
{66A4E7BD-E2E8-4373-9B75-8750EB5AE683} = {66A4E7BD-E2E8-4373-9B75-8750EB5AE683}
|
||||
{E5D1F0C0-AA07-4841-A4EB-4CF4DAA6B0FA} = {E5D1F0C0-AA07-4841-A4EB-4CF4DAA6B0FA}
|
||||
{29C2ABC1-ADA5-42CD-A5FC-96022D52A510} = {29C2ABC1-ADA5-42CD-A5FC-96022D52A510}
|
||||
{4D3CD4C5-412B-4B49-9B1B-A68A2A129C77} = {4D3CD4C5-412B-4B49-9B1B-A68A2A129C77}
|
||||
@@ -193,6 +194,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_GCPad", "Plugins\Plu
|
||||
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_GCPadNew", "Plugins\Plugin_GCPadNew\Plugin_GCPadNew.vcproj", "{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{05C75041-D67D-4903-A362-8395A7B35C75} = {05C75041-D67D-4903-A362-8395A7B35C75}
|
||||
{11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED}
|
||||
{0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} = {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E}
|
||||
{1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} = {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE}
|
||||
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@@ -553,6 +563,18 @@ Global
|
||||
{9FF603F8-B3BB-4144-9688-B2B802FA0F16}.Release|Win32.Build.0 = Release|Win32
|
||||
{9FF603F8-B3BB-4144-9688-B2B802FA0F16}.Release|x64.ActiveCfg = Release|x64
|
||||
{9FF603F8-B3BB-4144-9688-B2B802FA0F16}.Release|x64.Build.0 = Release|x64
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Debug|x64.Build.0 = Debug|x64
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.DebugFast|Win32.Build.0 = DebugFast|Win32
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.DebugFast|x64.Build.0 = DebugFast|x64
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Release|Win32.Build.0 = Release|Win32
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Release|x64.ActiveCfg = Release|x64
|
||||
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -35,6 +35,9 @@ typedef struct
|
||||
{
|
||||
HWND hWnd;
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2
|
||||
void *pPanel;
|
||||
#endif
|
||||
void *pXWindow;
|
||||
#endif
|
||||
TLog pLog;
|
||||
|
||||
@@ -72,6 +72,9 @@ typedef struct
|
||||
{
|
||||
void *pWindowHandle;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2
|
||||
void *pPanel;
|
||||
#endif
|
||||
void *pXWindow;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ typedef struct
|
||||
{
|
||||
HWND hWnd;
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2
|
||||
void *pPanel;
|
||||
#endif
|
||||
void *pXWindow;
|
||||
#endif
|
||||
u32 ISOId;
|
||||
|
||||
@@ -36,6 +36,7 @@ void CConfig::Load()
|
||||
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "DSP.ini").c_str());
|
||||
file.Get("Config", "EnableHLEAudio", &m_EnableHLEAudio, true); // Sound Settings
|
||||
file.Get("Config", "EnableRE0AudioFix", &m_EnableRE0Fix, false); // RE0 Hack
|
||||
m_RE0Fix = m_EnableRE0Fix;
|
||||
ac_Config.Load(file);
|
||||
}
|
||||
|
||||
@@ -49,3 +50,10 @@ void CConfig::Save()
|
||||
|
||||
file.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "DSP.ini").c_str());
|
||||
}
|
||||
|
||||
void CConfig::LoadGameIni(const char* gameIniPath)
|
||||
{
|
||||
IniFile gameIni;
|
||||
gameIni.Load(gameIniPath);
|
||||
gameIni.Get("HLEaudio", "UseRE0Fix", &m_RE0Fix, m_EnableRE0Fix);
|
||||
}
|
||||
|
||||
@@ -23,12 +23,17 @@
|
||||
struct CConfig
|
||||
{
|
||||
bool m_EnableHLEAudio;
|
||||
//is the RE0 fix enabled in config?
|
||||
bool m_EnableRE0Fix;
|
||||
//is the RE0 supposed to be used?
|
||||
//this value includes game.ini, avoiding overwrite of config
|
||||
bool m_RE0Fix;
|
||||
|
||||
CConfig();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
void LoadGameIni(const char*);
|
||||
};
|
||||
|
||||
extern CConfig g_Config;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "../Globals.h"
|
||||
#include "Mixer.h"
|
||||
#include "../MailHandler.h"
|
||||
#include "../DSPHandler.h"
|
||||
|
||||
#include "UCodes.h"
|
||||
#include "UCode_AXStructs.h"
|
||||
@@ -65,7 +66,7 @@ static void ProcessUpdates(AXPB &PB)
|
||||
int on = 0, off = 0;
|
||||
for (int j = 0; j < numupd; j++)
|
||||
{
|
||||
int k = g_Config.m_EnableRE0Fix ? 0 : j;
|
||||
int k = g_Config.m_RE0Fix ? 0 : j;
|
||||
|
||||
const u16 updpar = Memory_Read_U16(updaddr + k);
|
||||
const u16 upddata = Memory_Read_U16(updaddr + k + 2);
|
||||
@@ -215,26 +216,43 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
|
||||
// Handle incoming mail
|
||||
void CUCode_AX::HandleMail(u32 _uMail)
|
||||
{
|
||||
if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
|
||||
{
|
||||
// We are expected to get a new CmdBlock
|
||||
DEBUG_LOG(DSPHLE, "GetNextCmdBlock (%ibytes)", (u16)_uMail);
|
||||
static s8 newucodemails = -1;
|
||||
|
||||
if (newucodemails > -1) {
|
||||
newucodemails++;
|
||||
if (newucodemails == 10) {
|
||||
newucodemails = -1;
|
||||
m_rMailHandler.PushMail(DSP_RESUME);
|
||||
}
|
||||
}
|
||||
else if (_uMail == 0xCDD10000) // Action 0 - restart
|
||||
{
|
||||
m_rMailHandler.PushMail(DSP_RESUME);
|
||||
}
|
||||
else if (_uMail == 0xCDD10001) // Action 1 - new ucode upload
|
||||
{
|
||||
NOTICE_LOG(DSPHLE,"Game wanted to upload new ucode!");
|
||||
}
|
||||
else if ((_uMail & 0xFFFF0000) == 0xCDD10000) // Action 2/3
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(DSPHLE, " >>>> u32 MAIL : AXTask Mail (%08x)", _uMail);
|
||||
AXTask(_uMail);
|
||||
else {
|
||||
if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
|
||||
{
|
||||
// We are expected to get a new CmdBlock
|
||||
DEBUG_LOG(DSPHLE, "GetNextCmdBlock (%ibytes)", (u16)_uMail);
|
||||
}
|
||||
else if (_uMail == 0xCDD10000) // Action 0 - AX_ResumeTask();
|
||||
{
|
||||
m_rMailHandler.PushMail(DSP_RESUME);
|
||||
}
|
||||
else if (_uMail == 0xCDD10001) // Action 1 - new ucode upload ( GC: BayBlade S.T.B,...)
|
||||
{
|
||||
NOTICE_LOG(DSPHLE,"DSP IROM - New Ucode!");
|
||||
newucodemails = 0;
|
||||
}
|
||||
else if (_uMail == 0xCDD10002) // Action 2 - IROM_Reset(); ( GC: NFS Carbon, FF Crystal Chronicles,...)
|
||||
{
|
||||
NOTICE_LOG(DSPHLE,"DSP IROM - Reset!");
|
||||
CDSPHandler::GetInstance().SetUCode(UCODE_ROM);
|
||||
}
|
||||
else if (_uMail == 0xCDD10003) // Action 3 - AX_GetNextCmdBlock();
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(DSPHLE, " >>>> u32 MAIL : AXTask Mail (%08x)", _uMail);
|
||||
AXTask(_uMail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "../MailHandler.h"
|
||||
#include "Mixer.h"
|
||||
#include "../DSPHandler.h"
|
||||
|
||||
#include "UCodes.h"
|
||||
#include "UCode_AXStructs.h"
|
||||
@@ -50,24 +51,43 @@ CUCode_AXWii::~CUCode_AXWii()
|
||||
|
||||
void CUCode_AXWii::HandleMail(u32 _uMail)
|
||||
{
|
||||
if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
|
||||
{
|
||||
// a new List
|
||||
static s8 newucodemails = -1;
|
||||
|
||||
if (newucodemails > -1) {
|
||||
newucodemails++;
|
||||
if (newucodemails == 10) {
|
||||
newucodemails = -1;
|
||||
m_rMailHandler.PushMail(DSP_RESUME);
|
||||
}
|
||||
}
|
||||
else if (_uMail == 0xCDD10000) // Action 0 - restart
|
||||
{
|
||||
m_rMailHandler.PushMail(DSP_RESUME);
|
||||
}
|
||||
else if (_uMail == 0xCDD10001) // Action 1 - new ucode upload
|
||||
{
|
||||
NOTICE_LOG(DSPHLE,"Game wanted to upload new ucode!");
|
||||
}
|
||||
else if ((_uMail & 0xFFFF0000) == 0xCDD10000) // Action 2/3
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
AXTask(_uMail);
|
||||
else {
|
||||
if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
|
||||
{
|
||||
// We are expected to get a new CmdBlock
|
||||
DEBUG_LOG(DSPHLE, "GetNextCmdBlock (%ibytes)", (u16)_uMail);
|
||||
}
|
||||
else if (_uMail == 0xCDD10000) // Action 0 - AX_ResumeTask();
|
||||
{
|
||||
m_rMailHandler.PushMail(DSP_RESUME);
|
||||
}
|
||||
else if (_uMail == 0xCDD10001) // Action 1 - new ucode upload
|
||||
{
|
||||
NOTICE_LOG(DSPHLE,"DSP IROM - New Ucode!");
|
||||
newucodemails = 0;
|
||||
}
|
||||
else if (_uMail == 0xCDD10002) // Action 2 - IROM_Reset(); ( WII: De Blob, Cursed Mountain,...)
|
||||
{
|
||||
NOTICE_LOG(DSPHLE,"DSP IROM - Reset!");
|
||||
CDSPHandler::GetInstance().SetUCode(UCODE_ROM);
|
||||
}
|
||||
else if (_uMail == 0xCDD10003) // Action 3 - AX_GetNextCmdBlock();
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(DSPHLE, " >>>> u32 MAIL : AXTask Mail (%08x)", _uMail);
|
||||
AXTask(_uMail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,8 +142,9 @@ void GetDllInfo(PLUGIN_INFO* _PluginInfo)
|
||||
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
|
||||
{
|
||||
globals = _pPluginGlobals;
|
||||
LogManager::SetInstance((LogManager *)globals->logManager);
|
||||
globals = _pPluginGlobals;
|
||||
LogManager::SetInstance((LogManager *)globals->logManager);
|
||||
g_Config.LoadGameIni(globals->game_ini);
|
||||
}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
|
||||
@@ -129,10 +129,6 @@ GCPadConfigDialog::GCPadConfigDialog(wxWindow *parent, wxWindowID id, const wxSt
|
||||
#endif
|
||||
|
||||
UpdateGUI();
|
||||
|
||||
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
|
||||
wxKeyEventHandler(GCPadConfigDialog::OnKeyDown),
|
||||
(wxObject*)0, this);
|
||||
}
|
||||
|
||||
GCPadConfigDialog::~GCPadConfigDialog()
|
||||
@@ -245,10 +241,7 @@ void GCPadConfigDialog::OnKeyDown(wxKeyEvent& event)
|
||||
SaveButtonMapping(ClickedButton->GetId(), XKey);
|
||||
#endif
|
||||
}
|
||||
m_ButtonMappingTimer->Stop();
|
||||
GetButtonWaitingTimer = 0;
|
||||
GetButtonWaitingID = 0;
|
||||
ClickedButton = NULL;
|
||||
EndGetButtons();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +255,10 @@ void GCPadConfigDialog::OnButtonClick(wxCommandEvent& event)
|
||||
|
||||
if (m_ButtonMappingTimer->IsRunning()) return;
|
||||
|
||||
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
|
||||
wxKeyEventHandler(GCPadConfigDialog::OnKeyDown),
|
||||
(wxObject*)0, this);
|
||||
|
||||
// Create the button object
|
||||
ClickedButton = (wxButton *)event.GetEventObject();
|
||||
// Save old label so we can revert back
|
||||
|
||||
@@ -235,6 +235,7 @@ class GCPadConfigDialog : public wxDialog
|
||||
void ToBlank(bool ToBlank, int Id);
|
||||
|
||||
void DoGetButtons(int _GetId);
|
||||
void EndGetButtons();
|
||||
void SetButtonText(int id, const wxString &str);
|
||||
wxString GetButtonText(int id);
|
||||
};
|
||||
|
||||
@@ -208,10 +208,7 @@ void GCPadConfigDialog::DoGetButtons(int _GetId)
|
||||
{
|
||||
DEBUG_LOG(PAD, "Timer Stopped for Pad:%i _GetId:%i", GCMapping[m_Page].ID, _GetId);
|
||||
|
||||
m_ButtonMappingTimer->Stop();
|
||||
GetButtonWaitingTimer = 0;
|
||||
GetButtonWaitingID = 0;
|
||||
ClickedButton = NULL;
|
||||
EndGetButtons();
|
||||
}
|
||||
|
||||
// If we got a bad button
|
||||
@@ -227,6 +224,17 @@ void GCPadConfigDialog::DoGetButtons(int _GetId)
|
||||
}
|
||||
}
|
||||
|
||||
void GCPadConfigDialog::EndGetButtons(void)
|
||||
{
|
||||
wxTheApp->Disconnect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
|
||||
wxKeyEventHandler(GCPadConfigDialog::OnKeyDown),
|
||||
(wxObject*)0, this);
|
||||
m_ButtonMappingTimer->Stop();
|
||||
GetButtonWaitingTimer = 0;
|
||||
GetButtonWaitingID = 0;
|
||||
ClickedButton = NULL;
|
||||
}
|
||||
|
||||
// Convert the 0x8000 range values to BoxW and BoxH for the plot
|
||||
void GCPadConfigDialog::Convert2Box(int &x)
|
||||
{
|
||||
|
||||
@@ -658,12 +658,14 @@ bool IsFocus()
|
||||
return false;
|
||||
#elif defined HAVE_X11 && HAVE_X11
|
||||
Window GLWin = *(Window *)g_PADInitialize->pXWindow;
|
||||
bool bFocus = False;
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
bFocus = (wxPanel *)g_PADInitialize->pPanel == wxWindow::FindFocus();
|
||||
#endif
|
||||
Window FocusWin;
|
||||
int Revert;
|
||||
XGetInputFocus(GCdisplay, &FocusWin, &Revert);
|
||||
XWindowAttributes WinAttribs;
|
||||
XGetWindowAttributes (GCdisplay, GLWin, &WinAttribs);
|
||||
return (GLWin != 0 && (GLWin == FocusWin || WinAttribs.override_redirect));
|
||||
return (GLWin == FocusWin || bFocus);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,660 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="Plugin_GCPadNew"
|
||||
ProjectGUID="{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}"
|
||||
RootNamespace="Plugin_GCPadNew"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28ud.lib wxmsw28ud_core.lib"
|
||||
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName)D.dll"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28ud.lib wxmsw28ud_core.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName)D.dll"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="comctl32.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
|
||||
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName).dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="comctl32.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName).dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="DebugFast|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;DEBUGFAST;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
|
||||
OutputFile="..\..\..\Binary\Win32\Plugins\$(ProjectName)DF.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="DebugFast|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;DEBUGFAST;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="comctl32.lib rpcrt4.lib xinput.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\$(ProjectName)DF.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Config"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\Config.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Config.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="GUI"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\ConfigDiag.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ConfigDiag.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ConfigDiagBitmaps.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="IniFile"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\IniFile.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\IniFile.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="ControllerInterface"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\ControllerInterface.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\ControllerInterface.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="XInput"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\XInput\XInput.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\XInput\XInput.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="SDL"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\SDL\SDL.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\SDL\SDL.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="DirectInput"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInput.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInput.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputJoystick.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputJoystick.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputKeyboardMouse.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputKeyboardMouse.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerInterface\DirectInput\NamedKeys.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="ControllerEmu"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerEmu.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerEmu.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="GCPad"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerEmu\GCPad\GCPad.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ControllerEmu\GCPad\GCPad.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\Src\GCPadNew.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\SConscript"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
Plugin::Plugin()
|
||||
{
|
||||
// GCPads
|
||||
for ( unsigned int i = 0; i<4; ++i )
|
||||
controllers.push_back( new GCPad( i ) );
|
||||
};
|
||||
|
||||
Plugin::~Plugin()
|
||||
{
|
||||
// delete pads
|
||||
std::vector<ControllerEmu*>::const_iterator i = controllers.begin(),
|
||||
e = controllers.end();
|
||||
for ( ; i != e; ++i )
|
||||
delete *i;
|
||||
}
|
||||
|
||||
void Plugin::LoadConfig()
|
||||
{
|
||||
IniFile inifile;
|
||||
|
||||
std::ifstream file;
|
||||
file.open( (std::string(File::GetUserPath(D_CONFIG_IDX)) + CONFIG_FILE_NAME ).c_str() );
|
||||
inifile.Load( file );
|
||||
file.close();
|
||||
|
||||
std::vector< ControllerEmu* >::const_iterator i = controllers.begin(),
|
||||
e = controllers.end();
|
||||
for ( ; i!=e; ++i )
|
||||
(*i)->LoadConfig( inifile[ (*i)->GetName() ] );
|
||||
}
|
||||
|
||||
void Plugin::SaveConfig()
|
||||
{
|
||||
IniFile inifile;
|
||||
|
||||
std::vector< ControllerEmu* >::const_iterator i = controllers.begin(),
|
||||
e = controllers.end();
|
||||
for ( ; i!=e; ++i )
|
||||
(*i)->SaveConfig( inifile[ (*i)->GetName() ] );
|
||||
|
||||
// dont need to save empty values
|
||||
inifile.Clean();
|
||||
|
||||
std::ofstream file;
|
||||
file.open( (std::string(File::GetUserPath(D_CONFIG_IDX)) + CONFIG_FILE_NAME ).c_str() );
|
||||
inifile.Save( file );
|
||||
file.close();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#define CONFIG_FILE_NAME "GCPadNew.ini"
|
||||
|
||||
#include "ControllerInterface/ControllerInterface.h"
|
||||
#include "Thread.h"
|
||||
#include "FileUtil.h"
|
||||
#include "IniFile.h"
|
||||
|
||||
#include "ControllerEmu.h"
|
||||
#include "ControllerEmu/GCPad/GCPad.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
class Plugin
|
||||
{
|
||||
public:
|
||||
|
||||
Plugin();
|
||||
~Plugin();
|
||||
|
||||
void LoadConfig();
|
||||
void SaveConfig();
|
||||
|
||||
std::vector< ControllerEmu* > controllers;
|
||||
|
||||
Common::CriticalSection controls_crit, interface_crit; // lock controls first
|
||||
ControllerInterface controller_interface;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,833 @@
|
||||
|
||||
#include "ConfigDiag.h"
|
||||
|
||||
PadSettingCheckBox::PadSettingCheckBox( wxWindow* const parent, ControlState& _value, const char* const label )
|
||||
: PadSetting(_value)
|
||||
, wxCheckBox( parent, -1, wxString::FromAscii( label ), wxDefaultPosition )
|
||||
{
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void PadSettingCheckBox::UpdateGUI()
|
||||
{
|
||||
SetValue( value > 0 );
|
||||
}
|
||||
|
||||
void PadSettingCheckBox::UpdateValue()
|
||||
{
|
||||
// 0.01 so its saved to the ini file as just 1. :(
|
||||
value = 0.01 * GetValue();
|
||||
}
|
||||
|
||||
PadSettingChoice::PadSettingChoice( wxWindow* const parent, ControlState& _value, int min, int max )
|
||||
: PadSetting(_value)
|
||||
, wxChoice( parent, -1, wxDefaultPosition, wxSize( 48, -1 ) )
|
||||
{
|
||||
Append( wxT("0") );
|
||||
for ( ; min<=max; ++min )
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << min;
|
||||
Append( wxString::FromAscii( ss.str().c_str() ) );
|
||||
}
|
||||
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void PadSettingChoice::UpdateGUI()
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << int(value * 100);
|
||||
SetSelection( FindString( wxString::FromAscii( ss.str().c_str() ) ) );
|
||||
}
|
||||
|
||||
void PadSettingChoice::UpdateValue()
|
||||
{
|
||||
value = float( atoi( GetStringSelection().mb_str() ) ) / 100;
|
||||
}
|
||||
|
||||
ControlDialog::ControlDialog( wxWindow* const parent, ControllerInterface::ControlReference* const ref, const std::vector<ControllerInterface::Device*>& devs )
|
||||
:wxDialog( parent, -1, wxT("Configure Control"), wxDefaultPosition )
|
||||
,control_reference(ref)
|
||||
{
|
||||
|
||||
device_cbox = new wxComboBox( this, -1, wxString::FromAscii( ref->device_qualifier.ToString().c_str() ), wxDefaultPosition, wxSize(256,-1), wxArrayString(), wxTE_PROCESS_ENTER );
|
||||
|
||||
#define _connect_macro2_( b, f, c ) (b)->Connect( wxID_ANY, c, wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)parent );
|
||||
|
||||
_connect_macro2_( device_cbox, SetDevice, wxEVT_COMMAND_COMBOBOX_SELECTED );
|
||||
_connect_macro2_( device_cbox, SetDevice, wxEVT_COMMAND_TEXT_ENTER );
|
||||
|
||||
std::vector< ControllerInterface::Device* >::const_iterator i = devs.begin(),
|
||||
e = devs.end();
|
||||
ControllerInterface::DeviceQualifier dq;
|
||||
for ( ; i!=e; ++i )
|
||||
{
|
||||
dq.FromDevice( *i );
|
||||
device_cbox->Append( wxString::FromAscii( dq.ToString().c_str() ) );
|
||||
}
|
||||
|
||||
control_chooser = new ControlChooser( this, ref, parent );
|
||||
|
||||
wxStaticBoxSizer* d_szr = new wxStaticBoxSizer( wxVERTICAL, this, wxT("Device") );
|
||||
d_szr->Add( device_cbox, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
wxBoxSizer* szr = new wxBoxSizer( wxVERTICAL );
|
||||
szr->Add( d_szr, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
szr->Add( control_chooser, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
SetSizerAndFit( szr );
|
||||
|
||||
}
|
||||
|
||||
ControlButton::ControlButton( wxWindow* const parent, ControllerInterface::ControlReference* const _ref, const unsigned int width, const std::string& label )
|
||||
: wxButton( parent, -1, wxT(""), wxDefaultPosition, wxSize( width,20) )
|
||||
, control_reference( _ref )
|
||||
{
|
||||
if ( label.empty() )
|
||||
SetLabel( wxString::FromAscii( _ref->control_qualifier.name.c_str() ) );
|
||||
else
|
||||
SetLabel( wxString::FromAscii( label.c_str() ) );
|
||||
}
|
||||
|
||||
void ConfigDialog::UpdateProfileComboBox()
|
||||
{
|
||||
std::string pname( File::GetUserPath(D_CONFIG_IDX) );
|
||||
pname += PROFILES_PATH;
|
||||
|
||||
CFileSearch::XStringVector exts;
|
||||
exts.push_back("*.ini");
|
||||
CFileSearch::XStringVector dirs;
|
||||
dirs.push_back( pname );
|
||||
CFileSearch cfs( exts, dirs );
|
||||
const CFileSearch::XStringVector& sv = cfs.GetFileNames();
|
||||
|
||||
wxArrayString strs;
|
||||
CFileSearch::XStringVector::const_iterator si = sv.begin(),
|
||||
se = sv.end();
|
||||
for ( ; si!=se; ++si )
|
||||
{
|
||||
std::string str( si->begin() + si->find_last_of('/') + 1 , si->end() - 4 ) ;
|
||||
strs.push_back( wxString::FromAscii( str.c_str() ) );
|
||||
}
|
||||
|
||||
std::vector< GamepadPage* >::iterator i = m_padpages.begin(),
|
||||
e = m_padpages.end();
|
||||
for ( ; i != e; ++i )
|
||||
{
|
||||
(*i)->profile_cbox->Clear();
|
||||
(*i)->profile_cbox->Append(strs);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigDialog::UpdateControlReferences()
|
||||
{
|
||||
std::vector< GamepadPage* >::iterator i = m_padpages.begin(),
|
||||
e = m_padpages.end();
|
||||
for ( ; i != e; ++i )
|
||||
(*i)->controller->UpdateReferences( m_plugin.controller_interface );
|
||||
}
|
||||
|
||||
void ConfigDialog::ClickSave( wxCommandEvent& event )
|
||||
{
|
||||
m_plugin.SaveConfig();
|
||||
Close();
|
||||
};
|
||||
|
||||
void ControlChooser::UpdateGUI()
|
||||
{
|
||||
control_lbox->Clear();
|
||||
|
||||
// make sure it's a valid device
|
||||
if ( control_reference->device )
|
||||
{
|
||||
if ( control_reference->is_input )
|
||||
{
|
||||
// for inputs
|
||||
std::vector<ControllerInterface::Device::Input*>::const_iterator
|
||||
i = control_reference->device->Inputs().begin(),
|
||||
e = control_reference->device->Inputs().end();
|
||||
for ( ; i!=e; ++i )
|
||||
control_lbox->Append( wxString::FromAscii( (*i)->GetName().c_str() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// for outputs
|
||||
std::vector<ControllerInterface::Device::Output*>::const_iterator
|
||||
i = control_reference->device->Outputs().begin(),
|
||||
e = control_reference->device->Outputs().end();
|
||||
for ( ; i!=e; ++i )
|
||||
control_lbox->Append( wxString::FromAscii( (*i)->GetName().c_str() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// logic not 100% right here for a poorly formated qualifier
|
||||
// but its just for selecting crap in the listbox
|
||||
wxArrayString control_names = control_lbox->GetStrings();
|
||||
const std::string cname = control_reference->control_qualifier.name;
|
||||
for ( int i = int(control_names.size()) - 1; i >=0; --i )
|
||||
{
|
||||
if ( cname == std::string(control_names[i].ToAscii()) ||
|
||||
cname.find( control_names[i].Prepend(wxT('|')).Append(wxT('|')).ToAscii() ) != std::string::npos )
|
||||
control_lbox->Select( i );
|
||||
else
|
||||
control_lbox->Deselect( i );
|
||||
}
|
||||
|
||||
size_t bound = control_reference->controls.size();
|
||||
std::ostringstream ss;
|
||||
ss << "Bound Controls: ";
|
||||
if ( bound ) ss << bound; else ss << "None";
|
||||
m_bound_label->SetLabel( wxString::FromAscii(ss.str().c_str()) );
|
||||
|
||||
textctrl->SetValue( wxString::FromAscii( control_reference->control_qualifier.name.c_str() ) );
|
||||
};
|
||||
|
||||
void GamepadPage::UpdateGUI()
|
||||
{
|
||||
device_cbox->SetLabel( wxString::FromAscii( controller->default_device.ToString().c_str() ) );
|
||||
|
||||
std::vector< ControlGroupBox* >::const_iterator
|
||||
g = control_groups.begin(),
|
||||
ge = control_groups.end();
|
||||
for ( ; g!=ge; ++g )
|
||||
{
|
||||
// buttons
|
||||
std::vector<ControlButton*>::const_iterator
|
||||
i = (*g)->control_buttons.begin(),
|
||||
e = (*g)->control_buttons.end();
|
||||
for ( ; i!=e; ++i )
|
||||
(*i)->SetLabel( wxString::FromAscii( (*i)->control_reference->control_qualifier.name.c_str() ) );
|
||||
|
||||
// settings
|
||||
std::vector<PadSetting*>::const_iterator
|
||||
si = (*g)->options.begin(),
|
||||
se = (*g)->options.end();
|
||||
for ( ; si!=se; ++si )
|
||||
(*si)->UpdateGUI();
|
||||
}
|
||||
}
|
||||
|
||||
void GamepadPage::ClearAll( wxCommandEvent& event )
|
||||
{
|
||||
m_plugin.controls_crit.Enter(); // enter
|
||||
|
||||
// just load an empty ini section to clear everything :P
|
||||
IniSection Section = IniSection();
|
||||
ControllerInterface Face = ControllerInterface();
|
||||
controller->LoadConfig( Section );
|
||||
|
||||
// no point in using the real ControllerInterface i guess
|
||||
controller->UpdateReferences( Face );
|
||||
|
||||
UpdateGUI();
|
||||
|
||||
m_plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
void GamepadPage::SetControl( wxCommandEvent& event )
|
||||
{
|
||||
m_plugin.controls_crit.Enter(); // enter
|
||||
|
||||
m_control_dialog->control_reference->control_qualifier.name = std::string( m_control_dialog->control_chooser->textctrl->GetValue().ToAscii() );
|
||||
m_control_dialog->control_reference->UpdateControls();
|
||||
m_control_dialog->control_chooser->UpdateGUI();
|
||||
|
||||
UpdateGUI();
|
||||
|
||||
m_plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
void GamepadPage::SetDevice( wxCommandEvent& event )
|
||||
{
|
||||
m_plugin.controls_crit.Enter(); // enter
|
||||
|
||||
// TODO: need to handle the ConfigControl device in here
|
||||
|
||||
// default device
|
||||
if ( event.GetEventObject() == device_cbox )
|
||||
{
|
||||
controller->default_device.FromString( std::string( device_cbox->GetValue().ToAscii() ) );
|
||||
|
||||
// show user what it was validated as
|
||||
device_cbox->SetValue( wxString::FromAscii( controller->default_device.ToString().c_str() ) );
|
||||
|
||||
// this will set all the controls to this default device
|
||||
controller->UpdateDefaultDevice();
|
||||
|
||||
// update references
|
||||
controller->UpdateReferences( m_plugin.controller_interface );
|
||||
}
|
||||
// control dialog
|
||||
else
|
||||
{
|
||||
m_control_dialog->control_reference->device_qualifier.FromString( std::string( m_control_dialog->device_cbox->GetValue().ToAscii() ) );
|
||||
|
||||
m_control_dialog->device_cbox->SetValue( wxString::FromAscii( m_control_dialog->control_reference->device_qualifier.ToString().c_str() ) );
|
||||
|
||||
m_plugin.controller_interface.UpdateReference( m_control_dialog->control_reference );
|
||||
|
||||
m_control_dialog->control_chooser->UpdateGUI();
|
||||
|
||||
}
|
||||
|
||||
m_plugin.controls_crit.Leave(); // leave
|
||||
|
||||
}
|
||||
|
||||
void GamepadPage::ClearControl( wxCommandEvent& event )
|
||||
{
|
||||
m_control_dialog->control_reference->control_qualifier.name.clear();
|
||||
m_control_dialog->control_reference->UpdateControls();
|
||||
m_control_dialog->control_chooser->UpdateGUI();
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void GamepadPage::AdjustSetting( wxCommandEvent& event )
|
||||
{
|
||||
m_plugin.controls_crit.Enter(); // enter
|
||||
|
||||
// updates the setting value from the GUI control
|
||||
(dynamic_cast<PadSetting*>(event.GetEventObject()))->UpdateValue();
|
||||
|
||||
m_plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
void GamepadPage::AdjustControlOption( wxCommandEvent& event )
|
||||
{
|
||||
m_plugin.controls_crit.Enter(); // enter
|
||||
|
||||
m_control_dialog->control_reference->range = ControlState( m_control_dialog->control_chooser->range_slider->GetValue() ) / SLIDER_TICK_COUNT;
|
||||
|
||||
if ( m_control_dialog->control_reference->is_input )
|
||||
{
|
||||
((ControllerInterface::InputReference*)m_control_dialog->control_reference)->mode = m_control_dialog->control_chooser->mode_cbox->GetSelection();
|
||||
}
|
||||
|
||||
m_plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
void GamepadPage::ConfigControl( wxCommandEvent& event )
|
||||
{
|
||||
m_control_dialog = new ControlDialog( this, ((ControlButton*)event.GetEventObject())->control_reference, m_plugin.controller_interface.Devices() );
|
||||
m_control_dialog->ShowModal();
|
||||
m_control_dialog->Destroy();
|
||||
}
|
||||
|
||||
void GamepadPage::ConfigDetectControl( wxCommandEvent& event )
|
||||
{
|
||||
m_plugin.controls_crit.Enter(); // enter
|
||||
|
||||
// major major hacks
|
||||
wxChar num = ((wxButton*)event.GetEventObject())->GetLabel()[0];
|
||||
if ( num > '9' )
|
||||
num = 1;
|
||||
else
|
||||
num -= 0x30;
|
||||
|
||||
if ( m_control_dialog->control_reference->Detect( DETECT_WAIT_TIME, num ) ) // if we got input, update control
|
||||
{
|
||||
UpdateGUI();
|
||||
m_control_dialog->control_chooser->UpdateGUI();
|
||||
}
|
||||
|
||||
m_plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
void GamepadPage::DetectControl( wxCommandEvent& event )
|
||||
{
|
||||
ControlButton* btn = (ControlButton*)event.GetEventObject();
|
||||
|
||||
m_plugin.controls_crit.Enter(); // enter
|
||||
|
||||
btn->control_reference->Detect( DETECT_WAIT_TIME );
|
||||
btn->SetLabel( wxString::FromAscii( btn->control_reference->control_qualifier.name.c_str() ) );
|
||||
|
||||
m_plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
void ControlDialog::SelectControl( wxCommandEvent& event )
|
||||
{
|
||||
wxListBox* lb = (wxListBox*)event.GetEventObject();
|
||||
|
||||
wxArrayInt sels;
|
||||
lb->GetSelections( sels );
|
||||
wxArrayString names = lb->GetStrings();
|
||||
|
||||
wxString final_label;
|
||||
|
||||
if ( sels.size() == 1 )
|
||||
final_label = names[ sels[0] ];
|
||||
//else if ( sels.size() == lb->GetCount() )
|
||||
// final_label = "||";
|
||||
else
|
||||
{
|
||||
final_label = wxT('|');
|
||||
for ( unsigned int i=0; i<sels.size(); ++i )
|
||||
final_label += names[ sels[i] ] + wxT('|');
|
||||
}
|
||||
if (!final_label.CompareTo(wxT("|")))
|
||||
final_label.Empty();
|
||||
|
||||
#ifdef __linux__
|
||||
if (!((wxWindow*)this)->IsBeingDeleted())
|
||||
#endif
|
||||
control_chooser->textctrl->SetValue( final_label );
|
||||
|
||||
#ifndef __linux__ // This causes the application to hang in linux
|
||||
// kinda dumb
|
||||
wxCommandEvent nullevent;
|
||||
((GamepadPage*)m_parent)->SetControl( nullevent );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
ControlChooser::ControlChooser( wxWindow* const parent, ControllerInterface::ControlReference* const ref, wxWindow* const eventsink )
|
||||
: wxStaticBoxSizer( wxVERTICAL, parent, ref->is_input ? wxT("Input") : wxT("Output") )
|
||||
, control_reference(ref)
|
||||
{
|
||||
#define _connect_macro_( b, f, c ) (b)->Connect( wxID_ANY, (c), wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)eventsink );
|
||||
|
||||
textctrl = new wxTextCtrl( parent, -1 );
|
||||
wxButton* detect_button = new wxButton( parent, -1, ref->is_input ? wxT("Detect 1") : wxT("Test") );
|
||||
wxButton* clear_button = new wxButton( parent, -1, wxT("Clear"), wxDefaultPosition );
|
||||
wxButton* set_button = new wxButton( parent, -1, wxT("Set")/*, wxDefaultPosition, wxSize( 32, -1 )*/ );
|
||||
|
||||
control_lbox = new wxListBox( parent, -1, wxDefaultPosition, wxSize( 256, 128 ), wxArrayString(), wxLB_EXTENDED );
|
||||
|
||||
control_lbox->Connect( wxID_ANY, wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( ControlDialog::SelectControl ), (wxObject*)0, parent );
|
||||
|
||||
wxBoxSizer* button_sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
button_sizer->Add( detect_button, 1, 0, 5 );
|
||||
if ( ref->is_input )
|
||||
for ( unsigned int i = 2; i<5; ++i )
|
||||
{
|
||||
wxButton* d_btn = new wxButton( parent, -1, wxChar( '0'+i ), wxDefaultPosition, wxSize(16,-1) );
|
||||
_connect_macro_( d_btn, ConfigDetectControl, wxEVT_COMMAND_BUTTON_CLICKED);
|
||||
button_sizer->Add( d_btn );
|
||||
}
|
||||
button_sizer->Add( clear_button, 1, 0, 5 );
|
||||
button_sizer->Add( set_button, 1, 0, 5 );
|
||||
|
||||
range_slider = new wxSlider( parent, -1, SLIDER_TICK_COUNT, 0, SLIDER_TICK_COUNT, wxDefaultPosition, wxDefaultSize, wxSL_TOP | wxSL_LABELS /*| wxSL_AUTOTICKS*/ );
|
||||
|
||||
range_slider->SetValue( control_reference->range * SLIDER_TICK_COUNT );
|
||||
|
||||
_connect_macro_( detect_button, ConfigDetectControl, wxEVT_COMMAND_BUTTON_CLICKED);
|
||||
_connect_macro_( clear_button, ClearControl, wxEVT_COMMAND_BUTTON_CLICKED);
|
||||
_connect_macro_( set_button, SetControl, wxEVT_COMMAND_BUTTON_CLICKED);
|
||||
|
||||
_connect_macro_( range_slider, AdjustControlOption, wxEVT_SCROLL_CHANGED);
|
||||
wxStaticText* range_label = new wxStaticText( parent, -1, wxT("Range"));
|
||||
m_bound_label = new wxStaticText( parent, -1, wxT("") );
|
||||
|
||||
wxBoxSizer* range_sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
range_sizer->Add( range_label, 0, wxCENTER|wxLEFT, 5 );
|
||||
range_sizer->Add( range_slider, 1, wxEXPAND|wxLEFT, 5 );
|
||||
|
||||
wxBoxSizer* txtbox_szr = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
txtbox_szr->Add( textctrl, 1, wxEXPAND, 0 );
|
||||
|
||||
wxBoxSizer* mode_szr = NULL;
|
||||
if ( control_reference->is_input )
|
||||
{
|
||||
mode_cbox = new wxChoice( parent, -1 );
|
||||
mode_cbox->Append( wxT("OR") );
|
||||
mode_cbox->Append( wxT("AND") );
|
||||
mode_cbox->Append( wxT("NOT") );
|
||||
mode_cbox->Select( ((ControllerInterface::InputReference*)control_reference)->mode );
|
||||
|
||||
_connect_macro_( mode_cbox, AdjustControlOption, wxEVT_COMMAND_CHOICE_SELECTED );
|
||||
|
||||
mode_szr = new wxBoxSizer( wxHORIZONTAL );
|
||||
mode_szr->Add( new wxStaticText( parent, -1, wxT("Mode") ), 0, wxCENTER|wxLEFT|wxRIGHT, 5 );
|
||||
mode_szr->Add( mode_cbox, 0, wxLEFT, 5 );
|
||||
}
|
||||
|
||||
Add( range_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
if ( control_reference->is_input )
|
||||
Add( mode_szr, 0, wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
Add( txtbox_szr, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
|
||||
Add( button_sizer, 0, wxEXPAND|wxBOTTOM|wxLEFT|wxRIGHT, 5 );
|
||||
Add( control_lbox, 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
|
||||
Add( m_bound_label, 0, wxEXPAND|wxLEFT, 80 );
|
||||
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void GamepadPage::LoadProfile( wxCommandEvent& event )
|
||||
{
|
||||
// TODO: check for dumb characters maybe
|
||||
if ( profile_cbox->GetValue().empty() )
|
||||
return;
|
||||
|
||||
m_plugin.controls_crit.Enter();
|
||||
|
||||
std::ifstream file;
|
||||
std::string fname( File::GetUserPath(D_CONFIG_IDX) );
|
||||
fname += PROFILES_PATH; fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
|
||||
|
||||
if ( false == File::Exists( fname.c_str() ) )
|
||||
return;
|
||||
|
||||
file.open( fname.c_str() );
|
||||
IniFile inifile;
|
||||
inifile.Load( file );
|
||||
controller->LoadConfig( inifile["Profile"] );
|
||||
file.close();
|
||||
|
||||
controller->UpdateReferences( m_plugin.controller_interface );
|
||||
|
||||
m_plugin.controls_crit.Leave();
|
||||
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void GamepadPage::SaveProfile( wxCommandEvent& event )
|
||||
{
|
||||
// TODO: check for dumb characters
|
||||
if ( profile_cbox->GetValue().empty() )
|
||||
return;
|
||||
|
||||
// don't need lock
|
||||
IniFile inifile;
|
||||
controller->SaveConfig( inifile["Profile"] );
|
||||
std::ofstream file;
|
||||
std::string fname( File::GetUserPath(D_CONFIG_IDX) );
|
||||
fname += PROFILES_PATH;
|
||||
|
||||
if ( false == File::Exists( fname.c_str() ) )
|
||||
File::CreateFullPath( fname.c_str() );
|
||||
|
||||
fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
|
||||
|
||||
file.open( fname.c_str() );
|
||||
inifile.Save( file );
|
||||
file.close();
|
||||
|
||||
m_config_dialog->UpdateProfileComboBox();
|
||||
}
|
||||
|
||||
void GamepadPage::DeleteProfile( wxCommandEvent& event )
|
||||
{
|
||||
// TODO: check for dumb characters maybe
|
||||
if ( profile_cbox->GetValue().empty() )
|
||||
return;
|
||||
|
||||
// don't need lock
|
||||
std::string fname( File::GetUserPath(D_CONFIG_IDX) );
|
||||
fname += PROFILES_PATH; fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
|
||||
if ( File::Exists( fname.c_str() ) )
|
||||
File::Delete( fname.c_str() );
|
||||
|
||||
m_config_dialog->UpdateProfileComboBox();
|
||||
}
|
||||
|
||||
void ConfigDialog::UpdateDeviceComboBox()
|
||||
{
|
||||
std::vector< GamepadPage* >::iterator i = m_padpages.begin(),
|
||||
e = m_padpages.end();
|
||||
ControllerInterface::DeviceQualifier dq;
|
||||
for ( ; i != e; ++i )
|
||||
{
|
||||
(*i)->device_cbox->Clear();
|
||||
std::vector<ControllerInterface::Device*>::const_iterator di = m_plugin.controller_interface.Devices().begin(),
|
||||
de = m_plugin.controller_interface.Devices().end();
|
||||
for ( ; di!=de; ++di )
|
||||
{
|
||||
dq.FromDevice( *di );
|
||||
(*i)->device_cbox->Append( wxString::FromAscii( dq.ToString().c_str() ) );
|
||||
}
|
||||
(*i)->device_cbox->SetValue( wxString::FromAscii( (*i)->controller->default_device.ToString().c_str() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void GamepadPage::RefreshDevices( wxCommandEvent& event )
|
||||
{
|
||||
m_plugin.controls_crit.Enter(); // enter
|
||||
|
||||
// refresh devices
|
||||
m_plugin.controller_interface.DeInit();
|
||||
m_plugin.controller_interface.Init();
|
||||
|
||||
// update all control references
|
||||
m_config_dialog->UpdateControlReferences();
|
||||
|
||||
// update device cbox
|
||||
m_config_dialog->UpdateDeviceComboBox();
|
||||
|
||||
m_plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent )
|
||||
: wxStaticBoxSizer( wxVERTICAL, parent, wxString::FromAscii( group->name ) )
|
||||
{
|
||||
|
||||
control_group = group;
|
||||
static_bitmap = NULL;
|
||||
|
||||
for ( unsigned int c = 0; c < group->controls.size(); ++c )
|
||||
{
|
||||
|
||||
wxStaticText* label = new wxStaticText( parent, -1, wxString::FromAscii( group->controls[c]->name )/*.append(wxT(" :"))*/ );
|
||||
ControlButton* control_button = new ControlButton( parent, group->controls[c]->control_ref, 80 );
|
||||
controls.push_back( control_button );
|
||||
ControlButton* adv_button = new ControlButton( parent, group->controls[c]->control_ref, 16, "+" );
|
||||
|
||||
control_buttons.push_back( control_button );
|
||||
|
||||
control_button->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GamepadPage::DetectControl ),
|
||||
(wxObject*)0, (wxEvtHandler*)parent );
|
||||
|
||||
adv_button->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GamepadPage::ConfigControl ),
|
||||
(wxObject*)0, (wxEvtHandler*)parent );
|
||||
|
||||
wxBoxSizer* control_sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
control_sizer->AddStretchSpacer( 1 );
|
||||
control_sizer->Add( label, 0, wxCENTER | wxRIGHT, 5 );
|
||||
control_sizer->Add( control_button, 0, 0, 0 );
|
||||
control_sizer->Add( adv_button, 0, 0, 5 );
|
||||
|
||||
Add( control_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
}
|
||||
|
||||
switch ( group->type )
|
||||
{
|
||||
case GROUP_TYPE_STICK :
|
||||
{
|
||||
wxBitmap bitmap(64, 64);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
dc.Clear();
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
|
||||
static_bitmap = new wxStaticBitmap( parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP );
|
||||
|
||||
PadSettingChoice* deadzone_cbox = new PadSettingChoice( parent, group->settings[0]->value, 1, 50 );
|
||||
PadSettingChoice* diagonal_cbox = new PadSettingChoice( parent, group->settings[1]->value, 1, 100 );
|
||||
|
||||
deadzone_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
|
||||
diagonal_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
|
||||
|
||||
options.push_back( deadzone_cbox );
|
||||
options.push_back( diagonal_cbox );
|
||||
|
||||
wxBoxSizer* szr = new wxBoxSizer( wxVERTICAL );
|
||||
szr->Add( new wxStaticText( parent, -1, wxString::FromAscii( group->settings[0]->name ) ) );
|
||||
szr->Add( deadzone_cbox, 0, wxLEFT, 0 );
|
||||
szr->Add( new wxStaticText( parent, -1, wxString::FromAscii( group->settings[1]->name ) ) );
|
||||
szr->Add( diagonal_cbox, 0, wxLEFT, 0 );
|
||||
|
||||
wxBoxSizer* h_szr = new wxBoxSizer( wxHORIZONTAL );
|
||||
h_szr->Add( szr, 1, 0, 5 );
|
||||
h_szr->Add( static_bitmap, 0, wxALL|wxCENTER, 5 );
|
||||
|
||||
Add( h_szr, 0, wxEXPAND|wxLEFT|wxCENTER|wxTOP, 5 );
|
||||
}
|
||||
break;
|
||||
case GROUP_TYPE_BUTTONS :
|
||||
{
|
||||
wxBitmap bitmap(int(12*group->controls.size()+1), 12);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
dc.Clear();
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
static_bitmap = new wxStaticBitmap( parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP );
|
||||
|
||||
PadSettingChoice* threshold_cbox = new PadSettingChoice( parent, group->settings[0]->value, 1, 99 );
|
||||
threshold_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
|
||||
|
||||
options.push_back( threshold_cbox );
|
||||
|
||||
wxBoxSizer* szr = new wxBoxSizer( wxHORIZONTAL );
|
||||
szr->Add( new wxStaticText( parent, -1, wxString::FromAscii( group->settings[0]->name ) ), 0, wxCENTER|wxRIGHT, 5 );
|
||||
szr->Add( threshold_cbox, 0, wxRIGHT, 5 );
|
||||
|
||||
Add( szr, 0, wxALL|wxCENTER, 5 );
|
||||
Add( static_bitmap, 0, wxALL|wxCENTER, 5 );
|
||||
}
|
||||
break;
|
||||
case GROUP_TYPE_MIXED_TRIGGERS :
|
||||
{
|
||||
wxBitmap bitmap(64+12+1, int(6*group->controls.size())+1);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
dc.Clear();
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
static_bitmap = new wxStaticBitmap( parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP );
|
||||
|
||||
PadSettingChoice* threshold_cbox = new PadSettingChoice( parent, group->settings[0]->value, 1, 99 );
|
||||
threshold_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
|
||||
|
||||
options.push_back( threshold_cbox );
|
||||
|
||||
wxBoxSizer* szr = new wxBoxSizer( wxHORIZONTAL );
|
||||
szr->Add( new wxStaticText( parent, -1, wxString::FromAscii( group->settings[0]->name ) ), 0, wxCENTER|wxRIGHT, 5 );
|
||||
szr->Add( threshold_cbox, 0, wxRIGHT, 5 );
|
||||
|
||||
Add( szr, 0, wxALL|wxCENTER, 5 );
|
||||
Add( static_bitmap, 0, wxALL|wxCENTER, 5 );
|
||||
}
|
||||
break;
|
||||
default :
|
||||
{
|
||||
std::vector<ControllerEmu::ControlGroup::Setting*>::const_iterator
|
||||
i = group->settings.begin(),
|
||||
e = group->settings.end();
|
||||
for ( ; i!=e; ++i )
|
||||
{
|
||||
PadSettingCheckBox* setting_cbox = new PadSettingCheckBox( parent, (*i)->value, (*i)->name );
|
||||
setting_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
|
||||
options.push_back( setting_cbox );
|
||||
|
||||
Add( setting_cbox, 0, wxALL|wxCENTER, 5 );
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
//AddStretchSpacer( 0 );
|
||||
}
|
||||
|
||||
GamepadPage::GamepadPage( wxWindow* parent, Plugin& plugin, const unsigned int pad_num, ConfigDialog* const config_dialog )
|
||||
: wxNotebookPage( parent, -1 , wxDefaultPosition, wxDefaultSize )
|
||||
,controller(plugin.controllers[pad_num])
|
||||
,m_plugin(plugin)
|
||||
,m_config_dialog(config_dialog)
|
||||
{
|
||||
|
||||
wxBoxSizer* control_group_sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* stacked_groups = NULL;
|
||||
for ( unsigned int i = 0; i < m_plugin.controllers[pad_num]->groups.size(); ++i )
|
||||
{
|
||||
ControlGroupBox* control_group = new ControlGroupBox( m_plugin.controllers[pad_num]->groups[i], this );
|
||||
|
||||
if ( control_group->control_buttons.size() > 2 )
|
||||
{
|
||||
if ( stacked_groups )
|
||||
control_group_sizer->Add( stacked_groups, 0, /*wxEXPAND|*/wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
stacked_groups = new wxBoxSizer( wxVERTICAL );
|
||||
stacked_groups->Add( control_group, 0, wxEXPAND );
|
||||
}
|
||||
else
|
||||
stacked_groups->Add( control_group, 0, wxEXPAND );
|
||||
|
||||
control_groups.push_back( control_group );
|
||||
}
|
||||
|
||||
if ( stacked_groups )
|
||||
control_group_sizer->Add( stacked_groups, 0, /*wxEXPAND|*/wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
wxStaticBoxSizer* profile_sbox = new wxStaticBoxSizer( wxHORIZONTAL, this, wxT("Profile") );
|
||||
|
||||
// device chooser
|
||||
|
||||
wxStaticBoxSizer* device_sbox = new wxStaticBoxSizer( wxHORIZONTAL, this, wxT("Device") );
|
||||
|
||||
device_cbox = new wxComboBox( this, -1, wxT(""), wxDefaultPosition, wxSize(128,-1), 0, 0, wxTE_PROCESS_ENTER );
|
||||
|
||||
wxButton* refresh_button = new wxButton( this, -1, wxT("Refresh"), wxDefaultPosition, wxSize(48,-1) );
|
||||
|
||||
#define _connect_macro3_( b, f, c ) (b)->Connect( wxID_ANY, c, wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)this );
|
||||
|
||||
_connect_macro3_( device_cbox, SetDevice, wxEVT_COMMAND_COMBOBOX_SELECTED );
|
||||
_connect_macro3_( device_cbox, SetDevice, wxEVT_COMMAND_TEXT_ENTER );
|
||||
_connect_macro3_( refresh_button, RefreshDevices, wxEVT_COMMAND_BUTTON_CLICKED );
|
||||
|
||||
device_sbox->Add( device_cbox, 1, wxLEFT|wxRIGHT, 5 );
|
||||
device_sbox->Add( refresh_button, 0, wxRIGHT|wxBOTTOM, 5 );
|
||||
|
||||
wxStaticBoxSizer* clear_sbox = new wxStaticBoxSizer( wxHORIZONTAL, this, wxT("Clear") );
|
||||
wxButton* all_button = new wxButton( this, -1, wxT("All"), wxDefaultPosition, wxSize(48,-1) );
|
||||
clear_sbox->Add( all_button, 1, wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
all_button->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GamepadPage::ClearAll ),
|
||||
(wxObject*)0, (wxEvtHandler*)this );
|
||||
|
||||
profile_cbox = new wxComboBox( this, -1, wxT(""), wxDefaultPosition, wxSize(128,-1) );
|
||||
|
||||
wxButton* const pload_btn = new wxButton( this, -1, wxT("Load"), wxDefaultPosition, wxSize(48,-1) );
|
||||
wxButton* const psave_btn = new wxButton( this, -1, wxT("Save"), wxDefaultPosition, wxSize(48,-1) );
|
||||
wxButton* const pdelete_btn = new wxButton( this, -1, wxT("Delete"), wxDefaultPosition, wxSize(48,-1) );
|
||||
|
||||
pload_btn->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GamepadPage::LoadProfile ),
|
||||
(wxObject*)0, (wxEvtHandler*)this );
|
||||
psave_btn->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GamepadPage::SaveProfile ),
|
||||
(wxObject*)0, (wxEvtHandler*)this );
|
||||
pdelete_btn->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GamepadPage::DeleteProfile ),
|
||||
(wxObject*)0, (wxEvtHandler*)this );
|
||||
|
||||
profile_sbox->Add( profile_cbox, 1, wxLEFT, 5 );
|
||||
profile_sbox->Add( pload_btn, 0, wxLEFT, 5 );
|
||||
profile_sbox->Add( psave_btn, 0, 0, 5 );
|
||||
profile_sbox->Add( pdelete_btn, 0, wxRIGHT|wxBOTTOM, 5 );
|
||||
|
||||
wxBoxSizer* dio = new wxBoxSizer( wxHORIZONTAL );
|
||||
dio->Add( device_sbox, 1, wxEXPAND|wxRIGHT, 5 );
|
||||
dio->Add( clear_sbox, 0, wxEXPAND|wxRIGHT, 5 );
|
||||
dio->Add( profile_sbox, 1, wxEXPAND|wxRIGHT, 5 );
|
||||
|
||||
wxBoxSizer* mapping = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
mapping->Add( dio, 1, wxEXPAND|wxLEFT|wxTOP|wxBOTTOM, 5 );
|
||||
mapping->Add( control_group_sizer, 0, wxLEFT|wxEXPAND, 5 );
|
||||
|
||||
UpdateGUI();
|
||||
|
||||
SetSizerAndFit( mapping );
|
||||
Layout();
|
||||
};
|
||||
|
||||
ConfigDialog::~ConfigDialog()
|
||||
{
|
||||
m_update_timer->Stop();
|
||||
}
|
||||
|
||||
ConfigDialog::ConfigDialog( wxWindow* const parent, Plugin& plugin, const std::string& name, const bool _is_game_running )
|
||||
: wxDialog( parent, wxID_ANY, wxString::FromAscii(name.c_str()), wxPoint(128,-1), wxDefaultSize )
|
||||
, is_game_running(_is_game_running)
|
||||
, m_plugin(plugin)
|
||||
{
|
||||
m_pad_notebook = new wxNotebook( this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT );
|
||||
for ( unsigned int i = 0; i < plugin.controllers.size(); ++i )
|
||||
{
|
||||
GamepadPage* gp = new GamepadPage( m_pad_notebook, plugin, i, this );
|
||||
m_padpages.push_back( gp );
|
||||
m_pad_notebook->AddPage( gp, wxString::FromAscii((plugin.controllers[i]->GetName().c_str())) );
|
||||
}
|
||||
|
||||
UpdateDeviceComboBox();
|
||||
UpdateProfileComboBox();
|
||||
|
||||
wxButton* close_button = new wxButton( this, -1, wxT("Save"));
|
||||
|
||||
close_button->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigDialog::ClickSave ), (wxObject*)0, (wxEvtHandler*)this );
|
||||
|
||||
wxBoxSizer* btns = new wxBoxSizer( wxHORIZONTAL );
|
||||
//btns->Add( new wxStaticText( this, -1, wxString::FromAscii(ver.c_str())), 0, wxLEFT|wxTOP, 5 );
|
||||
btns->AddStretchSpacer();
|
||||
btns->Add( close_button, 0, 0, 0 );
|
||||
|
||||
wxBoxSizer* szr = new wxBoxSizer( wxVERTICAL );
|
||||
szr->Add( m_pad_notebook, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
|
||||
szr->Add( btns, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
SetSizerAndFit( szr );
|
||||
// not needed here it seems, but it cant hurt
|
||||
//Layout();
|
||||
|
||||
Center();
|
||||
|
||||
// live preview update timer
|
||||
m_update_timer = new wxTimer( this, -1 );
|
||||
Connect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( ConfigDialog::UpdateBitmaps ), (wxObject*)0, this );
|
||||
m_update_timer->Start( PREVIEW_UPDATE_TIME, wxTIMER_CONTINUOUS);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
#ifndef _CONFIGBOX_H_
|
||||
#define _CONFIGBOX_H_
|
||||
|
||||
#define SLIDER_TICK_COUNT 100
|
||||
#define DETECT_WAIT_TIME 1500
|
||||
#define PREVIEW_UPDATE_TIME 25
|
||||
|
||||
// might have to change this setup for wiimote
|
||||
#define PROFILES_PATH "Profiles/GCPad/"
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/listbox.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "ControllerInterface/ControllerInterface.h"
|
||||
#include "Config.h"
|
||||
#include "FileSearch.h"
|
||||
|
||||
class PadSetting
|
||||
{
|
||||
protected:
|
||||
PadSetting( ControlState& _value ) : value(_value) {}
|
||||
|
||||
public:
|
||||
virtual void UpdateGUI() = 0;
|
||||
virtual void UpdateValue() = 0;
|
||||
|
||||
ControlState& value;
|
||||
};
|
||||
|
||||
class PadSettingChoice : public PadSetting, public wxChoice
|
||||
{
|
||||
public:
|
||||
PadSettingChoice( wxWindow* const parent, ControlState& _value, int min, int max );
|
||||
void UpdateGUI();
|
||||
void UpdateValue();
|
||||
};
|
||||
|
||||
class PadSettingCheckBox : public PadSetting, public wxCheckBox
|
||||
{
|
||||
public:
|
||||
PadSettingCheckBox( wxWindow* const parent, ControlState& _value, const char* const label );
|
||||
void UpdateGUI();
|
||||
void UpdateValue();
|
||||
};
|
||||
|
||||
|
||||
class ControlChooser : public wxStaticBoxSizer
|
||||
{
|
||||
public:
|
||||
ControlChooser( wxWindow* const parent, ControllerInterface::ControlReference* const ref, wxWindow* const eventsink );
|
||||
|
||||
void UpdateGUI();
|
||||
|
||||
ControllerInterface::ControlReference* control_reference;
|
||||
|
||||
wxTextCtrl* textctrl;
|
||||
wxListBox* control_lbox;
|
||||
wxChoice* mode_cbox;
|
||||
wxSlider* range_slider;
|
||||
|
||||
private:
|
||||
wxStaticText* m_bound_label;
|
||||
};
|
||||
|
||||
class ControlList : public wxDialog
|
||||
{
|
||||
public:
|
||||
|
||||
ControlList( wxWindow* const parent, ControllerInterface::ControlReference* const ref, ControlChooser* const chooser );
|
||||
|
||||
private:
|
||||
ControlChooser* const m_control_chooser;
|
||||
};
|
||||
|
||||
class ControlDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
ControlDialog( wxWindow* const parent, ControllerInterface::ControlReference* const ref, const std::vector<ControllerInterface::Device*>& devs );
|
||||
void SelectControl( wxCommandEvent& event );
|
||||
|
||||
ControllerInterface::ControlReference* const control_reference;
|
||||
wxComboBox* device_cbox;
|
||||
ControlChooser* control_chooser;
|
||||
};
|
||||
|
||||
class ControlButton : public wxButton
|
||||
{
|
||||
public:
|
||||
ControlButton( wxWindow* const parent, ControllerInterface::ControlReference* const _ref, const unsigned int width, const std::string& label = "" );
|
||||
|
||||
ControllerInterface::ControlReference* const control_reference;
|
||||
};
|
||||
|
||||
class ControlGroupBox : public wxStaticBoxSizer
|
||||
{
|
||||
public:
|
||||
ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent );
|
||||
|
||||
ControllerEmu::ControlGroup* control_group;
|
||||
wxStaticBitmap* static_bitmap;
|
||||
std::vector< PadSetting* > options;
|
||||
std::vector< wxButton* > controls;
|
||||
std::vector<ControlButton*> control_buttons;
|
||||
};
|
||||
|
||||
class ConfigDialog;
|
||||
|
||||
class GamepadPage : public wxNotebookPage
|
||||
{
|
||||
friend class ConfigDialog;
|
||||
|
||||
public:
|
||||
GamepadPage( wxWindow* parent, Plugin& plugin, const unsigned int pad_num, ConfigDialog* const config_dialog );
|
||||
|
||||
void UpdateGUI();
|
||||
|
||||
void RefreshDevices( wxCommandEvent& event );
|
||||
|
||||
void LoadProfile( wxCommandEvent& event );
|
||||
void SaveProfile( wxCommandEvent& event );
|
||||
void DeleteProfile( wxCommandEvent& event );
|
||||
|
||||
void ConfigControl( wxCommandEvent& event );
|
||||
void ConfigDetectControl( wxCommandEvent& event );
|
||||
void DetectControl( wxCommandEvent& event );
|
||||
void ClearControl( wxCommandEvent& event );
|
||||
|
||||
void SetDevice( wxCommandEvent& event );
|
||||
void SetControl( wxCommandEvent& event );
|
||||
|
||||
void ClearAll( wxCommandEvent& event );
|
||||
|
||||
void AdjustControlOption( wxCommandEvent& event );
|
||||
void AdjustSetting( wxCommandEvent& event );
|
||||
|
||||
wxComboBox* profile_cbox;
|
||||
wxComboBox* device_cbox;
|
||||
|
||||
std::vector<ControlGroupBox*> control_groups;
|
||||
|
||||
protected:
|
||||
|
||||
ControllerEmu* const controller;
|
||||
|
||||
private:
|
||||
|
||||
ControlDialog* m_control_dialog;
|
||||
Plugin& m_plugin;
|
||||
ConfigDialog* const m_config_dialog;
|
||||
};
|
||||
|
||||
class ConfigDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
|
||||
ConfigDialog( wxWindow* const parent, Plugin& plugin, const std::string& name, const bool _is_game_running );
|
||||
~ConfigDialog();
|
||||
|
||||
void ClickSave( wxCommandEvent& event );
|
||||
|
||||
void UpdateDeviceComboBox();
|
||||
void UpdateProfileComboBox();
|
||||
|
||||
void UpdateControlReferences();
|
||||
void UpdateBitmaps(wxTimerEvent&);
|
||||
|
||||
const bool is_game_running;
|
||||
|
||||
private:
|
||||
|
||||
wxNotebook* m_pad_notebook;
|
||||
std::vector<GamepadPage*> m_padpages;
|
||||
Plugin& m_plugin;
|
||||
wxTimer* m_update_timer;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,187 @@
|
||||
|
||||
#include "ConfigDiag.h"
|
||||
|
||||
void ConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
|
||||
{
|
||||
|
||||
GamepadPage* const current_page = (GamepadPage*)m_pad_notebook->GetPage( m_pad_notebook->GetSelection() );
|
||||
|
||||
std::vector< ControlGroupBox* >::iterator g = current_page->control_groups.begin(),
|
||||
ge = current_page->control_groups.end();
|
||||
for ( ; g != ge; ++g )
|
||||
{
|
||||
|
||||
if ( (*g)->static_bitmap )
|
||||
{
|
||||
|
||||
// don't want game thread updating input when we are using it here
|
||||
if ( false == m_plugin.interface_crit.TryEnter() )
|
||||
return;
|
||||
|
||||
//if ( false == is_game_running )
|
||||
// just always update
|
||||
m_plugin.controller_interface.UpdateInput();
|
||||
|
||||
switch ( (*g)->control_group->type )
|
||||
{
|
||||
case GROUP_TYPE_STICK :
|
||||
{
|
||||
float x, y;
|
||||
float xx, yy;
|
||||
((ControllerEmu::AnalogStick*)(*g)->control_group)->GetState( &x, &y, 32.0, 32-1.5 );
|
||||
|
||||
xx = ((ControllerEmu::AnalogStick*)(*g)->control_group)->controls[3]->control_ref->State();
|
||||
xx -= ((ControllerEmu::AnalogStick*)(*g)->control_group)->controls[2]->control_ref->State();
|
||||
yy = ((ControllerEmu::AnalogStick*)(*g)->control_group)->controls[1]->control_ref->State();
|
||||
yy -= ((ControllerEmu::AnalogStick*)(*g)->control_group)->controls[0]->control_ref->State();
|
||||
xx *= 32 - 1; xx += 32;
|
||||
yy *= 32 - 1; yy += 32;
|
||||
|
||||
// setup
|
||||
wxBitmap bitmap(64, 64);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
dc.Clear();
|
||||
|
||||
// draw the shit
|
||||
|
||||
// circle for visual aid for diagonal adjustment
|
||||
dc.SetPen(*wxLIGHT_GREY_PEN);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawCircle( 32, 32, 32);
|
||||
|
||||
// deadzone circle
|
||||
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
|
||||
dc.DrawCircle( 32, 32, ((ControllerEmu::AnalogStick*)(*g)->control_group)->settings[0]->value * 32 );
|
||||
|
||||
// raw dot
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
dc.SetBrush(*wxGREY_BRUSH);
|
||||
// i like the dot better than the cross i think
|
||||
dc.DrawRectangle( xx - 2, yy - 2, 4, 4 );
|
||||
//dc.DrawRectangle( xx-1, 64-yy-4, 2, 8 );
|
||||
//dc.DrawRectangle( xx-4, 64-yy-1, 8, 2 );
|
||||
|
||||
// adjusted dot
|
||||
if ( x!=32 || y!=32 )
|
||||
{
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
dc.DrawRectangle( x-2, 64-y-2, 4, 4 );
|
||||
// i like the dot better than the cross i think
|
||||
//dc.DrawRectangle( x-1, 64-y-4, 2, 8 );
|
||||
//dc.DrawRectangle( x-4, 64-y-1, 8, 2 );
|
||||
}
|
||||
|
||||
// box outline
|
||||
// Windows XP color
|
||||
dc.SetPen(wxPen(_T("#7f9db9")));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(0, 0, 64, 64);
|
||||
|
||||
// done drawing
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
|
||||
// set the shit
|
||||
(*g)->static_bitmap->SetBitmap( bitmap );
|
||||
}
|
||||
break;
|
||||
case GROUP_TYPE_BUTTONS :
|
||||
{
|
||||
const unsigned int button_count = ((unsigned int)(*g)->control_group->controls.size());
|
||||
// setup
|
||||
wxBitmap bitmap(12*button_count+1, 12);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
dc.Clear();
|
||||
|
||||
// draw the shit
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
|
||||
unsigned int * const bitmasks = new unsigned int[ button_count ];
|
||||
for ( unsigned int n = 0; n<button_count; ++n )
|
||||
bitmasks[n] = ( 1 << n );
|
||||
|
||||
unsigned int buttons = 0;
|
||||
((ControllerEmu::Buttons*)(*g)->control_group)->GetState( &buttons, bitmasks );
|
||||
|
||||
for ( unsigned int n = 0; n<button_count; ++n )
|
||||
{
|
||||
// TODO: threshold stuff, actually redo this crap with the GetState func
|
||||
if ( buttons & bitmasks[n] )
|
||||
dc.SetBrush( *wxRED_BRUSH );
|
||||
else
|
||||
{
|
||||
unsigned char amt = 255 - (*g)->control_group->controls[n]->control_ref->State() * 128;
|
||||
dc.SetBrush( wxBrush( wxColor( amt, amt, amt ) ) );
|
||||
}
|
||||
dc.DrawRectangle(n*12, 0, 14, 12);
|
||||
}
|
||||
|
||||
delete bitmasks;
|
||||
|
||||
// box outline
|
||||
// Windows XP color
|
||||
dc.SetPen(wxPen(_T("#7f9db9")));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
|
||||
|
||||
// done drawing
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
|
||||
// set the shit
|
||||
(*g)->static_bitmap->SetBitmap( bitmap );
|
||||
}
|
||||
break;
|
||||
|
||||
case GROUP_TYPE_MIXED_TRIGGERS :
|
||||
{
|
||||
const unsigned int trigger_count = ((unsigned int)((*g)->control_group->controls.size() / 2));
|
||||
// setup
|
||||
wxBitmap bitmap( 64+12+1, 12*trigger_count+1);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
dc.Clear();
|
||||
|
||||
// draw the shit
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
ControlState thresh = (*g)->control_group->settings[0]->value;
|
||||
|
||||
for ( unsigned int n = 0; n < trigger_count; ++n )
|
||||
{
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
ControlState trig_d = (*g)->control_group->controls[n]->control_ref->State();
|
||||
|
||||
ControlState trig_a = trig_d > thresh ? 1
|
||||
: (*g)->control_group->controls[n+trigger_count]->control_ref->State();
|
||||
|
||||
dc.DrawRectangle(0, n*12, 64+20, 14);
|
||||
if ( trig_d <= thresh )
|
||||
dc.SetBrush(*wxWHITE_BRUSH);
|
||||
dc.DrawRectangle(trig_a*64, n*12, 64+20, 14);
|
||||
dc.DrawRectangle(64, n*12, 32, 14);
|
||||
}
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(thresh*64, 0, 128, trigger_count*14);
|
||||
|
||||
// box outline
|
||||
// Windows XP color
|
||||
dc.SetPen(wxPen(_T("#7f9db9")));
|
||||
dc.DrawRectangle(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
|
||||
|
||||
// done drawing
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
|
||||
// set the shit
|
||||
(*g)->static_bitmap->SetBitmap( bitmap );
|
||||
}
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
m_plugin.interface_crit.Leave();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
#include "ControllerEmu.h"
|
||||
|
||||
#include "ControllerEmu/GCPad/GCPad.h"
|
||||
|
||||
const char modifier[] = "Modifier";
|
||||
|
||||
// TODO: make this use iterators
|
||||
ControllerEmu::~ControllerEmu()
|
||||
{
|
||||
for ( unsigned int g = 0; g<groups.size(); ++g )
|
||||
delete groups[g];
|
||||
}
|
||||
// TODO: make this use iterators
|
||||
ControllerEmu::ControlGroup::~ControlGroup()
|
||||
{
|
||||
for ( unsigned int i = 0; i < controls.size(); ++i )
|
||||
delete controls[i];
|
||||
for ( unsigned int i = 0; i < settings.size(); ++i )
|
||||
delete settings[i];
|
||||
}
|
||||
|
||||
// TODO: make this use iterators
|
||||
void ControllerEmu::UpdateReferences( ControllerInterface& devi )
|
||||
{
|
||||
for ( unsigned int g = 0; g<groups.size(); ++g )
|
||||
for ( unsigned int i = 0; i < groups[g]->controls.size(); ++i )
|
||||
devi.UpdateReference( groups[g]->controls[i]->control_ref );
|
||||
}
|
||||
|
||||
void ControllerEmu::UpdateDefaultDevice()
|
||||
{
|
||||
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
|
||||
e = groups.end();
|
||||
for ( ; i!=e; ++i )
|
||||
{
|
||||
std::vector<ControlGroup::Control*>::const_iterator ci = (*i)->controls.begin(),
|
||||
ce = (*i)->controls.end();
|
||||
for ( ; ci!=ce; ++ci )
|
||||
(*ci)->control_ref->device_qualifier = default_device;
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerEmu::LoadConfig( IniFile::Section& sec )
|
||||
{
|
||||
const std::string default_dev = sec[ "Device" ];
|
||||
default_device.FromString( default_dev );
|
||||
|
||||
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
|
||||
e = groups.end();
|
||||
for ( ; i!=e; ++i )
|
||||
{
|
||||
std::string group( (*i)->name ); group += "/";
|
||||
|
||||
// settings
|
||||
std::vector<ControlGroup::Setting*>::const_iterator si = (*i)->settings.begin(),
|
||||
se = (*i)->settings.end();
|
||||
for ( ; si!=se; ++si )
|
||||
(*si)->value = sec.Get(group+(*si)->name, (*si)->default_value*100) / 100;
|
||||
|
||||
// controls
|
||||
std::vector<ControlGroup::Control*>::const_iterator ci = (*i)->controls.begin(),
|
||||
ce = (*i)->controls.end();
|
||||
for ( ; ci!=ce; ++ci )
|
||||
{
|
||||
// control and dev qualifier
|
||||
(*ci)->control_ref->control_qualifier.name = sec[group + (*ci)->name];
|
||||
(*ci)->control_ref->device_qualifier.FromString( sec.Get( group+(*ci)->name+"/Device", default_dev ) );
|
||||
|
||||
// range
|
||||
(*ci)->control_ref->range = sec.Get( group+(*ci)->name+"/Range", 100.0f ) / 100;
|
||||
|
||||
// input mode
|
||||
if ( (*ci)->control_ref->is_input )
|
||||
((ControllerInterface::InputReference*)((*ci)->control_ref))->mode
|
||||
= sec.Get( group+(*ci)->name+"/Mode", 0 );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerEmu::SaveConfig( IniFile::Section& sec )
|
||||
{
|
||||
const std::string default_dev = default_device.ToString();
|
||||
sec[ " Device" ] = default_dev;
|
||||
|
||||
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
|
||||
e = groups.end();
|
||||
for ( ; i!=e; ++i )
|
||||
{
|
||||
std::string group( (*i)->name ); group += "/";
|
||||
|
||||
// settings
|
||||
std::vector<ControlGroup::Setting*>::const_iterator si = (*i)->settings.begin(),
|
||||
se = (*i)->settings.end();
|
||||
for ( ; si!=se; ++si )
|
||||
sec.Set( group+(*si)->name, (*si)->value*100, (*si)->default_value*100 );
|
||||
|
||||
// controls
|
||||
std::vector<ControlGroup::Control*>::const_iterator ci = (*i)->controls.begin(),
|
||||
ce = (*i)->controls.end();
|
||||
for ( ; ci!=ce; ++ci )
|
||||
{
|
||||
// control and dev qualifier
|
||||
sec[group + (*ci)->name] = (*ci)->control_ref->control_qualifier.name;
|
||||
sec.Set( group+(*ci)->name+"/Device", (*ci)->control_ref->device_qualifier.ToString(), default_dev );
|
||||
|
||||
// range
|
||||
sec.Set( group+(*ci)->name+"/Range", (*ci)->control_ref->range*100, 100 );
|
||||
|
||||
// input mode
|
||||
if ( (*ci)->control_ref->is_input )
|
||||
sec.Set( group+(*ci)->name+"/Mode",
|
||||
((ControllerInterface::InputReference*)((*ci)->control_ref))->mode, (unsigned int)0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ControllerEmu::AnalogStick::AnalogStick( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_STICK )
|
||||
{
|
||||
for ( unsigned int i = 0; i < 4; ++i )
|
||||
controls.push_back( new Input( named_directions[i] ) );
|
||||
|
||||
controls.push_back( new Input( modifier ) );
|
||||
|
||||
settings.push_back( new Setting("Dead Zone", 0 ) );
|
||||
settings.push_back( new Setting("Square Stick", 0 ) );
|
||||
|
||||
}
|
||||
|
||||
ControllerEmu::Buttons::Buttons( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_BUTTONS )
|
||||
{
|
||||
settings.push_back( new Setting("Threshold", 0.5f ) );
|
||||
}
|
||||
|
||||
ControllerEmu::MixedTriggers::MixedTriggers( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_MIXED_TRIGGERS )
|
||||
{
|
||||
settings.push_back( new Setting("Threshold", 0.9f ) );
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
#ifndef _CONTROLLEREMU_H_
|
||||
#define _CONTROLLEREMU_H_
|
||||
|
||||
// windows crap
|
||||
#define NOMINMAX
|
||||
|
||||
#include "pluginspecs_pad.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
//#include <CommonTypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "ControllerInterface/ControllerInterface.h"
|
||||
#include "IniFile.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#define sign(x) ((x)?(x)<0?-1:1:0)
|
||||
|
||||
enum
|
||||
{
|
||||
GROUP_TYPE_OTHER
|
||||
,GROUP_TYPE_STICK
|
||||
,GROUP_TYPE_MIXED_TRIGGERS
|
||||
,GROUP_TYPE_BUTTONS
|
||||
};
|
||||
|
||||
const char * const named_directions[] =
|
||||
{
|
||||
"Up",
|
||||
"Down",
|
||||
"Left",
|
||||
"Right"
|
||||
};
|
||||
|
||||
class ControllerEmu
|
||||
{
|
||||
public:
|
||||
|
||||
class ControlGroup
|
||||
{
|
||||
public:
|
||||
|
||||
class Control
|
||||
{
|
||||
protected:
|
||||
Control( ControllerInterface::ControlReference* const _ref, const char * const _name )
|
||||
: control_ref(_ref), name(_name){}
|
||||
public:
|
||||
|
||||
|
||||
//virtual std::string GetName() const = 0;
|
||||
|
||||
ControllerInterface::ControlReference* const control_ref;
|
||||
const char * const name;
|
||||
|
||||
};
|
||||
|
||||
class Input : public Control
|
||||
{
|
||||
public:
|
||||
|
||||
Input( const char * const _name )
|
||||
: Control( new ControllerInterface::InputReference, _name ) {}
|
||||
|
||||
};
|
||||
|
||||
class Output : public Control
|
||||
{
|
||||
public:
|
||||
|
||||
Output( const char * const _name )
|
||||
: Control( new ControllerInterface::OutputReference, _name ) {}
|
||||
|
||||
};
|
||||
|
||||
class Setting
|
||||
{
|
||||
public:
|
||||
|
||||
Setting(const char* const _name, const float def_value ) : name(_name), value(def_value), default_value(def_value) {}
|
||||
|
||||
const char* const name;
|
||||
ControlState value;
|
||||
const ControlState default_value;
|
||||
};
|
||||
|
||||
ControlGroup( const char* const _name, const unsigned int _type = GROUP_TYPE_OTHER ) : name(_name), type(_type) {}
|
||||
virtual ~ControlGroup();
|
||||
|
||||
//ControlGroup( const ControlGroup& ctrl );
|
||||
|
||||
//const unsigned int type;
|
||||
const char* const name;
|
||||
const unsigned int type;
|
||||
|
||||
std::vector< Control* > controls;
|
||||
std::vector< Setting* > settings;
|
||||
|
||||
};
|
||||
|
||||
class AnalogStick : public ControlGroup
|
||||
{
|
||||
public:
|
||||
|
||||
template <typename C>
|
||||
void GetState( C* const x, C* const y, const unsigned int base, const unsigned int range )
|
||||
{
|
||||
// this is all a mess
|
||||
|
||||
ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
|
||||
ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
|
||||
|
||||
ControlState deadzone = settings[0]->value;
|
||||
ControlState square = settings[1]->value;
|
||||
ControlState m = controls[4]->control_ref->State();
|
||||
|
||||
// modifier code
|
||||
if ( m )
|
||||
{
|
||||
yy = (abs(yy)>deadzone) * sign(yy) * m;
|
||||
xx = (abs(xx)>deadzone) * sign(xx) * m;
|
||||
}
|
||||
|
||||
// deadzone / square stick code
|
||||
if ( deadzone || square )
|
||||
{
|
||||
// this section might be all wrong, but its working good enough, i think
|
||||
|
||||
ControlState ang = atan2( yy, xx );
|
||||
ControlState ang_sin = sin(ang);
|
||||
ControlState ang_cos = cos(ang);
|
||||
|
||||
// the amt a full square stick would have at current angle
|
||||
ControlState square_full = std::min( 1/abs(ang_sin), 1/abs(ang_cos) );
|
||||
|
||||
// the amt a full stick would have that was ( user setting squareness) at current angle
|
||||
// i think this is more like a pointed circle rather than a rounded square like it should be
|
||||
ControlState stick_full = ( 1 + ( square_full - 1 ) * square );
|
||||
|
||||
ControlState dist = sqrt(xx*xx + yy*yy);
|
||||
|
||||
// dead zone code
|
||||
dist = std::max( 0.0f, dist - deadzone * stick_full );
|
||||
dist /= ( 1 - deadzone );
|
||||
|
||||
// square stick code
|
||||
ControlState amt = ( dist ) / stick_full;
|
||||
dist -= ((square_full - 1) * amt * square);
|
||||
|
||||
yy = std::max( -1.0f, std::min( 1.0f, ang_sin * dist ) );
|
||||
xx = std::max( -1.0f, std::min( 1.0f, ang_cos * dist ) );
|
||||
}
|
||||
|
||||
*y = C( yy * range + base );
|
||||
*x = C( xx * range + base );
|
||||
}
|
||||
|
||||
AnalogStick( const char* const _name );
|
||||
|
||||
};
|
||||
|
||||
class Buttons : public ControlGroup
|
||||
{
|
||||
public:
|
||||
Buttons( const char* const _name );
|
||||
|
||||
template <typename C>
|
||||
void GetState( C* const buttons, const C* bitmasks )
|
||||
{
|
||||
std::vector<Control*>::iterator i = controls.begin(),
|
||||
e = controls.end();
|
||||
for ( ; i!=e; ++i, ++bitmasks )
|
||||
if ( (*i)->control_ref->State() > settings[0]->value ) // threshold
|
||||
*buttons |= *bitmasks;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class MixedTriggers : public ControlGroup
|
||||
{
|
||||
public:
|
||||
|
||||
template <typename C, typename S>
|
||||
void GetState( C* const digital, const C* bitmasks, S* analog, const unsigned int range )
|
||||
{
|
||||
const unsigned int trig_count = ((unsigned int) (controls.size() / 2));
|
||||
for ( unsigned int i=0; i<trig_count; ++i,++bitmasks,++analog )
|
||||
{
|
||||
if ( controls[i]->control_ref->State() > settings[0]->value ) //threshold
|
||||
{
|
||||
*analog = range;
|
||||
*digital |= *bitmasks;
|
||||
}
|
||||
else
|
||||
*analog = S(controls[i+trig_count]->control_ref->State() * range);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
MixedTriggers( const char* const _name );
|
||||
|
||||
};
|
||||
|
||||
virtual ~ControllerEmu();
|
||||
|
||||
virtual std::string GetName() const = 0;
|
||||
|
||||
void LoadConfig( IniFile::Section& sec );
|
||||
void SaveConfig( IniFile::Section& sec );
|
||||
void UpdateDefaultDevice();
|
||||
|
||||
void UpdateReferences( ControllerInterface& devi );
|
||||
|
||||
std::vector< ControlGroup* > groups;
|
||||
|
||||
ControlGroup* options;
|
||||
|
||||
ControllerInterface::DeviceQualifier default_device;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,101 @@
|
||||
|
||||
#include "GCPad.h"
|
||||
|
||||
// this is all temporary, but sticking with the padspecs ...for now
|
||||
const u16 button_bitmasks[] =
|
||||
{
|
||||
PAD_BUTTON_A,
|
||||
PAD_BUTTON_B,
|
||||
PAD_BUTTON_X,
|
||||
PAD_BUTTON_Y,
|
||||
PAD_TRIGGER_Z,
|
||||
PAD_BUTTON_START
|
||||
};
|
||||
|
||||
const u16 trigger_bitmasks[] =
|
||||
{
|
||||
PAD_TRIGGER_L,
|
||||
PAD_TRIGGER_R,
|
||||
};
|
||||
|
||||
const u16 dpad_bitmasks[] =
|
||||
{
|
||||
PAD_BUTTON_UP, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT
|
||||
};
|
||||
|
||||
const char* const named_buttons[] =
|
||||
{
|
||||
"A",
|
||||
"B",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"Start",
|
||||
};
|
||||
|
||||
const char* const named_triggers[] =
|
||||
{
|
||||
"L", "R", "L-Analog", "R-Analog"
|
||||
};
|
||||
|
||||
GCPad::GCPad( const unsigned int index ) : m_index(index)
|
||||
{
|
||||
|
||||
// buttons
|
||||
groups.push_back( m_buttons = new Buttons( "Buttons" ) );
|
||||
for ( unsigned int i=0; i < sizeof(named_buttons)/sizeof(*named_buttons); ++i )
|
||||
m_buttons->controls.push_back( new ControlGroup::Input( named_buttons[i] ) );
|
||||
|
||||
// sticks
|
||||
groups.push_back( m_main_stick = new AnalogStick( "Main Stick" ) );
|
||||
groups.push_back( m_c_stick = new AnalogStick( "C-Stick" ) );
|
||||
|
||||
// triggers
|
||||
groups.push_back( m_triggers = new MixedTriggers( "Triggers" ) );
|
||||
for ( unsigned int i=0; i < sizeof(named_triggers)/sizeof(*named_triggers); ++i )
|
||||
m_triggers->controls.push_back( new ControlGroup::Input( named_triggers[i] ) );
|
||||
|
||||
// rumble
|
||||
groups.push_back( m_rumble = new ControlGroup( "Rumble" ) );
|
||||
m_rumble->controls.push_back( new ControlGroup::Output( "Motor" ) );
|
||||
|
||||
// dpad
|
||||
groups.push_back( m_dpad = new Buttons( "D-Pad" ) );
|
||||
for ( unsigned int i=0; i < 4; ++i )
|
||||
m_dpad->controls.push_back( new ControlGroup::Input( named_directions[i] ) );
|
||||
|
||||
// options
|
||||
groups.push_back( options = new ControlGroup( "Options" ) );
|
||||
options->settings.push_back( new ControlGroup::Setting( "Background Input", false ) );
|
||||
|
||||
}
|
||||
|
||||
std::string GCPad::GetName() const
|
||||
{
|
||||
return std::string("GCPad") + char('1'+m_index);
|
||||
}
|
||||
|
||||
void GCPad::GetInput( SPADStatus* const pad )
|
||||
{
|
||||
std::vector< ControlGroup::Control* >::iterator i,e;
|
||||
|
||||
// buttons
|
||||
m_buttons->GetState( &pad->button, button_bitmasks );
|
||||
|
||||
// TODO: set analog A/B to full or w/e
|
||||
|
||||
// dpad
|
||||
m_dpad->GetState( &pad->button, dpad_bitmasks );
|
||||
|
||||
// sticks
|
||||
m_main_stick->GetState( &pad->stickX, &pad->stickY, 0x80, 127 );
|
||||
m_c_stick->GetState( &pad->substickX, &pad->substickY, 0x80, 127 );
|
||||
|
||||
// triggers
|
||||
m_triggers->GetState( &pad->button, trigger_bitmasks, &pad->triggerLeft, 0xFF );
|
||||
}
|
||||
|
||||
void GCPad::SetOutput( const bool on )
|
||||
{
|
||||
m_rumble->controls[0]->control_ref->State( on );
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef _CONEMU_GCPAD_H_
|
||||
#define _CONEMU_GCPAD_H_
|
||||
|
||||
#include "../../ControllerEmu.h"
|
||||
|
||||
class GCPad : public ControllerEmu
|
||||
{
|
||||
public:
|
||||
|
||||
GCPad( const unsigned int index );
|
||||
void GetInput( SPADStatus* const pad );
|
||||
void SetOutput( const bool on );
|
||||
|
||||
std::string GetName() const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Buttons* m_buttons;
|
||||
AnalogStick* m_main_stick;
|
||||
AnalogStick* m_c_stick;
|
||||
Buttons* m_dpad;
|
||||
MixedTriggers* m_triggers;
|
||||
ControlGroup* m_rumble;
|
||||
|
||||
const unsigned int m_index;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,551 @@
|
||||
#include "ControllerInterface.h"
|
||||
|
||||
namespace ciface {
|
||||
}
|
||||
#ifdef CIFACE_USE_XINPUT
|
||||
#include "XInput/XInput.h"
|
||||
#endif
|
||||
#ifdef CIFACE_USE_DIRECTINPUT
|
||||
#include "DirectInput/DirectInput.h"
|
||||
#endif
|
||||
#ifdef CIFACE_USE_XLIB
|
||||
#include "Xlib/Xlib.h"
|
||||
#endif
|
||||
#ifdef CIFACE_USE_OSX
|
||||
#include "OSX/OSX.h"
|
||||
#endif
|
||||
#ifdef CIFACE_USE_SDL
|
||||
#include "SDL/SDL.h"
|
||||
#endif
|
||||
#include "Thread.h"
|
||||
|
||||
//#define MAX_DOUBLE_TAP_TIME 400
|
||||
//#define MAX_HOLD_DOWN_TIME 400
|
||||
#define INPUT_DETECT_THRESHOLD 0.85
|
||||
|
||||
//
|
||||
// Init
|
||||
//
|
||||
// detect devices and inputs outputs / will make refresh function later
|
||||
//
|
||||
void ControllerInterface::Init()
|
||||
{
|
||||
if ( m_is_init )
|
||||
return;
|
||||
|
||||
#ifdef CIFACE_USE_XINPUT
|
||||
ciface::XInput::Init( m_devices );
|
||||
#endif
|
||||
#ifdef CIFACE_USE_DIRECTINPUT
|
||||
ciface::DirectInput::Init( m_devices/*, (HWND)m_hwnd*/ );
|
||||
#endif
|
||||
#ifdef CIFACE_USE_XLIB
|
||||
ciface::Xlib::Init( m_devices, m_hwnd );
|
||||
#endif
|
||||
#ifdef CIFACE_USE_OSX
|
||||
ciface::OSX::Init( m_devices, m_hwnd );
|
||||
#endif
|
||||
#ifdef CIFACE_USE_SDL
|
||||
ciface::SDL::Init( m_devices );
|
||||
#endif
|
||||
|
||||
m_is_init = true;
|
||||
}
|
||||
|
||||
//
|
||||
// DeInit
|
||||
//
|
||||
// remove all devices/ call library cleanup functions
|
||||
//
|
||||
void ControllerInterface::DeInit()
|
||||
{
|
||||
if ( false == m_is_init )
|
||||
return;
|
||||
|
||||
std::vector<Device*>::const_iterator d = m_devices.begin(),
|
||||
Devices_end = m_devices.end();
|
||||
for ( ;d != Devices_end; ++d )
|
||||
{
|
||||
std::vector<Device::Output*>::const_iterator o = (*d)->Outputs().begin(),
|
||||
e = (*d)->Outputs().end();
|
||||
// set outputs to ZERO before destroying device
|
||||
for ( ;o!=e; ++o)
|
||||
(*d)->SetOutputState( *o, 0 );
|
||||
// update output
|
||||
(*d)->UpdateOutput();
|
||||
//delete device
|
||||
delete *d;
|
||||
}
|
||||
|
||||
m_devices.clear();
|
||||
|
||||
#ifdef CIFACE_USE_XINPUT
|
||||
// nothing needed
|
||||
#endif
|
||||
#ifdef CIFACE_USE_DIRECTINPUT
|
||||
// nothing needed
|
||||
#endif
|
||||
#ifdef CIFACE_USE_XLIB
|
||||
// nothing needed
|
||||
#endif
|
||||
#ifdef CIFACE_USE_OSX
|
||||
// nothing needed
|
||||
#endif
|
||||
#ifdef CIFACE_USE_SDL
|
||||
// there seems to be some sort of memory leak with SDL, quit isn't freeing everything up
|
||||
SDL_Quit();
|
||||
#endif
|
||||
|
||||
m_is_init = false;
|
||||
}
|
||||
|
||||
//
|
||||
// SetHwnd
|
||||
//
|
||||
// sets the hwnd used for some crap when initializing, use before calling Init
|
||||
//
|
||||
void ControllerInterface::SetHwnd( void* const hwnd )
|
||||
{
|
||||
m_hwnd = hwnd;
|
||||
}
|
||||
|
||||
//
|
||||
// UpdateInput
|
||||
//
|
||||
// update input for all devices, return true if all devices returned successful
|
||||
//
|
||||
bool ControllerInterface::UpdateInput()
|
||||
{
|
||||
size_t ok_count = 0;
|
||||
|
||||
std::vector<Device*>::const_iterator d = m_devices.begin(),
|
||||
e = m_devices.end();
|
||||
for ( ;d != e; ++d )
|
||||
{
|
||||
if ( (*d)->UpdateInput() )
|
||||
++ok_count;
|
||||
else
|
||||
(*d)->ClearInputState();
|
||||
}
|
||||
|
||||
return ( m_devices.size() == ok_count );
|
||||
}
|
||||
|
||||
//
|
||||
// UpdateOutput
|
||||
//
|
||||
// update output for all devices, return true if all devices returned successful
|
||||
//
|
||||
bool ControllerInterface::UpdateOutput()
|
||||
{
|
||||
size_t ok_count = 0;
|
||||
|
||||
std::vector<Device*>::const_iterator d = m_devices.begin(),
|
||||
e = m_devices.end();
|
||||
for ( ;d != e; ++d )
|
||||
(*d)->UpdateOutput();
|
||||
|
||||
return ( m_devices.size() == ok_count );
|
||||
}
|
||||
|
||||
//
|
||||
// Devices
|
||||
//
|
||||
// i dont really like this but,
|
||||
// return : constant copy of the devices vector
|
||||
//
|
||||
const std::vector<ControllerInterface::Device*>& ControllerInterface::Devices()
|
||||
{
|
||||
return m_devices;
|
||||
}
|
||||
|
||||
//
|
||||
// Device :: ~Device
|
||||
//
|
||||
// dtor, delete all inputs/outputs on device destruction
|
||||
//
|
||||
ControllerInterface::Device::~Device()
|
||||
{
|
||||
{
|
||||
// delete inputs
|
||||
std::vector<Device::Input*>::iterator i = inputs.begin(),
|
||||
e = inputs.end();
|
||||
for ( ;i!=e; ++i)
|
||||
delete *i;
|
||||
}
|
||||
|
||||
{
|
||||
// delete outputs
|
||||
std::vector<Device::Output*>::iterator o = outputs.begin(),
|
||||
e = outputs.end();
|
||||
for ( ;o!=e; ++o)
|
||||
delete *o;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Device :: ClearInputState
|
||||
//
|
||||
// device classes should override this func
|
||||
// ControllerInterface will call this when the device returns failure durring UpdateInput
|
||||
// used to try to set all buttons and axes to their default state when user unplugs a gamepad durring play
|
||||
// buttons/axes that were held down at the time of unplugging should be seen as not pressed after unplugging
|
||||
//
|
||||
void ControllerInterface::Device::ClearInputState()
|
||||
{
|
||||
// this is going to be called for every UpdateInput call that fails
|
||||
// kinda slow but, w/e, should only happen when user unplugs a device while playing
|
||||
}
|
||||
|
||||
//
|
||||
// Device :: Inputs
|
||||
//
|
||||
// get a const version of the device's input vector
|
||||
//
|
||||
const std::vector<ControllerInterface::Device::Input*>& ControllerInterface::Device::Inputs()
|
||||
{
|
||||
return inputs;
|
||||
}
|
||||
|
||||
//
|
||||
// Device :: Outputs
|
||||
//
|
||||
// get a const version of the device's outputs vector
|
||||
//
|
||||
const std::vector<ControllerInterface::Device::Output*>& ControllerInterface::Device::Outputs()
|
||||
{
|
||||
return outputs;
|
||||
}
|
||||
|
||||
//
|
||||
// HasInit
|
||||
//
|
||||
// check if interface is inited
|
||||
//
|
||||
bool ControllerInterface::IsInit()
|
||||
{
|
||||
return m_is_init;
|
||||
}
|
||||
|
||||
//
|
||||
// InputReference :: State
|
||||
//
|
||||
// get the state of an input reference
|
||||
// override function for ControlReference::State ...
|
||||
//
|
||||
ControlState ControllerInterface::InputReference::State( const ControlState ignore )
|
||||
{
|
||||
if ( NULL == device )
|
||||
return 0;
|
||||
|
||||
ControlState state = 0;
|
||||
// this mode thing will be turned into a switch statement
|
||||
switch ( mode )
|
||||
{
|
||||
// OR
|
||||
case 0 :
|
||||
{
|
||||
state = 0;
|
||||
std::vector<Device::Control*>::const_iterator ci = controls.begin(),
|
||||
ce = controls.end();
|
||||
for ( ; ci != ce; ++ci )
|
||||
state = std::max( state, device->GetInputState( (Device::Input*)*ci ) ); // meh casting
|
||||
break;
|
||||
}
|
||||
// AND
|
||||
case 1 :
|
||||
{
|
||||
// TODO: i think i can remove the if here
|
||||
|
||||
state = 1;
|
||||
bool is_bound = false;
|
||||
std::vector<Device::Control*>::const_iterator ci = controls.begin(),
|
||||
ce = controls.end();
|
||||
for ( ; ci != ce; ++ci )
|
||||
{
|
||||
is_bound = true;
|
||||
state = std::min( state, device->GetInputState( (Device::Input*)*ci ) ); // meh casting
|
||||
}
|
||||
if ( !is_bound )
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
// NOT
|
||||
case 2 :
|
||||
{
|
||||
state = 0;
|
||||
std::vector<Device::Control*>::const_iterator ci = controls.begin(),
|
||||
ce = controls.end();
|
||||
for ( ; ci != ce; ++ci )
|
||||
state = std::max( state, device->GetInputState( (Device::Input*)*ci ) ); // meh casting
|
||||
state = std::max( 0.0, 1.0 - state );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return std::min( 1.0f, state * range );
|
||||
}
|
||||
|
||||
//
|
||||
// OutputReference :: State
|
||||
//
|
||||
// set the state of all binded outputs
|
||||
// overrides ControlReference::State .. combined them so i could make the gui simple / inputs == same as outputs one list
|
||||
// i was lazy and it works so watever
|
||||
//
|
||||
ControlState ControllerInterface::OutputReference::State( const ControlState state )
|
||||
{
|
||||
std::vector<Device::Control*>::iterator ci = controls.begin(),
|
||||
ce = controls.end();
|
||||
for ( ; ci != ce; ++ci )
|
||||
device->SetOutputState( (Device::Output*)*ci, state * range ); // casting again
|
||||
|
||||
return state; // just return the output, watever
|
||||
}
|
||||
|
||||
//
|
||||
// DeviceQualifier :: ToString
|
||||
//
|
||||
// get string from a device qualifier / serialize
|
||||
//
|
||||
std::string ControllerInterface::DeviceQualifier::ToString() const
|
||||
{
|
||||
if ( source.empty() && (cid < 0) && name.empty() )
|
||||
return "";
|
||||
std::ostringstream ss;
|
||||
ss << source << '/';
|
||||
if ( cid > -1 )
|
||||
ss << cid;
|
||||
ss << '/' << name;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
//
|
||||
// DeviceQualifier :: FromString
|
||||
//
|
||||
// set a device qualifier from a string / unserialize
|
||||
//
|
||||
void ControllerInterface::DeviceQualifier::FromString(const std::string& str)
|
||||
{
|
||||
std::istringstream ss(str);
|
||||
|
||||
// good
|
||||
std::getline( ss, source = "", '/' );
|
||||
|
||||
|
||||
// dum
|
||||
std::getline( ss, name, '/' );
|
||||
std::istringstream(name) >> (cid = -1);
|
||||
|
||||
// good
|
||||
std::getline( ss, name = "");
|
||||
}
|
||||
|
||||
//
|
||||
// DeviceQualifier :: FromDevice
|
||||
//
|
||||
// set a device qualifier from a device
|
||||
//
|
||||
void ControllerInterface::DeviceQualifier::FromDevice(const ControllerInterface::Device* const dev)
|
||||
{
|
||||
name = dev->GetName();
|
||||
cid = dev->GetId();
|
||||
source= dev->GetSource();
|
||||
}
|
||||
|
||||
//
|
||||
// DeviceQualifier = = Device*
|
||||
//
|
||||
// check if a device matches a device qualifier
|
||||
//
|
||||
bool ControllerInterface::DeviceQualifier::operator==(const ControllerInterface::Device* const dev) const
|
||||
{
|
||||
return (dev->GetName() == name) && (dev->GetId() == cid) && (dev->GetSource() == source);
|
||||
}
|
||||
|
||||
//
|
||||
// ControlQualifier = FromControl
|
||||
//
|
||||
// set a control qualifier from a device control
|
||||
//
|
||||
void ControllerInterface::ControlQualifier::FromControl(const ControllerInterface::Device::Control* const c)
|
||||
{
|
||||
// hardly needs a function for this
|
||||
name = c->GetName();
|
||||
}
|
||||
|
||||
//
|
||||
// ControlQualifier = = Device :: Control*
|
||||
//
|
||||
// check if a control qualifier matches a device control
|
||||
// also |control1|control2| form, || matches all
|
||||
//
|
||||
bool ControllerInterface::ControlQualifier::operator==(const ControllerInterface::Device::Control* const control) const
|
||||
{
|
||||
if ( name.size() )
|
||||
{
|
||||
if ( '|' == name[0] && '|' == (*name.rbegin()) ) // check if using |button1|button2| format
|
||||
{
|
||||
return ( name.find( '|' + control->GetName() + '|' ) != name.npos || "||" == name );
|
||||
}
|
||||
}
|
||||
return (control->GetName() == name);
|
||||
}
|
||||
|
||||
//
|
||||
// UpdateReference
|
||||
//
|
||||
// updates a controlreference's binded devices then update binded controls
|
||||
// need to call this after changing a device qualifier on a control reference
|
||||
// if the device qualifier hasnt changed, the below functions: "UpdateControls" can be used
|
||||
//
|
||||
void ControllerInterface::UpdateReference( ControllerInterface::ControlReference* ref )
|
||||
{
|
||||
ref->device = NULL;
|
||||
std::vector<Device*>::const_iterator d = m_devices.begin(),
|
||||
e = m_devices.end();
|
||||
for ( ; d!=e; ++d )
|
||||
if ( ref->device_qualifier == *d )
|
||||
{
|
||||
ref->device = *d;
|
||||
break;
|
||||
}
|
||||
ref->UpdateControls();
|
||||
}
|
||||
|
||||
//
|
||||
// InputReference :: UpdateControls
|
||||
//
|
||||
// after changing a control qualifier, need to call this to rebind the new matching controls
|
||||
//
|
||||
void ControllerInterface::InputReference::UpdateControls()
|
||||
{
|
||||
controls.clear();
|
||||
if ( device )
|
||||
{
|
||||
std::vector<Device::Input*>::const_iterator i = device->Inputs().begin(),
|
||||
e = device->Inputs().end();
|
||||
for ( ;i != e; ++i )
|
||||
if ( control_qualifier == *i )
|
||||
controls.push_back( *i );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// OutputReference :: UpdateControls
|
||||
//
|
||||
// same as the inputRef version
|
||||
// after changing a control qualifier, need to call this to rebind the new matching controls
|
||||
//
|
||||
void ControllerInterface::OutputReference::UpdateControls()
|
||||
{
|
||||
controls.clear();
|
||||
if ( device )
|
||||
{
|
||||
std::vector<Device::Output*>::const_iterator i = device->Outputs().begin(),
|
||||
e = device->Outputs().end();
|
||||
for ( ;i != e; ++i )
|
||||
if ( control_qualifier == *i )
|
||||
controls.push_back( *i );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// InputReference :: Detect
|
||||
//
|
||||
// wait for input on all binded devices
|
||||
// supports waiting for n number of inputs
|
||||
// supports not detecting inputs that were held down at the time of Detect start,
|
||||
// which is useful for those crazy flightsticks that have certain buttons that are always held down
|
||||
// or some crazy axes or something
|
||||
// upon input, set control qualifier, update controls and return true
|
||||
// else return false
|
||||
//
|
||||
bool ControllerInterface::InputReference::Detect( const unsigned int ms, const unsigned int count )
|
||||
{
|
||||
|
||||
unsigned int time = 0;
|
||||
|
||||
// don't wait if we don't have a device
|
||||
if ( device )
|
||||
{
|
||||
bool* const states = new bool[device->Inputs().size()];
|
||||
|
||||
std::vector<Device::Input*>::const_iterator i = device->Inputs().begin(),
|
||||
e = device->Inputs().end();
|
||||
for ( unsigned int n=0;i != e; ++i,++n )
|
||||
states[n] = ( device->GetInputState( *i ) > INPUT_DETECT_THRESHOLD );
|
||||
|
||||
std::vector<Device::Control*> detected;
|
||||
|
||||
while ( (time < ms) && (detected.size() < count) )
|
||||
{
|
||||
device->UpdateInput();
|
||||
i = device->Inputs().begin();
|
||||
e = device->Inputs().end();
|
||||
|
||||
for ( unsigned int n=0;i != e; ++i,++n )
|
||||
{
|
||||
if ( device->GetInputState( *i ) > INPUT_DETECT_THRESHOLD )
|
||||
{
|
||||
if ( false == states[n] )
|
||||
if ( std::find( detected.begin(), detected.end(), *i ) == detected.end() )
|
||||
detected.push_back( *i );
|
||||
}
|
||||
else
|
||||
states[n] = false;
|
||||
}
|
||||
Common::SleepCurrentThread( 10 ); time += 10;
|
||||
}
|
||||
|
||||
delete states;
|
||||
|
||||
if ( detected.size() == count )
|
||||
{
|
||||
controls = detected;
|
||||
|
||||
if ( controls.size() > 1 )
|
||||
{
|
||||
control_qualifier.name = '|';
|
||||
std::vector<Device::Control*>::const_iterator c_i = controls.begin(),
|
||||
c_e = controls.end();
|
||||
for ( ; c_i != c_e; ++c_i )
|
||||
control_qualifier.name += (*c_i)->GetName() + '|';
|
||||
}
|
||||
else
|
||||
control_qualifier.FromControl( controls[0] );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// OutputReference :: Detect
|
||||
//
|
||||
// totally different from the inputReference detect / i have them combined so it was simplier to make the gui.
|
||||
// the gui doesnt know the difference between an input and an output / its odd but i was lazy and it was easy
|
||||
//
|
||||
// set all binded outputs to <range> power for x milliseconds return false
|
||||
//
|
||||
bool ControllerInterface::OutputReference::Detect( const unsigned int ms, const unsigned int ignored )
|
||||
{
|
||||
// dont hang if we dont even have any controls mapped
|
||||
if ( controls.size() )
|
||||
{
|
||||
State( 1 );
|
||||
unsigned int slept = 0;
|
||||
// this loop is to make stuff like flashing keyboard LEDs work
|
||||
while ( ms > ( slept += 10 ) )
|
||||
{
|
||||
device->UpdateOutput();
|
||||
Common::SleepCurrentThread( 10 );
|
||||
}
|
||||
|
||||
State( 0 );
|
||||
device->UpdateOutput();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
#ifndef _DEVICEINTERFACE_H_
|
||||
#define _DEVICEINTERFACE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include "Common.h"
|
||||
|
||||
// enable disable sources
|
||||
#ifdef _WIN32
|
||||
#define CIFACE_USE_XINPUT
|
||||
#define CIFACE_USE_DIRECTINPUT_JOYSTICK
|
||||
#define CIFACE_USE_DIRECTINPUT_KBM
|
||||
#define CIFACE_USE_DIRECTINPUT
|
||||
#endif
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
// Xlib is not tested at all currently, it is like 80% complete at least though
|
||||
#define CIFACE_USE_XLIB
|
||||
#endif
|
||||
#ifndef CIFACE_USE_DIRECTINPUT_JOYSTICK
|
||||
#define CIFACE_USE_SDL
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
//#define CIFACE_USE_OSX
|
||||
#endif
|
||||
|
||||
// idk in case i wanted to change it to double or somethin, idk what's best
|
||||
typedef float ControlState;
|
||||
|
||||
//
|
||||
// ControllerInterface
|
||||
//
|
||||
// some crazy shit i made to control different device inputs and outputs
|
||||
// from lots of different sources, hopefully more easily
|
||||
//
|
||||
class ControllerInterface
|
||||
{
|
||||
public:
|
||||
|
||||
//
|
||||
// Device
|
||||
//
|
||||
// Pretty obviously, a device class
|
||||
//
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
|
||||
//
|
||||
// Control
|
||||
//
|
||||
// control includes inputs and outputs
|
||||
//
|
||||
class Control // input or output
|
||||
{
|
||||
public:
|
||||
virtual std::string GetName() const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// Input
|
||||
//
|
||||
// an input on a device
|
||||
//
|
||||
class Input : public Control
|
||||
{
|
||||
public:
|
||||
virtual ~Input() {}
|
||||
};
|
||||
|
||||
//
|
||||
// Output
|
||||
//
|
||||
// guess wut it is, yup and output
|
||||
//
|
||||
class Output : public Control
|
||||
{
|
||||
public:
|
||||
virtual ~Output() {}
|
||||
};
|
||||
|
||||
virtual ~Device();
|
||||
|
||||
virtual std::string GetName() const = 0;
|
||||
virtual int GetId() const = 0;
|
||||
virtual std::string GetSource() const = 0;
|
||||
|
||||
virtual ControlState GetInputState( const Input* const input ) = 0;
|
||||
virtual void SetOutputState( const Output* const output, const ControlState state ) = 0;
|
||||
|
||||
virtual bool UpdateInput() = 0;
|
||||
virtual bool UpdateOutput() = 0;
|
||||
|
||||
virtual void ClearInputState();
|
||||
|
||||
const std::vector< Input* >& Inputs();
|
||||
const std::vector< Output* >& Outputs();
|
||||
|
||||
protected:
|
||||
std::vector<Input*> inputs;
|
||||
std::vector<Output*> outputs;
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// DeviceQualifier
|
||||
//
|
||||
// device qualifier used to match devices
|
||||
// currently has ( source, id, name ) properties which match a device
|
||||
//
|
||||
class DeviceQualifier
|
||||
{
|
||||
public:
|
||||
DeviceQualifier() : cid(-1){}
|
||||
DeviceQualifier( const std::string& _source, const int _id, const std::string& _name )
|
||||
: source(_source), cid(_id), name(_name) {}
|
||||
bool operator==(const Device* const dev) const;
|
||||
void FromDevice(const Device* const dev);
|
||||
void FromString(const std::string& str);
|
||||
std::string ToString() const;
|
||||
|
||||
std::string source;
|
||||
int cid;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
//
|
||||
// ControlQualifier
|
||||
//
|
||||
// control qualifier includes input and output qualifiers
|
||||
// used to match controls on devices, only has name property
|
||||
// |input1|input2| form as well, || matches anything, might change this to * or something
|
||||
//
|
||||
class ControlQualifier
|
||||
{
|
||||
public:
|
||||
ControlQualifier() {};
|
||||
ControlQualifier( const std::string& _name ) : name(_name) {}
|
||||
virtual bool operator==(const Device::Control* const in) const;
|
||||
void FromControl(const Device::Control* const in);
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
//
|
||||
// InputQualifier
|
||||
//
|
||||
// ControlQualifier for inputs
|
||||
//
|
||||
class InputQualifier : public ControlQualifier
|
||||
{
|
||||
public:
|
||||
InputQualifier() {};
|
||||
InputQualifier( const std::string& _name ) : ControlQualifier(_name) {}
|
||||
};
|
||||
|
||||
//
|
||||
// OutputQualifier
|
||||
//
|
||||
// ControlQualifier for outputs
|
||||
//
|
||||
class OutputQualifier : public ControlQualifier
|
||||
{
|
||||
public:
|
||||
OutputQualifier() {};
|
||||
OutputQualifier( const std::string& _name ) : ControlQualifier(_name) {}
|
||||
};
|
||||
|
||||
//
|
||||
// ControlReference
|
||||
//
|
||||
// these are what you create to actually use the inputs, InputReference or OutputReference
|
||||
// they have a vector < struct { device , vector < controls > } >
|
||||
//
|
||||
// after being binded to devices and controls with ControllerInterface::UpdateReference,
|
||||
// each one can binded to a devices, and 0+ controls the device
|
||||
// ControlReference can update its own controls when you change its control qualifier
|
||||
// using ControlReference::UpdateControls but when you change its device qualifer
|
||||
// you must use ControllerInterface::UpdateReference
|
||||
//
|
||||
class ControlReference
|
||||
{
|
||||
public:
|
||||
ControlReference( const bool _is_input ) : range(1), is_input(_is_input), device(NULL) {}
|
||||
|
||||
virtual ControlState State( const ControlState state = 0 ) = 0;
|
||||
virtual bool Detect( const unsigned int ms, const unsigned int count = 1 ) = 0;
|
||||
virtual void UpdateControls() = 0;
|
||||
|
||||
ControlState range;
|
||||
|
||||
DeviceQualifier device_qualifier;
|
||||
ControlQualifier control_qualifier;
|
||||
|
||||
const bool is_input;
|
||||
Device* device;
|
||||
|
||||
std::vector<Device::Control*> controls;
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// InputReference
|
||||
//
|
||||
// control reference for inputs
|
||||
//
|
||||
class InputReference : public ControlReference
|
||||
{
|
||||
public:
|
||||
InputReference() : ControlReference( true ) {}
|
||||
ControlState State( const ControlState state );
|
||||
bool Detect( const unsigned int ms, const unsigned int count );
|
||||
void UpdateControls();
|
||||
|
||||
unsigned int mode;
|
||||
};
|
||||
|
||||
//
|
||||
// OutputReference
|
||||
//
|
||||
// control reference for outputs
|
||||
//
|
||||
class OutputReference : public ControlReference
|
||||
{
|
||||
public:
|
||||
OutputReference() : ControlReference( false ) {}
|
||||
ControlState State( const ControlState state );
|
||||
bool Detect( const unsigned int ms, const unsigned int count );
|
||||
void UpdateControls();
|
||||
};
|
||||
|
||||
ControllerInterface() : m_is_init(false) {}
|
||||
|
||||
void SetHwnd( void* const hwnd );
|
||||
void Init();
|
||||
void DeInit();
|
||||
bool IsInit();
|
||||
|
||||
void UpdateReference( ControlReference* control );
|
||||
bool UpdateInput();
|
||||
bool UpdateOutput();
|
||||
|
||||
const std::vector<Device*>& Devices();
|
||||
|
||||
private:
|
||||
bool m_is_init;
|
||||
std::vector<Device*> m_devices;
|
||||
void* m_hwnd;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef CIFACE_USE_DIRECTINPUT
|
||||
|
||||
#include "DirectInput.h"
|
||||
|
||||
#pragma comment(lib, "Dinput8.lib")
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace DirectInput
|
||||
{
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices/*, HWND hwnd*/ )
|
||||
{
|
||||
IDirectInput8* idi8;
|
||||
if ( DI_OK != DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&idi8, NULL ) )
|
||||
return;
|
||||
|
||||
#ifdef CIFACE_USE_DIRECTINPUT_KBM
|
||||
InitKeyboardMouse( idi8, devices );
|
||||
#endif
|
||||
#ifdef CIFACE_USE_DIRECTINPUT_JOYSTICK
|
||||
InitJoystick( idi8, devices/*, hwnd*/ );
|
||||
#endif
|
||||
|
||||
idi8->Release();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef _CIFACE_DIRECTINPUT_H_
|
||||
#define _CIFACE_DIRECTINPUT_H_
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <dinput.h>
|
||||
|
||||
#ifdef CIFACE_USE_DIRECTINPUT_JOYSTICK
|
||||
#include "DirectInputJoystick.h"
|
||||
#endif
|
||||
#ifdef CIFACE_USE_DIRECTINPUT_KBM
|
||||
#include "DirectInputKeyboardMouse.h"
|
||||
#endif
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace DirectInput
|
||||
{
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices/*, HWND hwnd*/ );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+514
@@ -0,0 +1,514 @@
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef CIFACE_USE_DIRECTINPUT_JOYSTICK
|
||||
|
||||
#include "DirectInputJoystick.h"
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace DirectInput
|
||||
{
|
||||
|
||||
#ifdef NO_DUPLICATE_DINPUT_XINPUT
|
||||
//-----------------------------------------------------------------------------
|
||||
// Modified some MSDN code to get all the XInput device GUID.Data1 values in a vector,
|
||||
// faster than checking all the devices for each DirectInput device, like MSDN says to do
|
||||
//-----------------------------------------------------------------------------
|
||||
void GetXInputGUIDS( std::vector<DWORD>& guids )
|
||||
{
|
||||
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
IWbemLocator* pIWbemLocator = NULL;
|
||||
IEnumWbemClassObject* pEnumDevices = NULL;
|
||||
IWbemClassObject* pDevices[20] = {0};
|
||||
IWbemServices* pIWbemServices = NULL;
|
||||
BSTR bstrNamespace = NULL;
|
||||
BSTR bstrDeviceID = NULL;
|
||||
BSTR bstrClassName = NULL;
|
||||
DWORD uReturned = 0;
|
||||
VARIANT var;
|
||||
HRESULT hr;
|
||||
|
||||
// CoInit if needed
|
||||
hr = CoInitialize(NULL);
|
||||
bool bCleanupCOM = SUCCEEDED(hr);
|
||||
|
||||
// Create WMI
|
||||
hr = CoCreateInstance( __uuidof(WbemLocator),
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWbemLocator),
|
||||
(LPVOID*) &pIWbemLocator);
|
||||
if( FAILED(hr) || pIWbemLocator == NULL )
|
||||
goto LCleanup;
|
||||
|
||||
bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );if( bstrNamespace == NULL ) goto LCleanup;
|
||||
bstrClassName = SysAllocString( L"Win32_PNPEntity" ); if( bstrClassName == NULL ) goto LCleanup;
|
||||
bstrDeviceID = SysAllocString( L"DeviceID" ); if( bstrDeviceID == NULL ) goto LCleanup;
|
||||
|
||||
// Connect to WMI
|
||||
hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices );
|
||||
if( FAILED(hr) || pIWbemServices == NULL )
|
||||
goto LCleanup;
|
||||
|
||||
// Switch security level to IMPERSONATE.
|
||||
CoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
|
||||
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
|
||||
|
||||
hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices );
|
||||
if( FAILED(hr) || pEnumDevices == NULL )
|
||||
goto LCleanup;
|
||||
|
||||
// Loop over all devices
|
||||
while( true )
|
||||
{
|
||||
// Get 20 at a time
|
||||
hr = pEnumDevices->Next( 10000, 20, pDevices, &uReturned );
|
||||
if( FAILED(hr) || uReturned == 0 )
|
||||
break;
|
||||
|
||||
for( UINT iDevice=0; iDevice<uReturned; ++iDevice )
|
||||
{
|
||||
// For each device, get its device ID
|
||||
hr = pDevices[iDevice]->Get( bstrDeviceID, 0L, &var, NULL, NULL );
|
||||
if( SUCCEEDED( hr ) && var.vt == VT_BSTR && var.bstrVal != NULL )
|
||||
{
|
||||
// Check if the device ID contains "IG_". If it does, then it's an XInput device
|
||||
// This information can not be found from DirectInput
|
||||
if( wcsstr( var.bstrVal, L"IG_" ) )
|
||||
{
|
||||
// If it does, then get the VID/PID from var.bstrVal
|
||||
DWORD dwPid = 0, dwVid = 0;
|
||||
WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
|
||||
if( strVid && swscanf( strVid, L"VID_%4X", &dwVid ) != 1 )
|
||||
dwVid = 0;
|
||||
WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
|
||||
if( strPid && swscanf( strPid, L"PID_%4X", &dwPid ) != 1 )
|
||||
dwPid = 0;
|
||||
|
||||
// Compare the VID/PID to the DInput device
|
||||
DWORD dwVidPid = MAKELONG( dwVid, dwPid );
|
||||
guids.push_back( dwVidPid );
|
||||
//bIsXinputDevice = true;
|
||||
}
|
||||
}
|
||||
SAFE_RELEASE( pDevices[iDevice] );
|
||||
}
|
||||
}
|
||||
|
||||
LCleanup:
|
||||
if(bstrNamespace)
|
||||
SysFreeString(bstrNamespace);
|
||||
if(bstrDeviceID)
|
||||
SysFreeString(bstrDeviceID);
|
||||
if(bstrClassName)
|
||||
SysFreeString(bstrClassName);
|
||||
for( UINT iDevice=0; iDevice<20; iDevice++ )
|
||||
SAFE_RELEASE( pDevices[iDevice] );
|
||||
SAFE_RELEASE( pEnumDevices );
|
||||
SAFE_RELEASE( pIWbemLocator );
|
||||
SAFE_RELEASE( pIWbemServices );
|
||||
|
||||
if( bCleanupCOM )
|
||||
CoUninitialize();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string TStringToString( const std::basic_string<TCHAR>& in )
|
||||
{
|
||||
const int size = WideCharToMultiByte( CP_UTF8, 0, in.data(), int(in.length()), NULL, 0, NULL, NULL );
|
||||
|
||||
if ( 0 == size )
|
||||
return "";
|
||||
|
||||
char* const data = new char[size];
|
||||
WideCharToMultiByte( CP_UTF8, 0, in.data(), int(in.length()), data, size, NULL, NULL );
|
||||
const std::string out( data, size );
|
||||
delete[] data;
|
||||
return out;
|
||||
}
|
||||
|
||||
//BOOL CALLBACK DIEnumEffectsCallback( LPCDIEFFECTINFO pdei, LPVOID pvRef )
|
||||
//{
|
||||
// ((std::vector<DIEFFECTINFO>*)pvRef)->push_back( *pdei );
|
||||
// return DIENUM_CONTINUE;
|
||||
//}
|
||||
|
||||
BOOL CALLBACK DIEnumDeviceObjectsCallback( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef )
|
||||
{
|
||||
((std::vector<DIDEVICEOBJECTINSTANCE>*)pvRef)->push_back( *lpddoi );
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
BOOL CALLBACK DIEnumDevicesCallback( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef )
|
||||
{
|
||||
((std::vector<DIDEVICEINSTANCE>*)pvRef)->push_back( *lpddi );
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
void InitJoystick( IDirectInput8* const idi8, std::vector<ControllerInterface::Device*>& devices/*, HWND hwnd*/ )
|
||||
{
|
||||
std::vector<DIDEVICEINSTANCE> joysticks;
|
||||
idi8->EnumDevices( DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, (LPVOID)&joysticks, DIEDFL_ATTACHEDONLY );
|
||||
|
||||
// just a struct with an int that is set to ZERO by default
|
||||
struct ZeroedInt{ZeroedInt():value(0){}unsigned int value;};
|
||||
// this is used to number the joysticks
|
||||
// multiple joysticks with the same name shall get unique ids starting at 0
|
||||
std::map< std::basic_string<TCHAR>, ZeroedInt > name_counts;
|
||||
|
||||
#ifdef NO_DUPLICATE_DINPUT_XINPUT
|
||||
std::vector<DWORD> xinput_guids;
|
||||
GetXInputGUIDS( xinput_guids );
|
||||
#endif
|
||||
|
||||
std::vector<DIDEVICEINSTANCE>::iterator i = joysticks.begin(),
|
||||
e = joysticks.end();
|
||||
for ( ; i!=e; ++i )
|
||||
{
|
||||
#ifdef NO_DUPLICATE_DINPUT_XINPUT
|
||||
// skip XInput Devices
|
||||
if ( std::find( xinput_guids.begin(), xinput_guids.end(), i->guidProduct.Data1 ) != xinput_guids.end() )
|
||||
continue;
|
||||
#endif
|
||||
// TODO: this has potential to mess up on createdev or setdatafmt failure
|
||||
LPDIRECTINPUTDEVICE8 js_device;
|
||||
if ( DI_OK == idi8->CreateDevice( i->guidInstance, &js_device, NULL ) )
|
||||
if ( DI_OK == js_device->SetDataFormat( &c_dfDIJoystick ) )
|
||||
// using foregroundwindow seems like a hack
|
||||
if ( DI_OK != js_device->SetCooperativeLevel( GetForegroundWindow(), DISCL_BACKGROUND | DISCL_EXCLUSIVE ) )
|
||||
{
|
||||
// fall back to non-exclusive mode, with no rumble
|
||||
if ( DI_OK != js_device->SetCooperativeLevel( NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE ) )
|
||||
{
|
||||
js_device->Release();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( DI_OK == js_device->Acquire() )
|
||||
{
|
||||
Joystick* js = new Joystick( /*&*i, */js_device, name_counts[i->tszInstanceName].value++ );
|
||||
// only add if it has some inputs/outpus
|
||||
if ( js->Inputs().size() || js->Outputs().size() )
|
||||
devices.push_back( js );
|
||||
else
|
||||
delete js;
|
||||
}
|
||||
else
|
||||
js_device->Release();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Joystick::Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVICE8 device, const unsigned int index )
|
||||
: m_device(device)
|
||||
, m_index(index)
|
||||
//, m_name(TStringToString(lpddi->tszInstanceName))
|
||||
{
|
||||
// get joystick caps
|
||||
DIDEVCAPS js_caps;
|
||||
ZeroMemory( &js_caps, sizeof(js_caps) );
|
||||
js_caps.dwSize = sizeof(js_caps);
|
||||
m_device->GetCapabilities(&js_caps);
|
||||
|
||||
// max of 32 buttons and 4 hats / the limit of the data format i am using
|
||||
js_caps.dwButtons = std::min((DWORD)32, js_caps.dwButtons);
|
||||
js_caps.dwPOVs = std::min((DWORD)4, js_caps.dwPOVs);
|
||||
|
||||
m_must_poll = ( ( js_caps.dwFlags & DIDC_POLLEDDATAFORMAT ) > 0 );
|
||||
|
||||
// buttons
|
||||
for ( unsigned int i = 0; i < js_caps.dwButtons; ++i )
|
||||
inputs.push_back( new Button( i ) );
|
||||
// hats
|
||||
for ( unsigned int i = 0; i < js_caps.dwPOVs; ++i )
|
||||
{
|
||||
// each hat gets 4 input instances associated with it, (up down left right)
|
||||
for ( unsigned int d = 0; d<4; ++d )
|
||||
inputs.push_back( new Hat( i, d ) );
|
||||
}
|
||||
// get up to 6 axes and 2 sliders
|
||||
std::vector<DIDEVICEOBJECTINSTANCE> axes;
|
||||
unsigned int cur_slider = 0;
|
||||
m_device->EnumObjects( DIEnumDeviceObjectsCallback, (LPVOID)&axes, DIDFT_AXIS );
|
||||
|
||||
// going in reverse leaves the list more organized in the end for me :/
|
||||
std::vector<DIDEVICEOBJECTINSTANCE>::const_reverse_iterator i = axes.rbegin(),
|
||||
e = axes.rend();
|
||||
for( ; i!=e; ++i )
|
||||
{
|
||||
DIPROPRANGE range;
|
||||
ZeroMemory( &range, sizeof(range ) );
|
||||
range.diph.dwSize = sizeof(range);
|
||||
range.diph.dwHeaderSize = sizeof(range.diph);
|
||||
range.diph.dwHow = DIPH_BYID;
|
||||
range.diph.dwObj = i->dwType;
|
||||
// try to set some nice power of 2 values (8192)
|
||||
range.lMin = -(1<<13);
|
||||
range.lMax = (1<<13);
|
||||
// but i guess not all devices support setting range
|
||||
m_device->SetProperty( DIPROP_RANGE, &range.diph );
|
||||
// so i getproperty right afterward incase it didn't set :P
|
||||
if ( DI_OK == m_device->GetProperty( DIPROP_RANGE, &range.diph ) )
|
||||
{
|
||||
int offset = -1;
|
||||
const GUID type = i->guidType;
|
||||
|
||||
// figure out which axis this is
|
||||
if ( type == GUID_XAxis )
|
||||
offset = 0;
|
||||
else if ( type == GUID_YAxis )
|
||||
offset = 1;
|
||||
else if ( type == GUID_ZAxis )
|
||||
offset = 2;
|
||||
else if ( type == GUID_RxAxis )
|
||||
offset = 3;
|
||||
else if ( type == GUID_RyAxis )
|
||||
offset = 4;
|
||||
else if ( type == GUID_RzAxis )
|
||||
offset = 5;
|
||||
else if ( type == GUID_Slider )
|
||||
if ( cur_slider < 2 )
|
||||
offset = 6 + cur_slider++;
|
||||
|
||||
if ( offset >= 0 )
|
||||
{
|
||||
const LONG base = (range.lMin + range.lMax) / 2;
|
||||
// each axis gets a negative and a positive input instance associated with it
|
||||
inputs.push_back( new Axis( offset, base, range.lMin-base ) );
|
||||
inputs.push_back( new Axis( offset, base, range.lMax-base ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get supported ff effects
|
||||
std::vector<DIDEVICEOBJECTINSTANCE> objects;
|
||||
m_device->EnumObjects( DIEnumDeviceObjectsCallback, (LPVOID)&objects, DIDFT_AXIS );
|
||||
// got some ff axes or something
|
||||
if ( objects.size() )
|
||||
{
|
||||
// temporary
|
||||
DWORD rgdwAxes[] = { DIJOFS_X, DIJOFS_Y };
|
||||
LONG rglDirection[] = { 0, 0 };
|
||||
DICONSTANTFORCE cf = { 0 };
|
||||
DIEFFECT eff;
|
||||
ZeroMemory( &eff, sizeof( DIEFFECT ) );
|
||||
eff.dwSize = sizeof( DIEFFECT );
|
||||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||
eff.dwDuration = INFINITE;
|
||||
eff.dwGain = DI_FFNOMINALMAX;
|
||||
eff.dwTriggerButton = DIEB_NOTRIGGER;
|
||||
eff.cAxes = std::min( (DWORD)2, (DWORD)objects.size() );
|
||||
eff.rgdwAxes = rgdwAxes;
|
||||
eff.rglDirection = rglDirection;
|
||||
eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE );
|
||||
eff.lpvTypeSpecificParams = &cf;
|
||||
|
||||
LPDIRECTINPUTEFFECT pEffect;
|
||||
if ( DI_OK == m_device->CreateEffect( GUID_ConstantForce, &eff, &pEffect, NULL ) )
|
||||
{
|
||||
// temp
|
||||
outputs.push_back( new Force( 0 ) );
|
||||
m_state_out.push_back( EffectState( pEffect ) );
|
||||
}
|
||||
}
|
||||
|
||||
// disable autocentering
|
||||
if ( outputs.size() )
|
||||
{
|
||||
DIPROPDWORD dipdw;
|
||||
dipdw.diph.dwSize = sizeof( DIPROPDWORD );
|
||||
dipdw.diph.dwHeaderSize = sizeof( DIPROPHEADER );
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = FALSE;
|
||||
m_device->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph );
|
||||
}
|
||||
|
||||
ClearInputState();
|
||||
}
|
||||
|
||||
Joystick::~Joystick()
|
||||
{
|
||||
// release the ff effect iface's
|
||||
std::vector<EffectState>::iterator i = m_state_out.begin(),
|
||||
e = m_state_out.end();
|
||||
for ( ; i!=e; ++i )
|
||||
{
|
||||
i->iface->Stop();
|
||||
i->iface->Unload();
|
||||
i->iface->Release();
|
||||
}
|
||||
|
||||
m_device->Unacquire();
|
||||
m_device->Release();
|
||||
}
|
||||
|
||||
void Joystick::ClearInputState()
|
||||
{
|
||||
ZeroMemory(&m_state_in, sizeof(m_state_in));
|
||||
// set hats to center
|
||||
memset( m_state_in.rgdwPOV, 0xFF, sizeof(m_state_in.rgdwPOV) );
|
||||
}
|
||||
|
||||
std::string Joystick::GetName() const
|
||||
{
|
||||
DIPROPSTRING str;
|
||||
ZeroMemory( &str, sizeof(str) );
|
||||
str.diph.dwSize = sizeof(str);
|
||||
str.diph.dwHeaderSize = sizeof(str.diph);
|
||||
str.diph.dwHow = DIPH_DEVICE;
|
||||
m_device->GetProperty( DIPROP_PRODUCTNAME, &str.diph );
|
||||
return TStringToString( str.wsz );
|
||||
//return m_name;
|
||||
}
|
||||
|
||||
int Joystick::GetId() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
std::string Joystick::GetSource() const
|
||||
{
|
||||
return "DirectInput";
|
||||
}
|
||||
|
||||
// update IO
|
||||
|
||||
|
||||
bool Joystick::UpdateInput()
|
||||
{
|
||||
if ( m_must_poll )
|
||||
m_device->Poll();
|
||||
//return false;
|
||||
|
||||
HRESULT hr = m_device->GetDeviceState( sizeof(m_state_in), &m_state_in );
|
||||
|
||||
// try reacquire if input lost
|
||||
if ( DIERR_INPUTLOST == hr )
|
||||
hr = m_device->Acquire();
|
||||
|
||||
return ( DI_OK == hr );
|
||||
}
|
||||
|
||||
bool Joystick::UpdateOutput()
|
||||
{
|
||||
// temporary
|
||||
size_t ok_count = 0;
|
||||
std::vector<EffectState>::iterator i = m_state_out.begin(),
|
||||
e = m_state_out.end();
|
||||
for ( ; i!=e; ++i )
|
||||
{
|
||||
if ( i->changed )
|
||||
{
|
||||
i->changed = false;
|
||||
DICONSTANTFORCE cf;
|
||||
cf.lMagnitude = LONG(10000 * i->magnitude);
|
||||
|
||||
if ( cf.lMagnitude )
|
||||
{
|
||||
DIEFFECT eff;
|
||||
ZeroMemory( &eff, sizeof( eff ) );
|
||||
eff.dwSize = sizeof( DIEFFECT );
|
||||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||
eff.cbTypeSpecificParams = sizeof( cf );
|
||||
eff.lpvTypeSpecificParams = &cf;
|
||||
// set params and start effect
|
||||
ok_count += ( DI_OK == i->iface->SetParameters( &eff, DIEP_TYPESPECIFICPARAMS | DIEP_START ) );
|
||||
}
|
||||
else
|
||||
ok_count += ( DI_OK == i->iface->Stop() );
|
||||
}
|
||||
else
|
||||
++ok_count;
|
||||
}
|
||||
|
||||
return ( m_state_out.size() == ok_count );
|
||||
}
|
||||
|
||||
// get name
|
||||
|
||||
std::string Joystick::Button::GetName() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Button " << m_index;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Joystick::Axis::GetName() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
// axis
|
||||
if ( m_index < 6 )
|
||||
{
|
||||
ss << "Axis " << "XYZ"[m_index%3];
|
||||
if ( m_index > 2 )
|
||||
ss << 'r';
|
||||
}
|
||||
// slider
|
||||
else
|
||||
ss << "Slider " << m_index-6;
|
||||
|
||||
ss << ( m_range>0 ? '+' : '-' );
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Joystick::Hat::GetName() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Hat " << m_index << ' ' << "NESW"[m_direction];
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Joystick::Force::GetName() const
|
||||
{
|
||||
// temporary
|
||||
return "Constant";
|
||||
}
|
||||
|
||||
// get / set state
|
||||
|
||||
ControlState Joystick::GetInputState( const ControllerInterface::Device::Input* const input )
|
||||
{
|
||||
return ((Input*)input)->GetState( &m_state_in );
|
||||
}
|
||||
|
||||
void Joystick::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
|
||||
{
|
||||
((Output*)output)->SetState( state, &m_state_out[0] );
|
||||
}
|
||||
|
||||
// get / set state
|
||||
|
||||
ControlState Joystick::Axis::GetState( const DIJOYSTATE* const joystate )
|
||||
{
|
||||
return std::max( 0.0f, ControlState((&joystate->lX)[m_index]-m_base) / m_range );
|
||||
}
|
||||
|
||||
ControlState Joystick::Button::GetState( const DIJOYSTATE* const joystate )
|
||||
{
|
||||
return ControlState( joystate->rgbButtons[m_index] > 0 );
|
||||
}
|
||||
|
||||
ControlState Joystick::Hat::GetState( const DIJOYSTATE* const joystate )
|
||||
{
|
||||
// can this func be simplified ?
|
||||
const DWORD val = joystate->rgdwPOV[m_index];
|
||||
// hat centered code from msdn
|
||||
if ( 0xFFFF == LOWORD(val) )
|
||||
return 0;
|
||||
return ( abs( (int)(val/4500-m_direction*2+8)%8 - 4) > 2 );
|
||||
}
|
||||
|
||||
void Joystick::Force::SetState( const ControlState state, Joystick::EffectState* const joystate )
|
||||
{
|
||||
joystate[m_index].magnitude = state;
|
||||
joystate[m_index].changed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
#ifndef _CIFACE_DIRECTINPUT_JOYSTICK_H_
|
||||
#define _CIFACE_DIRECTINPUT_JOYSTICK_H_
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <dinput.h>
|
||||
|
||||
#ifdef CIFACE_USE_XINPUT
|
||||
// this takes so long, idk if it should be enabled :(
|
||||
#define NO_DUPLICATE_DINPUT_XINPUT
|
||||
#include <wbemidl.h>
|
||||
#include <oleauto.h>
|
||||
#endif
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace DirectInput
|
||||
{
|
||||
|
||||
void InitJoystick( IDirectInput8* const idi8, std::vector<ControllerInterface::Device*>& devices/*, HWND hwnd*/ );
|
||||
|
||||
class Joystick : public ControllerInterface::Device
|
||||
{
|
||||
friend class ControllerInterface;
|
||||
friend class ControllerInterface::ControlReference;
|
||||
|
||||
protected:
|
||||
|
||||
struct EffectState
|
||||
{
|
||||
EffectState( LPDIRECTINPUTEFFECT eff ) : changed(0), iface(eff) {}
|
||||
LPDIRECTINPUTEFFECT iface;
|
||||
ControlState magnitude;
|
||||
bool changed;
|
||||
};
|
||||
|
||||
class Input : public ControllerInterface::Device::Input
|
||||
{
|
||||
friend class Joystick;
|
||||
protected:
|
||||
virtual ControlState GetState( const DIJOYSTATE* const joystate ) = 0;
|
||||
};
|
||||
|
||||
// can probably eliminate this base class
|
||||
class Output : public ControllerInterface::Device::Output
|
||||
{
|
||||
friend class Joystick;
|
||||
protected:
|
||||
virtual void SetState( const ControlState state, EffectState* const joystate ) = 0;
|
||||
};
|
||||
|
||||
class Button : public Input
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Button( const unsigned int index ) : m_index(index) {}
|
||||
ControlState GetState( const DIJOYSTATE* const joystate );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
};
|
||||
|
||||
class Axis : public Input
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Axis( const unsigned int index, const LONG base, const LONG range ) : m_index(index), m_base(base), m_range(range) {}
|
||||
ControlState GetState( const DIJOYSTATE* const joystate );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
const LONG m_base;
|
||||
const LONG m_range;
|
||||
};
|
||||
|
||||
class Hat : public Input
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Hat( const unsigned int index, const unsigned int direction ) : m_index(index), m_direction(direction) {}
|
||||
ControlState GetState( const DIJOYSTATE* const joystate );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
const unsigned int m_direction;
|
||||
};
|
||||
|
||||
class Force : public Output
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Force( const unsigned int index ) : m_index(index) {}
|
||||
void SetState( const ControlState state, EffectState* const joystate );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
};
|
||||
|
||||
bool UpdateInput();
|
||||
bool UpdateOutput();
|
||||
|
||||
ControlState GetInputState( const ControllerInterface::Device::Input* const input );
|
||||
void SetOutputState( const ControllerInterface::Device::Output* const input, const ControlState state );
|
||||
|
||||
void ClearInputState();
|
||||
|
||||
public:
|
||||
Joystick( /*const LPCDIDEVICEINSTANCE lpddi, */const LPDIRECTINPUTDEVICE8 device, const unsigned int index );
|
||||
~Joystick();
|
||||
|
||||
std::string GetName() const;
|
||||
int GetId() const;
|
||||
std::string GetSource() const;
|
||||
|
||||
private:
|
||||
const LPDIRECTINPUTDEVICE8 m_device;
|
||||
const unsigned int m_index;
|
||||
//const std::string m_name;
|
||||
|
||||
DIJOYSTATE m_state_in;
|
||||
std::vector<EffectState> m_state_out;
|
||||
|
||||
bool m_must_poll;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef CIFACE_USE_DIRECTINPUT_KBM
|
||||
|
||||
#include "DirectInputKeyboardMouse.h"
|
||||
|
||||
// TODO: maybe add a ClearInputState function to this device
|
||||
|
||||
// (lower would be more sensitive) user can lower sensitivity by setting range
|
||||
// seems decent here ( at 8 ), I dont think anyone would need more sensitive than this
|
||||
// and user can lower it much farther than they would want to with the range
|
||||
#define MOUSE_AXIS_SENSITIVITY 8
|
||||
|
||||
// if input hasn't been received for this many ms, mouse input will be skipped
|
||||
// otherwise it is just some crazy value
|
||||
#define DROP_INPUT_TIME 250
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace DirectInput
|
||||
{
|
||||
|
||||
struct
|
||||
{
|
||||
const BYTE code;
|
||||
const char* const name;
|
||||
} named_keys[] =
|
||||
{
|
||||
#include "NamedKeys.h"
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
const BYTE code;
|
||||
const char* const name;
|
||||
} named_lights[] =
|
||||
{
|
||||
{ VK_NUMLOCK, "NUM LOCK" },
|
||||
{ VK_CAPITAL, "CAPS LOCK" },
|
||||
{ VK_SCROLL, "SCROLL LOCK" }
|
||||
};
|
||||
|
||||
void InitKeyboardMouse( IDirectInput8* const idi8, std::vector<ControllerInterface::Device*>& devices )
|
||||
{
|
||||
// mouse and keyboard are a combined device, to allow shift+click and stuff
|
||||
// if thats dumb, i will make a VirtualDevice class that just uses ranges of inputs/outputs from other devices
|
||||
// so there can be a separated Keyboard and mouse, as well as combined KeyboardMouse
|
||||
|
||||
// TODO: this has potential to not release devices if set datafmt or cooplevel fails
|
||||
|
||||
LPDIRECTINPUTDEVICE8 kb_device;
|
||||
LPDIRECTINPUTDEVICE8 mo_device;
|
||||
|
||||
if ( DI_OK == idi8->CreateDevice( GUID_SysKeyboard, &kb_device, NULL ) )
|
||||
if ( DI_OK == kb_device->SetDataFormat( &c_dfDIKeyboard ) )
|
||||
if ( DI_OK == kb_device->SetCooperativeLevel( NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE) )
|
||||
if ( DI_OK == kb_device->Acquire() )
|
||||
{
|
||||
|
||||
if ( DI_OK == idi8->CreateDevice( GUID_SysMouse, &mo_device, NULL ) )
|
||||
if ( DI_OK == mo_device->SetDataFormat( &c_dfDIMouse2 ) )
|
||||
if ( DI_OK == mo_device->SetCooperativeLevel( NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE) )
|
||||
if ( DI_OK == mo_device->Acquire() )
|
||||
{
|
||||
devices.push_back( new KeyboardMouse( kb_device, mo_device ) );
|
||||
return;
|
||||
}
|
||||
else
|
||||
goto release_mouse;
|
||||
|
||||
goto unacquire_kb;
|
||||
}
|
||||
else
|
||||
goto release_kb;
|
||||
|
||||
release_mouse:
|
||||
mo_device->Release();
|
||||
unacquire_kb:
|
||||
kb_device->Unacquire();
|
||||
release_kb:
|
||||
kb_device->Release();
|
||||
}
|
||||
|
||||
KeyboardMouse::~KeyboardMouse()
|
||||
{
|
||||
// kb
|
||||
m_kb_device->Unacquire();
|
||||
m_kb_device->Release();
|
||||
// mouse
|
||||
m_mo_device->Unacquire();
|
||||
m_mo_device->Release();
|
||||
}
|
||||
|
||||
KeyboardMouse::KeyboardMouse( const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device )
|
||||
: m_kb_device(kb_device)
|
||||
, m_mo_device(mo_device)
|
||||
{
|
||||
m_last_update = wxGetLocalTimeMillis();
|
||||
|
||||
ZeroMemory( &m_state_in, sizeof(m_state_in) );
|
||||
ZeroMemory( m_state_out, sizeof(m_state_out) );
|
||||
ZeroMemory( &m_current_state_out, sizeof(m_current_state_out) );
|
||||
|
||||
// KEYBOARD
|
||||
// add keys
|
||||
for ( unsigned int i = 0; i < sizeof(named_keys)/sizeof(*named_keys); ++i )
|
||||
inputs.push_back( new Key( i ) );
|
||||
// add lights
|
||||
for ( unsigned int i = 0; i < sizeof(named_lights)/sizeof(*named_lights); ++i )
|
||||
outputs.push_back( new Light( i ) );
|
||||
|
||||
// MOUSE
|
||||
// get caps
|
||||
DIDEVCAPS mouse_caps;
|
||||
ZeroMemory( &mouse_caps, sizeof(mouse_caps) );
|
||||
mouse_caps.dwSize = sizeof(mouse_caps);
|
||||
m_mo_device->GetCapabilities(&mouse_caps);
|
||||
// mouse buttons
|
||||
for ( unsigned int i = 0; i < mouse_caps.dwButtons; ++i )
|
||||
inputs.push_back( new Button( i ) );
|
||||
// mouse axes
|
||||
for ( unsigned int i = 0; i < mouse_caps.dwAxes; ++i )
|
||||
{
|
||||
// each axis gets a negative and a positive input instance associated with it
|
||||
inputs.push_back( new Axis( i, (2==i) ? -1 : -MOUSE_AXIS_SENSITIVITY ) );
|
||||
inputs.push_back( new Axis( i, -(2==i) ? 1 : MOUSE_AXIS_SENSITIVITY ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool KeyboardMouse::UpdateInput()
|
||||
{
|
||||
DIMOUSESTATE2 tmp_mouse;
|
||||
|
||||
// if mouse position hasn't been updated in a short while, skip a dev state
|
||||
wxLongLong cur_time = wxGetLocalTimeMillis();
|
||||
if ( cur_time - m_last_update > DROP_INPUT_TIME )
|
||||
{
|
||||
// set axes to zero
|
||||
ZeroMemory( &m_state_in.mouse, sizeof(m_state_in.mouse) );
|
||||
// skip this input state
|
||||
m_mo_device->GetDeviceState( sizeof(tmp_mouse), &tmp_mouse );
|
||||
}
|
||||
|
||||
m_last_update = cur_time;
|
||||
|
||||
if ( DI_OK == m_kb_device->GetDeviceState( sizeof(m_state_in.keyboard), &m_state_in.keyboard )
|
||||
&& DI_OK == m_mo_device->GetDeviceState( sizeof(tmp_mouse), &tmp_mouse ) )
|
||||
{
|
||||
// need to smooth out the axes, otherwise it doesnt work for shit
|
||||
for ( unsigned int i = 0; i < 3; ++i )
|
||||
((&m_state_in.mouse.lX)[i] += (&tmp_mouse.lX)[i]) /= 2;
|
||||
|
||||
// copy over the buttons
|
||||
memcpy( m_state_in.mouse.rgbButtons, tmp_mouse.rgbButtons, sizeof(m_state_in.mouse.rgbButtons) );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyboardMouse::UpdateOutput()
|
||||
{
|
||||
class KInput : public INPUT
|
||||
{
|
||||
public:
|
||||
KInput( const unsigned char key, const bool up = false )
|
||||
{
|
||||
memset( this, 0, sizeof(*this) );
|
||||
type = INPUT_KEYBOARD;
|
||||
ki.wVk = key;
|
||||
if (up) ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector< KInput > kbinputs;
|
||||
for ( unsigned int i = 0; i < sizeof(m_state_out)/sizeof(*m_state_out); ++i )
|
||||
{
|
||||
bool want_on = false;
|
||||
if ( m_state_out[i] )
|
||||
want_on = m_state_out[i] > wxGetLocalTimeMillis() % 255 ; // light should flash when output is 0.5
|
||||
|
||||
// lights are set to their original state when output is zero
|
||||
if ( want_on ^ m_current_state_out[i] )
|
||||
{
|
||||
kbinputs.push_back( KInput( named_lights[i].code ) ); // press
|
||||
kbinputs.push_back( KInput( named_lights[i].code, true ) ); // release
|
||||
|
||||
m_current_state_out[i] ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( kbinputs.size() )
|
||||
return ( kbinputs.size() == SendInput( (UINT)kbinputs.size(), &kbinputs[0], sizeof( kbinputs[0] ) ) );
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string KeyboardMouse::GetName() const
|
||||
{
|
||||
return "Keyboard Mouse";
|
||||
}
|
||||
|
||||
int KeyboardMouse::GetId() const
|
||||
{
|
||||
// should this be -1, idk
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string KeyboardMouse::GetSource() const
|
||||
{
|
||||
return "DirectInput";
|
||||
}
|
||||
|
||||
ControlState KeyboardMouse::GetInputState( const ControllerInterface::Device::Input* const input )
|
||||
{
|
||||
return ( ((Input*)input)->GetState( &m_state_in ) );
|
||||
}
|
||||
|
||||
void KeyboardMouse::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
|
||||
{
|
||||
((Output*)output)->SetState( state, m_state_out );
|
||||
}
|
||||
|
||||
// names
|
||||
std::string KeyboardMouse::Key::GetName() const
|
||||
{
|
||||
return named_keys[m_index].name;
|
||||
}
|
||||
|
||||
std::string KeyboardMouse::Button::GetName() const
|
||||
{
|
||||
return std::string("Button ") + char('0'+m_index);
|
||||
}
|
||||
|
||||
std::string KeyboardMouse::Axis::GetName() const
|
||||
{
|
||||
std::string tmpstr("Mouse ");
|
||||
tmpstr += "XYZ"[m_index]; tmpstr += ( m_range>0 ? '+' : '-' );
|
||||
return tmpstr;
|
||||
}
|
||||
|
||||
std::string KeyboardMouse::Light::GetName() const
|
||||
{
|
||||
return named_lights[ m_index ].name;
|
||||
}
|
||||
|
||||
// get/set state
|
||||
ControlState KeyboardMouse::Key::GetState( const State* const state )
|
||||
{
|
||||
return ( state->keyboard[named_keys[m_index].code] > 0 );
|
||||
}
|
||||
|
||||
ControlState KeyboardMouse::Button::GetState( const State* const state )
|
||||
{
|
||||
return ( state->mouse.rgbButtons[m_index] > 0 );
|
||||
}
|
||||
|
||||
ControlState KeyboardMouse::Axis::GetState( const State* const state )
|
||||
{
|
||||
return std::max( 0.0f, ControlState((&state->mouse.lX)[m_index]) / m_range );
|
||||
}
|
||||
|
||||
void KeyboardMouse::Light::SetState( const ControlState state, unsigned char* const state_out )
|
||||
{
|
||||
state_out[ m_index ] = state * 255;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
#ifndef _CIFACE_DIRECTINPUT_KBM_H_
|
||||
#define _CIFACE_DIRECTINPUT_KBM_H_
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <dinput.h>
|
||||
|
||||
#include <wx/stopwatch.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace DirectInput
|
||||
{
|
||||
|
||||
void InitKeyboardMouse( IDirectInput8* const idi8, std::vector<ControllerInterface::Device*>& devices );
|
||||
|
||||
class KeyboardMouse : public ControllerInterface::Device
|
||||
{
|
||||
friend class ControllerInterface;
|
||||
friend class ControllerInterface::ControlReference;
|
||||
|
||||
protected:
|
||||
|
||||
struct State
|
||||
{
|
||||
BYTE keyboard[256];
|
||||
DIMOUSESTATE2 mouse;
|
||||
};
|
||||
|
||||
class Input : public ControllerInterface::Device::Input
|
||||
{
|
||||
friend class KeyboardMouse;
|
||||
protected:
|
||||
virtual ControlState GetState( const State* const boardstate ) = 0;
|
||||
};
|
||||
|
||||
class Output : public ControllerInterface::Device::Output
|
||||
{
|
||||
friend class KeyboardMouse;
|
||||
protected:
|
||||
virtual void SetState( const ControlState state, unsigned char* const state_out ) = 0;
|
||||
};
|
||||
|
||||
class Key : public Input
|
||||
{
|
||||
friend class KeyboardMouse;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Key( const unsigned int index ) : m_index(index) {}
|
||||
ControlState GetState( const State* const state );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
};
|
||||
|
||||
class Button : public Input
|
||||
{
|
||||
friend class KeyboardMouse;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Button( const unsigned int index ) : m_index(index) {}
|
||||
ControlState GetState( const State* const state );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
};
|
||||
|
||||
class Axis : public Input
|
||||
{
|
||||
friend class KeyboardMouse;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Axis( const unsigned int index, const LONG range ) : m_index(index), m_range(range) {}
|
||||
ControlState GetState( const State* const state );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
const LONG m_range;
|
||||
};
|
||||
|
||||
class Light : public Output
|
||||
{
|
||||
friend class KeyboardMouse;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Light( const unsigned int index ) : m_index(index) {}
|
||||
void SetState( const ControlState state, unsigned char* const state_out );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
};
|
||||
|
||||
bool UpdateInput();
|
||||
bool UpdateOutput();
|
||||
|
||||
ControlState GetInputState( const ControllerInterface::Device::Input* const input );
|
||||
void SetOutputState( const ControllerInterface::Device::Output* const input, const ControlState state );
|
||||
|
||||
public:
|
||||
KeyboardMouse( const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device );
|
||||
~KeyboardMouse();
|
||||
|
||||
std::string GetName() const;
|
||||
int GetId() const;
|
||||
std::string GetSource() const;
|
||||
|
||||
private:
|
||||
const LPDIRECTINPUTDEVICE8 m_kb_device;
|
||||
const LPDIRECTINPUTDEVICE8 m_mo_device;
|
||||
|
||||
wxLongLong m_last_update;
|
||||
State m_state_in;
|
||||
unsigned char m_state_out[3]; // NUM CAPS SCROLL
|
||||
bool m_current_state_out[3]; // NUM CAPS SCROLL
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,144 @@
|
||||
{ DIK_A, "A" },
|
||||
{ DIK_B, "B" },
|
||||
{ DIK_C, "C" },
|
||||
{ DIK_D, "D" },
|
||||
{ DIK_E, "E" },
|
||||
{ DIK_F, "F" },
|
||||
{ DIK_G, "G" },
|
||||
{ DIK_H, "H" },
|
||||
{ DIK_I, "I" },
|
||||
{ DIK_J, "J" },
|
||||
{ DIK_K, "K" },
|
||||
{ DIK_L, "L" },
|
||||
{ DIK_M, "M" },
|
||||
{ DIK_N, "N" },
|
||||
{ DIK_O, "O" },
|
||||
{ DIK_P, "P" },
|
||||
{ DIK_Q, "Q" },
|
||||
{ DIK_R, "R" },
|
||||
{ DIK_S, "S" },
|
||||
{ DIK_T, "T" },
|
||||
{ DIK_U, "U" },
|
||||
{ DIK_V, "V" },
|
||||
{ DIK_W, "W" },
|
||||
{ DIK_X, "X" },
|
||||
{ DIK_Y, "Y" },
|
||||
{ DIK_Z, "Z" },
|
||||
{ DIK_0, "0" },
|
||||
{ DIK_1, "1" },
|
||||
{ DIK_2, "2" },
|
||||
{ DIK_3, "3" },
|
||||
{ DIK_4, "4" },
|
||||
{ DIK_5, "5" },
|
||||
{ DIK_6, "6" },
|
||||
{ DIK_7, "7" },
|
||||
{ DIK_8, "8" },
|
||||
{ DIK_9, "9" },
|
||||
{ DIK_UP, "UP" },
|
||||
{ DIK_DOWN, "DOWN" },
|
||||
{ DIK_LEFT, "LEFT" },
|
||||
{ DIK_RIGHT, "RIGHT" },
|
||||
{ DIK_ABNT_C1, "ABNT_C1" },
|
||||
{ DIK_ABNT_C2, "ABNT_C2" },
|
||||
{ DIK_ADD, "ADD" },
|
||||
{ DIK_APOSTROPHE, "APOSTROPHE" },
|
||||
{ DIK_APPS, "APPS" },
|
||||
{ DIK_AT, "AT" },
|
||||
{ DIK_AX, "AX" },
|
||||
{ DIK_BACK, "BACK" },
|
||||
{ DIK_BACKSLASH, "BACKSLASH" },
|
||||
{ DIK_CALCULATOR, "CALCULATOR" },
|
||||
{ DIK_CAPITAL, "CAPITAL" },
|
||||
{ DIK_COLON, "COLON" },
|
||||
{ DIK_COMMA, "COMMA" },
|
||||
{ DIK_CONVERT, "CONVERT" },
|
||||
{ DIK_DECIMAL, "DECIMAL" },
|
||||
{ DIK_DELETE, "DELETE" },
|
||||
{ DIK_DIVIDE, "DIVIDE" },
|
||||
{ DIK_EQUALS, "EQUALS" },
|
||||
{ DIK_ESCAPE, "ESCAPE" },
|
||||
{ DIK_F1, "F1" },
|
||||
{ DIK_F2, "F2" },
|
||||
{ DIK_F3, "F3" },
|
||||
{ DIK_F4, "F4" },
|
||||
{ DIK_F5, "F5" },
|
||||
{ DIK_F6, "F6" },
|
||||
{ DIK_F7, "F7" },
|
||||
{ DIK_F8, "F8" },
|
||||
{ DIK_F9, "F9" },
|
||||
{ DIK_F10, "F10" },
|
||||
{ DIK_F11, "F11" },
|
||||
{ DIK_F12, "F12" },
|
||||
{ DIK_F13, "F13" },
|
||||
{ DIK_F14, "F14" },
|
||||
{ DIK_F15, "F15" },
|
||||
{ DIK_GRAVE, "GRAVE" },
|
||||
{ DIK_HOME, "HOME" },
|
||||
{ DIK_END, "END" },
|
||||
{ DIK_INSERT, "INSERT" },
|
||||
{ DIK_KANA, "KANA" },
|
||||
{ DIK_KANJI, "KANJI" },
|
||||
{ DIK_MAIL, "MAIL" },
|
||||
{ DIK_MEDIASELECT, "MEDIASELECT" },
|
||||
{ DIK_MEDIASTOP, "MEDIASTOP" },
|
||||
{ DIK_MINUS, "MINUS" },
|
||||
{ DIK_MULTIPLY, "MULTIPLY" },
|
||||
{ DIK_MUTE, "MUTE" },
|
||||
{ DIK_MYCOMPUTER, "MYCOMPUTER" },
|
||||
{ DIK_NEXTTRACK, "NEXTTRACK" },
|
||||
{ DIK_NOCONVERT, "NOCONVERT" },
|
||||
{ DIK_NUMLOCK, "NUMLOCK" },
|
||||
{ DIK_NUMPAD0, "NUMPAD0" },
|
||||
{ DIK_NUMPAD1, "NUMPAD1" },
|
||||
{ DIK_NUMPAD2, "NUMPAD2" },
|
||||
{ DIK_NUMPAD3, "NUMPAD3" },
|
||||
{ DIK_NUMPAD4, "NUMPAD4" },
|
||||
{ DIK_NUMPAD5, "NUMPAD5" },
|
||||
{ DIK_NUMPAD6, "NUMPAD6" },
|
||||
{ DIK_NUMPAD7, "NUMPAD7" },
|
||||
{ DIK_NUMPAD8, "NUMPAD8" },
|
||||
{ DIK_NUMPAD9, "NUMPAD9" },
|
||||
{ DIK_NUMPADCOMMA, "NUMPADCOMMA" },
|
||||
{ DIK_NUMPADENTER, "NUMPADENTER" },
|
||||
{ DIK_NUMPADEQUALS, "NUMPADEQUALS" },
|
||||
{ DIK_OEM_102, "OEM_102" },
|
||||
{ DIK_PAUSE, "PAUSE" },
|
||||
{ DIK_PERIOD, "PERIOD" },
|
||||
{ DIK_PLAYPAUSE, "PLAYPAUSE" },
|
||||
{ DIK_POWER, "POWER" },
|
||||
{ DIK_PREVTRACK, "PREVTRACK" },
|
||||
{ DIK_PRIOR, "PRIOR" },
|
||||
{ DIK_NEXT, "NEXT" },
|
||||
{ DIK_RETURN, "RETURN" },
|
||||
{ DIK_LBRACKET, "LBRACKET" },
|
||||
{ DIK_RBRACKET, "RBRACKET" },
|
||||
{ DIK_LCONTROL, "LCONTROL" },
|
||||
{ DIK_RCONTROL, "RCONTROL" },
|
||||
{ DIK_LMENU, "LMENU" },
|
||||
{ DIK_RMENU, "RMENU" },
|
||||
{ DIK_LSHIFT, "LSHIFT" },
|
||||
{ DIK_RSHIFT, "RSHIFT" },
|
||||
{ DIK_LWIN, "LWIN" },
|
||||
{ DIK_RWIN, "RWIN" },
|
||||
{ DIK_SCROLL, "SCROLL" },
|
||||
{ DIK_SEMICOLON, "SEMICOLON" },
|
||||
{ DIK_SLASH, "SLASH" },
|
||||
{ DIK_SLEEP, "SLEEP" },
|
||||
{ DIK_SPACE, "SPACE" },
|
||||
{ DIK_STOP, "STOP" },
|
||||
{ DIK_SUBTRACT, "SUBTRACT" },
|
||||
{ DIK_SYSRQ, "SYSRQ" },
|
||||
{ DIK_TAB, "TAB" },
|
||||
{ DIK_UNDERLINE, "UNDERLINE" },
|
||||
{ DIK_UNLABELED, "UNLABELED" },
|
||||
{ DIK_VOLUMEDOWN, "VOLUMEDOWN" },
|
||||
{ DIK_VOLUMEUP, "VOLUMEUP" },
|
||||
{ DIK_WAKE, "WAKE" },
|
||||
{ DIK_WEBBACK, "WEBBACK" },
|
||||
{ DIK_WEBFAVORITES, "WEBFAVORITES" },
|
||||
{ DIK_WEBFORWARD, "WEBFORWARD" },
|
||||
{ DIK_WEBHOME, "WEBHOME" },
|
||||
{ DIK_WEBREFRESH, "WEBREFRESH" },
|
||||
{ DIK_WEBSEARCH, "WEBSEARCH" },
|
||||
{ DIK_WEBSTOP, "WEBSTOP" },
|
||||
{ DIK_YEN, "YEN" },
|
||||
@@ -0,0 +1,266 @@
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef CIFACE_USE_SDL
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||
#pragma comment(lib, "SDL.1.3.lib")
|
||||
#else
|
||||
#pragma comment(lib, "SDL.lib")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace SDL
|
||||
{
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices )
|
||||
{
|
||||
if ( SDL_Init( SDL_INIT_FLAGS ) >= 0 )
|
||||
{
|
||||
// joysticks
|
||||
for( int i = 0; i < SDL_NumJoysticks(); ++i )
|
||||
{
|
||||
SDL_Joystick* dev = SDL_JoystickOpen( i );
|
||||
if ( dev )
|
||||
{
|
||||
Joystick* js = new Joystick( dev, i );
|
||||
// only add if it has some inputs/outputs
|
||||
if ( js->Inputs().size() || js->Outputs().size() )
|
||||
devices.push_back( js );
|
||||
else
|
||||
delete js;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Joystick::Joystick( SDL_Joystick* const joystick, const unsigned int index ) : m_joystick(joystick), m_index(index)
|
||||
{
|
||||
// get buttons
|
||||
for ( int i = 0; i < SDL_JoystickNumButtons( m_joystick ); ++i )
|
||||
{
|
||||
inputs.push_back( new Button( i ) );
|
||||
}
|
||||
|
||||
// get hats
|
||||
for ( int i = 0; i < SDL_JoystickNumHats( m_joystick ); ++i )
|
||||
{
|
||||
// each hat gets 4 input instances associated with it, (up down left right)
|
||||
for ( unsigned int d = 0; d < 4; ++d )
|
||||
inputs.push_back( new Hat( i, d ) );
|
||||
}
|
||||
|
||||
// get axes
|
||||
for ( int i = 0; i < SDL_JoystickNumAxes( m_joystick ); ++i )
|
||||
{
|
||||
// each axis gets a negative and a positive input instance associated with it
|
||||
inputs.push_back( new Axis( i, -32768 ) );
|
||||
inputs.push_back( new Axis( i, 32767 ) );
|
||||
}
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
// try to get supported ff effects
|
||||
m_haptic = SDL_HapticOpenFromJoystick( m_joystick );
|
||||
if ( m_haptic )
|
||||
{
|
||||
//SDL_HapticSetGain( m_haptic, 1000 );
|
||||
//SDL_HapticSetAutocenter( m_haptic, 0 );
|
||||
|
||||
const unsigned int supported_effects = SDL_HapticQuery( m_haptic );
|
||||
|
||||
// constant effect
|
||||
if ( supported_effects & SDL_HAPTIC_CONSTANT )
|
||||
{
|
||||
outputs.push_back( new ConstantEffect( m_state_out.size() ) );
|
||||
m_state_out.push_back( EffectIDState() );
|
||||
}
|
||||
|
||||
// ramp effect
|
||||
if ( supported_effects & SDL_HAPTIC_RAMP )
|
||||
{
|
||||
outputs.push_back( new RampEffect( m_state_out.size() ) );
|
||||
m_state_out.push_back( EffectIDState() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Joystick::~Joystick()
|
||||
{
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
if ( m_haptic )
|
||||
{
|
||||
// stop/destroy all effects
|
||||
SDL_HapticStopAll( m_haptic );
|
||||
std::vector<EffectIDState>::iterator i = m_state_out.begin(),
|
||||
e = m_state_out.end();
|
||||
for ( ; i!=e; ++i )
|
||||
if ( i->id != -1 )
|
||||
SDL_HapticDestroyEffect( m_haptic, i->id );
|
||||
// close haptic first
|
||||
SDL_HapticClose( m_haptic );
|
||||
}
|
||||
#endif
|
||||
|
||||
// close joystick
|
||||
SDL_JoystickClose( m_joystick );
|
||||
}
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
std::string Joystick::ConstantEffect::GetName() const
|
||||
{
|
||||
return "Constant";
|
||||
}
|
||||
|
||||
std::string Joystick::RampEffect::GetName() const
|
||||
{
|
||||
return "Ramp";
|
||||
}
|
||||
|
||||
void Joystick::ConstantEffect::SetState( const ControlState state, Joystick::EffectIDState* const effect )
|
||||
{
|
||||
if ( state )
|
||||
{
|
||||
effect->effect.type = SDL_HAPTIC_CONSTANT;
|
||||
effect->effect.constant.length = SDL_HAPTIC_INFINITY;
|
||||
}
|
||||
else
|
||||
effect->effect.type = 0;
|
||||
|
||||
Sint16 old = effect->effect.constant.level;
|
||||
effect->effect.constant.level = state * 0x7FFF;
|
||||
if ( old != effect->effect.constant.level )
|
||||
effect->changed = true;
|
||||
}
|
||||
|
||||
void Joystick::RampEffect::SetState( const ControlState state, Joystick::EffectIDState* const effect )
|
||||
{
|
||||
if ( state )
|
||||
{
|
||||
effect->effect.type = SDL_HAPTIC_RAMP;
|
||||
effect->effect.ramp.length = SDL_HAPTIC_INFINITY;
|
||||
}
|
||||
else
|
||||
effect->effect.type = 0;
|
||||
|
||||
Sint16 old = effect->effect.ramp.start;
|
||||
effect->effect.ramp.start = state * 0x7FFF;
|
||||
if ( old != effect->effect.ramp.start )
|
||||
effect->changed = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
ControlState Joystick::GetInputState(const ControllerInterface::Device::Input* input)
|
||||
{
|
||||
return ((Input*)input)->GetState( m_joystick );
|
||||
}
|
||||
|
||||
void Joystick::SetOutputState(const ControllerInterface::Device::Output* output, const ControlState state)
|
||||
{
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
((Output*)output)->SetState( state, &m_state_out[ ((Output*)output)->m_index ] );
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Joystick::UpdateInput()
|
||||
{
|
||||
// each joystick is doin this, o well
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Joystick::UpdateOutput()
|
||||
{
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
std::vector<EffectIDState>::iterator i = m_state_out.begin(),
|
||||
e = m_state_out.end();
|
||||
for ( ; i!=e; ++i )
|
||||
if ( i->changed ) // if SetState was called on this output
|
||||
{
|
||||
if ( -1 == i->id ) // effect isn't currently uploaded
|
||||
{
|
||||
if ( i->effect.type ) // if outputstate is >0 this would be true
|
||||
if ( (i->id = SDL_HapticNewEffect( m_haptic, &i->effect )) > -1 ) // upload the effect
|
||||
SDL_HapticRunEffect( m_haptic, i->id, 1 ); // run the effect
|
||||
}
|
||||
else // effect is already uploaded
|
||||
{
|
||||
if ( i->effect.type ) // if ouputstate >0
|
||||
SDL_HapticUpdateEffect( m_haptic, i->id, &i->effect ); // update the effect
|
||||
else
|
||||
{
|
||||
SDL_HapticStopEffect( m_haptic, i->id ); // else, stop and remove the effect
|
||||
SDL_HapticDestroyEffect( m_haptic, i->id );
|
||||
i->id = -1; // mark it as not uploaded
|
||||
}
|
||||
}
|
||||
|
||||
i->changed = false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Joystick::GetName() const
|
||||
{
|
||||
return SDL_JoystickName( m_index );
|
||||
}
|
||||
|
||||
std::string Joystick::GetSource() const
|
||||
{
|
||||
return "SDL";
|
||||
}
|
||||
|
||||
int Joystick::GetId() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
std::string Joystick::Button::GetName() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Button " << m_index;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Joystick::Axis::GetName() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Axis " << m_index << ( m_range>0 ? '+' : '-' );
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Joystick::Hat::GetName() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Hat " << m_index << ' ' << "NESW"[m_direction];
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
ControlState Joystick::Button::GetState( SDL_Joystick* const js ) const
|
||||
{
|
||||
return SDL_JoystickGetButton( js, m_index );
|
||||
}
|
||||
|
||||
ControlState Joystick::Axis::GetState( SDL_Joystick* const js ) const
|
||||
{
|
||||
return std::max( 0.0f, ControlState(SDL_JoystickGetAxis( js, m_index )) / m_range );
|
||||
}
|
||||
|
||||
ControlState Joystick::Hat::GetState( SDL_Joystick* const js ) const
|
||||
{
|
||||
return (SDL_JoystickGetHat( js, m_index ) & ( 1 << m_direction )) > 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,159 @@
|
||||
#ifndef _CIFACE_SDL_H_
|
||||
#define _CIFACE_SDL_H_
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <SDL.h>
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||
#define USE_SDL_HAPTIC
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
#define SDL_INIT_FLAGS SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC
|
||||
#ifdef _WIN32
|
||||
#include <SDL_haptic.h>
|
||||
#else
|
||||
#include <SDL/SDL_haptic.h>
|
||||
#endif
|
||||
#else
|
||||
#define SDL_INIT_FLAGS SDL_INIT_JOYSTICK
|
||||
#endif
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace SDL
|
||||
{
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices );
|
||||
|
||||
class Joystick : public ControllerInterface::Device
|
||||
{
|
||||
friend class ControllerInterface;
|
||||
friend class ControllerInterface::ControlReference;
|
||||
|
||||
protected:
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
class EffectIDState
|
||||
{
|
||||
friend class Joystick;
|
||||
protected:
|
||||
EffectIDState() : id(-1), changed(false) { memset( &effect, 0, sizeof(effect)); }
|
||||
protected:
|
||||
SDL_HapticEffect effect;
|
||||
int id;
|
||||
bool changed;
|
||||
};
|
||||
#endif
|
||||
|
||||
class Input : public ControllerInterface::Device::Input
|
||||
{
|
||||
friend class Joystick;
|
||||
protected:
|
||||
Input( const unsigned int index ) : m_index(index) {}
|
||||
virtual ControlState GetState( SDL_Joystick* const js ) const = 0;
|
||||
|
||||
const unsigned int m_index;
|
||||
};
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
class Output : public ControllerInterface::Device::Output
|
||||
{
|
||||
friend class Joystick;
|
||||
protected:
|
||||
Output( const size_t index ) : m_index(index) {}
|
||||
virtual void SetState( const ControlState state, EffectIDState* const effect ) = 0;
|
||||
|
||||
const size_t m_index;
|
||||
};
|
||||
#endif
|
||||
|
||||
class Button : public Input
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Button( const unsigned int index ) : Input(index) {}
|
||||
ControlState GetState( SDL_Joystick* const js ) const;
|
||||
};
|
||||
class Axis : public Input
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Axis( const unsigned int index, const Sint16 range ) : Input(index), m_range(range) {}
|
||||
ControlState GetState( SDL_Joystick* const js ) const;
|
||||
private:
|
||||
const Sint16 m_range;
|
||||
};
|
||||
|
||||
class Hat : public Input
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Hat( const unsigned int index, const unsigned int direction ) : Input(index), m_direction(direction) {}
|
||||
ControlState GetState( SDL_Joystick* const js ) const;
|
||||
private:
|
||||
const unsigned int m_direction;
|
||||
};
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
class ConstantEffect : public Output
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
ConstantEffect( const size_t index ) : Output(index) {}
|
||||
void SetState( const ControlState state, EffectIDState* const effect );
|
||||
};
|
||||
|
||||
class RampEffect : public Output
|
||||
{
|
||||
friend class Joystick;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
RampEffect( const size_t index ) : Output(index) {}
|
||||
void SetState( const ControlState state, EffectIDState* const effect );
|
||||
};
|
||||
#endif
|
||||
|
||||
bool UpdateInput();
|
||||
bool UpdateOutput();
|
||||
|
||||
ControlState GetInputState( const ControllerInterface::Device::Input* const input );
|
||||
void SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state );
|
||||
|
||||
public:
|
||||
Joystick( SDL_Joystick* const joystick, const unsigned int index );
|
||||
~Joystick();
|
||||
|
||||
std::string GetName() const;
|
||||
int GetId() const;
|
||||
std::string GetSource() const;
|
||||
|
||||
private:
|
||||
SDL_Joystick* const m_joystick;
|
||||
const unsigned int m_index;
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
std::vector<EffectIDState> m_state_out;
|
||||
SDL_Haptic* m_haptic;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,214 @@
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#ifdef CIFACE_USE_XINPUT
|
||||
|
||||
#include "XInput.h"
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace XInput
|
||||
{
|
||||
|
||||
struct
|
||||
{
|
||||
const char* const name;
|
||||
const WORD bitmask;
|
||||
} named_buttons[] =
|
||||
{
|
||||
{ "Button A", XINPUT_GAMEPAD_A },
|
||||
{ "Button B", XINPUT_GAMEPAD_B },
|
||||
{ "Button X", XINPUT_GAMEPAD_X },
|
||||
{ "Button Y", XINPUT_GAMEPAD_Y },
|
||||
{ "Pad N", XINPUT_GAMEPAD_DPAD_UP },
|
||||
{ "Pad S", XINPUT_GAMEPAD_DPAD_DOWN },
|
||||
{ "Pad W", XINPUT_GAMEPAD_DPAD_LEFT },
|
||||
{ "Pad E", XINPUT_GAMEPAD_DPAD_RIGHT },
|
||||
{ "Start", XINPUT_GAMEPAD_START },
|
||||
{ "Back", XINPUT_GAMEPAD_BACK },
|
||||
{ "Shoulder L", XINPUT_GAMEPAD_LEFT_SHOULDER },
|
||||
{ "Shoulder R", XINPUT_GAMEPAD_RIGHT_SHOULDER },
|
||||
{ "Thumb L", XINPUT_GAMEPAD_LEFT_THUMB },
|
||||
{ "Thumb R", XINPUT_GAMEPAD_RIGHT_THUMB }
|
||||
};
|
||||
|
||||
const char* named_triggers[] =
|
||||
{
|
||||
"Trigger L",
|
||||
"Trigger R"
|
||||
};
|
||||
|
||||
const char* named_axes[] =
|
||||
{
|
||||
"Left X",
|
||||
"Left Y",
|
||||
"Right X",
|
||||
"Right Y"
|
||||
};
|
||||
|
||||
const char* named_motors[] =
|
||||
{
|
||||
"Motor L",
|
||||
"Motor R"
|
||||
};
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices )
|
||||
{
|
||||
XINPUT_CAPABILITIES caps;
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
if ( ERROR_SUCCESS == XInputGetCapabilities( i, 0, &caps ) )
|
||||
devices.push_back( new Device( &caps, i ) );
|
||||
|
||||
}
|
||||
|
||||
Device::Device( const XINPUT_CAPABILITIES* const caps, const unsigned int index )
|
||||
: m_index(index), m_subtype(caps->SubType)
|
||||
{
|
||||
ZeroMemory( &m_state_out, sizeof(m_state_out) );
|
||||
|
||||
// XInputGetCaps seems to always claim all capabilities are supported
|
||||
// but i will leave all this stuff in, incase m$ fixes xinput up a bit
|
||||
|
||||
// get supported buttons
|
||||
for ( int i = 0; i < sizeof(named_buttons)/sizeof(*named_buttons); ++i )
|
||||
if ( named_buttons[i].bitmask & caps->Gamepad.wButtons )
|
||||
inputs.push_back( new Button( /*xinput_named_buttons[i].bitmask, */i ) );
|
||||
|
||||
// get supported triggers
|
||||
for ( int i = 0; i < sizeof(named_triggers)/sizeof(*named_triggers); ++i )
|
||||
{
|
||||
//BYTE val = (&caps->Gamepad.bLeftTrigger)[i]; // should be max value / msdn lies
|
||||
if ( (&caps->Gamepad.bLeftTrigger)[i] )
|
||||
inputs.push_back( new Trigger( i, 255 ) );
|
||||
}
|
||||
|
||||
// get supported axes
|
||||
for ( int i = 0; i < sizeof(named_axes)/sizeof(*named_axes); ++i )
|
||||
{
|
||||
//SHORT val = (&caps->Gamepad.sThumbLX)[i]; // xinput doesnt give the range / msdn is lier
|
||||
if ( (&caps->Gamepad.sThumbLX)[i] )
|
||||
{
|
||||
// each axis gets a negative and a positive input instance associated with it
|
||||
inputs.push_back( new Axis( i, -32768 ) );
|
||||
inputs.push_back( new Axis( i, 32767 ) );
|
||||
}
|
||||
}
|
||||
|
||||
// get supported motors
|
||||
for ( int i = 0; i < sizeof(named_motors)/sizeof(*named_motors); ++i )
|
||||
{
|
||||
//WORD val = (&caps->Vibration.wLeftMotorSpeed)[i]; // should be max value / nope, more lies
|
||||
if ( (&caps->Vibration.wLeftMotorSpeed)[i] )
|
||||
outputs.push_back( new Motor(i, 65535 ) );
|
||||
}
|
||||
|
||||
ClearInputState();
|
||||
|
||||
}
|
||||
|
||||
void Device::ClearInputState()
|
||||
{
|
||||
ZeroMemory( &m_state_in, sizeof(m_state_in) );
|
||||
}
|
||||
|
||||
std::string Device::GetName() const
|
||||
{
|
||||
// why aren't these defined
|
||||
// subtype doesn't seem to work, i tested with 2 diff arcade sticks, both were shown as gamepad
|
||||
// ill leave it in anyway, maybe m$ will fix it
|
||||
|
||||
switch ( m_subtype )
|
||||
{
|
||||
case XINPUT_DEVSUBTYPE_GAMEPAD : return "Gamepad"; break;
|
||||
case 0x02 /*XINPUT_DEVSUBTYPE_WHEEL*/ : return "Wheel"; break;
|
||||
case 0x03 /*XINPUT_DEVSUBTYPE_ARCADE_STICK*/ : return "Arcade Stick"; break;
|
||||
case 0x04 /*XINPUT_DEVSUBTYPE_FLIGHT_STICK*/ : return "Flight Stick"; break;
|
||||
case 0x05 /*XINPUT_DEVSUBTYPE_DANCE_PAD*/ : return "Dance Pad"; break;
|
||||
case 0x06 /*XINPUT_DEVSUBTYPE_GUITAR*/ : return "Guitar"; break;
|
||||
case 0x08 /*XINPUT_DEVSUBTYPE_DRUM_KIT*/ : return "Drum Kit"; break;
|
||||
default : return "Device"; break;
|
||||
}
|
||||
}
|
||||
|
||||
int Device::GetId() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
std::string Device::GetSource() const
|
||||
{
|
||||
return "XInput";
|
||||
}
|
||||
|
||||
// update i/o
|
||||
|
||||
bool Device::UpdateInput()
|
||||
{
|
||||
return ( ERROR_SUCCESS == XInputGetState( m_index, &m_state_in ) );
|
||||
}
|
||||
|
||||
bool Device::UpdateOutput()
|
||||
{
|
||||
return ( ERROR_SUCCESS == XInputSetState( m_index, &m_state_out ) );
|
||||
}
|
||||
|
||||
// GET name/source/id
|
||||
|
||||
|
||||
std::string Device::Button::GetName() const
|
||||
{
|
||||
return named_buttons[m_index].name;
|
||||
}
|
||||
|
||||
std::string Device::Axis::GetName() const
|
||||
{
|
||||
return std::string(named_axes[m_index]) + ( m_range>0 ? '+' : '-' );
|
||||
}
|
||||
|
||||
std::string Device::Trigger::GetName() const
|
||||
{
|
||||
return named_triggers[m_index];
|
||||
}
|
||||
|
||||
std::string Device::Motor::GetName() const
|
||||
{
|
||||
return named_motors[m_index];
|
||||
}
|
||||
|
||||
// get/set control state
|
||||
|
||||
ControlState Device::GetInputState( const ControllerInterface::Device::Input* const input )
|
||||
{
|
||||
return ((Input*)input)->GetState( &m_state_in.Gamepad );
|
||||
}
|
||||
|
||||
void Device::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
|
||||
{
|
||||
return ((Output*)output)->SetState( state, &m_state_out );
|
||||
}
|
||||
|
||||
// GET / SET STATES
|
||||
|
||||
ControlState Device::Button::GetState( const XINPUT_GAMEPAD* const gamepad )
|
||||
{
|
||||
return (gamepad->wButtons & named_buttons[m_index].bitmask) > 0;
|
||||
}
|
||||
|
||||
ControlState Device::Trigger::GetState( const XINPUT_GAMEPAD* const gamepad )
|
||||
{
|
||||
return ControlState((&gamepad->bLeftTrigger)[m_index]) / m_range;
|
||||
}
|
||||
|
||||
ControlState Device::Axis::GetState( const XINPUT_GAMEPAD* const gamepad )
|
||||
{
|
||||
return std::max( 0.0f, ControlState((&gamepad->sThumbLX)[m_index]) / m_range );
|
||||
}
|
||||
|
||||
void Device::Motor::SetState( const ControlState state, XINPUT_VIBRATION* const vibration )
|
||||
{
|
||||
(&vibration->wLeftMotorSpeed)[m_index] = (WORD)(state * m_range);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,116 @@
|
||||
#ifndef _CIFACE_XINPUT_H_
|
||||
#define _CIFACE_XINPUT_H_
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <XInput.h>
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace XInput
|
||||
{
|
||||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices );
|
||||
|
||||
class Device : public ControllerInterface::Device
|
||||
{
|
||||
friend class ControllerInterface;
|
||||
friend class ControllerInterface::ControlReference;
|
||||
|
||||
protected:
|
||||
|
||||
class Input : public ControllerInterface::Device::Input
|
||||
{
|
||||
friend class Device;
|
||||
protected:
|
||||
virtual ControlState GetState( const XINPUT_GAMEPAD* const gamepad ) = 0;
|
||||
};
|
||||
|
||||
class Output : public ControllerInterface::Device::Output
|
||||
{
|
||||
friend class Device;
|
||||
protected:
|
||||
virtual void SetState( const ControlState state, XINPUT_VIBRATION* const vibration ) = 0;
|
||||
};
|
||||
|
||||
class Button : public Input
|
||||
{
|
||||
friend class Device;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Button( const unsigned int index ) : m_index(index) {}
|
||||
ControlState GetState( const XINPUT_GAMEPAD* const gamepad );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
};
|
||||
|
||||
class Axis : public Input
|
||||
{
|
||||
friend class Device;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Axis( const unsigned int index, const SHORT range ) : m_index(index), m_range(range) {}
|
||||
ControlState GetState( const XINPUT_GAMEPAD* const gamepad );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
const SHORT m_range;
|
||||
};
|
||||
|
||||
class Trigger : public Input
|
||||
{
|
||||
friend class Device;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Trigger( const unsigned int index, const BYTE range ) : m_index(index), m_range(range) {}
|
||||
ControlState GetState( const XINPUT_GAMEPAD* const gamepad );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
const BYTE m_range;
|
||||
};
|
||||
|
||||
class Motor : public Output
|
||||
{
|
||||
friend class Device;
|
||||
public:
|
||||
std::string GetName() const;
|
||||
protected:
|
||||
Motor( const unsigned int index, const WORD range ) : m_index(index), m_range(range) {}
|
||||
void SetState( const ControlState state, XINPUT_VIBRATION* const vibration );
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
const WORD m_range;
|
||||
};
|
||||
|
||||
bool UpdateInput();
|
||||
bool UpdateOutput();
|
||||
|
||||
ControlState GetInputState( const ControllerInterface::Device::Input* const input );
|
||||
void SetOutputState( const ControllerInterface::Device::Output* const input, const ControlState state );
|
||||
|
||||
void ClearInputState();
|
||||
|
||||
public:
|
||||
Device( const XINPUT_CAPABILITIES* const capabilities, const unsigned int index );
|
||||
|
||||
std::string GetName() const;
|
||||
int GetId() const;
|
||||
std::string GetSource() const;
|
||||
|
||||
private:
|
||||
const unsigned int m_index;
|
||||
XINPUT_STATE m_state_in;
|
||||
XINPUT_VIBRATION m_state_out;
|
||||
const unsigned int m_subtype;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "Xlib.h"
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace Xlib
|
||||
{
|
||||
|
||||
void Init(std::vector<ControllerInterface::Device*>& devices, void* const hwnd)
|
||||
{
|
||||
// mouse will be added to this, Keyboard class will be turned into KeyboardMouse
|
||||
// single device for combined keyboard/mouse, this will allow combinations like shift+click more easily
|
||||
devices.push_back(new Keyboard((Display*)hwnd));
|
||||
}
|
||||
|
||||
Keyboard::Keyboard(Display* display) : m_display(display)
|
||||
{
|
||||
memset(&m_state, 0, sizeof(m_state));
|
||||
|
||||
int min_keycode, max_keycode;
|
||||
XDisplayKeycodes(m_display, &min_keycode, &max_keycode);
|
||||
|
||||
for (int i = min_keycode; i <= max_keycode; ++i)
|
||||
{
|
||||
Key *temp_key = new Key(m_display, i);
|
||||
if (temp_key->m_keyname.length())
|
||||
inputs.push_back(temp_key);
|
||||
else
|
||||
delete temp_key;
|
||||
}
|
||||
}
|
||||
|
||||
Keyboard::~Keyboard()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ControlState Keyboard::GetInputState(const ControllerInterface::Device::Input* const input)
|
||||
{
|
||||
return ((Input*)input)->GetState(&m_state);
|
||||
}
|
||||
|
||||
void Keyboard::SetOutputState(const ControllerInterface::Device::Output* const output, const ControlState state)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Keyboard::UpdateInput()
|
||||
{
|
||||
XQueryKeymap(m_display, m_state.keyboard);
|
||||
|
||||
// mouse stuff in here too
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Keyboard::UpdateOutput()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string Keyboard::GetName() const
|
||||
{
|
||||
return "Keyboard";
|
||||
//return "Keyboard Mouse"; // change to this later
|
||||
}
|
||||
|
||||
std::string Keyboard::GetSource() const
|
||||
{
|
||||
return "Xlib";
|
||||
}
|
||||
|
||||
int Keyboard::GetId() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Keyboard::Key::Key(Display* const display, KeyCode keycode)
|
||||
: m_display(display), m_keycode(keycode)
|
||||
{
|
||||
int i = 0;
|
||||
KeySym keysym = 0;
|
||||
do
|
||||
{
|
||||
keysym = XKeycodeToKeysym(m_display, keycode, i);
|
||||
i++;
|
||||
}
|
||||
while (keysym == NoSymbol && i < 8);
|
||||
|
||||
if (keysym == NoSymbol)
|
||||
m_keyname = std::string();
|
||||
else
|
||||
m_keyname = std::string(XKeysymToString(keysym));
|
||||
}
|
||||
|
||||
ControlState Keyboard::Key::GetState(const State* const state)
|
||||
{
|
||||
return (state->keyboard[m_keycode/8] & (1 << (m_keycode%8))) != 0;
|
||||
}
|
||||
|
||||
std::string Keyboard::Key::GetName() const
|
||||
{
|
||||
return m_keyname;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#ifndef _CIFACE_XLIB_H_
|
||||
#define _CIFACE_XLIB_H_
|
||||
|
||||
#include "../ControllerInterface.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
namespace ciface
|
||||
{
|
||||
namespace Xlib
|
||||
{
|
||||
|
||||
void Init(std::vector<ControllerInterface::Device*>& devices, void* const hwnd);
|
||||
|
||||
class Keyboard : public ControllerInterface::Device
|
||||
{
|
||||
friend class ControllerInterface;
|
||||
friend class ControllerInterface::ControlReference;
|
||||
|
||||
protected:
|
||||
|
||||
struct State
|
||||
{
|
||||
char keyboard[32];
|
||||
// mouse crap will go here
|
||||
};
|
||||
|
||||
class Input : public ControllerInterface::Device::Input
|
||||
{
|
||||
friend class Keyboard;
|
||||
|
||||
protected:
|
||||
virtual ControlState GetState(const State* const state) = 0;
|
||||
};
|
||||
|
||||
class Key : public Input
|
||||
{
|
||||
friend class Keyboard;
|
||||
|
||||
public:
|
||||
std::string GetName() const;
|
||||
|
||||
protected:
|
||||
Key(Display* const display, KeyCode keycode);
|
||||
ControlState GetState(const State* const state);
|
||||
|
||||
private:
|
||||
Display* const m_display;
|
||||
const KeyCode m_keycode;
|
||||
std::string m_keyname;
|
||||
|
||||
};
|
||||
|
||||
bool UpdateInput();
|
||||
bool UpdateOutput();
|
||||
|
||||
ControlState GetInputState(const ControllerInterface::Device::Input* const input);
|
||||
void SetOutputState(const ControllerInterface::Device::Output* const output, const ControlState state);
|
||||
|
||||
public:
|
||||
Keyboard(Display* display);
|
||||
~Keyboard();
|
||||
|
||||
std::string GetName() const;
|
||||
std::string GetSource() const;
|
||||
int GetId() const;
|
||||
|
||||
private:
|
||||
Display* m_display;
|
||||
State m_state;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,378 @@
|
||||
|
||||
#include <math.h>
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_pad.h"
|
||||
|
||||
#include "ControllerInterface/ControllerInterface.h"
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include "ConfigDiag.h"
|
||||
#endif
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#define PLUGIN_VERSION 0x0100
|
||||
|
||||
#ifdef DEBUGFAST
|
||||
#define PLUGIN_FULL_NAME "Dolphin GCPad New (DebugFast)"
|
||||
#else
|
||||
#ifdef _DEBUG
|
||||
#define PLUGIN_FULL_NAME "Dolphin GCPad New (Debug)"
|
||||
#else
|
||||
#define PLUGIN_FULL_NAME "Dolphin GCPad New"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
class wxDLLApp : public wxApp
|
||||
{
|
||||
bool OnInit()
|
||||
{
|
||||
return true;
|
||||
};
|
||||
};
|
||||
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
||||
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||
#endif
|
||||
// copied from GCPad
|
||||
SPADInitialize *g_PADInitialize = NULL;
|
||||
// Check if Dolphin is in focus
|
||||
// ----------------
|
||||
bool IsFocus()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HWND RenderingWindow = (g_PADInitialize) ? g_PADInitialize->hWnd : NULL;
|
||||
HWND Parent = GetParent(RenderingWindow);
|
||||
HWND TopLevel = GetParent(Parent);
|
||||
|
||||
if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#elif defined HAVE_X11 && HAVE_X11
|
||||
Display* GCdisplay = (Display*)g_PADInitialize->hWnd;
|
||||
Window GLWin = *(Window *)g_PADInitialize->pXWindow;
|
||||
bool bFocus = False;
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
bFocus = (wxPanel *)g_PADInitialize->pPanel == wxWindow::FindFocus();
|
||||
#endif
|
||||
Window FocusWin;
|
||||
int Revert;
|
||||
XGetInputFocus(GCdisplay, &FocusWin, &Revert);
|
||||
return (GLWin == FocusWin || bFocus);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// copied from GCPad
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
// copied from GCPad
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxWindow* GetParentedWxWindow(HWND Parent)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wxSetInstance((HINSTANCE)g_hInstance);
|
||||
#endif
|
||||
wxWindow *win = new wxWindow();
|
||||
#ifdef _WIN32
|
||||
win->SetHWND((WXHWND)Parent);
|
||||
win->AdoptAttributesFromHWND();
|
||||
#endif
|
||||
return win;
|
||||
}
|
||||
#endif
|
||||
// /
|
||||
|
||||
// the plugin
|
||||
Plugin g_plugin;
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
|
||||
{
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
wxSetInstance(hinstDLL);
|
||||
wxInitialize();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
wxUninitialize();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if plugin isn't initialized, init and load config
|
||||
void InitPlugin( void* const hwnd )
|
||||
{
|
||||
//g_plugin.controls_crit.Enter(); // enter
|
||||
//g_plugin.interface_crit.Enter();
|
||||
|
||||
if ( false == g_plugin.controller_interface.IsInit() )
|
||||
{
|
||||
// load the saved controller config
|
||||
g_plugin.LoadConfig();
|
||||
|
||||
// needed for Xlib and exclusive dinput
|
||||
g_plugin.controller_interface.SetHwnd( hwnd );
|
||||
g_plugin.controller_interface.Init();
|
||||
|
||||
// update control refs
|
||||
std::vector<ControllerEmu*>::const_iterator i = g_plugin.controllers.begin(),
|
||||
e = g_plugin.controllers.end();
|
||||
for ( ; i!=e; ++i )
|
||||
(*i)->UpdateReferences( g_plugin.controller_interface );
|
||||
|
||||
}
|
||||
|
||||
//g_plugin.interface_crit.Leave();
|
||||
//g_plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
// I N T E R F A C E
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function:
|
||||
// Purpose:
|
||||
// input:
|
||||
// output:
|
||||
//
|
||||
void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
{
|
||||
// why not, i guess
|
||||
if ( NULL == _pPADStatus )
|
||||
return;
|
||||
|
||||
memset( _pPADStatus, 0, sizeof(*_pPADStatus) );
|
||||
_pPADStatus->err = PAD_ERR_NONE;
|
||||
// wtf is this?
|
||||
_pPADStatus->button |= PAD_USE_ORIGIN;
|
||||
|
||||
// try lock
|
||||
if ( false == g_plugin.controls_crit.TryEnter() )
|
||||
{
|
||||
// if gui has lock (messing with controls), skip this input cycle
|
||||
// center axes and return
|
||||
memset( &_pPADStatus->stickX, 0x80, 4 );
|
||||
return;
|
||||
}
|
||||
|
||||
// if we are on the next input cycle, update output and input
|
||||
// if we can get a lock
|
||||
static int _last_numPAD = 4;
|
||||
if ( _numPAD <= _last_numPAD && g_plugin.interface_crit.TryEnter() )
|
||||
{
|
||||
g_plugin.controller_interface.UpdateOutput();
|
||||
g_plugin.controller_interface.UpdateInput();
|
||||
g_plugin.interface_crit.Leave();
|
||||
}
|
||||
_last_numPAD = _numPAD;
|
||||
|
||||
// if we want background input or have focus
|
||||
if ( g_plugin.controllers[_numPAD]->options[0].settings[0]->value || IsFocus() )
|
||||
{
|
||||
// get input
|
||||
((GCPad*)g_plugin.controllers[ _numPAD ])->GetInput( _pPADStatus );
|
||||
}
|
||||
else
|
||||
{
|
||||
// center sticks
|
||||
memset( &_pPADStatus->stickX, 0x80, 4 );
|
||||
// stop rumble
|
||||
((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( false );
|
||||
}
|
||||
|
||||
// leave
|
||||
g_plugin.controls_crit.Leave();
|
||||
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: Send keyboard input to the plugin
|
||||
// Purpose:
|
||||
// input: The key and if it's pressed or released
|
||||
// output: None
|
||||
//
|
||||
void PAD_Input(u16 _Key, u8 _UpDown)
|
||||
{
|
||||
// nofin
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: PAD_Rumble
|
||||
// Purpose: Pad rumble!
|
||||
// input: PAD number, Command type (Stop=0, Rumble=1, Stop Hard=2) and strength of Rumble
|
||||
// output: none
|
||||
//
|
||||
void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
|
||||
{
|
||||
// enter
|
||||
if ( g_plugin.controls_crit.TryEnter() )
|
||||
{
|
||||
// only on/off rumble, if we have focus or background input on
|
||||
if ( g_plugin.controllers[_numPAD]->options[0].settings[0]->value || IsFocus() )
|
||||
((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( 1 == _uType && _uStrength > 2 );
|
||||
|
||||
// leave
|
||||
g_plugin.controls_crit.Leave();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GLOBAL I N T E R F A C E
|
||||
// Function: GetDllInfo
|
||||
// Purpose: This function allows the emulator to gather information
|
||||
// about the DLL by filling in the PluginInfo structure.
|
||||
// input: A pointer to a PLUGIN_INFO structure that needs to be
|
||||
// filled by the function. (see def above)
|
||||
// output: none
|
||||
//
|
||||
void GetDllInfo(PLUGIN_INFO* _pPluginInfo)
|
||||
{
|
||||
// don't feel like messing around with all those strcpy functions and warnings
|
||||
//char *s1 = CIFACE_PLUGIN_FULL_NAME, *s2 = _pPluginInfo->Name;
|
||||
//while ( *s2++ = *s1++ );
|
||||
memcpy( _pPluginInfo->Name, PLUGIN_FULL_NAME, sizeof(PLUGIN_FULL_NAME) );
|
||||
_pPluginInfo->Type = PLUGIN_TYPE_PAD;
|
||||
_pPluginInfo->Version = PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: DllConfig
|
||||
// Purpose: This function is optional function that is provided
|
||||
// to allow the user to configure the DLL
|
||||
// input: A handle to the window that calls this function
|
||||
// output: none
|
||||
//
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
bool was_init = false;
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
Display *dpy = NULL;
|
||||
#endif
|
||||
if ( g_plugin.controller_interface.IsInit() ) // hack for showing dialog when game isnt running
|
||||
was_init = true;
|
||||
else
|
||||
{
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
dpy = XOpenDisplay(0);
|
||||
InitPlugin(dpy);
|
||||
#else
|
||||
InitPlugin(_hParent);
|
||||
#endif
|
||||
}
|
||||
|
||||
// copied from GCPad
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxWindow *frame = GetParentedWxWindow(_hParent);
|
||||
ConfigDialog* m_ConfigFrame = new ConfigDialog( frame, g_plugin, PLUGIN_FULL_NAME, was_init );
|
||||
|
||||
#ifdef _WIN32
|
||||
frame->Disable();
|
||||
m_ConfigFrame->ShowModal();
|
||||
frame->Enable();
|
||||
#else
|
||||
m_ConfigFrame->ShowModal();
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
wxMilliSleep( 50 ); // hooray for hacks
|
||||
frame->SetFocus();
|
||||
frame->SetHWND(NULL);
|
||||
#endif
|
||||
|
||||
m_ConfigFrame->Destroy();
|
||||
m_ConfigFrame = NULL;
|
||||
frame->Destroy();
|
||||
#endif
|
||||
// /
|
||||
|
||||
if ( !was_init ) // hack for showing dialog when game isnt running
|
||||
{
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
XCloseDisplay(dpy);
|
||||
#endif
|
||||
g_plugin.controller_interface.DeInit();
|
||||
}
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: DllDebugger
|
||||
// Purpose: Open the debugger
|
||||
// input: a handle to the window that calls this function
|
||||
// output: none
|
||||
//
|
||||
void DllDebugger(HWND _hParent, bool Show)
|
||||
{
|
||||
// wut?
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: DllSetGlobals
|
||||
// Purpose: Set the pointer for globals variables
|
||||
// input: a pointer to the global struct
|
||||
// output: none
|
||||
//
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
|
||||
{
|
||||
// wut?
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: Initialize
|
||||
// Purpose: Initialize the plugin
|
||||
// input: Init
|
||||
// output: none
|
||||
//
|
||||
void Initialize(void *init)
|
||||
{
|
||||
g_PADInitialize = (SPADInitialize*)init;
|
||||
if ( false == g_plugin.controller_interface.IsInit() )
|
||||
InitPlugin( ((SPADInitialize*)init)->hWnd );
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: Shutdown
|
||||
// Purpose: This function is called when the emulator is shutting down
|
||||
// a game allowing the dll to de-initialise.
|
||||
// input: none
|
||||
// output: none
|
||||
//
|
||||
void Shutdown(void)
|
||||
{
|
||||
//plugin.controls_crit.Enter(); // enter
|
||||
if ( g_plugin.controller_interface.IsInit() )
|
||||
g_plugin.controller_interface.DeInit();
|
||||
//plugin.controls_crit.Leave(); // leave
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: DoState
|
||||
// Purpose: Saves/load state
|
||||
// input/output: ptr
|
||||
// input: mode
|
||||
//
|
||||
void DoState(unsigned char **ptr, int mode)
|
||||
{
|
||||
// prolly won't need this
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: EmuStateChange
|
||||
// Purpose: Notifies the plugin of a change in emulation state
|
||||
// input: newState
|
||||
// output: none
|
||||
//
|
||||
void EmuStateChange(PLUGIN_EMUSTATE newState)
|
||||
{
|
||||
// maybe use this later
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
|
||||
#include "IniFile.h"
|
||||
|
||||
//
|
||||
// TrimChars
|
||||
//
|
||||
// trim whitespace, or any, chars from both ends
|
||||
//
|
||||
template <typename S>
|
||||
std::string TrimChars( const std::string& str, const S space )
|
||||
{
|
||||
const size_t start = str.find_first_not_of( space );
|
||||
|
||||
if ( str.npos == start )
|
||||
return "";
|
||||
|
||||
return str.substr( start, str.find_last_not_of( space ) - start + 1 );
|
||||
}
|
||||
|
||||
//
|
||||
// IniSection :: Set
|
||||
//
|
||||
// set key's value if it doesn't match the default
|
||||
// otherwise remove the key from the section if it exists
|
||||
//
|
||||
void IniSection::Set( const std::string& key, const std::string& val, const std::string& def )
|
||||
{
|
||||
if ( val != def )
|
||||
operator[](key) = val;
|
||||
else
|
||||
{
|
||||
iterator f = find(key);
|
||||
if ( f != end() )
|
||||
erase( f );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// IniSection :: Get
|
||||
//
|
||||
// return a key's value if it exists
|
||||
// otherwise return the default
|
||||
//
|
||||
std::string IniSection::Get( const std::string& key, const std::string& def )
|
||||
{
|
||||
const const_iterator f = find(key);
|
||||
if ( f != end() )
|
||||
if ( false == f->second.empty() )
|
||||
return f->second;
|
||||
return def;
|
||||
}
|
||||
|
||||
//
|
||||
// IniFile :: Save
|
||||
//
|
||||
// save a file
|
||||
//
|
||||
void IniFile::Save( std::ostream& file )
|
||||
{
|
||||
const_iterator i = begin(),
|
||||
e = end();
|
||||
for ( ; i != e; ++i )
|
||||
{
|
||||
// skip a line at new sections
|
||||
file << "\n[" << i->first << "]\n";
|
||||
Section::const_iterator si = i->second.begin(),
|
||||
se = i->second.end();
|
||||
for ( ; si != se; ++si )
|
||||
file << si->first << " = " << si->second << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// IniFile :: Load
|
||||
//
|
||||
// load a file
|
||||
//
|
||||
void IniFile::Load( std::istream& file )
|
||||
{
|
||||
const char* const space = "\t\r ";
|
||||
std::string line;
|
||||
// start off with an empty section
|
||||
Section* section = &(*this)[""];
|
||||
while ( std::getline( file, line ).good() ) // read a line
|
||||
{
|
||||
line = TrimChars(line,space);
|
||||
if ( line.size() )
|
||||
{
|
||||
switch ( line[0] )
|
||||
{
|
||||
// comment
|
||||
case '#' :
|
||||
case ';' :
|
||||
break;
|
||||
// section
|
||||
case '[' :
|
||||
// kinda odd trimming
|
||||
section = &(*this)[ TrimChars(line,"][\t\r ") ];
|
||||
break;
|
||||
// key/value
|
||||
default :
|
||||
{
|
||||
std::istringstream ss(line);
|
||||
std::string key; std::getline( ss, key, '=' );
|
||||
std::string val; std::getline( ss, val );
|
||||
(*section)[ TrimChars(key,space) ] = TrimChars(val,space);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Clean();
|
||||
}
|
||||
|
||||
//
|
||||
// IniFile :: Clean
|
||||
//
|
||||
// remove empty key/values and sections
|
||||
// after trying to access ini sections/values, they are automatically allocated
|
||||
// this deletes the empty stuff
|
||||
//
|
||||
void IniFile::Clean()
|
||||
{
|
||||
iterator i = begin(),
|
||||
e = end();
|
||||
for ( ; i != e; )
|
||||
{
|
||||
Section::iterator si = i->second.begin(),
|
||||
se = i->second.end();
|
||||
for ( ; si != se; )
|
||||
{
|
||||
if ( si->second.empty() )
|
||||
i->second.erase( si++ );
|
||||
else
|
||||
++si;
|
||||
}
|
||||
if ( i->second.empty() )
|
||||
erase( i++ );
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef _INIFILE_H_
|
||||
#define _INIFILE_H_
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
//
|
||||
// IniFile
|
||||
//
|
||||
class IniSection : public std::map< std::string, std::string >
|
||||
{
|
||||
public:
|
||||
void Set( const std::string& key, const std::string& val, const std::string& def = "" );
|
||||
std::string Get( const std::string& key, const std::string& def = "" );
|
||||
|
||||
template <typename V, typename D>
|
||||
void Set( const std::string& key, const V& val, const D& def = 0 )
|
||||
{
|
||||
if ( val != def )
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << long(val);
|
||||
operator[](key) = ss.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
iterator f = find(key);
|
||||
if ( f != end() )
|
||||
erase( f );
|
||||
}
|
||||
}
|
||||
template <typename V>
|
||||
V Get( const std::string& key, const V& def = 0 )
|
||||
{
|
||||
const const_iterator f = find(key);
|
||||
if ( f != end() )
|
||||
if ( false == f->second.empty() )
|
||||
{
|
||||
std::istringstream ss(f->second);
|
||||
int val;
|
||||
ss >> val;
|
||||
return V(val);
|
||||
}
|
||||
return def;
|
||||
}
|
||||
};
|
||||
|
||||
class IniFile : public std::map< std::string, IniSection >
|
||||
{
|
||||
public:
|
||||
typedef IniSection Section;
|
||||
|
||||
void Clean();
|
||||
void Save( std::ostream& file );
|
||||
void Load( std::istream& file );
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
# -*- python -*-
|
||||
|
||||
Import('env')
|
||||
import sys
|
||||
|
||||
name = "Plugin_GCPadNew"
|
||||
padenv = env.Clone()
|
||||
|
||||
files = [
|
||||
'Config.cpp',
|
||||
'ControllerEmu.cpp',
|
||||
'ControllerEmu/GCPad/GCPad.cpp',
|
||||
'GCPadNew.cpp',
|
||||
'ControllerInterface/ControllerInterface.cpp',
|
||||
'IniFile.cpp'
|
||||
]
|
||||
|
||||
if padenv['HAVE_SDL']:
|
||||
files += [ 'ControllerInterface/SDL/SDL.cpp' ]
|
||||
if sys.platform == 'linux2':
|
||||
files += [ 'ControllerInterface/Xlib/Xlib.cpp' ]
|
||||
|
||||
if padenv['HAVE_WX']:
|
||||
files += [
|
||||
'ConfigDiag.cpp',
|
||||
'ConfigDiagBitmaps.cpp',
|
||||
]
|
||||
|
||||
padenv.Append(
|
||||
LIBS = [ 'inputcommon', 'common' ],
|
||||
)
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
padenv['FRAMEWORKS'] = ['CoreFoundation', 'System', 'Cocoa' ]
|
||||
|
||||
padenv.SharedLibrary(env['plugin_dir']+name, files)
|
||||
@@ -173,7 +173,7 @@ unsigned int Callback_PeekMessages()
|
||||
void UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
char temp[512];
|
||||
sprintf_s(temp, 512, "SVN R%i: DX9: %s", SVN_REV, text);
|
||||
sprintf_s(temp, 512, "%s: DX9: %s", SVN_REV_STR, text);
|
||||
SetWindowTextA(EmuWindow::GetWnd(), temp);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,58 +113,95 @@ unsigned int Callback_PeekMessages()
|
||||
void UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
char temp[512];
|
||||
sprintf(temp, "SVN R%s: GL: %s", SVN_REV_STR, text);
|
||||
sprintf(temp, "%s: GL: %s", SVN_REV_STR, text);
|
||||
OpenGL_SetWindowText(temp);
|
||||
}
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
THREAD_RETURN XEventThread(void *pArg);
|
||||
|
||||
void X11_EWMH_Fullscreen(int action)
|
||||
{
|
||||
_assert_(action == _NET_WM_STATE_REMOVE || action == _NET_WM_STATE_ADD
|
||||
|| action == _NET_WM_STATE_TOGGLE);
|
||||
|
||||
// Init X event structure for _NET_WM_STATE_FULLSCREEN client message
|
||||
XEvent event;
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.message_type = XInternAtom(GLWin.dpy, "_NET_WM_STATE", False);
|
||||
event.xclient.window = GLWin.win;
|
||||
event.xclient.format = 32;
|
||||
event.xclient.data.l[0] = action;
|
||||
event.xclient.data.l[1] = XInternAtom(GLWin.dpy, "_NET_WM_STATE_FULLSCREEN", False);
|
||||
|
||||
// Send the event
|
||||
if (!XSendEvent(GLWin.dpy, DefaultRootWindow(GLWin.dpy), False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask, &event))
|
||||
ERROR_LOG(VIDEO, "Failed to switch fullscreen/windowed mode.\n");
|
||||
}
|
||||
|
||||
void CreateXWindow (void)
|
||||
{
|
||||
Atom wmProtocols[3];
|
||||
int width, height;
|
||||
Window parent;
|
||||
|
||||
if (GLWin.fs)
|
||||
{
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
if (GLWin.fullSize >= 0)
|
||||
XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
|
||||
GLWin.fullSize, GLWin.screenRotation, CurrentTime);
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
wxMutexGuiEnter();
|
||||
#endif
|
||||
GLWin.attr.override_redirect = True;
|
||||
width = GLWin.fullWidth;
|
||||
height = GLWin.fullHeight;
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
if (GLWin.fs && !GLWin.renderToMain)
|
||||
XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
|
||||
GLWin.fullSize, GLWin.screenRotation, CurrentTime);
|
||||
#endif
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
if (GLWin.renderToMain)
|
||||
{
|
||||
GLWin.panel->GetSize((int *)&GLWin.width, (int *)&GLWin.height);
|
||||
GLWin.panel->GetPosition(&GLWin.x, &GLWin.y);
|
||||
parent = GDK_WINDOW_XID(GTK_WIDGET(GLWin.panel->GetHandle())->window);
|
||||
GLWin.panel->SetFocus();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GLWin.attr.override_redirect = False;
|
||||
width = GLWin.winWidth;
|
||||
height = GLWin.winHeight;
|
||||
GLWin.x = 0;
|
||||
GLWin.y = 0;
|
||||
GLWin.width = GLWin.winWidth;
|
||||
GLWin.height = GLWin.winHeight;
|
||||
parent = RootWindow(GLWin.dpy, GLWin.vi->screen);
|
||||
}
|
||||
|
||||
// Control window size and picture scaling
|
||||
s_backbuffer_width = width;
|
||||
s_backbuffer_height = height;
|
||||
s_backbuffer_width = GLWin.width;
|
||||
s_backbuffer_height = GLWin.height;
|
||||
|
||||
// create the window
|
||||
GLWin.attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
|
||||
StructureNotifyMask | ResizeRedirectMask;
|
||||
GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, GLWin.vi->screen),
|
||||
0, 0, width, height, 0, GLWin.vi->depth, InputOutput, GLWin.vi->visual,
|
||||
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &GLWin.attr);
|
||||
GLWin.win = XCreateWindow(GLWin.dpy, parent,
|
||||
GLWin.x, GLWin.y, GLWin.width, GLWin.height, 0, GLWin.vi->depth, InputOutput, GLWin.vi->visual,
|
||||
CWBorderPixel | CWBackPixel | CWColormap | CWEventMask, &GLWin.attr);
|
||||
wmProtocols[0] = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True);
|
||||
wmProtocols[1] = XInternAtom(GLWin.dpy, "WM_TAKE_FOCUS", True);
|
||||
wmProtocols[2] = XInternAtom(GLWin.dpy, "TOGGLE_FULLSCREEN", False);
|
||||
wmProtocols[1] = XInternAtom(GLWin.dpy, "_NET_WM_STATE", False);
|
||||
wmProtocols[2] = XInternAtom(GLWin.dpy, "_NET_WM_STATE_FULLSCREEN", False);
|
||||
XSetWMProtocols(GLWin.dpy, GLWin.win, wmProtocols, 3);
|
||||
XSetStandardProperties(GLWin.dpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL);
|
||||
XMapRaised(GLWin.dpy, GLWin.win);
|
||||
if (GLWin.fs)
|
||||
{
|
||||
XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
XGrabPointer(GLWin.dpy, GLWin.win, True, NULL,
|
||||
GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime);
|
||||
XSetInputFocus(GLWin.dpy, GLWin.win, RevertToPointerRoot, CurrentTime);
|
||||
}
|
||||
XSync(GLWin.dpy, True);
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
wxMutexGuiLeave();
|
||||
#endif
|
||||
|
||||
if (g_Config.bHideCursor)
|
||||
{
|
||||
// make a blank cursor
|
||||
Pixmap Blank;
|
||||
XColor DummyColor;
|
||||
char ZeroData[1] = {0};
|
||||
Blank = XCreateBitmapFromData (GLWin.dpy, GLWin.win, ZeroData, 1, 1);
|
||||
GLWin.blankCursor = XCreatePixmapCursor(GLWin.dpy, Blank, Blank, &DummyColor, &DummyColor, 0, 0);
|
||||
XFreePixmap (GLWin.dpy, Blank);
|
||||
}
|
||||
|
||||
GLWin.xEventThread = new Common::Thread(XEventThread, NULL);
|
||||
}
|
||||
|
||||
void DestroyXWindow(void)
|
||||
@@ -179,25 +216,180 @@ void DestroyXWindow(void)
|
||||
/* switch back to original desktop resolution if we were in fullscreen */
|
||||
if( GLWin.fs )
|
||||
{
|
||||
XUngrabKeyboard (GLWin.dpy, CurrentTime);
|
||||
XUngrabPointer (GLWin.dpy, CurrentTime);
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
if (GLWin.fullSize >= 0)
|
||||
XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
|
||||
GLWin.deskSize, GLWin.screenRotation, CurrentTime);
|
||||
XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
|
||||
GLWin.deskSize, GLWin.screenRotation, CurrentTime);
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
if (!GLWin.renderToMain)
|
||||
#endif
|
||||
X11_EWMH_Fullscreen(_NET_WM_STATE_REMOVE);
|
||||
#endif
|
||||
}
|
||||
XUndefineCursor(GLWin.dpy, GLWin.win);
|
||||
XUnmapWindow(GLWin.dpy, GLWin.win);
|
||||
XSync(GLWin.dpy, True);
|
||||
GLWin.win = 0;
|
||||
}
|
||||
|
||||
void ToggleFullscreenMode (void)
|
||||
{
|
||||
DestroyXWindow();
|
||||
GLWin.fs = !GLWin.fs;
|
||||
CreateXWindow();
|
||||
OpenGL_MakeCurrent();
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
if (GLWin.fs)
|
||||
XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
|
||||
GLWin.fullSize, GLWin.screenRotation, CurrentTime);
|
||||
else
|
||||
XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
|
||||
GLWin.deskSize, GLWin.screenRotation, CurrentTime);
|
||||
#endif
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
if (!GLWin.renderToMain)
|
||||
#endif
|
||||
{
|
||||
X11_EWMH_Fullscreen(_NET_WM_STATE_TOGGLE);
|
||||
XRaiseWindow(GLWin.dpy, GLWin.win);
|
||||
XSetInputFocus(GLWin.dpy, GLWin.win, RevertToPointerRoot, CurrentTime);
|
||||
}
|
||||
XSync(GLWin.dpy, False);
|
||||
}
|
||||
|
||||
THREAD_RETURN XEventThread(void *pArg)
|
||||
{
|
||||
bool bPaused = False;
|
||||
while (GLWin.win)
|
||||
{
|
||||
XEvent event;
|
||||
KeySym key;
|
||||
for (int num_events = XPending(GLWin.dpy); num_events > 0; num_events--) {
|
||||
XNextEvent(GLWin.dpy, &event);
|
||||
switch(event.type) {
|
||||
case KeyPress:
|
||||
key = XLookupKeysym((XKeyEvent*)&event, 0);
|
||||
switch (key)
|
||||
{
|
||||
case XK_F1: case XK_F2: case XK_F3: case XK_F4: case XK_F5: case XK_F6:
|
||||
case XK_F7: case XK_F8: case XK_F9: case XK_F11: case XK_F12:
|
||||
g_VideoInitialize.pKeyPress(key - 0xff4e,
|
||||
event.xkey.state & ShiftMask,
|
||||
event.xkey.state & ControlMask);
|
||||
break;
|
||||
case XK_Escape:
|
||||
if (GLWin.fs && !bPaused)
|
||||
{
|
||||
printf("toggling fullscreen\n");
|
||||
ToggleFullscreenMode();
|
||||
}
|
||||
g_VideoInitialize.pKeyPress(0x1c, False, False);
|
||||
break;
|
||||
case XK_Return:
|
||||
if (event.xkey.state & Mod1Mask)
|
||||
ToggleFullscreenMode();
|
||||
break;
|
||||
case XK_3:
|
||||
OSDChoice = 1;
|
||||
// Toggle native resolution
|
||||
if (!(g_Config.bNativeResolution || g_Config.b2xResolution))
|
||||
g_Config.bNativeResolution = true;
|
||||
else if (g_Config.bNativeResolution && Renderer::AllowCustom())
|
||||
{ g_Config.bNativeResolution = false; if (Renderer::Allow2x()) {g_Config.b2xResolution = true;} }
|
||||
else if (Renderer::AllowCustom())
|
||||
g_Config.b2xResolution = false;
|
||||
break;
|
||||
case XK_4:
|
||||
OSDChoice = 2;
|
||||
// Toggle aspect ratio
|
||||
g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
|
||||
break;
|
||||
case XK_5:
|
||||
OSDChoice = 3;
|
||||
// Toggle EFB copy
|
||||
if (g_Config.bEFBCopyDisable || g_Config.bCopyEFBToTexture)
|
||||
{
|
||||
g_Config.bEFBCopyDisable = !g_Config.bEFBCopyDisable;
|
||||
g_Config.bCopyEFBToTexture = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Config.bCopyEFBToTexture = !g_Config.bCopyEFBToTexture;
|
||||
}
|
||||
break;
|
||||
case XK_6:
|
||||
OSDChoice = 4;
|
||||
g_Config.bDisableFog = !g_Config.bDisableFog;
|
||||
break;
|
||||
case XK_7:
|
||||
OSDChoice = 5;
|
||||
g_Config.bDisableLighting = !g_Config.bDisableLighting;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FocusIn:
|
||||
if (g_Config.bHideCursor && !bPaused && !GLWin.renderToMain)
|
||||
XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor);
|
||||
break;
|
||||
case FocusOut:
|
||||
if (g_Config.bHideCursor && !bPaused && !GLWin.renderToMain)
|
||||
XUndefineCursor(GLWin.dpy, GLWin.win);
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
Window winDummy;
|
||||
unsigned int borderDummy;
|
||||
XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
|
||||
&GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
|
||||
s_backbuffer_width = GLWin.width;
|
||||
s_backbuffer_height = GLWin.height;
|
||||
// Save windowed mode size for return from fullscreen
|
||||
if (!GLWin.fs)
|
||||
{
|
||||
GLWin.winWidth = GLWin.width;
|
||||
GLWin.winHeight = GLWin.height;
|
||||
}
|
||||
break;
|
||||
case ClientMessage:
|
||||
if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", False))
|
||||
g_VideoInitialize.pKeyPress(0x1b, False, False);
|
||||
if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "TOGGLE_FULLSCREEN", False))
|
||||
ToggleFullscreenMode();
|
||||
if (g_Config.bHideCursor &&
|
||||
(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "PAUSE", False))
|
||||
{
|
||||
bPaused = True;
|
||||
XUndefineCursor(GLWin.dpy, GLWin.win);
|
||||
}
|
||||
if (g_Config.bHideCursor &&
|
||||
(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "RESUME", False))
|
||||
{
|
||||
bPaused = False;
|
||||
XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor);
|
||||
}
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
if (GLWin.renderToMain &&
|
||||
(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "RESIZE", False))
|
||||
{
|
||||
GLWin.panel->GetSize((int *)&GLWin.width, (int *)&GLWin.height);
|
||||
GLWin.panel->GetPosition(&GLWin.x, &GLWin.y);
|
||||
XMoveResizeWindow(GLWin.dpy, GLWin.win, GLWin.x, GLWin.y, GLWin.width, GLWin.height);
|
||||
}
|
||||
if (GLWin.renderToMain &&
|
||||
(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "FOCUSIN", False))
|
||||
{
|
||||
GLWin.panel->SetFocus();
|
||||
if (g_Config.bHideCursor)
|
||||
XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor);
|
||||
}
|
||||
if (GLWin.renderToMain && g_Config.bHideCursor &&
|
||||
(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "FOCUSOUT", False))
|
||||
XUndefineCursor(GLWin.dpy, GLWin.win);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Common::SleepCurrentThread(20);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -352,7 +544,6 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
|
||||
// --------------------------------------
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
Colormap cmap;
|
||||
int glxMajorVersion, glxMinorVersion;
|
||||
int vidModeMajorVersion, vidModeMinorVersion;
|
||||
|
||||
@@ -375,11 +566,20 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
|
||||
|
||||
|
||||
GLWin.dpy = XOpenDisplay(0);
|
||||
g_VideoInitialize.pWindowHandle = (HWND)GLWin.dpy;
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
GLWin.panel = (wxPanel *)g_VideoInitialize.pPanel;
|
||||
#endif
|
||||
g_VideoInitialize.pWindowHandle = (Display *)GLWin.dpy;
|
||||
GLWin.screen = DefaultScreen(GLWin.dpy);
|
||||
|
||||
// Fullscreen option.
|
||||
GLWin.fs = g_Config.bFullscreen; //Set to setting in Options
|
||||
// Render to main option.
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
GLWin.renderToMain = g_Config.RenderToMainframe;
|
||||
#else
|
||||
GLWin.renderToMain = False;
|
||||
#endif
|
||||
|
||||
/* get an appropriate visual */
|
||||
GLWin.vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl);
|
||||
@@ -402,9 +602,12 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
|
||||
PanicAlert("Couldn't Create GLX context.Quit");
|
||||
exit(0); // TODO: Don't bring down entire Emu
|
||||
}
|
||||
// Create a color map.
|
||||
cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, GLWin.vi->screen), GLWin.vi->visual, AllocNone);
|
||||
GLWin.attr.colormap = cmap;
|
||||
// Create a color map and set the event masks
|
||||
GLWin.attr.colormap = XCreateColormap(GLWin.dpy,
|
||||
RootWindow(GLWin.dpy, GLWin.vi->screen), GLWin.vi->visual, AllocNone);
|
||||
GLWin.attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
|
||||
StructureNotifyMask | ResizeRedirectMask;
|
||||
GLWin.attr.background_pixel = BlackPixel(GLWin.dpy, GLWin.screen);
|
||||
GLWin.attr.border_pixel = 0;
|
||||
XkbSetDetectableAutoRepeat(GLWin.dpy, True, NULL);
|
||||
|
||||
@@ -459,19 +662,14 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
|
||||
GLWin.fullHeight = DisplayHeight(GLWin.dpy, GLWin.screen);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
if (GLWin.renderToMain)
|
||||
g_VideoInitialize.pKeyPress(0, False, False);
|
||||
#endif
|
||||
|
||||
CreateXWindow();
|
||||
g_VideoInitialize.pXWindow = (Window *) &GLWin.win;
|
||||
|
||||
if (g_Config.bHideCursor)
|
||||
{
|
||||
// make a blank cursor
|
||||
Pixmap Blank;
|
||||
XColor DummyColor;
|
||||
char ZeroData[1] = {0};
|
||||
Blank = XCreateBitmapFromData (GLWin.dpy, GLWin.win, ZeroData, 1, 1);
|
||||
GLWin.blankCursor = XCreatePixmapCursor(GLWin.dpy, Blank, Blank, &DummyColor, &DummyColor, 0, 0);
|
||||
XFreePixmap (GLWin.dpy, Blank);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -501,6 +699,19 @@ bool OpenGL_MakeCurrent()
|
||||
ERROR_LOG(VIDEO, "no Direct Rendering possible!");
|
||||
}
|
||||
|
||||
if (GLWin.fs)
|
||||
{
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
if (GLWin.renderToMain)
|
||||
{
|
||||
GLWin.fs = False;
|
||||
g_VideoInitialize.pKeyPress(0x1d, False, False);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
X11_EWMH_Fullscreen(_NET_WM_STATE_ADD);
|
||||
}
|
||||
|
||||
// Hide the cursor now
|
||||
if (g_Config.bHideCursor)
|
||||
XDefineCursor (GLWin.dpy, GLWin.win, GLWin.blankCursor);
|
||||
@@ -557,118 +768,6 @@ void OpenGL_Update()
|
||||
s_backbuffer_height = height;
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
// We just check all of our events here
|
||||
XEvent event;
|
||||
KeySym key;
|
||||
int num_events;
|
||||
for (num_events = XPending(GLWin.dpy);num_events > 0;num_events--) {
|
||||
XNextEvent(GLWin.dpy, &event);
|
||||
switch(event.type) {
|
||||
case KeyPress:
|
||||
key = XLookupKeysym((XKeyEvent*)&event, 0);
|
||||
switch (key)
|
||||
{
|
||||
case XK_F4:
|
||||
if(event.xkey.state & Mod1Mask)
|
||||
{
|
||||
g_VideoInitialize.pKeyPress(0x1b, False, False);
|
||||
break;
|
||||
}
|
||||
case XK_F1: case XK_F2: case XK_F3: case XK_F5:
|
||||
case XK_F6: case XK_F7: case XK_F8: case XK_F9:
|
||||
g_VideoInitialize.pKeyPress(key - 0xff4e,
|
||||
event.xkey.state & ShiftMask,
|
||||
event.xkey.state & ControlMask);
|
||||
break;
|
||||
case XK_Escape:
|
||||
if (GLWin.fs)
|
||||
{
|
||||
ToggleFullscreenMode();
|
||||
XEvent mapevent;
|
||||
do {
|
||||
XMaskEvent(GLWin.dpy, StructureNotifyMask, &mapevent);
|
||||
} while ( (mapevent.type != MapNotify) || (mapevent.xmap.event != GLWin.win) );
|
||||
}
|
||||
g_VideoInitialize.pKeyPress(0x1c, False, False);
|
||||
break;
|
||||
case XK_Return:
|
||||
if (event.xkey.state & Mod1Mask)
|
||||
ToggleFullscreenMode();
|
||||
break;
|
||||
case XK_3:
|
||||
OSDChoice = 1;
|
||||
// Toggle native resolution
|
||||
if (!(g_Config.bNativeResolution || g_Config.b2xResolution))
|
||||
g_Config.bNativeResolution = true;
|
||||
else if (g_Config.bNativeResolution && Renderer::AllowCustom())
|
||||
{ g_Config.bNativeResolution = false; if (Renderer::Allow2x()) {g_Config.b2xResolution = true;} }
|
||||
else if (Renderer::AllowCustom())
|
||||
g_Config.b2xResolution = false;
|
||||
break;
|
||||
case XK_4:
|
||||
OSDChoice = 2;
|
||||
// Toggle aspect ratio
|
||||
g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
|
||||
break;
|
||||
case XK_5:
|
||||
OSDChoice = 3;
|
||||
// Toggle EFB copy
|
||||
if (g_Config.bEFBCopyDisable || g_Config.bCopyEFBToTexture)
|
||||
{
|
||||
g_Config.bEFBCopyDisable = !g_Config.bEFBCopyDisable;
|
||||
g_Config.bCopyEFBToTexture = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Config.bCopyEFBToTexture = !g_Config.bCopyEFBToTexture;
|
||||
}
|
||||
break;
|
||||
case XK_6:
|
||||
OSDChoice = 4;
|
||||
g_Config.bDisableFog = !g_Config.bDisableFog;
|
||||
break;
|
||||
case XK_7:
|
||||
OSDChoice = 5;
|
||||
g_Config.bDisableLighting = !g_Config.bDisableLighting;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case FocusIn:
|
||||
if (g_Config.bHideCursor)
|
||||
XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor);
|
||||
break;
|
||||
case FocusOut:
|
||||
if (g_Config.bHideCursor && !GLWin.fs)
|
||||
XUndefineCursor(GLWin.dpy, GLWin.win);
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
Window winDummy;
|
||||
unsigned int borderDummy;
|
||||
XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
|
||||
&GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
|
||||
s_backbuffer_width = GLWin.width;
|
||||
s_backbuffer_height = GLWin.height;
|
||||
// Save windowed mode size for return from fullscreen
|
||||
if (!GLWin.fs)
|
||||
{
|
||||
GLWin.winWidth = GLWin.width;
|
||||
GLWin.winHeight = GLWin.height;
|
||||
}
|
||||
break;
|
||||
case ClientMessage:
|
||||
if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", False))
|
||||
g_VideoInitialize.pKeyPress(0x1b, False, False);
|
||||
if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "TOGGLE_FULLSCREEN", False))
|
||||
ToggleFullscreenMode();
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -708,6 +807,9 @@ void OpenGL_Shutdown()
|
||||
}
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
DestroyXWindow();
|
||||
if (GLWin.xEventThread)
|
||||
GLWin.xEventThread->WaitForDeath();
|
||||
GLWin.xEventThread = NULL;
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
if (GLWin.fullSize >= 0)
|
||||
XRRFreeScreenConfigInfo(GLWin.screenConfig);
|
||||
@@ -717,6 +819,7 @@ void OpenGL_Shutdown()
|
||||
if (GLWin.ctx)
|
||||
{
|
||||
glXDestroyContext(GLWin.dpy, GLWin.ctx);
|
||||
XFreeColormap(GLWin.dpy, GLWin.attr.colormap);
|
||||
XCloseDisplay(GLWin.dpy);
|
||||
GLWin.ctx = NULL;
|
||||
}
|
||||
|
||||
@@ -31,19 +31,38 @@
|
||||
#include <GLew/gl.h>
|
||||
#include <GLew/glext.h>
|
||||
|
||||
#else // linux basic definitions
|
||||
#else // linux and apple basic definitions
|
||||
|
||||
#if defined(USE_WX) && USE_WX
|
||||
#include <GL/glew.h>
|
||||
#include "wx/wx.h"
|
||||
#include "wx/glcanvas.h"
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
#define I_NEED_OS2_H // HAXXOR
|
||||
#include <GL/glxew.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 // Needed for render to main
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include "Thread.h"
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif // XRANDR
|
||||
// EWMH state actions, see
|
||||
// http://freedesktop.org/wiki/Specifications/wm-spec?action=show&redirect=Standards%2Fwm-spec
|
||||
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
|
||||
#define _NET_WM_STATE_ADD 1 /* add/set property */
|
||||
#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
|
||||
|
||||
#elif defined(USE_SDL) && USE_SDL
|
||||
#include <GL/glew.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
#include <GL/glew.h>
|
||||
#include "cocoaGL.h"
|
||||
@@ -65,15 +84,6 @@
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif // XRANDR
|
||||
#endif // X11
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -85,6 +95,9 @@ typedef struct {
|
||||
NSOpenGLContext *cocoaCtx;
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
Window win;
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
wxPanel *panel;
|
||||
#endif
|
||||
Display *dpy;
|
||||
XVisualInfo *vi;
|
||||
GLXContext ctx;
|
||||
@@ -94,6 +107,8 @@ typedef struct {
|
||||
Bool doubleBuffered;
|
||||
int fullWidth, fullHeight;
|
||||
int winWidth, winHeight;
|
||||
Common::Thread *xEventThread;
|
||||
Bool renderToMain;
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
XRRScreenConfiguration *screenConfig;
|
||||
Rotation screenRotation;
|
||||
|
||||
@@ -833,8 +833,10 @@ void GFXConfigDialogOGL::UpdateGUI()
|
||||
m_AutoScale->Enable(!g_Config.bUseXFB);
|
||||
|
||||
// These options are for the separate rendering window
|
||||
#if !defined(HAVE_GTK2) || !HAVE_GTK2 || !defined(wxGTK)
|
||||
m_Fullscreen->Enable(!g_Config.RenderToMainframe);
|
||||
if (g_Config.RenderToMainframe) m_Fullscreen->SetValue(false);
|
||||
#endif
|
||||
|
||||
// Resolution settings
|
||||
//disable native/2x choice when real xfb is on. native simply looks best, as ector noted above.
|
||||
@@ -842,7 +844,11 @@ void GFXConfigDialogOGL::UpdateGUI()
|
||||
m_NativeResolution->Enable(!g_Config.bUseXFB);
|
||||
m_2xResolution->Enable(!g_Config.bUseXFB && (!g_Config.bRunning || Renderer::Allow2x()));
|
||||
m_WindowResolutionCB->Enable(!g_Config.bRunning);
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
m_WindowFSResolutionCB->Enable(!g_Config.bRunning);
|
||||
#else
|
||||
m_WindowFSResolutionCB->Enable(!g_Config.bRunning && !g_Config.RenderToMainframe);
|
||||
#endif
|
||||
|
||||
// Disable the Copy to options when EFBCopy is disabled
|
||||
m_Radio_CopyEFBToRAM->Enable(!(g_Config.bEFBCopyDisable));
|
||||
|
||||
@@ -31,7 +31,7 @@ compileFlags = [
|
||||
linkFlags = [
|
||||
]
|
||||
libs = [
|
||||
'videocommon', 'soil', 'common'
|
||||
'videocommon', 'SOIL', 'common'
|
||||
]
|
||||
|
||||
gfxenv = env.Clone()
|
||||
@@ -105,6 +105,10 @@ gfxenv['HAVE_XRANDR'] = gfxenv['HAVE_X11'] and conf.CheckPKG('xrandr')
|
||||
|
||||
conf.Define('HAVE_XRANDR', gfxenv['HAVE_XRANDR'])
|
||||
|
||||
# check for libgtk2.0
|
||||
gfxenv['HAVE_GTK2'] = gfxenv['HAVE_WX'] and conf.CheckPKG('gtk+-2.0')
|
||||
conf.Define('HAVE_GTK2', gfxenv['HAVE_GTK2'])
|
||||
|
||||
conf.Finish()
|
||||
|
||||
# Sanity check
|
||||
|
||||
@@ -208,12 +208,18 @@ void Win32AddResolutions()
|
||||
}
|
||||
#elif defined(HAVE_X11) && HAVE_X11 && defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
void X11AddResolutions() {
|
||||
GLWin.dpy = XOpenDisplay(0);
|
||||
// Don't modify GLWin.dpy here.
|
||||
// If the emulator is running that is bad.
|
||||
Display *dpy;
|
||||
int screen;
|
||||
dpy = XOpenDisplay(0);
|
||||
screen = DefaultScreen(dpy);
|
||||
//Get all full screen resos for the config dialog
|
||||
XRRScreenSize *sizes = NULL;
|
||||
int modeNum = 0;
|
||||
|
||||
sizes = XRRSizes(GLWin.dpy, GLWin.screen, &modeNum);
|
||||
sizes = XRRSizes(dpy, screen, &modeNum);
|
||||
XCloseDisplay(dpy);
|
||||
if (modeNum > 0 && sizes != NULL)
|
||||
{
|
||||
for (int i = 0; i < modeNum; i++)
|
||||
@@ -349,10 +355,6 @@ void Initialize(void *init)
|
||||
}
|
||||
|
||||
void DoState(unsigned char **ptr, int mode) {
|
||||
#ifndef _WIN32
|
||||
// WHY is this here??
|
||||
OpenGL_MakeCurrent();
|
||||
#endif
|
||||
// Clear all caches that touch RAM
|
||||
TextureMngr::Invalidate(false);
|
||||
VertexLoaderManager::MarkAllDirty();
|
||||
|
||||
@@ -117,7 +117,7 @@ unsigned int Callback_PeekMessages()
|
||||
void UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
char temp[512];
|
||||
sprintf(temp, "SVN R%s: SW: %s", SVN_REV_STR, text);
|
||||
sprintf(temp, "%s: SW: %s", SVN_REV_STR, text);
|
||||
OpenGL_SetWindowText(temp);
|
||||
}
|
||||
// =========================
|
||||
|
||||
@@ -42,7 +42,7 @@ compileFlags = [
|
||||
linkFlags = [
|
||||
]
|
||||
libs = [
|
||||
'videocommon', 'soil', 'common'
|
||||
'videocommon', 'SOIL', 'common'
|
||||
]
|
||||
|
||||
gfxenv = env.Clone()
|
||||
|
||||
@@ -222,10 +222,7 @@ void WiimotePadConfigDialog::DoGetButtons(int _GetId)
|
||||
DEBUG_LOG(WIIMOTE, "Timer Stopped for Pad:%i _GetId:%i",
|
||||
WiiMoteEmu::WiiMapping[m_Page].ID, _GetId);
|
||||
|
||||
m_ButtonMappingTimer->Stop();
|
||||
GetButtonWaitingTimer = 0;
|
||||
GetButtonWaitingID = 0;
|
||||
ClickedButton = NULL;
|
||||
EndGetButtons();
|
||||
}
|
||||
|
||||
// If we got a bad button
|
||||
@@ -241,6 +238,17 @@ void WiimotePadConfigDialog::DoGetButtons(int _GetId)
|
||||
}
|
||||
}
|
||||
|
||||
void WiimotePadConfigDialog::EndGetButtons(void)
|
||||
{
|
||||
wxTheApp->Disconnect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
|
||||
wxKeyEventHandler(WiimotePadConfigDialog::OnKeyDown),
|
||||
(wxObject*)0, this);
|
||||
m_ButtonMappingTimer->Stop();
|
||||
GetButtonWaitingTimer = 0;
|
||||
GetButtonWaitingID = 0;
|
||||
ClickedButton = NULL;
|
||||
}
|
||||
|
||||
// Convert the 0x8000 range values to BoxW and BoxH for the plot
|
||||
void WiimotePadConfigDialog::Convert2Box(int &x)
|
||||
{
|
||||
|
||||
@@ -135,10 +135,6 @@ WiimotePadConfigDialog::WiimotePadConfigDialog(wxWindow *parent, wxWindowID id,
|
||||
m_Notebook->ChangeSelection(m_Page);
|
||||
// Set control values
|
||||
UpdateGUI();
|
||||
|
||||
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
|
||||
wxKeyEventHandler(WiimotePadConfigDialog::OnKeyDown),
|
||||
(wxObject*)0, this);
|
||||
}
|
||||
|
||||
WiimotePadConfigDialog::~WiimotePadConfigDialog()
|
||||
@@ -247,10 +243,7 @@ void WiimotePadConfigDialog::OnKeyDown(wxKeyEvent& event)
|
||||
SaveButtonMapping(ClickedButton->GetId(), XKey);
|
||||
#endif
|
||||
}
|
||||
m_ButtonMappingTimer->Stop();
|
||||
GetButtonWaitingTimer = 0;
|
||||
GetButtonWaitingID = 0;
|
||||
ClickedButton = NULL;
|
||||
EndGetButtons();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,6 +257,10 @@ void WiimotePadConfigDialog::OnButtonClick(wxCommandEvent& event)
|
||||
|
||||
if (m_ButtonMappingTimer->IsRunning()) return;
|
||||
|
||||
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
|
||||
wxKeyEventHandler(WiimotePadConfigDialog::OnKeyDown),
|
||||
(wxObject*)0, this);
|
||||
|
||||
// Create the button object
|
||||
ClickedButton = (wxButton *)event.GetEventObject();
|
||||
// Save old label so we can revert back
|
||||
@@ -867,6 +864,7 @@ void WiimotePadConfigDialog::CreatePadGUIControls()
|
||||
{
|
||||
m_statictext_GH3[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, gh3Text[x]);
|
||||
m_Button_GH3[x][i] = new wxButton(m_Controller[i], x, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH));
|
||||
m_Button_GH3[x][i]->SetFont(m_SmallFont);
|
||||
m_Sizer_GH3[x][i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_Sizer_GH3[x][i]->Add(m_statictext_GH3[x][i], 0, (wxUP), 4);
|
||||
m_Sizer_GH3[x][i]->Add(m_Button_GH3[x][i], 0, (wxLEFT), 2);
|
||||
|
||||
@@ -288,6 +288,7 @@ class WiimotePadConfigDialog : public wxDialog
|
||||
wxString GetButtonText(int id);
|
||||
|
||||
void DoGetButtons(int id);
|
||||
void EndGetButtons();
|
||||
void UpdatePadInfo(wxTimerEvent& WXUNUSED(event));
|
||||
void ToBlank(bool ToBlank, int Id);
|
||||
void DoChangeDeadZone();
|
||||
|
||||
@@ -397,12 +397,14 @@ bool IsFocus()
|
||||
return false;
|
||||
#elif defined HAVE_X11 && HAVE_X11
|
||||
Window GLWin = *(Window *)g_WiimoteInitialize.pXWindow;
|
||||
bool bFocus = False;
|
||||
#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
|
||||
bFocus = (wxPanel *)g_WiimoteInitialize.pPanel == wxWindow::FindFocus();
|
||||
#endif
|
||||
Window FocusWin;
|
||||
int Revert;
|
||||
XGetInputFocus(WMdisplay, &FocusWin, &Revert);
|
||||
XWindowAttributes WinAttribs;
|
||||
XGetWindowAttributes (WMdisplay, GLWin, &WinAttribs);
|
||||
return (GLWin != 0 && (GLWin == FocusWin || WinAttribs.override_redirect));
|
||||
return (GLWin == FocusWin || bFocus);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@@ -720,6 +720,7 @@ int WiimotePairUp(void)
|
||||
|
||||
}
|
||||
} while (BluetoothFindNextDevice(hFind, &btdi));
|
||||
BluetoothFindRadioClose(hFind);
|
||||
}
|
||||
|
||||
SLEEP(10);
|
||||
|
||||
Reference in New Issue
Block a user