smsvn -> ssc-hg glue: rearrange directory structure
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#include "global.h"
|
||||
#include "Crash.h"
|
||||
#include "ProductInfo.h"
|
||||
#include "arch/ArchHooks/ArchHooks.h"
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
RString CrashHandler::GetLogsDirectory()
|
||||
{
|
||||
FSRef fs;
|
||||
char dir[PATH_MAX];
|
||||
|
||||
if( FSFindFolder(kUserDomain, kDomainLibraryFolderType, kDontCreateFolder, &fs) ||
|
||||
FSRefMakePath(&fs, (UInt8 *)dir, PATH_MAX) )
|
||||
{
|
||||
return "/tmp";
|
||||
}
|
||||
return RString( dir ) + "/Logs/" PRODUCT_ID;
|
||||
}
|
||||
|
||||
// XXX Can we use LocalizedString here instead?
|
||||
#define LSTRING(b,x) CFBundleCopyLocalizedString( (b), CFSTR(x), NULL, CFSTR("Localizable") )
|
||||
|
||||
void CrashHandler::InformUserOfCrash( const RString& sPath )
|
||||
{
|
||||
CFBundleRef bundle = CFBundleGetMainBundle();
|
||||
CFStringRef sAlternate = LSTRING( bundle, "Quit " PRODUCT_FAMILY );
|
||||
/* XXX Translate these and remove the redefine of LSTRING. Another way to do this
|
||||
* would be to pass bundle's URL to CFUserNotificationDisplayAlert's localizationURL
|
||||
* parameter and let it do it. This wouldn't work for sBody though. */
|
||||
#undef LSTRING
|
||||
#define LSTRING(b,x) CFSTR(x)
|
||||
CFStringRef sDefault = LSTRING( bundle, "File Bug Report" );
|
||||
CFStringRef sOther = LSTRING( bundle, "Open crashinfo.txt" );
|
||||
CFStringRef sTitle = LSTRING( bundle, PRODUCT_FAMILY " has crashed" );
|
||||
CFStringRef sFormat = LSTRING( bundle, PRODUCT_FAMILY " has crashed. "
|
||||
"Debugging information has been output to\n\n%s\n\n"
|
||||
"Please file a bug report at\n\n%s" );
|
||||
CFStringRef sBody = CFStringCreateWithFormat( kCFAllocatorDefault, NULL, sFormat,
|
||||
sPath.c_str(), REPORT_BUG_URL );
|
||||
CFOptionFlags response = kCFUserNotificationCancelResponse;
|
||||
CFTimeInterval timeout = 0.0; // Should we ever time out?
|
||||
|
||||
CFUserNotificationDisplayAlert( timeout, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL,
|
||||
sTitle, sBody, sDefault, sAlternate, sOther, &response );
|
||||
|
||||
switch( response )
|
||||
{
|
||||
case kCFUserNotificationDefaultResponse:
|
||||
HOOKS->GoToURL( REPORT_BUG_URL );
|
||||
// Fall through.
|
||||
case kCFUserNotificationOtherResponse:
|
||||
// Open the file with the default application (probably TextEdit).
|
||||
HOOKS->GoToURL( "file://" + sPath );
|
||||
break;
|
||||
}
|
||||
CFRelease( sBody );
|
||||
CFRelease( sFormat );
|
||||
CFRelease( sTitle );
|
||||
CFRelease( sOther );
|
||||
CFRelease( sDefault );
|
||||
CFRelease( sAlternate );
|
||||
}
|
||||
|
||||
/* IMPORTANT: Because the definition of the kinfo_proc structure (in <sys/sysctl.h>)
|
||||
* is conditionalized by __APPLE_API_UNSTABLE, you should restrict use of the [below]
|
||||
* code to the debug build of your program.
|
||||
* http://developer.apple.com/qa/qa2004/qa1361.html */
|
||||
bool CrashHandler::IsDebuggerPresent()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
int ret;
|
||||
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
|
||||
struct kinfo_proc info;
|
||||
size_t size;
|
||||
|
||||
// Initialize the flags so that, if sysctl fails for some bizarre
|
||||
// reason, we get a predictable result.
|
||||
|
||||
info.kp_proc.p_flag = 0;
|
||||
|
||||
// Call sysctl.
|
||||
size = sizeof( info );
|
||||
ret = sysctl( mib, sizeof(mib)/sizeof(*mib), &info, &size, NULL, 0 );
|
||||
|
||||
// We're being debugged if the P_TRACED flag is set.
|
||||
|
||||
return ret == 0 && (info.kp_proc.p_flag & P_TRACED) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CrashHandler::DebugBreak()
|
||||
{
|
||||
DebugStr( "\pDebugBreak()" );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef DARWIN_CRASH_H
|
||||
#define DARWIN_CRASH_H
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
RString GetLogsDirectory();
|
||||
void InformUserOfCrash( const RString& sPath );
|
||||
bool IsDebuggerPresent();
|
||||
void DebugBreak();
|
||||
}
|
||||
|
||||
#endif /* DARWIN_CRASH_H */
|
||||
|
||||
/*
|
||||
* (c) 2003-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,90 @@
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/thread_act.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/mach_error.h>
|
||||
#include "Backtrace.h"
|
||||
|
||||
bool SuspendThread( uint64_t threadHandle )
|
||||
{
|
||||
return !thread_suspend( thread_act_t(threadHandle) );
|
||||
}
|
||||
|
||||
bool ResumeThread( uint64_t threadHandle )
|
||||
{
|
||||
return !thread_resume( thread_act_t(threadHandle) );
|
||||
}
|
||||
|
||||
uint64_t GetCurrentThreadId()
|
||||
{
|
||||
return mach_thread_self();
|
||||
}
|
||||
|
||||
bool GetThreadBacktraceContext( uint64_t iID, BacktraceContext *ctx )
|
||||
{
|
||||
/* Can't GetThreadBacktraceContext the current thread. */
|
||||
ASSERT( iID != GetCurrentThreadId() );
|
||||
SuspendThread( iID );
|
||||
|
||||
thread_act_t thread = thread_act_t( iID );
|
||||
|
||||
#if defined(__ppc__)
|
||||
ppc_thread_state state;
|
||||
mach_msg_type_number_t count = PPC_THREAD_STATE_COUNT;
|
||||
|
||||
if( thread_get_state(thread, PPC_THREAD_STATE, thread_state_t(&state), &count) )
|
||||
return false;
|
||||
ctx->FramePtr = (const Frame *)state.r1;
|
||||
ctx->PC = (void *)state.srr0;
|
||||
return true;
|
||||
#elif defined(__i386__)
|
||||
i386_thread_state state;
|
||||
mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
|
||||
|
||||
if( thread_get_state(thread, i386_THREAD_STATE, thread_state_t(&state), &count) )
|
||||
return false;
|
||||
ctx->ip = (void *)state.eip;
|
||||
ctx->bp = (void *)state.ebp;
|
||||
ctx->sp = (void *)state.esp;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
RString SetThreadPrecedence( float prec )
|
||||
{
|
||||
// Real values are between 0 and 63.
|
||||
DEBUG_ASSERT( 0.0f <= prec && prec <= 1.0f );
|
||||
thread_precedence_policy po = { integer_t( lrintf(prec * 63) ) };
|
||||
kern_return_t ret = thread_policy_set( mach_thread_self(), THREAD_PRECEDENCE_POLICY,
|
||||
(thread_policy_t)&po, THREAD_PRECEDENCE_POLICY_COUNT );
|
||||
|
||||
if( ret != KERN_SUCCESS )
|
||||
return mach_error_string( ret );
|
||||
return RString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef DARWIN_THREAD_HELPERS_H
|
||||
#define DARWIN_THREAD_HELPERS_H
|
||||
|
||||
bool SuspendThread( uint64_t threadHandle );
|
||||
bool ResumeThread( uint64_t threadHandle );
|
||||
uint64_t GetCurrentThreadId();
|
||||
// Valid values are from 0.0f to 1.0f. 0.5f is default.
|
||||
RString SetThreadPrecedence( float prec );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2004-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,279 @@
|
||||
#include "global.h"
|
||||
#include "HIDDevice.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
HIDDevice::HIDDevice() : m_Interface( NULL ), m_Queue( NULL ), m_bRunning( false )
|
||||
{
|
||||
}
|
||||
|
||||
HIDDevice::~HIDDevice()
|
||||
{
|
||||
if( m_Queue )
|
||||
{
|
||||
CFRunLoopSourceRef runLoopSource;
|
||||
|
||||
if( m_bRunning )
|
||||
{
|
||||
CALL( m_Queue, stop );
|
||||
runLoopSource = CALL( m_Queue, getAsyncEventSource );
|
||||
CFRunLoopSourceInvalidate( runLoopSource );
|
||||
CFRelease( runLoopSource );
|
||||
}
|
||||
|
||||
CALL( m_Queue, dispose );
|
||||
CALL( m_Queue, Release );
|
||||
}
|
||||
if( m_Interface )
|
||||
{
|
||||
CALL( m_Interface, close );
|
||||
CALL( m_Interface, Release );
|
||||
}
|
||||
}
|
||||
|
||||
bool HIDDevice::Open( io_object_t device )
|
||||
{
|
||||
IOReturn ret;
|
||||
CFMutableDictionaryRef properties;
|
||||
kern_return_t result;
|
||||
CFTypeRef object;
|
||||
|
||||
result = IORegistryEntryCreateCFProperties( device, &properties, kCFAllocatorDefault, kNilOptions );
|
||||
if( result != KERN_SUCCESS || !properties )
|
||||
{
|
||||
LOG->Warn( "Couldn't get properties." );
|
||||
return false;
|
||||
}
|
||||
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDProductKey) );
|
||||
|
||||
CFTypeRef vidRef = CFDictionaryGetValue( properties, CFSTR(kIOHIDVendorIDKey) );
|
||||
CFTypeRef pidRef = CFDictionaryGetValue( properties, CFSTR(kIOHIDProductIDKey) );
|
||||
int vid, pid;
|
||||
|
||||
if( !IntValue(vidRef, vid) )
|
||||
vid = 0;
|
||||
if( !IntValue(pidRef, pid) )
|
||||
pid = 0;
|
||||
if( !InitDevice(vid, pid) )
|
||||
{
|
||||
LOG->Warn( "Couldn't initialize device." );
|
||||
CFRelease( properties );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( object && CFGetTypeID(object) == CFStringGetTypeID() )
|
||||
{
|
||||
const char *str = CFStringGetCStringPtr( CFStringRef(object), CFStringGetSystemEncoding() );
|
||||
m_sDescription = str? str:"";
|
||||
}
|
||||
if( m_sDescription == "" )
|
||||
m_sDescription = ssprintf( "%04x:%04x", vid, pid );
|
||||
LOG->Trace( "\t\tDevice description: %s", m_sDescription.c_str() );
|
||||
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDElementKey) );
|
||||
if ( !object || CFGetTypeID(object) != CFArrayGetTypeID() )
|
||||
{
|
||||
LOG->Warn( "Couldn't get HID elements." );
|
||||
CFRelease( properties );
|
||||
return false;
|
||||
}
|
||||
|
||||
CFArrayRef logicalDevices = CFArrayRef( object );
|
||||
CFRange r = { 0, CFArrayGetCount(logicalDevices) };
|
||||
|
||||
CFArrayApplyFunction( logicalDevices, r, HIDDevice::AddLogicalDevice, this );
|
||||
|
||||
CFRelease( properties );
|
||||
|
||||
// Create the interface
|
||||
IOCFPlugInInterface **plugInInterface;
|
||||
HRESULT hresult;
|
||||
SInt32 score;
|
||||
|
||||
ret = IOCreatePlugInInterfaceForService( device, kIOHIDDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID, &plugInInterface, &score );
|
||||
if( ret != kIOReturnSuccess )
|
||||
{
|
||||
PrintIOErr( ret, "Failed to create plugin interface." );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call a method of the plugin to create the device interface
|
||||
CFUUIDBytes bytes = CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID );
|
||||
|
||||
hresult = CALL( plugInInterface, QueryInterface, bytes, (void **)&m_Interface );
|
||||
|
||||
CALL( plugInInterface, Release );
|
||||
|
||||
if( hresult != S_OK )
|
||||
{
|
||||
LOG->Warn( "Couldn't get device interface from plugin interface." );
|
||||
m_Interface = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// open the interface
|
||||
if( (ret = CALL(m_Interface, open, 0)) != kIOReturnSuccess )
|
||||
{
|
||||
PrintIOErr( ret, "Failed to open the interface." );
|
||||
CALL( m_Interface, Release );
|
||||
m_Interface = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// alloc/create queue
|
||||
m_Queue = CALL( m_Interface, allocQueue );
|
||||
if( !m_Queue )
|
||||
{
|
||||
LOG->Warn( "Couldn't allocate a queue." );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (ret = CALL(m_Queue, create, 0, 32)) != kIOReturnSuccess )
|
||||
{
|
||||
PrintIOErr( ret, "Failed to create the queue." );
|
||||
CALL( m_Queue, Release );
|
||||
m_Queue = NULL;
|
||||
CALL( m_Interface, Release );
|
||||
m_Interface = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
Open();
|
||||
LOG->Trace( "\t\tDevice open" );
|
||||
return true;
|
||||
}
|
||||
|
||||
void HIDDevice::StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon )
|
||||
{
|
||||
CFRunLoopSourceRef runLoopSource;
|
||||
// This creates a run loop source. It is released in the dtor.
|
||||
IOReturn ret = CALL( m_Queue, createAsyncEventSource, &runLoopSource );
|
||||
|
||||
if( ret != kIOReturnSuccess )
|
||||
{
|
||||
PrintIOErr( ret, "Failed to create async event source." );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !CFRunLoopContainsSource(loopRef, runLoopSource, kCFRunLoopDefaultMode) )
|
||||
CFRunLoopAddSource( loopRef, runLoopSource, kCFRunLoopDefaultMode );
|
||||
|
||||
ret = CALL( m_Queue, setEventCallout, callback, target, (void *)refCon );
|
||||
|
||||
if( ret != kIOReturnSuccess )
|
||||
{
|
||||
PrintIOErr( ret, "Failed to set the call back." );
|
||||
return;
|
||||
}
|
||||
|
||||
// start the queue
|
||||
ret = CALL( m_Queue, start );
|
||||
|
||||
if( ret != kIOReturnSuccess )
|
||||
{
|
||||
CFRunLoopSourceInvalidate( runLoopSource );
|
||||
CFRelease( runLoopSource );
|
||||
|
||||
PrintIOErr( ret, "Failed to start the queue." );
|
||||
return;
|
||||
}
|
||||
m_bRunning = true;
|
||||
}
|
||||
|
||||
void HIDDevice::AddLogicalDevice( const void *value, void *context )
|
||||
{
|
||||
if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() )
|
||||
return;
|
||||
|
||||
CFDictionaryRef properties = CFDictionaryRef( value );
|
||||
HIDDevice *This = (HIDDevice *)context;
|
||||
CFTypeRef object;
|
||||
int usage, usagePage;
|
||||
|
||||
// Get usage page
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDElementUsagePageKey) );
|
||||
if( !IntValue(object, usagePage) )
|
||||
return;
|
||||
|
||||
// Get usage
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDElementUsageKey) );
|
||||
if( !IntValue(object, usage) )
|
||||
return;
|
||||
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDElementKey) );
|
||||
if( !object || CFGetTypeID(object) != CFArrayGetTypeID() )
|
||||
return;
|
||||
|
||||
if( !This->AddLogicalDevice(usagePage, usage) )
|
||||
return;
|
||||
|
||||
CFArrayRef elements = CFArrayRef( object );
|
||||
CFRange r = { 0, CFArrayGetCount(elements) };
|
||||
|
||||
CFArrayApplyFunction( elements, r, HIDDevice::AddElement, This );
|
||||
}
|
||||
|
||||
void HIDDevice::AddElement( const void *value, void *context )
|
||||
{
|
||||
if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() )
|
||||
return;
|
||||
|
||||
CFDictionaryRef properties = CFDictionaryRef( value );
|
||||
HIDDevice *This = (HIDDevice *)context;
|
||||
CFTypeRef object;
|
||||
int usage, usagePage;
|
||||
long cookie;
|
||||
|
||||
// Recursively add elements
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDElementKey) );
|
||||
if( object && CFGetTypeID(object) == CFArrayGetTypeID() )
|
||||
{
|
||||
CFArrayRef elements = CFArrayRef( object );
|
||||
CFRange r = { 0, CFArrayGetCount(elements) };
|
||||
|
||||
CFArrayApplyFunction( elements, r, AddElement, context );
|
||||
}
|
||||
|
||||
// Get usage page
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDElementUsagePageKey) );
|
||||
if( !IntValue(object, usagePage) )
|
||||
return;
|
||||
|
||||
// Get usage
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDElementUsageKey) );
|
||||
if( !IntValue(object, usage) )
|
||||
return;
|
||||
|
||||
|
||||
// Get cookie
|
||||
object = CFDictionaryGetValue( properties, CFSTR(kIOHIDElementCookieKey) );
|
||||
if( !LongValue(object, cookie) )
|
||||
return;
|
||||
This->AddElement( usagePage, usage, IOHIDElementCookie(cookie), properties );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2005-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,169 @@
|
||||
#ifndef HIDDEVICE_H
|
||||
#define HIDDEVICE_H
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
#include <IOKit/hid/IOHIDUsageTables.h>
|
||||
#include <IOKit/usb/USB.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_error.h>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <ext/hash_map>
|
||||
|
||||
#include "RageLog.h"
|
||||
#include "RageInputDevice.h"
|
||||
|
||||
/* A few helper functions. */
|
||||
|
||||
// The result needs to be released.
|
||||
inline CFNumberRef CFInt( int n )
|
||||
{
|
||||
return CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &n );
|
||||
}
|
||||
|
||||
inline void PrintIOErr( IOReturn err, const char *s )
|
||||
{
|
||||
LOG->Warn( "%s - %s(%x,%d)", s, mach_error_string(err), err, err & 0xFFFFFF );
|
||||
}
|
||||
|
||||
inline Boolean IntValue( CFTypeRef o, int &n )
|
||||
{
|
||||
if( !o || CFGetTypeID(o) != CFNumberGetTypeID() )
|
||||
return false;
|
||||
return CFNumberGetValue( CFNumberRef(o), kCFNumberIntType, &n );
|
||||
}
|
||||
|
||||
inline Boolean LongValue( CFTypeRef o, long &n )
|
||||
{
|
||||
if( !o || CFGetTypeID(o) != CFNumberGetTypeID() )
|
||||
return false;
|
||||
return CFNumberGetValue( CFNumberRef(o), kCFNumberLongType, &n );
|
||||
}
|
||||
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
template<>
|
||||
struct hash<IOHIDElementCookie> : private hash<uintptr_t>
|
||||
{
|
||||
size_t operator()( const IOHIDElementCookie& cookie ) const
|
||||
{
|
||||
return hash<unsigned long>::operator()( uintptr_t(cookie) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* This is just awful, these aren't objects, treating them as such leads
|
||||
* to: (*object)->function(object [, argument]...)
|
||||
* Instead, do: CALL(object, function [, argument]...)
|
||||
*/
|
||||
#define CALL(o,f,...) (*(o))->f((o), ## __VA_ARGS__)
|
||||
|
||||
class HIDDevice
|
||||
{
|
||||
private:
|
||||
IOHIDDeviceInterface **m_Interface;
|
||||
IOHIDQueueInterface **m_Queue;
|
||||
bool m_bRunning;
|
||||
RString m_sDescription;
|
||||
|
||||
static void AddLogicalDevice( const void *value, void *context );
|
||||
static void AddElement( const void *value, void *context );
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Each physical device has zero or more logical devices. If this device allows
|
||||
* a logical device of type (usagePage, usage), then allocate storage as necessary
|
||||
* and return true, otherwise, return false.
|
||||
*/
|
||||
virtual bool AddLogicalDevice( int usagePage, int usage ) = 0;
|
||||
|
||||
/*
|
||||
* If the most recently added logical device cares about the state of an element of type
|
||||
* (usagePage, usage), store the cookie.
|
||||
*/
|
||||
virtual void AddElement( int usagePage, int usage, IOHIDElementCookie cookie, const CFDictionaryRef properties ) = 0;
|
||||
|
||||
/*
|
||||
* Add any elements to the queue by calling AddElementToQueue() with the stored cookies.
|
||||
*/
|
||||
virtual void Open() = 0;
|
||||
|
||||
/*
|
||||
* Optional. Subclasses can initialize the device, if required.
|
||||
*/
|
||||
virtual bool InitDevice( int vid, int pid ) { return true; }
|
||||
|
||||
// This adds the element with the given cookie to the queue to be notified of state changes.
|
||||
inline void AddElementToQueue( IOHIDElementCookie cookie )
|
||||
{
|
||||
IOReturn ret = CALL( m_Queue, addElement, cookie, 0 );
|
||||
if( ret != KERN_SUCCESS )
|
||||
LOG->Warn( "Failed to add HID element with cookie %p to queue: %u", cookie, ret );
|
||||
}
|
||||
|
||||
// Perform a synchronous set report on the HID interface.
|
||||
inline IOReturn SetReport( IOHIDReportType type, UInt32 reportID, void *buffer, UInt32 size, UInt32 timeoutMS )
|
||||
{
|
||||
return CALL( m_Interface, setReport, type, reportID, buffer, size, timeoutMS, NULL, NULL, NULL );
|
||||
}
|
||||
public:
|
||||
HIDDevice();
|
||||
virtual ~HIDDevice();
|
||||
|
||||
bool Open( io_object_t device );
|
||||
void StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon );
|
||||
inline const RString& GetDescription() const { return m_sDescription; }
|
||||
|
||||
|
||||
/*
|
||||
* Add button presses (or releases) to vPresses for the given cookie. More than one DeviceInput
|
||||
* can be added at a time. For example, Two axes presses may be generated by a single element.
|
||||
* The value of the element is passed to determine if this is a push or a release. The time
|
||||
* is provided as an optimization.
|
||||
*/
|
||||
virtual void GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const = 0;
|
||||
|
||||
/*
|
||||
* Returns the number of IDs assigned starting from startID. This is not meaningful for devices like
|
||||
* keyboards that all share the same InputDevice id. If a particular device has multiple logical
|
||||
* devices, then it must ensure that AssignIDs does not assign an ID outside of its range. Return
|
||||
* -1 to indicate that the device does not share the same InputDevice and none could be assigned.
|
||||
*/
|
||||
virtual int AssignIDs( InputDevice startID ) { return 0; }
|
||||
|
||||
/*
|
||||
* Add a device and a description for each logical device.
|
||||
*/
|
||||
virtual void GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices ) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2005-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,297 @@
|
||||
#include "global.h"
|
||||
#include "JoystickDevice.h"
|
||||
#include "RageLog.h"
|
||||
#include "Foreach.h"
|
||||
|
||||
using __gnu_cxx::hash_map;
|
||||
|
||||
Joystick::Joystick() : id( InputDevice_Invalid ),
|
||||
x_axis( 0 ), x_min( 0 ), x_max( 0 ),
|
||||
y_axis( 0 ), y_min( 0 ), y_max( 0 ),
|
||||
z_axis( 0 ), z_min( 0 ), z_max( 0 ),
|
||||
x_rot( 0 ), rx_min( 0 ), rx_max( 0 ),
|
||||
y_rot( 0 ), ry_min( 0 ), ry_max( 0 ),
|
||||
z_rot( 0 ), rz_min( 0 ), rz_max( 0 ),
|
||||
hat( 0 ), hat_min( 0 ), hat_max( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool JoystickDevice::AddLogicalDevice( int usagePage, int usage )
|
||||
{
|
||||
if( usagePage != kHIDPage_GenericDesktop )
|
||||
return false;
|
||||
switch( usage )
|
||||
{
|
||||
case kHIDUsage_GD_Joystick:
|
||||
case kHIDUsage_GD_GamePad:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
m_vSticks.push_back( Joystick() );
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoystickDevice::AddElement( int usagePage, int usage, IOHIDElementCookie cookie, const CFDictionaryRef properties )
|
||||
{
|
||||
if( usagePage >= kHIDPage_VendorDefinedStart )
|
||||
return;
|
||||
|
||||
ASSERT( m_vSticks.size() );
|
||||
Joystick& js = m_vSticks.back();
|
||||
|
||||
switch( usagePage )
|
||||
{
|
||||
case kHIDPage_GenericDesktop:
|
||||
{
|
||||
int iMin = 0;
|
||||
int iMax = 0;
|
||||
|
||||
IntValue( CFDictionaryGetValue(properties, CFSTR(kIOHIDElementMinKey)), iMin );
|
||||
IntValue( CFDictionaryGetValue(properties, CFSTR(kIOHIDElementMaxKey)), iMax );
|
||||
|
||||
switch( usage )
|
||||
{
|
||||
case kHIDUsage_GD_X:
|
||||
js.x_axis = cookie;
|
||||
js.x_min = iMin;
|
||||
js.x_max = iMax;
|
||||
break;
|
||||
case kHIDUsage_GD_Y:
|
||||
js.y_axis = cookie;
|
||||
js.y_min = iMin;
|
||||
js.y_max = iMax;
|
||||
break;
|
||||
case kHIDUsage_GD_Z:
|
||||
js.z_axis = cookie;
|
||||
js.z_min = iMin;
|
||||
js.z_max = iMax;
|
||||
break;
|
||||
case kHIDUsage_GD_Rx:
|
||||
js.x_rot = cookie;
|
||||
js.rx_min = iMin;
|
||||
js.rx_max = iMax;
|
||||
break;
|
||||
case kHIDUsage_GD_Ry:
|
||||
js.y_rot = cookie;
|
||||
js.ry_min = iMin;
|
||||
js.ry_max = iMax;
|
||||
break;
|
||||
case kHIDUsage_GD_Rz:
|
||||
js.z_rot = cookie;
|
||||
js.rz_min = iMin;
|
||||
js.rz_max = iMax;
|
||||
break;
|
||||
case kHIDUsage_GD_DPadUp:
|
||||
js.mapping[cookie] = JOY_UP;
|
||||
break;
|
||||
case kHIDUsage_GD_DPadDown:
|
||||
js.mapping[cookie] = JOY_DOWN;
|
||||
break;
|
||||
case kHIDUsage_GD_DPadRight:
|
||||
js.mapping[cookie] = JOY_RIGHT;
|
||||
break;
|
||||
case kHIDUsage_GD_DPadLeft:
|
||||
js.mapping[cookie] = JOY_LEFT;
|
||||
break;
|
||||
case kHIDUsage_GD_Hatswitch:
|
||||
{
|
||||
if( iMax - iMin != 7 && iMax - iMin != 3 )
|
||||
break;
|
||||
js.hat = cookie;
|
||||
js.hat_min = iMin;
|
||||
js.hat_max = iMax;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//LOG->Warn( "Unknown usagePage usage pair: (kHIDPage_GenericDesktop, %d).", usage );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kHIDPage_Button:
|
||||
{
|
||||
const DeviceButton buttonID = enum_add2( JOY_BUTTON_1, usage - kHIDUsage_Button_1 );
|
||||
|
||||
if( buttonID <= JOY_BUTTON_32 )
|
||||
js.mapping[cookie] = buttonID;
|
||||
else
|
||||
LOG->Warn( "Button id too large: %d.", int(buttonID) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//LOG->Warn( "Unknown usagePage usage pair: (%d, %d).", usagePage, usage );
|
||||
break;
|
||||
} // end switch (usagePage)
|
||||
}
|
||||
|
||||
void JoystickDevice::Open()
|
||||
{
|
||||
// Add elements to the queue for each Joystick
|
||||
FOREACH_CONST( Joystick, m_vSticks, i )
|
||||
{
|
||||
const Joystick& js = *i;
|
||||
#define ADD(x) if( js.x ) AddElementToQueue( js.x )
|
||||
ADD( x_axis ); ADD( y_axis ); ADD( z_axis );
|
||||
ADD( x_rot ); ADD( y_rot ); ADD( z_rot );
|
||||
ADD( hat );
|
||||
#undef ADD
|
||||
for( hash_map<IOHIDElementCookie,DeviceButton>::const_iterator j = js.mapping.begin(); j != js.mapping.end(); ++j )
|
||||
AddElementToQueue( j->first );
|
||||
}
|
||||
}
|
||||
|
||||
bool JoystickDevice::InitDevice( int vid, int pid )
|
||||
{
|
||||
if( vid != 0x0507 || pid != 0x0011 )
|
||||
return true;
|
||||
// It's a Para controller so try to power it on.
|
||||
uint8_t powerOn = 1;
|
||||
IOReturn ret = SetReport( kIOHIDReportTypeFeature, 0, &powerOn, 1, 10 );
|
||||
|
||||
if( ret )
|
||||
LOG->Warn( "Failed to power on the Para controller: %#08x", ret );
|
||||
return ret == kIOReturnSuccess;
|
||||
}
|
||||
|
||||
void JoystickDevice::GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const
|
||||
{
|
||||
FOREACH_CONST( Joystick, m_vSticks, i )
|
||||
{
|
||||
const Joystick& js = *i;
|
||||
|
||||
if( js.x_axis == cookie )
|
||||
{
|
||||
float level = SCALE( value, js.x_min, js.x_max, -1.0f, 1.0f );
|
||||
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_LEFT, max(-level, 0.0f), now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_RIGHT, max(level, 0.0f), now) );
|
||||
break;
|
||||
}
|
||||
else if( js.y_axis == cookie )
|
||||
{
|
||||
float level = SCALE( value, js.y_min, js.y_max, -1.0f, 1.0f );
|
||||
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_UP, max(-level, 0.0f), now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_DOWN, max(level, 0.0f), now) );
|
||||
break;
|
||||
}
|
||||
else if( js.z_axis == cookie )
|
||||
{
|
||||
float level = SCALE( value, js.z_min, js.z_max, -1.0f, 1.0f );
|
||||
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_Z_UP, max(-level, 0.0f), now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_Z_DOWN, max(level, 0.0f), now) );
|
||||
break;
|
||||
}
|
||||
else if( js.x_rot == cookie )
|
||||
{
|
||||
float level = SCALE( value, js.rx_min, js.rx_max, -1.0f, 1.0f );
|
||||
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_ROT_LEFT, max(-level, 0.0f), now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_ROT_RIGHT, max(level, 0.0f), now) );
|
||||
break;
|
||||
}
|
||||
else if( js.y_rot == cookie )
|
||||
{
|
||||
float level = SCALE( value, js.ry_min, js.ry_max, -1.0f, 1.0f );
|
||||
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_ROT_UP, max(-level, 0.0f), now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_ROT_DOWN, max(level, 0.0f), now) );
|
||||
break;
|
||||
}
|
||||
else if( js.z_rot == cookie )
|
||||
{
|
||||
float level = SCALE( value, js.rz_min, js.rz_max, -1.0f, 1.0f );
|
||||
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_ROT_Z_UP, max(-level, 0.0f), now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_ROT_Z_DOWN, max(level, 0.0f), now) );
|
||||
break;
|
||||
}
|
||||
else if( js.hat == cookie )
|
||||
{
|
||||
float levelUp = 0.f, levelRight = 0.f, levelDown = 0.f, levelLeft = 0.f;
|
||||
|
||||
value -= js.hat_min; // Probably just subtracting 0.
|
||||
if( js.hat_max - js.hat_min == 3 )
|
||||
value *= 2;
|
||||
switch( value )
|
||||
{
|
||||
case 0: levelUp = 1.f; break; // U
|
||||
case 1: levelUp = 1.f; levelRight = 1.f; break; // UR
|
||||
case 2: levelRight = 1.f; break; // R
|
||||
case 3: levelDown = 1.f; levelRight = 1.f; break; // DR
|
||||
case 4: levelDown = 1.f; break; // D
|
||||
case 5: levelDown = 1.f; levelLeft = 1.f; break; // DL
|
||||
case 6: levelLeft = 1.f; break; // L
|
||||
case 7: levelUp = 1.f; levelLeft = 1.f; break; // UL
|
||||
}
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_HAT_UP, levelUp, now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_HAT_RIGHT, levelRight, now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_HAT_DOWN, levelDown, now) );
|
||||
vPresses.push_back( DeviceInput(js.id, JOY_HAT_LEFT, levelLeft, now) );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hash_map<T,U>::operator[] is not const
|
||||
hash_map<IOHIDElementCookie, DeviceButton>::const_iterator iter;
|
||||
|
||||
iter = js.mapping.find( cookie );
|
||||
if( iter != js.mapping.end() )
|
||||
{
|
||||
vPresses.push_back( DeviceInput(js.id, iter->second, value, now) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int JoystickDevice::AssignIDs( InputDevice startID )
|
||||
{
|
||||
if( !IsJoystick(startID) )
|
||||
return -1;
|
||||
FOREACH( Joystick, m_vSticks, i )
|
||||
{
|
||||
if( !IsJoystick(startID) )
|
||||
{
|
||||
m_vSticks.erase( i, m_vSticks.end() );
|
||||
break;
|
||||
}
|
||||
i->id = startID;
|
||||
enum_add( startID, 1 );
|
||||
}
|
||||
return m_vSticks.size();
|
||||
}
|
||||
|
||||
void JoystickDevice::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices ) const
|
||||
{
|
||||
FOREACH_CONST( Joystick, m_vSticks, i )
|
||||
vDevices.push_back( InputDeviceInfo(i->id,GetDescription()) );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2005-2007 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef JOYSTICK_DEVICE_H
|
||||
#define JOYSTICK_DEVICE_H
|
||||
|
||||
#include "HIDDevice.h"
|
||||
|
||||
struct Joystick
|
||||
{
|
||||
InputDevice id;
|
||||
// map cookie to button
|
||||
__gnu_cxx::hash_map<IOHIDElementCookie, DeviceButton> mapping;
|
||||
IOHIDElementCookie x_axis, y_axis, z_axis, x_rot, y_rot, z_rot, hat;
|
||||
int x_min, x_max;
|
||||
int y_min, y_max;
|
||||
int z_min, z_max;
|
||||
int rx_min, rx_max;
|
||||
int ry_min, ry_max;
|
||||
int rz_min, rz_max;
|
||||
int hat_min, hat_max;
|
||||
|
||||
Joystick();
|
||||
};
|
||||
|
||||
class JoystickDevice : public HIDDevice
|
||||
{
|
||||
private:
|
||||
vector<Joystick> m_vSticks;
|
||||
|
||||
protected:
|
||||
bool AddLogicalDevice( int usagePage, int usage );
|
||||
void AddElement( int usagePage, int usage, IOHIDElementCookie cookie, const CFDictionaryRef properties );
|
||||
void Open();
|
||||
bool InitDevice( int vid, int pid );
|
||||
|
||||
public:
|
||||
void GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const;
|
||||
int AssignIDs( InputDevice startID );
|
||||
void GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices ) const;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2005-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,514 @@
|
||||
#include "global.h"
|
||||
#include "KeyboardDevice.h"
|
||||
|
||||
using namespace __gnu_cxx;
|
||||
|
||||
bool KeyboardDevice::AddLogicalDevice( int usagePage, int usage )
|
||||
{
|
||||
return usagePage == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Keyboard;
|
||||
}
|
||||
|
||||
static bool UsbKeyToDeviceButton( UInt8 iUsbKey, DeviceButton &buttonOut )
|
||||
{
|
||||
UInt8 usage = iUsbKey;
|
||||
|
||||
if( usage < kHIDUsage_KeyboardA )
|
||||
return false;
|
||||
|
||||
if( usage <= kHIDUsage_KeyboardZ )
|
||||
{
|
||||
buttonOut = enum_add2( KEY_Ca, usage - kHIDUsage_KeyboardA );
|
||||
return true;
|
||||
}
|
||||
|
||||
// KEY_C0 = KEY_C1 - 1, kHIDUsage_Keyboard0 = kHIDUsage_Keyboard9 + 1
|
||||
if( usage <= kHIDUsage_Keyboard9 )
|
||||
{
|
||||
buttonOut = enum_add2( KEY_C1, usage - kHIDUsage_Keyboard1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
if( usage >= kHIDUsage_KeyboardF1 && usage <= kHIDUsage_KeyboardF12 )
|
||||
{
|
||||
buttonOut = enum_add2( KEY_F1, usage - kHIDUsage_KeyboardF1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
if( usage >= kHIDUsage_KeyboardF13 && usage <= kHIDUsage_KeyboardF16 )
|
||||
{
|
||||
buttonOut = enum_add2( KEY_F13, usage - kHIDUsage_KeyboardF13 );
|
||||
return true;
|
||||
}
|
||||
|
||||
// keypad 0 is again backward
|
||||
if( usage >= kHIDUsage_Keypad1 && usage <= kHIDUsage_Keypad9 )
|
||||
{
|
||||
buttonOut = enum_add2( KEY_KP_C1, usage - kHIDUsage_Keypad1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
#define OTHER(n) (enum_add2(KEY_OTHER_0, (n)))
|
||||
|
||||
// [0, 8]
|
||||
if( usage >= kHIDUsage_KeyboardF17 && usage <= kHIDUsage_KeyboardExecute )
|
||||
{
|
||||
buttonOut = OTHER( 0 + usage - kHIDUsage_KeyboardF17 );
|
||||
return true;
|
||||
}
|
||||
|
||||
// [9, 19]
|
||||
if( usage >= kHIDUsage_KeyboardSelect && usage <= kHIDUsage_KeyboardVolumeDown )
|
||||
{
|
||||
buttonOut = OTHER( 9 + usage - kHIDUsage_KeyboardSelect );
|
||||
return true;
|
||||
}
|
||||
|
||||
// [20, 41]
|
||||
if( usage >= kHIDUsage_KeypadEqualSignAS400 && usage <= kHIDUsage_KeyboardCancel )
|
||||
{
|
||||
buttonOut = OTHER( 20 + usage - kHIDUsage_KeypadEqualSignAS400 );
|
||||
return true;
|
||||
}
|
||||
|
||||
// [42, 47]
|
||||
// XXX kHIDUsage_KeyboardClearOrAgain
|
||||
if( usage >= kHIDUsage_KeyboardSeparator && usage <= kHIDUsage_KeyboardExSel )
|
||||
{
|
||||
buttonOut = OTHER( 32 + usage - kHIDUsage_KeyboardSeparator );
|
||||
return true;
|
||||
}
|
||||
|
||||
#define X(x,y) case x: buttonOut = y; return true
|
||||
|
||||
// Time for the special cases
|
||||
switch( usage )
|
||||
{
|
||||
X( kHIDUsage_Keyboard0, KEY_C0 );
|
||||
X( kHIDUsage_Keypad0, KEY_KP_C0 );
|
||||
X( kHIDUsage_KeyboardReturnOrEnter, KEY_ENTER );
|
||||
X( kHIDUsage_KeyboardEscape, KEY_ESC );
|
||||
X( kHIDUsage_KeyboardDeleteOrBackspace, KEY_BACK );
|
||||
X( kHIDUsage_KeyboardTab, KEY_TAB );
|
||||
X( kHIDUsage_KeyboardSpacebar, KEY_SPACE );
|
||||
X( kHIDUsage_KeyboardHyphen, KEY_HYPHEN );
|
||||
X( kHIDUsage_KeyboardEqualSign, KEY_EQUAL );
|
||||
X( kHIDUsage_KeyboardOpenBracket, KEY_LBRACKET );
|
||||
X( kHIDUsage_KeyboardCloseBracket, KEY_RBRACKET );
|
||||
X( kHIDUsage_KeyboardBackslash, KEY_BACKSLASH );
|
||||
X( kHIDUsage_KeyboardNonUSPound, KEY_HASH );
|
||||
X( kHIDUsage_KeyboardSemicolon, KEY_SEMICOLON );
|
||||
X( kHIDUsage_KeyboardQuote, KEY_SQUOTE );
|
||||
X( kHIDUsage_KeyboardGraveAccentAndTilde, KEY_ACCENT );
|
||||
X( kHIDUsage_KeyboardComma, KEY_COMMA );
|
||||
X( kHIDUsage_KeyboardPeriod, KEY_PERIOD );
|
||||
X( kHIDUsage_KeyboardSlash, KEY_SLASH );
|
||||
X( kHIDUsage_KeyboardCapsLock, KEY_CAPSLOCK );
|
||||
X( kHIDUsage_KeyboardPrintScreen, KEY_PRTSC );
|
||||
X( kHIDUsage_KeyboardScrollLock, KEY_SCRLLOCK );
|
||||
X( kHIDUsage_KeyboardPause, KEY_PAUSE );
|
||||
X( kHIDUsage_KeyboardInsert, KEY_INSERT );
|
||||
X( kHIDUsage_KeyboardHome, KEY_HOME );
|
||||
X( kHIDUsage_KeyboardPageUp, KEY_PGUP );
|
||||
X( kHIDUsage_KeyboardDeleteForward, KEY_DEL );
|
||||
X( kHIDUsage_KeyboardEnd, KEY_END );
|
||||
X( kHIDUsage_KeyboardPageDown, KEY_PGDN );
|
||||
X( kHIDUsage_KeyboardRightArrow, KEY_RIGHT );
|
||||
X( kHIDUsage_KeyboardLeftArrow, KEY_LEFT );
|
||||
X( kHIDUsage_KeyboardDownArrow, KEY_DOWN );
|
||||
X( kHIDUsage_KeyboardUpArrow, KEY_UP );
|
||||
X( kHIDUsage_KeypadNumLock, KEY_NUMLOCK );
|
||||
X( kHIDUsage_KeypadSlash, KEY_KP_SLASH );
|
||||
X( kHIDUsage_KeypadEqualSign, KEY_KP_EQUAL );
|
||||
X( kHIDUsage_KeypadAsterisk, KEY_KP_ASTERISK );
|
||||
X( kHIDUsage_KeypadHyphen, KEY_KP_HYPHEN );
|
||||
X( kHIDUsage_KeypadPlus, KEY_KP_PLUS );
|
||||
X( kHIDUsage_KeypadEnter, KEY_KP_ENTER );
|
||||
X( kHIDUsage_KeypadPeriod, KEY_KP_PERIOD );
|
||||
X( kHIDUsage_KeyboardNonUSBackslash, OTHER(48) );
|
||||
X( kHIDUsage_KeyboardApplication, OTHER(49) );
|
||||
X( kHIDUsage_KeyboardClear, KEY_NUMLOCK ); // XXX
|
||||
X( kHIDUsage_KeyboardHelp, KEY_INSERT );
|
||||
X( kHIDUsage_KeyboardMenu, KEY_MENU );
|
||||
// XXX kHIDUsage_KeyboardLockingCapsLock
|
||||
// XXX kHIDUsage_KeyboardLockingNumLock
|
||||
// XXX kHIDUsage_KeyboardLockingScrollLock
|
||||
X( kHIDUsage_KeypadComma, KEY_KP_PERIOD ); // XXX
|
||||
X( kHIDUsage_KeyboardReturn, KEY_ENTER );
|
||||
X( kHIDUsage_KeyboardPrior, OTHER(50) );
|
||||
X( kHIDUsage_KeyboardLeftControl, KEY_LCTRL );
|
||||
X( kHIDUsage_KeyboardLeftShift, KEY_LSHIFT );
|
||||
X( kHIDUsage_KeyboardLeftAlt, KEY_LALT );
|
||||
X( kHIDUsage_KeyboardLeftGUI, KEY_LMETA );
|
||||
X( kHIDUsage_KeyboardRightControl, KEY_RCTRL );
|
||||
X( kHIDUsage_KeyboardRightShift, KEY_RSHIFT );
|
||||
X( kHIDUsage_KeyboardRightAlt, KEY_RALT );
|
||||
X( kHIDUsage_KeyboardRightGUI, KEY_RMETA );
|
||||
}
|
||||
#undef X
|
||||
#undef OTHER
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void KeyboardDevice::AddElement( int usagePage, int usage, IOHIDElementCookie cookie, const CFDictionaryRef properties )
|
||||
{
|
||||
if( usagePage != kHIDPage_KeyboardOrKeypad )
|
||||
return;
|
||||
|
||||
DeviceButton button;
|
||||
if( UsbKeyToDeviceButton(usage,button) )
|
||||
m_Mapping[cookie] = button;
|
||||
}
|
||||
|
||||
void KeyboardDevice::Open()
|
||||
{
|
||||
for( hash_map<IOHIDElementCookie,DeviceButton>::const_iterator i = m_Mapping.begin(); i != m_Mapping.end(); ++i )
|
||||
{
|
||||
//LOG->Trace( "Adding %s to queue, cookie %p", DeviceButtonToString(i->second).c_str(), i->first );
|
||||
AddElementToQueue( i->first );
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardDevice::GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const
|
||||
{
|
||||
hash_map<IOHIDElementCookie, DeviceButton>::const_iterator iter = m_Mapping.find( cookie );
|
||||
|
||||
if( iter != m_Mapping.end() )
|
||||
{
|
||||
//LOG->Trace( "Pushed %s", DeviceButtonToString(iter->second).c_str() );
|
||||
vPresses.push_back( DeviceInput(DEVICE_KEYBOARD, iter->second, value, now) );
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardDevice::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices ) const
|
||||
{
|
||||
if( vDevices.size() && vDevices[0].id == DEVICE_KEYBOARD )
|
||||
return;
|
||||
vDevices.insert( vDevices.begin(), InputDeviceInfo(DEVICE_KEYBOARD, "Keyboard") );
|
||||
}
|
||||
|
||||
|
||||
// http://lists.apple.com/archives/carbon-dev/2005/Feb/msg00071.html
|
||||
// index represents USB keyboard usage value, content is Mac virtual keycode
|
||||
static UInt8 g_iUsbKeyToMacVirtualKey[256] =
|
||||
{
|
||||
0xFF, /* 00 no event */
|
||||
0xFF, /* 01 ErrorRollOver */
|
||||
0xFF, /* 02 POSTFail */
|
||||
0xFF, /* 03 ErrorUndefined */
|
||||
0x00, /* 04 A */
|
||||
0x0B, /* 05 B */
|
||||
0x08, /* 06 C */
|
||||
0x02, /* 07 D */
|
||||
0x0E, /* 08 E */
|
||||
0x03, /* 09 F */
|
||||
0x05, /* 0A G */
|
||||
0x04, /* 0B H */
|
||||
0x22, /* 0C I */
|
||||
0x26, /* 0D J */
|
||||
0x28, /* 0E K */
|
||||
0x25, /* 0F L */
|
||||
|
||||
0x2E, /* 10 M */
|
||||
0x2D, /* 11 N */
|
||||
0x1F, /* 12 O */
|
||||
0x23, /* 13 P */
|
||||
0x0C, /* 14 Q */
|
||||
0x0F, /* 15 R */
|
||||
0x01, /* 16 S */
|
||||
0x11, /* 17 T */
|
||||
0x20, /* 18 U */
|
||||
0x09, /* 19 V */
|
||||
0x0D, /* 1A W */
|
||||
0x07, /* 1B X */
|
||||
0x10, /* 1C Y */
|
||||
0x06, /* 1D Z */
|
||||
0x12, /* 1E 1/! */
|
||||
0x13, /* 1F 2/@ */
|
||||
|
||||
0x14, /* 20 3 # */
|
||||
0x15, /* 21 4 $ */
|
||||
0x17, /* 22 5 % */
|
||||
0x16, /* 23 6 ^ */
|
||||
0x1A, /* 24 7 & */
|
||||
0x1C, /* 25 8 * */
|
||||
0x19, /* 26 9 ( */
|
||||
0x1D, /* 27 0 ) */
|
||||
0x24, /* 28 Return (Enter) */
|
||||
0x35, /* 29 ESC */
|
||||
0x33, /* 2A Delete (Backspace) */
|
||||
0x30, /* 2B Tab */
|
||||
0x31, /* 2C Spacebar */
|
||||
0x1B, /* 2D - _ */
|
||||
0x18, /* 2E = + */
|
||||
0x21, /* 2F [ { */
|
||||
|
||||
0x1E, /* 30 ] } */
|
||||
0x2A, /* 31 \ | */
|
||||
0xFF, /* 32 Non-US # and ~ (what?!!!) */
|
||||
0x29, /* 33 ; : */
|
||||
0x27, /* 34 ' " */
|
||||
0x32, /* 35 ` ~ */
|
||||
0x2B, /* 36 , < */
|
||||
0x2F, /* 37 . > */
|
||||
0x2C, /* 38 / ? */
|
||||
0x39, /* 39 Caps Lock */
|
||||
0x7A, /* 3A F1 */
|
||||
0x78, /* 3B F2 */
|
||||
0x63, /* 3C F3 */
|
||||
0x76, /* 3D F4 */
|
||||
0x60, /* 3E F5 */
|
||||
0x61, /* 3F F6 */
|
||||
|
||||
0x62, /* 40 F7 */
|
||||
0x64, /* 41 F8 */
|
||||
0x65, /* 42 F9 */
|
||||
0x6D, /* 43 F10 */
|
||||
0x67, /* 44 F11 */
|
||||
0x6F, /* 45 F12 */
|
||||
0x69, /* 46 F13/PrintScreen */
|
||||
0x6B, /* 47 F14/ScrollLock */
|
||||
0x71, /* 48 F15/Pause */
|
||||
0x72, /* 49 Insert */
|
||||
0x73, /* 4A Home */
|
||||
0x74, /* 4B PageUp */
|
||||
0x75, /* 4C Delete Forward */
|
||||
0x77, /* 4D End */
|
||||
0x79, /* 4E PageDown */
|
||||
0x7C, /* 4F RightArrow */
|
||||
|
||||
0x7B, /* 50 LeftArrow */
|
||||
0x7D, /* 51 DownArrow */
|
||||
0x7E, /* 52 UpArrow */
|
||||
0x47, /* 53 NumLock/Clear */
|
||||
0x4B, /* 54 Keypad / */
|
||||
0x43, /* 55 Keypad * */
|
||||
0x4E, /* 56 Keypad - */
|
||||
0x45, /* 57 Keypad + */
|
||||
0x4C, /* 58 Keypad Enter */
|
||||
0x53, /* 59 Keypad 1 */
|
||||
0x54, /* 5A Keypad 2 */
|
||||
0x55, /* 5B Keypad 3 */
|
||||
0x56, /* 5C Keypad 4 */
|
||||
0x57, /* 5D Keypad 5 */
|
||||
0x58, /* 5E Keypad 6 */
|
||||
0x59, /* 5F Keypad 7 */
|
||||
|
||||
0x5B, /* 60 Keypad 8 */
|
||||
0x5C, /* 61 Keypad 9 */
|
||||
0x52, /* 62 Keypad 0 */
|
||||
0x41, /* 63 Keypad . */
|
||||
0xFF, /* 64 Non-US \ and | (what ??!!) */
|
||||
0x6E, /* 65 ApplicationKey (not on a mac!)*/
|
||||
0x7F, /* 66 PowerKey */
|
||||
0x51, /* 67 Keypad = */
|
||||
0x69, /* 68 F13 */
|
||||
0x6B, /* 69 F14 */
|
||||
0x71, /* 6A F15 */
|
||||
0xFF, /* 6B F16 */
|
||||
0xFF, /* 6C F17 */
|
||||
0xFF, /* 6D F18 */
|
||||
0xFF, /* 6E F19 */
|
||||
0xFF, /* 6F F20 */
|
||||
|
||||
0x5B, /* 70 F21 */
|
||||
0x5C, /* 71 F22 */
|
||||
0x52, /* 72 F23 */
|
||||
0x41, /* 73 F24 */
|
||||
0xFF, /* 74 Execute */
|
||||
0xFF, /* 75 Help */
|
||||
0x7F, /* 76 Menu */
|
||||
0x4C, /* 77 Select */
|
||||
0x69, /* 78 Stop */
|
||||
0x6B, /* 79 Again */
|
||||
0x71, /* 7A Undo */
|
||||
0xFF, /* 7B Cut */
|
||||
0xFF, /* 7C Copy */
|
||||
0xFF, /* 7D Paste */
|
||||
0xFF, /* 7E Find */
|
||||
0xFF, /* 7F Mute */
|
||||
|
||||
0xFF, /* 80 no event */
|
||||
0xFF, /* 81 no event */
|
||||
0xFF, /* 82 no event */
|
||||
0xFF, /* 83 no event */
|
||||
0xFF, /* 84 no event */
|
||||
0xFF, /* 85 no event */
|
||||
0xFF, /* 86 no event */
|
||||
0xFF, /* 87 no event */
|
||||
0xFF, /* 88 no event */
|
||||
0xFF, /* 89 no event */
|
||||
0xFF, /* 8A no event */
|
||||
0xFF, /* 8B no event */
|
||||
0xFF, /* 8C no event */
|
||||
0xFF, /* 8D no event */
|
||||
0xFF, /* 8E no event */
|
||||
0xFF, /* 8F no event */
|
||||
|
||||
0xFF, /* 90 no event */
|
||||
0xFF, /* 91 no event */
|
||||
0xFF, /* 92 no event */
|
||||
0xFF, /* 93 no event */
|
||||
0xFF, /* 94 no event */
|
||||
0xFF, /* 95 no event */
|
||||
0xFF, /* 96 no event */
|
||||
0xFF, /* 97 no event */
|
||||
0xFF, /* 98 no event */
|
||||
0xFF, /* 99 no event */
|
||||
0xFF, /* 9A no event */
|
||||
0xFF, /* 9B no event */
|
||||
0xFF, /* 9C no event */
|
||||
0xFF, /* 9D no event */
|
||||
0xFF, /* 9E no event */
|
||||
0xFF, /* 9F no event */
|
||||
|
||||
0xFF, /* A0 no event */
|
||||
0xFF, /* A1 no event */
|
||||
0xFF, /* A2 no event */
|
||||
0xFF, /* A3 no event */
|
||||
0xFF, /* A4 no event */
|
||||
0xFF, /* A5 no event */
|
||||
0xFF, /* A6 no event */
|
||||
0xFF, /* A7 no event */
|
||||
0xFF, /* A8 no event */
|
||||
0xFF, /* A9 no event */
|
||||
0xFF, /* AA no event */
|
||||
0xFF, /* AB no event */
|
||||
0xFF, /* AC no event */
|
||||
0xFF, /* AD no event */
|
||||
0xFF, /* AE no event */
|
||||
0xFF, /* AF no event */
|
||||
|
||||
0xFF, /* B0 no event */
|
||||
0xFF, /* B1 no event */
|
||||
0xFF, /* B2 no event */
|
||||
0xFF, /* B3 no event */
|
||||
0xFF, /* B4 no event */
|
||||
0xFF, /* B5 no event */
|
||||
0xFF, /* B6 no event */
|
||||
0xFF, /* B7 no event */
|
||||
0xFF, /* B8 no event */
|
||||
0xFF, /* B9 no event */
|
||||
0xFF, /* BA no event */
|
||||
0xFF, /* BB no event */
|
||||
0xFF, /* BC no event */
|
||||
0xFF, /* BD no event */
|
||||
0xFF, /* BE no event */
|
||||
0xFF, /* BF no event */
|
||||
|
||||
0xFF, /* C0 no event */
|
||||
0xFF, /* C1 no event */
|
||||
0xFF, /* C2 no event */
|
||||
0xFF, /* C3 no event */
|
||||
0xFF, /* C4 no event */
|
||||
0xFF, /* C5 no event */
|
||||
0xFF, /* C6 no event */
|
||||
0xFF, /* C7 no event */
|
||||
0xFF, /* C8 no event */
|
||||
0xFF, /* C9 no event */
|
||||
0xFF, /* CA no event */
|
||||
0xFF, /* CB no event */
|
||||
0xFF, /* CC no event */
|
||||
0xFF, /* CD no event */
|
||||
0xFF, /* CE no event */
|
||||
0xFF, /* CF no event */
|
||||
|
||||
0xFF, /* D0 no event */
|
||||
0xFF, /* D1 no event */
|
||||
0xFF, /* D2 no event */
|
||||
0xFF, /* D3 no event */
|
||||
0xFF, /* D4 no event */
|
||||
0xFF, /* D5 no event */
|
||||
0xFF, /* D6 no event */
|
||||
0xFF, /* D7 no event */
|
||||
0xFF, /* D8 no event */
|
||||
0xFF, /* D9 no event */
|
||||
0xFF, /* DA no event */
|
||||
0xFF, /* DB no event */
|
||||
0xFF, /* DC no event */
|
||||
0xFF, /* DD no event */
|
||||
0xFF, /* DE no event */
|
||||
0xFF, /* DF no event */
|
||||
|
||||
0x3B, /* E0 left control key */
|
||||
0x38, /* E1 left shift key key */
|
||||
0x3A, /* E2 left alt/option key */
|
||||
0x37, /* E3 left GUI (windows/cmd) key */
|
||||
|
||||
0x3B, /* E4 right control key */
|
||||
0x38, /* E5 right shift key key */
|
||||
0x3A, /* E6 right alt/option key */
|
||||
0x37, /* E7 right GUI (windows/cmd) key */
|
||||
0xFF, /* E8 no event */
|
||||
0xFF, /* E9 no event */
|
||||
0xFF, /* EA no event */
|
||||
0xFF, /* EB no event */
|
||||
0xFF, /* EC no event */
|
||||
0xFF, /* ED no event */
|
||||
0xFF, /* EE no event */
|
||||
0xFF, /* EF no event */
|
||||
|
||||
0xFF, /* F0 no event */
|
||||
0xFF, /* F1 no event */
|
||||
0xFF, /* F2 no event */
|
||||
0xFF, /* F3 no event */
|
||||
0xFF, /* F4 no event */
|
||||
0xFF, /* F5 no event */
|
||||
0xFF, /* F6 no event */
|
||||
0xFF, /* F7 no event */
|
||||
0xFF, /* F8 no event */
|
||||
0xFF, /* F9 no event */
|
||||
0xFF, /* FA no event */
|
||||
0xFF, /* FB no event */
|
||||
0xFF, /* FC no event */
|
||||
0xFF, /* FD no event */
|
||||
0xFF, /* FE no event */
|
||||
0xFF, /* FF no event */
|
||||
};
|
||||
|
||||
static UInt8 g_iDeviceButtonToMacVirtualKey[KEY_OTHER_0];
|
||||
|
||||
bool KeyboardDevice::DeviceButtonToMacVirtualKey( DeviceButton button, UInt8 &iMacVKOut )
|
||||
{
|
||||
static bool bInited = false;
|
||||
|
||||
if( !bInited )
|
||||
{
|
||||
memset( g_iDeviceButtonToMacVirtualKey, 0xFF, sizeof(g_iDeviceButtonToMacVirtualKey) );
|
||||
for( int iUsbKey = 0; iUsbKey < 256; ++iUsbKey )
|
||||
{
|
||||
DeviceButton button2;
|
||||
if( UsbKeyToDeviceButton(iUsbKey, button2) && size_t(button2) < sizeof(g_iDeviceButtonToMacVirtualKey) )
|
||||
g_iDeviceButtonToMacVirtualKey[button2] = g_iUsbKeyToMacVirtualKey[iUsbKey];
|
||||
}
|
||||
bInited = true;
|
||||
}
|
||||
iMacVKOut = g_iDeviceButtonToMacVirtualKey[button];
|
||||
return iMacVKOut != 0xFF;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (c) 2005-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef KEYBOARD_DEVICE_H
|
||||
#define KEYBOARD_DEVICE_H
|
||||
|
||||
#include "HIDDevice.h"
|
||||
|
||||
class KeyboardDevice : public HIDDevice
|
||||
{
|
||||
private:
|
||||
__gnu_cxx::hash_map<IOHIDElementCookie, DeviceButton> m_Mapping;
|
||||
|
||||
protected:
|
||||
bool AddLogicalDevice( int usagePage, int usage );
|
||||
void AddElement( int usagePage, int usage, IOHIDElementCookie cookie, const CFDictionaryRef properties );
|
||||
void Open();
|
||||
|
||||
public:
|
||||
void GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const;
|
||||
void GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices ) const;
|
||||
|
||||
static bool DeviceButtonToMacVirtualKey( DeviceButton button, UInt8 &iMacVKOut );
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2005-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,37 @@
|
||||
char *GetPreferredLanguage()
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
|
||||
NSArray *languages = [def objectForKey:@"AppleLanguages"];
|
||||
const char *lang = [[languages objectAtIndex:0] UTF8String];
|
||||
char *ret = (char *)malloc( strlen(lang) + 1 );
|
||||
|
||||
strcpy( ret, lang );
|
||||
[pool release];
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2005 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "global.h"
|
||||
#include "PumpDevice.h"
|
||||
|
||||
void PumpDevice::Open()
|
||||
{
|
||||
AddElementToQueue( IOHIDElementCookie(2) );
|
||||
AddElementToQueue( IOHIDElementCookie(3) );
|
||||
AddElementToQueue( IOHIDElementCookie(4) );
|
||||
AddElementToQueue( IOHIDElementCookie(6) );
|
||||
AddElementToQueue( IOHIDElementCookie(7) );
|
||||
AddElementToQueue( IOHIDElementCookie(8) );
|
||||
}
|
||||
|
||||
void PumpDevice::GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const
|
||||
{
|
||||
DeviceButton db1 = DeviceButton_Invalid;
|
||||
DeviceButton db2 = DeviceButton_Invalid;
|
||||
bool pressed1 = !(value & 0x1);
|
||||
bool pressed2 = !(value & 0x2);
|
||||
|
||||
switch( uintptr_t(cookie) )
|
||||
{
|
||||
case 2:
|
||||
db2 = JOY_BUTTON_1; // bit 9
|
||||
break;
|
||||
case 3:
|
||||
db1 = JOY_BUTTON_5; // bit 10
|
||||
db2 = JOY_BUTTON_4; // bit 11
|
||||
break;
|
||||
case 4:
|
||||
db1 = JOY_BUTTON_2; // bit 12
|
||||
db2 = JOY_BUTTON_3; // bit 13
|
||||
break;
|
||||
case 6:
|
||||
db1 = JOY_BUTTON_6; // bit 16
|
||||
db2 = JOY_BUTTON_7; // bit 17
|
||||
break;
|
||||
case 7:
|
||||
db1 = JOY_BUTTON_11; // bit 18
|
||||
db2 = JOY_BUTTON_10; // bit 19
|
||||
break;
|
||||
case 8:
|
||||
db1 = JOY_BUTTON_8; // bit 20
|
||||
db2 = JOY_BUTTON_9; // bit 21
|
||||
break;
|
||||
}
|
||||
if( db1 != DeviceButton_Invalid )
|
||||
vPresses.push_back( DeviceInput(m_Id, db1, pressed1 ? 1.0f : 0.0f , now) );
|
||||
if( db2 != DeviceButton_Invalid )
|
||||
vPresses.push_back( DeviceInput(m_Id, db2, pressed2 ? 1.0f : 0.0f , now) );
|
||||
}
|
||||
|
||||
int PumpDevice::AssignIDs( InputDevice startID )
|
||||
{
|
||||
if( !IsPump(startID) )
|
||||
return -1;
|
||||
m_Id = startID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PumpDevice::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices ) const
|
||||
{
|
||||
vDevices.push_back( InputDeviceInfo(m_Id, "Pump USB") );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef PUMP_DEVICE_H
|
||||
#define PUMP_DEVICE_H
|
||||
|
||||
#include "HIDDevice.h"
|
||||
|
||||
class PumpDevice : public HIDDevice
|
||||
{
|
||||
private:
|
||||
InputDevice m_Id;
|
||||
|
||||
protected:
|
||||
bool AddLogicalDevice( int usagePage, int usage ) { return true; }
|
||||
void AddElement( int usagePage, int usage, IOHIDElementCookie cookie,
|
||||
const CFDictionaryRef properties ) { }
|
||||
void Open();
|
||||
bool InitDevice( int vid, int pid ) { return vid == 0x0d2f && pid == 0x0001; }
|
||||
|
||||
public:
|
||||
void GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const;
|
||||
int AssignIDs( InputDevice startID );
|
||||
void GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices ) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
Executable
+227
@@ -0,0 +1,227 @@
|
||||
#include "global.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageThreads.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include "ProductInfo.h"
|
||||
#include "arch/ArchHooks/ArchHooks.h"
|
||||
|
||||
@interface NSApplication (PrivateShutUpWarning)
|
||||
- (void) setAppleMenu:(NSMenu *)menu;
|
||||
@end
|
||||
|
||||
/* Replacement NSApplication class.
|
||||
* Replaces sendEvent so that key down events are only sent to the
|
||||
* menu bar. We handle all other input by reading HID events from the
|
||||
* keyboard directly. */
|
||||
@interface SMApplication : NSApplication
|
||||
- (void) fullscreen:(id)sender;
|
||||
@end
|
||||
|
||||
@implementation SMApplication
|
||||
- (void)fullscreen:(id)sender
|
||||
{
|
||||
ArchHooks::SetToggleWindowed();
|
||||
}
|
||||
|
||||
- (void)sendEvent:(NSEvent *)event
|
||||
{
|
||||
if( [event type] == NSKeyDown )
|
||||
[[self mainMenu] performKeyEquivalent:event];
|
||||
else
|
||||
[super sendEvent:event];
|
||||
}
|
||||
@end
|
||||
|
||||
// The main class of the application, the application's delegate.
|
||||
@interface SMMain : NSObject
|
||||
{
|
||||
int m_iArgc;
|
||||
char **m_pArgv;
|
||||
BOOL m_bApplicationLaunched;
|
||||
}
|
||||
- (id) initWithArgc:(int)argc argv:(char **)argv;
|
||||
- (void) startGame:(id)sender;
|
||||
- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication *)sender;
|
||||
- (BOOL) application:(NSApplication *)app openFile:(NSString *)file;
|
||||
- (void) application:(NSApplication *)app openFiles:(NSArray *)files;
|
||||
- (void) setForInstall:(NSArray *)files;
|
||||
@end
|
||||
|
||||
@implementation SMMain
|
||||
|
||||
- (id) initWithArgc:(int)argc argv:(char **)argv
|
||||
{
|
||||
[super init];
|
||||
if( argc == 2 && !strncmp(argv[1], "-psn_", 5) )
|
||||
argc = 1;
|
||||
m_iArgc = argc;
|
||||
m_pArgv = new char*[argc];
|
||||
for( int i = 0; i < argc; ++i )
|
||||
m_pArgv[i] = argv[i];
|
||||
m_bApplicationLaunched = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) startGame:(id)sender
|
||||
{
|
||||
// Hand off to main application code.
|
||||
exit( SM_main(m_iArgc, m_pArgv) );
|
||||
}
|
||||
|
||||
// Called when the internal event loop has just started running.
|
||||
- (void) applicationDidFinishLaunching:(NSNotification *)note
|
||||
{
|
||||
m_bApplicationLaunched = YES;
|
||||
[NSThread detachNewThreadSelector:@selector(startGame:) toTarget:self withObject:nil];
|
||||
}
|
||||
|
||||
- (BOOL) application:(NSApplication *)app openFile:(NSString *)file
|
||||
{
|
||||
NSArray *files = [NSArray arrayWithObject:file];
|
||||
if( m_bApplicationLaunched )
|
||||
[NSTask launchedTaskWithLaunchPath:[NSString stringWithUTF8String:m_pArgv[0]] arguments:files];
|
||||
else
|
||||
[self setForInstall:files];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) application:(NSApplication *)app openFiles:(NSArray *)files
|
||||
{
|
||||
if( m_bApplicationLaunched )
|
||||
[NSTask launchedTaskWithLaunchPath:[NSString stringWithUTF8String:m_pArgv[0]] arguments:files];
|
||||
else
|
||||
[self setForInstall:files];
|
||||
[app replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
|
||||
}
|
||||
|
||||
- (void) setForInstall:(NSArray *)files
|
||||
{
|
||||
char **temp = new char*[[files count] + m_iArgc];
|
||||
for( int i = 0; i < m_iArgc; ++i )
|
||||
temp[i] = m_pArgv[i];
|
||||
for( unsigned i = 0; i < [files count]; ++i, ++m_iArgc )
|
||||
{
|
||||
const char *p = [[files objectAtIndex:i] fileSystemRepresentation];
|
||||
temp[m_iArgc] = new char[strlen(p)+1];
|
||||
strcpy( temp[m_iArgc], p );
|
||||
}
|
||||
delete[] m_pArgv;
|
||||
m_pArgv = temp;
|
||||
}
|
||||
|
||||
- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
ArchHooks::SetUserQuit();
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
@end
|
||||
|
||||
static void HandleNSException( NSException *exception )
|
||||
{
|
||||
FAIL_M( ssprintf("%s raised: %s", [[exception name] UTF8String], [[exception reason] UTF8String]) );
|
||||
}
|
||||
|
||||
static NSMenuItem *MenuItem( NSString *title, SEL action, NSString *code )
|
||||
{
|
||||
// Autorelease these because they'll be retained by the NSMenu.
|
||||
return [[[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:code] autorelease];
|
||||
}
|
||||
|
||||
static void SetupMenus( void )
|
||||
{
|
||||
// Get the localized strings from the file.
|
||||
NSString *sWindow = NSLocalizedString( @"Window", @"Menu title" );
|
||||
NSString *sHideOthers = NSLocalizedString( @"Hide Others", @"Menu item" );
|
||||
NSString *sAbout = NSLocalizedString( @"About " PRODUCT_FAMILY, @"Menu item" );
|
||||
NSString *sHide = NSLocalizedString( @"Hide " PRODUCT_FAMILY, @"Menu item" );
|
||||
NSString *sShowAll = NSLocalizedString( @"Show All", @"Menu item" );
|
||||
NSString *sQuit = NSLocalizedString( @"Quit " PRODUCT_FAMILY, @"Menu item" );
|
||||
NSString *sMinimize = NSLocalizedString( @"Minimize", @"Menu item" );
|
||||
NSString *sEnterFullScreen = NSLocalizedString( @"Enter Full Screen", @"Menu item" );
|
||||
|
||||
NSMenu *mainMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
|
||||
NSMenu *appMenu = [[[NSMenu alloc] initWithTitle:@PRODUCT_FAMILY] autorelease];
|
||||
NSMenu *windowMenu = [[[NSMenu alloc] initWithTitle:sWindow] autorelease];
|
||||
NSMenuItem *hideOthers = MenuItem( sHideOthers, @selector(hideOtherApplications:), @"h" );
|
||||
|
||||
[hideOthers setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask ];
|
||||
|
||||
[appMenu addItem:MenuItem( sAbout, @selector(orderFrontStandardAboutPanel:), @"" )];
|
||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||
[appMenu addItem:MenuItem( sHide, @selector(hide:), @"h" )];
|
||||
[appMenu addItem:hideOthers];
|
||||
[appMenu addItem:MenuItem( sShowAll, @selector(unhideAllApplications:), @"" )];
|
||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||
[appMenu addItem:MenuItem( sQuit, @selector(terminate:), @"q" )];
|
||||
|
||||
[windowMenu addItem:MenuItem( sMinimize, @selector(performMiniaturize:), @"m" )];
|
||||
[windowMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
// Add a Full Screen item.
|
||||
NSMenuItem *item = MenuItem( sEnterFullScreen, @selector(fullscreen:), @"\n" );
|
||||
|
||||
[item setKeyEquivalentModifierMask:NSAlternateKeyMask]; // opt-enter
|
||||
[windowMenu addItem:item];
|
||||
|
||||
[[mainMenu addItemWithTitle:[appMenu title] action:NULL keyEquivalent:@""] setSubmenu:appMenu];
|
||||
[[mainMenu addItemWithTitle:[windowMenu title] action:NULL keyEquivalent:@""] setSubmenu:windowMenu];
|
||||
|
||||
[NSApp setMainMenu:mainMenu];
|
||||
[NSApp setAppleMenu:appMenu]; // This isn't the apple menu, but it doesn't work without this.
|
||||
[NSApp setWindowsMenu:windowMenu];
|
||||
}
|
||||
|
||||
#undef main
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
RageThreadRegister guiThread( "GUI thread" );
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
SMMain *sm;
|
||||
|
||||
// Ensure the application object is initialised, this sets NSApp.
|
||||
[SMApplication sharedApplication];
|
||||
|
||||
// Set up NSException handler.
|
||||
NSSetUncaughtExceptionHandler( HandleNSException );
|
||||
|
||||
// Set up the menubar.
|
||||
SetupMenus();
|
||||
|
||||
// Create SMMain and make it the app delegate.
|
||||
sm = [[SMMain alloc] initWithArgc:argc argv:argv];
|
||||
[NSApp setDelegate:sm];
|
||||
|
||||
[pool release];
|
||||
// Start the main event loop.
|
||||
[NSApp run];
|
||||
[sm release];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2005-2009 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#define PBBUILD
|
||||
|
||||
// Only do this for c++ files.
|
||||
#ifdef __cplusplus
|
||||
# include "global.h"
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
# import <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
@@ -0,0 +1,265 @@
|
||||
#include "VectorHelper.h"
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#if defined(USE_VEC)
|
||||
#if defined(__VEC__)
|
||||
#include <vecLib/vecLib.h>
|
||||
|
||||
bool Vector::CheckForVector()
|
||||
{
|
||||
int32_t result = 0;
|
||||
size_t size = 4;
|
||||
|
||||
return !sysctlbyname( "hw.vectorunit", &result, &size, NULL, 0 ) && result;
|
||||
}
|
||||
|
||||
/* for( unsigned pos = 0; pos < size; ++pos )
|
||||
* dest[pos] += src[pos];
|
||||
* Idea from: http://developer.apple.com/hardwaredrivers/ve/downloads/add.c */
|
||||
void Vector::FastSoundWrite( float *dest, const float *src, unsigned size )
|
||||
{
|
||||
if( size > 4 )
|
||||
{
|
||||
int index = 0;
|
||||
vUInt8 one = (vUInt8)(1);
|
||||
vUInt8 srcMask = vec_add( vec_lvsl(15, src), one );
|
||||
vUInt8 destMask = vec_add(vec_lvsl(15, dest), one );
|
||||
vUInt8 storeMask = vec_lvsr( 0, dest );
|
||||
vFloat load1Src = vec_ld( 0, src );
|
||||
vFloat load1Dest = vec_ld( 0, dest );
|
||||
vFloat store = (vFloat)(0.0f);
|
||||
|
||||
// If dest is misaligned, pull the first loop iteration out.
|
||||
if( intptr_t(dest) & 0xF )
|
||||
{
|
||||
vFloat load2Src = vec_ld( 15, src );
|
||||
vFloat load2Dest = vec_ld( 15, dest );
|
||||
|
||||
load1Src = vec_perm( load1Src, load2Src, srcMask );
|
||||
load1Dest = vec_perm( load1Dest, load2Dest, destMask );
|
||||
|
||||
load1Dest = vec_add( load1Dest, load1Src );
|
||||
store = vec_perm( load1Dest, load1Dest, storeMask );
|
||||
|
||||
while( (intptr_t(dest) + index) & 0xC )
|
||||
{
|
||||
vec_ste( store, index, dest );
|
||||
index += 4;
|
||||
}
|
||||
load1Src = load2Src;
|
||||
store = load1Dest;
|
||||
load1Dest = load2Dest;
|
||||
src += 4;
|
||||
dest += 4;
|
||||
size -= 4;
|
||||
/* Incrementing the index is supposed to have the same effect
|
||||
* as incrementing dest but since we read from dest as well
|
||||
* we don't want to increment twice so decrement the index. */
|
||||
// XXX: What in the world did I mean here?
|
||||
index -= 16;
|
||||
}
|
||||
while( size >= 32 )
|
||||
{
|
||||
vFloat load2Src = vec_ld( 15, src );
|
||||
vFloat load3Src = vec_ld( 31, src );
|
||||
vFloat load4Src = vec_ld( 47, src );
|
||||
vFloat load5Src = vec_ld( 63, src );
|
||||
vFloat load6Src = vec_ld( 79, src );
|
||||
vFloat load7Src = vec_ld( 95, src );
|
||||
vFloat load8Src = vec_ld( 111, src );
|
||||
vFloat load9Src = vec_ld( 127, src );
|
||||
vFloat load2Dest = vec_ld( 15, dest );
|
||||
vFloat load3Dest = vec_ld( 31, dest );
|
||||
vFloat load4Dest = vec_ld( 47, dest );
|
||||
vFloat load5Dest = vec_ld( 63, dest );
|
||||
vFloat load6Dest = vec_ld( 79, dest );
|
||||
vFloat load7Dest = vec_ld( 95, dest );
|
||||
vFloat load8Dest = vec_ld( 111, dest );
|
||||
vFloat load9Dest = vec_ld( 127, dest );
|
||||
|
||||
// Align the data.
|
||||
load1Src = vec_perm( load1Src, load2Src, srcMask );
|
||||
load2Src = vec_perm( load2Src, load3Src, srcMask );
|
||||
load3Src = vec_perm( load3Src, load4Src, srcMask );
|
||||
load4Src = vec_perm( load4Src, load5Src, srcMask );
|
||||
load5Src = vec_perm( load5Src, load6Src, srcMask );
|
||||
load6Src = vec_perm( load6Src, load7Src, srcMask );
|
||||
load7Src = vec_perm( load7Src, load8Src, srcMask );
|
||||
load8Src = vec_perm( load8Src, load9Src, srcMask );
|
||||
// Not load5Src, it's untouched and used later.
|
||||
load1Dest = vec_perm( load1Dest, load2Dest, destMask );
|
||||
load2Dest = vec_perm( load2Dest, load3Dest, destMask );
|
||||
load3Dest = vec_perm( load3Dest, load4Dest, destMask );
|
||||
load4Dest = vec_perm( load4Dest, load5Dest, destMask );
|
||||
load5Dest = vec_perm( load5Dest, load6Dest, destMask );
|
||||
load6Dest = vec_perm( load6Dest, load7Dest, destMask );
|
||||
load7Dest = vec_perm( load7Dest, load8Dest, destMask );
|
||||
load8Dest = vec_perm( load8Dest, load9Dest, destMask );
|
||||
// Not load9Dest.
|
||||
|
||||
load1Dest = vec_add( load1Dest, load1Src );
|
||||
load2Dest = vec_add( load2Dest, load2Src );
|
||||
load3Dest = vec_add( load3Dest, load3Src );
|
||||
load4Dest = vec_add( load4Dest, load4Src );
|
||||
load5Dest = vec_add( load5Dest, load5Src );
|
||||
load6Dest = vec_add( load6Dest, load6Src );
|
||||
load7Dest = vec_add( load7Dest, load7Src );
|
||||
load8Dest = vec_add( load8Dest, load8Src );
|
||||
|
||||
// Unalign the results.
|
||||
store = vec_perm( store, load1Dest, storeMask );
|
||||
load1Dest = vec_perm( load1Dest, load2Dest, storeMask );
|
||||
load2Dest = vec_perm( load2Dest, load3Dest, storeMask );
|
||||
load3Dest = vec_perm( load3Dest, load4Dest, storeMask );
|
||||
load4Dest = vec_perm( load4Dest, load5Dest, storeMask );
|
||||
load5Dest = vec_perm( load5Dest, load6Dest, storeMask );
|
||||
load6Dest = vec_perm( load6Dest, load7Dest, storeMask );
|
||||
load7Dest = vec_perm( load7Dest, load8Dest, storeMask );
|
||||
|
||||
// store the results
|
||||
vec_st( store, index + 0, dest );
|
||||
vec_st( load1Dest, index + 16, dest );
|
||||
vec_st( load2Dest, index + 32, dest );
|
||||
vec_st( load3Dest, index + 48, dest );
|
||||
vec_st( load4Dest, index + 64, dest );
|
||||
vec_st( load5Dest, index + 80, dest );
|
||||
vec_st( load6Dest, index + 96, dest );
|
||||
vec_st( load7Dest, index + 112, dest );
|
||||
|
||||
load1Src = load9Src;
|
||||
load1Dest = load9Dest;
|
||||
store = load8Dest;
|
||||
dest += 32;
|
||||
src += 32;
|
||||
size -= 32;
|
||||
}
|
||||
|
||||
/* This completely baffles gcc's loop unrolling. If I make it > 3 instead,
|
||||
* then gcc produces 4 identical copies of the loop without scheduling them
|
||||
* in a sane manner (hence the manual unrolling above) but this loop will
|
||||
* never be executed more than 3 times so that code will never be used.
|
||||
* This produces code the way gcc _should_ do it by unrolling and scheduling
|
||||
* and then producing the rolled version. */
|
||||
while( size & ~0x3 )
|
||||
{
|
||||
vFloat load2Src = vec_ld( 15, src );
|
||||
vFloat load2Dest = vec_ld( 15, dest );
|
||||
|
||||
load1Src = vec_perm( load1Src, load2Src, srcMask );
|
||||
load1Dest = vec_perm( load1Dest, load2Dest, destMask );
|
||||
load1Dest = vec_add( load1Dest, load1Src );
|
||||
|
||||
store = vec_perm( store, load1Dest, storeMask );
|
||||
vec_st( store, index, dest );
|
||||
|
||||
load1Src = load2Src;
|
||||
store = load1Dest;
|
||||
load1Dest = load2Dest;
|
||||
src += 4;
|
||||
dest += 4;
|
||||
size -= 4;
|
||||
}
|
||||
|
||||
// Store the remainder of the vector, if it was misaligned.
|
||||
if( index < 0 )
|
||||
{
|
||||
store = vec_perm( store, store, storeMask );
|
||||
while( index < 0 )
|
||||
{
|
||||
vec_ste( store, index, dest );
|
||||
index += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If we account for both misaligned dest and src, there is really no way to
|
||||
* do this in vector code so do the last at most 3 elements in scalar code. */
|
||||
while( size-- )
|
||||
*(dest++) += *(src++);
|
||||
}
|
||||
|
||||
#elif defined(__SSE2__)
|
||||
#include <xmmintrin.h>
|
||||
// This is portable to other sysems since it uses Intel's intrinsics.
|
||||
|
||||
bool Vector::CheckForVector()
|
||||
{
|
||||
// MMX, SSE, and SSE2 must be present, we don't use SSE3 so no need to check for it.
|
||||
return true;
|
||||
}
|
||||
|
||||
void Vector::FastSoundWrite( float *dest, const float *src, unsigned size )
|
||||
{
|
||||
while( (intptr_t(dest) & 0xF) && size )
|
||||
{
|
||||
// Misaligned stores are slow.
|
||||
*(dest++) += *(src++);
|
||||
--size;
|
||||
}
|
||||
|
||||
// Misaligned loads are slower so specialize to aligned loads when possible.
|
||||
if( intptr_t(src) & 0xF )
|
||||
{
|
||||
while( size >= 8 )
|
||||
{
|
||||
__m128 data1 = _mm_loadu_ps( src + 0 );
|
||||
__m128 data2 = _mm_loadu_ps( src + 4 );
|
||||
|
||||
data1 = _mm_add_ps( data1, *(__m128 *)(dest + 0) );
|
||||
data2 = _mm_add_ps( data2, *(__m128 *)(dest + 4) );
|
||||
_mm_store_ps( dest + 0, data1 );
|
||||
_mm_store_ps( dest + 4, data2 );
|
||||
src += 8;
|
||||
dest += 8;
|
||||
size -= 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( size >= 8 )
|
||||
{
|
||||
__m128 data1 = _mm_load_ps( src + 0 );
|
||||
__m128 data2 = _mm_load_ps( src + 4 );
|
||||
|
||||
data1 = _mm_add_ps( data1, *(__m128 *)(dest + 0) );
|
||||
data2 = _mm_add_ps( data2, *(__m128 *)(dest + 4) );
|
||||
_mm_store_ps( dest + 0, data1 );
|
||||
_mm_store_ps( dest + 4, data2 );
|
||||
src += 8;
|
||||
dest += 8;
|
||||
size -= 8;
|
||||
}
|
||||
}
|
||||
while( size-- )
|
||||
*(dest++) += *(src++);
|
||||
}
|
||||
|
||||
#else
|
||||
#error huh?
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* (c) 2006-2007 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef VECTOR_HELPER_H
|
||||
#define VECTOR_HELPER_H
|
||||
|
||||
#if ( defined(__VEC__) || (defined(__SSE__) && defined(__SSE2__)) ) && defined(__GNUC__)
|
||||
namespace Vector
|
||||
{
|
||||
bool CheckForVector();
|
||||
void FastSoundWrite( float *dest, const float *src, unsigned size );
|
||||
}
|
||||
#define USE_VEC
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef ARCH_SETUP_DARWIN_H
|
||||
#define ARCH_SETUP_DARWIN_H
|
||||
|
||||
// Replace the main function.
|
||||
extern "C" int SM_main( int argc, char *argv[] );
|
||||
#define main(x,y) SM_main(x,y)
|
||||
|
||||
#define HAVE_VERSION_INFO
|
||||
#define HAVE_CXA_DEMANGLE
|
||||
#define HAVE_THEORA
|
||||
#define HAVE_FFMPEG
|
||||
#define HAVE_PTHREAD_COND_TIMEDWAIT
|
||||
/* This must be defined to 1 because autoconf's AC_CHECK_DECLS macro decides to define
|
||||
* this in all cases. If only they could be consistent... */
|
||||
#define HAVE_DECL_SIGUSR1 1
|
||||
|
||||
/* We have <machine/endian.h> which gets pulled in when we use gcc 4.0's <cstdlib>
|
||||
* but no <endian.h>. The definitions of LITTLE_ENDIAN, BIG_ENDIAN and end up conflicting
|
||||
* even though they resolve to the same thing (bug in gcc?). */
|
||||
#define HAVE_MACHINE_ENDIAN_H
|
||||
#define HAVE_INTTYPES_H
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#define CRASH_HANDLER
|
||||
|
||||
#define GL_GET_ERROR_IS_SLOW
|
||||
// CGFlushDrawable() performs a glFlush() and the docs say not to call glFlush()
|
||||
#define NO_GL_FLUSH
|
||||
|
||||
#if defined(__ppc__)
|
||||
# define CPU_PPC
|
||||
# define ENDIAN_BIG
|
||||
# define BACKTRACE_LOOKUP_METHOD_DARWIN_DYLD
|
||||
# define BACKTRACE_METHOD_POWERPC_DARWIN
|
||||
#elif defined(__i386__)
|
||||
# define CPU_X86
|
||||
# define ENDIAN_LITTLE
|
||||
# define BACKTRACE_METHOD_X86_DARWIN
|
||||
# define BACKTRACE_LOOKUP_METHOD_DLADDR
|
||||
#endif
|
||||
|
||||
#ifndef MACOSX
|
||||
# define MACOSX
|
||||
#endif
|
||||
#ifndef __MACOSX__
|
||||
# define __MACOSX__
|
||||
#endif
|
||||
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#define ArchSwap32(n) OSSwapInt32((n))
|
||||
#define ArchSwap24(n) (ArchSwap32((n)) >> 8)
|
||||
#define ArchSwap16(n) OSSwapInt16((n))
|
||||
#define HAVE_BYTE_SWAPS
|
||||
|
||||
// Define the work around if needed.
|
||||
#include <bits/c++config.h>
|
||||
#include <stdint.h>
|
||||
#if _GLIBCXX_USE_C99
|
||||
# define NEED_CSTDLIB_WORKAROUND
|
||||
#else
|
||||
inline int64_t llabs( int64_t x ) { return x < 0LL ? -x : x; }
|
||||
#endif
|
||||
|
||||
#define attribute_deprecated // Shut ffmpeg up!
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2003-2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
Reference in New Issue
Block a user