You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1169 lines
33 KiB
1169 lines
33 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: Xbox
|
|
//
|
|
//=====================================================================================//
|
|
|
|
#include "../pch_tier0.h"
|
|
#ifdef PLATFORM_PS3
|
|
#include "ps3/ps3_core.h"
|
|
#include "ps3/ps3_win32stubs.h"
|
|
#include "ps3/ps3_console.h"
|
|
#include "tls_ps3.h"
|
|
#include <sysutil/sysutil_common.h>
|
|
#include <sys/process.h>
|
|
#include <sysutil/sysutil_sysparam.h>
|
|
#else
|
|
#include "xbox/xbox_console.h"
|
|
#include "xbox/xbox_win32stubs.h"
|
|
#include "xbox/xbox_launch.h"
|
|
#endif
|
|
#include "tier0/threadtools.h"
|
|
#include "tier0/icommandline.h"
|
|
#include "tier0/memdbgon.h"
|
|
|
|
class CXbxEventQueue
|
|
{
|
|
public:
|
|
CXbxEventQueue() : m_pQueue( NULL ), m_dwCount( 0 ), m_dwAllocated( 0 ), m_bDispatching( false ) {}
|
|
|
|
public:
|
|
void AppendEvent( xevent_t const &xevt );
|
|
void Dispatch();
|
|
bool IsDispatching() const;
|
|
|
|
protected:
|
|
CThreadFastMutex m_mtx;
|
|
xevent_t *m_pQueue;
|
|
DWORD m_dwCount;
|
|
DWORD m_dwAllocated;
|
|
bool m_bDispatching;
|
|
|
|
static const int s_nQueueNormalSize = 32;
|
|
static const int s_nQueueAbnormalSize = 128;
|
|
};
|
|
|
|
static CXbxEventQueue g_xbx_EventQueue;
|
|
|
|
DWORD g_iStorageDeviceId[ XUSER_MAX_COUNT ] =
|
|
{
|
|
XBX_INVALID_STORAGE_ID, XBX_INVALID_STORAGE_ID, XBX_INVALID_STORAGE_ID, XBX_INVALID_STORAGE_ID
|
|
#ifdef PLATFORM_PS3
|
|
, XBX_INVALID_STORAGE_ID, XBX_INVALID_STORAGE_ID, XBX_INVALID_STORAGE_ID
|
|
#endif
|
|
};
|
|
DWORD g_iPrimaryUserId = XBX_INVALID_USER_ID;
|
|
DWORD g_bPrimaryUserIsGuest = 0;
|
|
DWORD g_numGameUsers = 0;
|
|
DWORD g_InvitedUserId = XBX_INVALID_USER_ID;
|
|
XUID g_InvitedUserXuid = 0ull;
|
|
XNKID g_InviteSessionId;
|
|
#ifdef _X360
|
|
HANDLE g_hListenHandle = INVALID_HANDLE_VALUE;
|
|
ULONG64 g_ListenCategories = 0;
|
|
#elif defined( _PS3 )
|
|
ps3syscbckeventhdlr_t g_ps3SysCbckEvHdlr;
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Convert an Xbox notification to a custom windows message
|
|
//-----------------------------------------------------------------------------
|
|
static int NotificationToWindowsMessage( DWORD id )
|
|
{
|
|
#ifdef _X360
|
|
switch( id )
|
|
{
|
|
case XN_SYS_UI: return WM_SYS_UI;
|
|
case XN_SYS_SIGNINCHANGED: return WM_SYS_SIGNINCHANGED;
|
|
case XN_SYS_STORAGEDEVICESCHANGED: return WM_SYS_STORAGEDEVICESCHANGED;
|
|
case XN_SYS_PROFILESETTINGCHANGED: return WM_SYS_PROFILESETTINGCHANGED;
|
|
case XN_SYS_MUTELISTCHANGED: return WM_SYS_MUTELISTCHANGED;
|
|
case XN_SYS_INPUTDEVICESCHANGED: return WM_SYS_INPUTDEVICESCHANGED;
|
|
case XN_SYS_INPUTDEVICECONFIGCHANGED: return WM_SYS_INPUTDEVICECONFIGCHANGED;
|
|
case XN_LIVE_CONNECTIONCHANGED: return WM_LIVE_CONNECTIONCHANGED;
|
|
case XN_LIVE_INVITE_ACCEPTED: return WM_LIVE_INVITE_ACCEPTED;
|
|
case XN_LIVE_LINK_STATE_CHANGED: return WM_LIVE_LINK_STATE_CHANGED;
|
|
case XN_LIVE_CONTENT_INSTALLED: return WM_LIVE_CONTENT_INSTALLED;
|
|
case XN_LIVE_MEMBERSHIP_PURCHASED: return WM_LIVE_MEMBERSHIP_PURCHASED;
|
|
case XN_LIVE_VOICECHAT_AWAY: return WM_LIVE_VOICECHAT_AWAY;
|
|
case XN_LIVE_PRESENCE_CHANGED: return WM_LIVE_PRESENCE_CHANGED;
|
|
case XN_FRIENDS_PRESENCE_CHANGED: return WM_FRIENDS_PRESENCE_CHANGED;
|
|
case XN_FRIENDS_FRIEND_ADDED: return WM_FRIENDS_FRIEND_ADDED;
|
|
case XN_FRIENDS_FRIEND_REMOVED: return WM_FRIENDS_FRIEND_REMOVED;
|
|
// deprecated in Jun08 XDK: case XN_CUSTOM_GAMEBANNERPRESSED: return WM_CUSTOM_GAMEBANNERPRESSED;
|
|
case XN_CUSTOM_ACTIONPRESSED: return WM_CUSTOM_ACTIONPRESSED;
|
|
case XN_XMP_STATECHANGED: return WM_XMP_STATECHANGED;
|
|
case XN_XMP_PLAYBACKBEHAVIORCHANGED: return WM_XMP_PLAYBACKBEHAVIORCHANGED;
|
|
case XN_XMP_PLAYBACKCONTROLLERCHANGED: return WM_XMP_PLAYBACKCONTROLLERCHANGED;
|
|
default:
|
|
Warning( "Unrecognized notification id %d\n", id );
|
|
return 0;
|
|
}
|
|
#endif
|
|
Assert( 0 );
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_Error
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_Error( const char* format, ... )
|
|
{
|
|
va_list args;
|
|
char message[XBX_MAX_MESSAGE];
|
|
|
|
va_start( args, format );
|
|
_vsnprintf( message, sizeof( message ), format, args );
|
|
va_end( args );
|
|
|
|
message[sizeof( message )-1] = '\0';
|
|
|
|
#if defined( _X360 )
|
|
XBX_DebugString( XMAKECOLOR(255,0,0), message );
|
|
XBX_FlushDebugOutput();
|
|
|
|
DebugBreak();
|
|
static volatile int doReturn;
|
|
|
|
while ( !doReturn );
|
|
#elif defined( _PS3 )
|
|
XBX_DebugString( 0xFFFFFFFF, message );
|
|
|
|
// primitive crash technique for now
|
|
DebuggerBreak();
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_OutputDebugStringA
|
|
//
|
|
// Replaces 'OutputDebugString' to send through debugging channel
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_OutputDebugStringA( LPCSTR lpOutputString )
|
|
{
|
|
#ifdef _X360
|
|
XBX_DebugString( XMAKECOLOR(0,0,0), lpOutputString );
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_ProcessXCommand
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
static void XBX_ProcessXCommand( xevent_t const &xe )
|
|
{
|
|
const char *pCommand = (char*)xe.arg1;
|
|
#if defined( _X360 )
|
|
// remote command
|
|
// pass it game via windows message
|
|
HWND hWnd = GetFocus();
|
|
WNDPROC windowProc = ( WNDPROC)GetWindowLong( hWnd, GWL_WNDPROC );
|
|
if ( windowProc )
|
|
{
|
|
windowProc( hWnd, WM_XREMOTECOMMAND, 0, (LPARAM)pCommand );
|
|
}
|
|
#elif defined ( _PS3 )
|
|
if ( g_ps3SysCbckEvHdlr.pfnHandler )
|
|
{
|
|
// recreate the event and send it to the handler (wtf?)
|
|
xevent_t ev = { XEV_REMOTECMD, WM_XREMOTECOMMAND, reinterpret_cast<int>(pCommand), 0 };
|
|
g_ps3SysCbckEvHdlr.pfnHandler( ev );
|
|
}
|
|
|
|
#endif
|
|
//
|
|
// VXBDM gives us a command as a pointer to the global buffer
|
|
// and then monitors this global buffer on a separate thread.
|
|
// As soon as the first byte in the buffer is set to NULL this
|
|
// serves as a signal to VXBDM that the command has been received
|
|
// and processed and that it can enqueue another command.
|
|
// Signal to VXBDM here:
|
|
( const_cast< char * >( pCommand ) )[0] = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_ProcessListenerNotification
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
static void XBX_ProcessListenerNotification( xevent_t const &xe )
|
|
{
|
|
#ifdef _X360
|
|
// pass it game via windows message
|
|
HWND hWnd = GetFocus();
|
|
WNDPROC windowProc = ( WNDPROC)GetWindowLong( hWnd, GWL_WNDPROC );
|
|
if ( windowProc )
|
|
{
|
|
windowProc( hWnd, xe.arg1, 0, (LPARAM)xe.arg2 );
|
|
}
|
|
#elif defined( _PS3 )
|
|
if ( g_ps3SysCbckEvHdlr.pfnHandler )
|
|
{
|
|
g_ps3SysCbckEvHdlr.pfnHandler( xe );
|
|
}
|
|
#else
|
|
Assert( 0 );
|
|
#endif
|
|
|
|
switch ( xe.arg1 )
|
|
{
|
|
case WM_SYS_SIGNINCHANGED:
|
|
delete reinterpret_cast< xevent_SYS_SIGNINCHANGED_t * >( xe.arg2 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_QueueEvent
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_QueueEvent(xevent_e event, int arg1, int arg2, int arg3)
|
|
{
|
|
xevent_t xEvt;
|
|
memset( &xEvt, 0, sizeof( xEvt ) );
|
|
xEvt.event = event;
|
|
xEvt.arg1 = arg1;
|
|
xEvt.arg2 = arg2;
|
|
xEvt.arg3 = arg3;
|
|
|
|
g_xbx_EventQueue.AppendEvent( xEvt );
|
|
}
|
|
|
|
#ifdef _PS3
|
|
static void XBX_QueueRemoteCommandEvent( const char *pBuf )
|
|
{
|
|
XBX_QueueEvent( XEV_REMOTECMD, ( int )pBuf, 0, 0 );
|
|
}
|
|
void PS3_CellSysutilCallback_Function(
|
|
uint64_t status,
|
|
uint64_t param,
|
|
void *userdata
|
|
);
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_ProcessEvents
|
|
//
|
|
// Assumed one per frame only!
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_ProcessEvents(void)
|
|
{
|
|
Assert( ThreadInMainThread() );
|
|
if ( g_xbx_EventQueue.IsDispatching() )
|
|
{
|
|
DevWarning( "XBX_ProcessEvents is ignored while the queue is dispatching!\n" );
|
|
return;
|
|
}
|
|
|
|
#ifdef _X360
|
|
|
|
DWORD id;
|
|
ULONG parameter;
|
|
while ( XNotifyGetNext( g_hListenHandle, 0, &id, ¶meter ) )
|
|
{
|
|
// Special handling
|
|
switch( id )
|
|
{
|
|
case XN_SYS_STORAGEDEVICESCHANGED:
|
|
{
|
|
bool bWarnOfDeviceChange = false;
|
|
#if defined ( CSTRIKE15 )
|
|
// cstrike15 saves info to profile; so we always want to check for profile
|
|
// backing store whenever a storage device is changed
|
|
bWarnOfDeviceChange = true;
|
|
#endif
|
|
|
|
for ( int k = 0; k < XUSER_MAX_COUNT; ++ k )
|
|
{
|
|
// Has anybody selected a storage device?
|
|
DWORD storageID = XBX_GetStorageDeviceId( k );
|
|
if ( XBX_DescribeStorageDevice( storageID ) == false )
|
|
continue;
|
|
|
|
// Validate the selected storage device
|
|
XDEVICE_DATA deviceData;
|
|
DWORD ret = XContentGetDeviceData( storageID, &deviceData );
|
|
if ( ret != ERROR_SUCCESS )
|
|
{
|
|
// Device was removed
|
|
Warning( "XN_SYS_STORAGEDEVICESCHANGED: device 0x%08X removed for ctrlr%d!\n",
|
|
storageID, k );
|
|
XBX_SetStorageDeviceId( k, XBX_INVALID_STORAGE_ID );
|
|
|
|
int iSplitscreenSlot = XBX_GetSlotByUserId( k );
|
|
if ( iSplitscreenSlot >= 0 )
|
|
{
|
|
bWarnOfDeviceChange = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Notify the user if something important has changed
|
|
if ( bWarnOfDeviceChange )
|
|
{
|
|
XBX_QueueEvent( XEV_LISTENER_NOTIFICATION, NotificationToWindowsMessage( id ), 0, 0 );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case XN_SYS_SIGNINCHANGED:
|
|
{
|
|
xevent_SYS_SIGNINCHANGED_t *pSysEvent = new xevent_SYS_SIGNINCHANGED_t; // deleted during dispatch
|
|
pSysEvent->dwParam = parameter;
|
|
for ( int k = 0; k < XUSER_MAX_COUNT; ++ k )
|
|
{
|
|
pSysEvent->state[k] = XUserGetSigninState( k );
|
|
pSysEvent->xuid[k] = 0ull;
|
|
|
|
if ( pSysEvent->state[k] != eXUserSigninState_NotSignedIn )
|
|
{
|
|
XUSER_SIGNIN_INFO xsi = {0};
|
|
if ( ERROR_SUCCESS != XUserGetSigninInfo( k, XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY, &xsi ) ||
|
|
!xsi.xuid )
|
|
{
|
|
if ( ERROR_SUCCESS == XUserGetXUID( k, &xsi.xuid ) )
|
|
pSysEvent->xuid[k] = xsi.xuid;
|
|
}
|
|
else
|
|
{
|
|
pSysEvent->xuid[k] = xsi.xuid;
|
|
}
|
|
}
|
|
}
|
|
XBX_QueueEvent( XEV_LISTENER_NOTIFICATION, NotificationToWindowsMessage( id ), reinterpret_cast< int >( pSysEvent ), parameter );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
XBX_QueueEvent( XEV_LISTENER_NOTIFICATION, NotificationToWindowsMessage( id ), parameter, 0 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
#elif defined( _PS3 )
|
|
if ( g_pValvePS3Console )
|
|
{
|
|
g_pValvePS3Console->PumpMessage( XBX_QueueRemoteCommandEvent );
|
|
}
|
|
|
|
int retval = cellSysutilCheckCallback();
|
|
if ( retval < 0 )
|
|
{
|
|
DevWarning( "cellSysutilCheckCallback failed! error 0x%08X!\n", retval );
|
|
}
|
|
#ifndef _CERT
|
|
static float s_flQuitAfter = CommandLine()->ParmValue( "-quitafter", 0.0f );
|
|
if( s_flQuitAfter > 0 && Plat_FloatTime() > s_flQuitAfter )
|
|
{
|
|
PS3_CellSysutilCallback_Function( CELL_SYSUTIL_REQUEST_EXITGAME, 0, 0 );
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void XBX_DispatchEventsQueue()
|
|
{
|
|
g_xbx_EventQueue.Dispatch();
|
|
}
|
|
|
|
#ifdef _PS3
|
|
void PS3_CellSysutilCallback_Function(
|
|
uint64_t status,
|
|
uint64_t param,
|
|
void *userdata
|
|
)
|
|
{
|
|
Assert( g_ps3SysCbckEvHdlr.pfnHandler );
|
|
|
|
// Prepare to queue the event
|
|
xevent_t xe;
|
|
memset( &xe, 0, sizeof( xe ) );
|
|
xe.event = XEV_LISTENER_NOTIFICATION;
|
|
|
|
switch ( status )
|
|
{
|
|
case CELL_SYSUTIL_REQUEST_EXITGAME:
|
|
xe.arg1 = WM_SYS_SHUTDOWNREQUEST;
|
|
GetTLSGlobals()->bNormalQuitRequested = true; // special flag to prevent the error screen from appearing
|
|
Warning( "[PS3 SYSTEM] REQUEST EXITGAME RECEIVED @ %.3f\n", Plat_FloatTime() );
|
|
break;
|
|
|
|
case CELL_SYSUTIL_DRAWING_BEGIN:
|
|
case CELL_SYSUTIL_DRAWING_END:
|
|
// not interesting notifications
|
|
return;
|
|
|
|
case CELL_SYSUTIL_SYSTEM_MENU_OPEN:
|
|
case CELL_SYSUTIL_SYSTEM_MENU_CLOSE:
|
|
xe.arg1 = WM_SYS_UI;
|
|
xe.arg2 = !!( status == CELL_SYSUTIL_SYSTEM_MENU_OPEN );
|
|
break;
|
|
|
|
case CELL_SYSUTIL_BGMPLAYBACK_PLAY:
|
|
case CELL_SYSUTIL_BGMPLAYBACK_STOP:
|
|
xe.arg1 = WM_XMP_PLAYBACKCONTROLLERCHANGED;
|
|
xe.arg2 = !!( status == CELL_SYSUTIL_BGMPLAYBACK_STOP );
|
|
break;
|
|
|
|
case CELL_SYSUTIL_NP_INVITATION_SELECTED:
|
|
xe.arg1 = WM_LIVE_INVITE_ACCEPTED;
|
|
xe.arg2 = XBX_GetPrimaryUserId(); // accept on primary controller
|
|
break;
|
|
}
|
|
|
|
// Queue the event
|
|
xe.arg3 = 1; // means that event has sysutil payload
|
|
xe.sysutil_status = status;
|
|
xe.sysutil_param = param;
|
|
g_xbx_EventQueue.AppendEvent( xe );
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_NotifyCreateListener
|
|
//
|
|
// Add notification categories to the listener object
|
|
//-----------------------------------------------------------------------------
|
|
bool XBX_NotifyCreateListener( uint64 categories )
|
|
{
|
|
#ifdef _X360
|
|
if ( categories != 0 )
|
|
{
|
|
categories |= g_ListenCategories;
|
|
}
|
|
|
|
g_hListenHandle = XNotifyCreateListener( categories );
|
|
if ( g_hListenHandle == NULL || g_hListenHandle == INVALID_HANDLE_VALUE )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_ListenCategories = categories;
|
|
#elif defined( _PS3 )
|
|
Assert( categories == (uint64)( (size_t) categories ) );
|
|
if ( ps3syscbckeventhdlr_t const *pHdlr = reinterpret_cast< ps3syscbckeventhdlr_t const * >( (size_t) categories ) )
|
|
{
|
|
Assert( !g_ps3SysCbckEvHdlr.pfnHandler );
|
|
g_ps3SysCbckEvHdlr = *pHdlr;
|
|
|
|
int retval = cellSysutilRegisterCallback( 0, PS3_CellSysutilCallback_Function, NULL );
|
|
if ( retval < 0 )
|
|
{
|
|
DevWarning( "cellSysutilRegisterCallback failed with error 0x%08X!\n", retval );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int retval = cellSysutilUnregisterCallback( 0 );
|
|
if ( retval < 0 )
|
|
{
|
|
DevWarning( "cellSysutilUnregisterCallback failed with error 0x%08X!\n", retval );
|
|
}
|
|
memset( &g_ps3SysCbckEvHdlr, 0, sizeof( g_ps3SysCbckEvHdlr ) );
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
struct Language_t
|
|
{
|
|
const char *pString;
|
|
int id;
|
|
bool bLocalizedAudio;
|
|
};
|
|
Language_t s_ValidLanguages[] =
|
|
{
|
|
#ifdef _GAMECONSOLE
|
|
#ifdef _PS3
|
|
#define XC_LANGUAGE_JAPANESE CELL_SYSUTIL_LANG_JAPANESE
|
|
#if CELL_SDK_VERSION >= 0x400000
|
|
#define XC_LANGUAGE_ENGLISH CELL_SYSUTIL_LANG_ENGLISH_US
|
|
#else
|
|
#define XC_LANGUAGE_ENGLISH CELL_SYSUTIL_LANG_ENGLISH
|
|
#endif
|
|
#define XC_LANGUAGE_FRENCH CELL_SYSUTIL_LANG_FRENCH
|
|
#define XC_LANGUAGE_SPANISH CELL_SYSUTIL_LANG_SPANISH
|
|
#define XC_LANGUAGE_GERMAN CELL_SYSUTIL_LANG_GERMAN
|
|
#define XC_LANGUAGE_ITALIAN CELL_SYSUTIL_LANG_ITALIAN
|
|
#define XC_LANGUAGE_DUTCH CELL_SYSUTIL_LANG_DUTCH
|
|
#if CELL_SDK_VERSION >= 0x400000
|
|
#define XC_LANGUAGE_PORTUGUESE CELL_SYSUTIL_LANG_PORTUGUESE_PT
|
|
#else
|
|
#define XC_LANGUAGE_PORTUGUESE CELL_SYSUTIL_LANG_PORTUGUESE
|
|
#endif
|
|
#define XC_LANGUAGE_RUSSIAN CELL_SYSUTIL_LANG_RUSSIAN
|
|
#define XC_LANGUAGE_KOREAN CELL_SYSUTIL_LANG_KOREAN
|
|
#define XC_LANGUAGE_TCHINESE CELL_SYSUTIL_LANG_CHINESE_T
|
|
#define XC_LANGUAGE_SCHINESE CELL_SYSUTIL_LANG_CHINESE_S
|
|
#define XC_LANGUAGE_FINNISH CELL_SYSUTIL_LANG_FINNISH
|
|
#define XC_LANGUAGE_SWEDISH CELL_SYSUTIL_LANG_SWEDISH
|
|
#define XC_LANGUAGE_DANISH CELL_SYSUTIL_LANG_DANISH
|
|
#define XC_LANGUAGE_NORWEGIAN CELL_SYSUTIL_LANG_NORWEGIAN
|
|
#define XC_LANGUAGE_POLISH CELL_SYSUTIL_LANG_POLISH
|
|
#endif
|
|
#ifdef _X360
|
|
// Xbox 360 doesn't support these languages in OS, but people can still test
|
|
// with them by running with appropriate command line
|
|
#define XC_LANGUAGE_DUTCH 0x7F1A4EF1
|
|
#define XC_LANGUAGE_FINNISH 0x7F1A4EF2
|
|
#define XC_LANGUAGE_SWEDISH 0x7F1A4EF3
|
|
#define XC_LANGUAGE_DANISH 0x7F1A4EF4
|
|
#define XC_LANGUAGE_NORWEGIAN 0x7F1A4EF5
|
|
#endif
|
|
#if 0 // to turn off all localization change it to #if 1
|
|
{"english", XC_LANGUAGE_ENGLISH, true},
|
|
#else
|
|
// known supported 360 languages
|
|
{"japanese", XC_LANGUAGE_JAPANESE, false},
|
|
{"german", XC_LANGUAGE_GERMAN, true},
|
|
{"french", XC_LANGUAGE_FRENCH, true},
|
|
{"spanish", XC_LANGUAGE_SPANISH, true},
|
|
{"italian", XC_LANGUAGE_ITALIAN, false},
|
|
{"dutch", XC_LANGUAGE_DUTCH, false},
|
|
{"korean", XC_LANGUAGE_KOREAN, false},
|
|
{"tchinese", XC_LANGUAGE_TCHINESE, false},
|
|
{"portuguese", XC_LANGUAGE_PORTUGUESE, false},
|
|
{"schinese", XC_LANGUAGE_SCHINESE, false},
|
|
{"finnish", XC_LANGUAGE_FINNISH, false},
|
|
{"swedish", XC_LANGUAGE_SWEDISH, false},
|
|
{"danish", XC_LANGUAGE_DANISH, false},
|
|
{"norwegian", XC_LANGUAGE_NORWEGIAN, false},
|
|
{"polish", XC_LANGUAGE_POLISH, false},
|
|
#if defined( _X360 )
|
|
{"russian", XC_LANGUAGE_RUSSIAN, false},
|
|
#else
|
|
{"russian", XC_LANGUAGE_RUSSIAN, true},
|
|
#endif
|
|
#endif
|
|
#else
|
|
#define XC_LANGUAGE_ENGLISH 0
|
|
{"english", XC_LANGUAGE_ENGLISH, true},
|
|
#endif
|
|
};
|
|
static const char *SupportedLanguageIDToString( int id )
|
|
{
|
|
// find it or force to english
|
|
for ( int i = 0; i < ARRAYSIZE( s_ValidLanguages ); i++ )
|
|
{
|
|
if ( id == s_ValidLanguages[i].id )
|
|
{
|
|
return s_ValidLanguages[i].pString;
|
|
}
|
|
}
|
|
return "english";
|
|
}
|
|
static int SupportedLanguageStringToID( const char *pName )
|
|
{
|
|
// find it or force to english
|
|
for ( int i = 0; i < ARRAYSIZE( s_ValidLanguages ); i++ )
|
|
{
|
|
// caller's argument could be substring from command line, i.e. "french -another arg"
|
|
if ( !strncmp( pName, s_ValidLanguages[i].pString, strlen( s_ValidLanguages[i].pString ) ) )
|
|
{
|
|
return s_ValidLanguages[i].id;
|
|
}
|
|
}
|
|
return XC_LANGUAGE_ENGLISH;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the true xbox language id, possibly an id that is not supported.
|
|
//-----------------------------------------------------------------------------
|
|
static int GetLanguage( void )
|
|
{
|
|
static int languageId = -1;
|
|
if ( languageId == -1 )
|
|
{
|
|
#ifdef _X360
|
|
languageId = XGetLanguage();
|
|
#elif defined( _PS3 )
|
|
if ( cellSysutilGetSystemParamInt( CELL_SYSUTIL_SYSTEMPARAM_ID_LANG, &languageId ) < 0 )
|
|
languageId = XC_LANGUAGE_ENGLISH;
|
|
#else
|
|
languageId = XC_LANGUAGE_ENGLISH;
|
|
#endif
|
|
|
|
// allow language to be overriden via command line for easier development
|
|
// otherwise must set via dashboard
|
|
const char *pLanguage = CommandLine()->ParmValue( "-language", (const char *)NULL );
|
|
if ( pLanguage && pLanguage[0] )
|
|
{
|
|
languageId = SupportedLanguageStringToID( pLanguage );
|
|
}
|
|
}
|
|
return languageId;
|
|
}
|
|
|
|
const char *XBX_GetNextSupportedLanguage( const char *pLanguage, bool *pbHasAudio )
|
|
{
|
|
int i = 0;
|
|
if ( pLanguage && pLanguage[0] )
|
|
{
|
|
for ( i = 0; i < ARRAYSIZE( s_ValidLanguages ); i++ )
|
|
{
|
|
if ( !V_tier0_stricmp( pLanguage, s_ValidLanguages[i].pString ) )
|
|
{
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( i >= ARRAYSIZE( s_ValidLanguages ) )
|
|
{
|
|
// end of list
|
|
return NULL;
|
|
}
|
|
|
|
if ( pbHasAudio )
|
|
{
|
|
*pbHasAudio = s_ValidLanguages[i].bLocalizedAudio;
|
|
}
|
|
return s_ValidLanguages[i].pString;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_GetLanguageString
|
|
//
|
|
// Returns the supported xbox language setting as a string, otherwise "english".
|
|
//-----------------------------------------------------------------------------
|
|
const char* XBX_GetLanguageString( void )
|
|
{
|
|
return ( SupportedLanguageIDToString( GetLanguage() ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_IsLocalized
|
|
//
|
|
// Returns true if configured for a supported non-english localization.
|
|
//-----------------------------------------------------------------------------
|
|
bool XBX_IsLocalized( void )
|
|
{
|
|
return ( V_tier0_stricmp( XBX_GetLanguageString(), "english" ) != 0 );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_IsRestrictiveLanguage
|
|
//
|
|
// Returns true if we are localized into one of the languages that needs
|
|
// specialized handling
|
|
//-----------------------------------------------------------------------------
|
|
bool XBX_IsRestrictiveLanguage( void )
|
|
{
|
|
#ifdef _GAMECONSOLE
|
|
// these languages have to use the xarial font mounted in memory
|
|
// cannot determine this from the font system at the times we need it, encoded it here
|
|
int languageId = GetLanguage();
|
|
switch ( languageId )
|
|
{
|
|
case XC_LANGUAGE_KOREAN:
|
|
case XC_LANGUAGE_JAPANESE:
|
|
case XC_LANGUAGE_SCHINESE:
|
|
case XC_LANGUAGE_TCHINESE:
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
// all other languages can be handled normally
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_IsAudioLocalized
|
|
//
|
|
// Returns true if audio is localized.
|
|
//-----------------------------------------------------------------------------
|
|
bool XBX_IsAudioLocalized( void )
|
|
{
|
|
// english is not a localized audio
|
|
if ( XBX_IsLocalized() )
|
|
{
|
|
int languageId = GetLanguage();
|
|
for ( int i = 0; i < ARRAYSIZE( s_ValidLanguages ); i++ )
|
|
{
|
|
if ( languageId == s_ValidLanguages[i].id )
|
|
{
|
|
return s_ValidLanguages[i].bLocalizedAudio;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_ResetStorageDeviceInfo
|
|
//
|
|
// Returns the xbox storage device ID
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_ResetStorageDeviceInfo()
|
|
{
|
|
for ( int k = 0; k < XUSER_MAX_COUNT; ++ k )
|
|
g_iStorageDeviceId[ k ] = XBX_INVALID_STORAGE_ID;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_DescribeStorageDevice
|
|
//
|
|
// Returns whether the storage device denotes a usable device or is
|
|
// denoting a state of unavailable device.
|
|
//-----------------------------------------------------------------------------
|
|
DWORD XBX_DescribeStorageDevice( DWORD nStorageID )
|
|
{
|
|
if ( nStorageID == XBX_INVALID_STORAGE_ID ||
|
|
nStorageID == XBX_STORAGE_DECLINED )
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_MakeStorageContainerRoot
|
|
//
|
|
// Returns whether the storage device denotes a usable device or is
|
|
// denoting a state of unavailable device.
|
|
//-----------------------------------------------------------------------------
|
|
char const* XBX_MakeStorageContainerRoot( int iController, char const *szRootName, char *pBuffer, int numBufferBytes )
|
|
{
|
|
if ( iController < 0 || iController >= XUSER_MAX_COUNT )
|
|
{
|
|
pBuffer[0] = '\0';
|
|
}
|
|
else
|
|
{
|
|
_snprintf( pBuffer, numBufferBytes, "X%d%s", iController, szRootName );
|
|
}
|
|
return pBuffer;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_GetStorageDeviceId
|
|
//
|
|
// Returns the xbox storage device ID for the given controller
|
|
//-----------------------------------------------------------------------------
|
|
DWORD XBX_GetStorageDeviceId( int iController )
|
|
{
|
|
#if defined( _DEMO ) && defined( _X360 )
|
|
// Demos are not allowed to access storage devices
|
|
return XBX_STORAGE_DECLINED;
|
|
#endif
|
|
|
|
if ( iController >= 0 && iController < XUSER_MAX_COUNT )
|
|
return g_iStorageDeviceId[ iController ];
|
|
else
|
|
return XBX_INVALID_STORAGE_ID;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_SetStorageDeviceId
|
|
//
|
|
// Sets the xbox storage device ID for the given controller
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetStorageDeviceId( int iController, DWORD id )
|
|
{
|
|
Msg( "XBX_SetStorageDeviceId: device 0x%08X set for ctrlr%d!\n",
|
|
id, iController );
|
|
|
|
if ( iController >= 0 && iController < XUSER_MAX_COUNT )
|
|
{
|
|
g_iStorageDeviceId[ iController ] = id;
|
|
}
|
|
else
|
|
{
|
|
Assert( iController >= 0 && iController < XUSER_MAX_COUNT );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_GetPrimaryUserId
|
|
//
|
|
// Returns the active user ID
|
|
//-----------------------------------------------------------------------------
|
|
DWORD XBX_GetPrimaryUserId( void )
|
|
{
|
|
#ifdef _PS3
|
|
return ( g_iPrimaryUserId != XBX_INVALID_USER_ID ) ? g_iPrimaryUserId : 0;
|
|
#else
|
|
return g_iPrimaryUserId;
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_SetPrimaryUserId
|
|
//
|
|
// Sets the active user ID
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetPrimaryUserId( DWORD idx )
|
|
{
|
|
g_iPrimaryUserId = idx;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_GetPrimaryUserIsGuest
|
|
//
|
|
// Returns zero (FALSE) if primary user is a real account
|
|
// Returns non-zero (TRUE) if primary user is a guest account
|
|
//-----------------------------------------------------------------------------
|
|
DWORD XBX_GetPrimaryUserIsGuest( void )
|
|
{
|
|
return g_bPrimaryUserIsGuest;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_SetPrimaryUserIsGuest
|
|
//
|
|
// Sets if primary user is a guest account
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetPrimaryUserIsGuest( DWORD bPrimaryUserIsGuest )
|
|
{
|
|
g_bPrimaryUserIsGuest = bPrimaryUserIsGuest;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_GetNumGameUsers
|
|
//
|
|
// Returns number of users for the game mode
|
|
//-----------------------------------------------------------------------------
|
|
DWORD XBX_GetNumGameUsers( void )
|
|
{
|
|
return g_numGameUsers;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// XBX_SetNumGameUsers
|
|
//
|
|
// Sets number of users for the game mode
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetNumGameUsers( DWORD numGameUsers )
|
|
{
|
|
g_numGameUsers = numGameUsers;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Returns the stored session ID for a cross-game invite
|
|
//-----------------------------------------------------------------------------
|
|
XNKID XBX_GetInviteSessionId( void )
|
|
{
|
|
return g_InviteSessionId;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Store a session ID for an invitation
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetInviteSessionId( XNKID nSessionId )
|
|
{
|
|
g_InviteSessionId = nSessionId;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Get the Id of the user who received an invite
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DWORD XBX_GetInvitedUserId( void )
|
|
{
|
|
#ifdef _PS3
|
|
return ( g_InvitedUserId != XBX_INVALID_USER_ID ) ? 0 : XBX_INVALID_USER_ID; // invited user will be the primary user = 0
|
|
#else
|
|
return g_InvitedUserId;
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Set the Id of the user who received an invite
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetInvitedUserId( DWORD nUserId )
|
|
{
|
|
g_InvitedUserId = nUserId;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Get the Id of the user who received an invite
|
|
//-----------------------------------------------------------------------------
|
|
|
|
XUID XBX_GetInvitedUserXuid( void )
|
|
{
|
|
return g_InvitedUserXuid;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Set the Id of the user who received an invite
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetInvitedUserXuid( XUID xuid )
|
|
{
|
|
g_InvitedUserXuid = xuid;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Maps the physical controllers to splitscreen slots
|
|
//-----------------------------------------------------------------------------
|
|
static int XBX_UserIndexToSlot[XUSER_MAX_COUNT] =
|
|
{
|
|
0,
|
|
1,
|
|
2,
|
|
3
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Maps the splitscreen slots to physical controllers
|
|
//-----------------------------------------------------------------------------
|
|
static int XBX_SlotToUserIndex[XUSER_MAX_COUNT] =
|
|
{
|
|
0,
|
|
1,
|
|
2,
|
|
3
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Maps slots to guest status
|
|
//-----------------------------------------------------------------------------
|
|
static DWORD XBX_SlotToUserIsGuest[XUSER_MAX_COUNT] =
|
|
{
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_ResetUserIdSlots()
|
|
{
|
|
Msg( "XBX_ResetUserIdSlots\n" );
|
|
|
|
for ( int i = 0; i < XUSER_MAX_COUNT; ++i )
|
|
{
|
|
XBX_UserIndexToSlot[i] = i;
|
|
XBX_SlotToUserIndex[i] = i;
|
|
XBX_SlotToUserIsGuest[i] = 0;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_ClearUserIdSlots()
|
|
{
|
|
Msg( "XBX_ClearUserIdSlots\n" );
|
|
|
|
for ( int i = 0; i < XUSER_MAX_COUNT; ++i )
|
|
{
|
|
XBX_UserIndexToSlot[i] = (int)XBX_INVALID_USER_ID;
|
|
XBX_SlotToUserIndex[i] = (int)XBX_INVALID_USER_ID;
|
|
XBX_SlotToUserIsGuest[i] = 0;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Return the split screen slot based on a controller index
|
|
// May return -1 if no slot has been asssigned to that controller
|
|
int XBX_GetSlotByUserId( int idx )
|
|
{
|
|
if ( idx >= 0 && idx <= XUSER_MAX_COUNT )
|
|
{
|
|
return XBX_UserIndexToSlot[ idx ];
|
|
}
|
|
else
|
|
{
|
|
Assert( idx >= 0 && idx <= XUSER_MAX_COUNT );
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Return the controller assigned to a splitscreen slot
|
|
// May return -1 if no controller has been asssigned to that slot
|
|
int XBX_GetUserId( int nSlot )
|
|
{
|
|
if ( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS )
|
|
{
|
|
return XBX_SlotToUserIndex[nSlot];
|
|
}
|
|
else
|
|
{
|
|
Assert( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS );
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetUserId( int nSlot, int idx )
|
|
{
|
|
if ( ( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS ) &&
|
|
( idx >= 0 && idx <= XUSER_MAX_COUNT ) )
|
|
{
|
|
XBX_SlotToUserIndex[nSlot] = idx;
|
|
XBX_UserIndexToSlot[idx] = nSlot;
|
|
}
|
|
else
|
|
{
|
|
Assert( "XBX_SetUserId" );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_ClearSlot( int nSlot )
|
|
{
|
|
if ( !( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS ) )
|
|
{
|
|
Assert( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS );
|
|
return;
|
|
}
|
|
|
|
int iCtrlr = XBX_SlotToUserIndex[nSlot];
|
|
if ( iCtrlr >= 0 && iCtrlr < XUSER_MAX_COUNT )
|
|
{
|
|
XBX_UserIndexToSlot[ iCtrlr ] = (int)XBX_INVALID_USER_ID;
|
|
}
|
|
|
|
XBX_SlotToUserIndex[nSlot] = (int)XBX_INVALID_USER_ID;
|
|
XBX_SlotToUserIsGuest[nSlot] = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_ClearUserId( int idx )
|
|
{
|
|
if ( !( idx >= 0 && idx <= XUSER_MAX_COUNT ) )
|
|
{
|
|
Assert( idx >= 0 && idx <= XUSER_MAX_COUNT );
|
|
return;
|
|
}
|
|
|
|
int iSlot = XBX_UserIndexToSlot[idx];
|
|
if ( iSlot >= 0 && iSlot <= MAX_SPLITSCREEN_CLIENTS )
|
|
{
|
|
XBX_SlotToUserIndex[iSlot] = (int)XBX_INVALID_USER_ID;
|
|
XBX_SlotToUserIsGuest[iSlot] = 0;
|
|
}
|
|
|
|
XBX_UserIndexToSlot[idx] = (int)XBX_INVALID_USER_ID;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
DWORD XBX_GetUserIsGuest( int nSlot )
|
|
{
|
|
if ( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS )
|
|
{
|
|
return XBX_SlotToUserIsGuest[nSlot];
|
|
}
|
|
else
|
|
{
|
|
Assert( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS );
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void XBX_SetUserIsGuest( int nSlot, DWORD dwUserIsGuest )
|
|
{
|
|
if ( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS )
|
|
{
|
|
XBX_SlotToUserIsGuest[nSlot] = dwUserIsGuest;
|
|
}
|
|
else
|
|
{
|
|
Assert( nSlot >= 0 && nSlot <= MAX_SPLITSCREEN_CLIENTS );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
#ifdef _X360
|
|
static CXboxLaunch g_XBoxLaunch;
|
|
CXboxLaunch *XboxLaunch()
|
|
{
|
|
return &g_XBoxLaunch;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Xbx dynamic event queue implementation
|
|
//
|
|
|
|
void CXbxEventQueue::AppendEvent( xevent_t const &xevt )
|
|
{
|
|
AUTO_LOCK( m_mtx );
|
|
|
|
if ( m_bDispatching )
|
|
{
|
|
Assert( !m_bDispatching );
|
|
Error( "CXbxEventQueue::AppendEvent during Dispatch is not allowed!\n" );
|
|
return;
|
|
}
|
|
|
|
// Check if we need more capacity
|
|
if ( m_dwCount == m_dwAllocated )
|
|
{
|
|
m_dwAllocated = MAX( m_dwAllocated * 2, s_nQueueNormalSize ); // New size is at least double old size or at least for 32 items
|
|
xevent_t *pNewQueue = new xevent_t[ m_dwAllocated ]; // Allocate the new size
|
|
if ( m_pQueue )
|
|
{
|
|
memcpy( pNewQueue, m_pQueue, m_dwCount * sizeof( xevent_t ) ); // Copy events queued so far
|
|
delete [] m_pQueue; // Free old event queue memory
|
|
}
|
|
m_pQueue = pNewQueue; // Now we are pointing a larger chunk of memory, preserved data and size
|
|
}
|
|
|
|
m_pQueue[ m_dwCount ++ ] = xevt;
|
|
}
|
|
|
|
void CXbxEventQueue::Dispatch()
|
|
{
|
|
AUTO_LOCK( m_mtx );
|
|
|
|
if ( !ThreadInMainThread() )
|
|
{
|
|
Assert( !"ThreadInMainThread()" );
|
|
Error( "CXbxEventQueue::Dispatch not on main thread!\n" );
|
|
return;
|
|
}
|
|
|
|
if ( m_bDispatching )
|
|
{
|
|
Assert( !m_bDispatching );
|
|
Error( "CXbxEventQueue::Dispatch is no reentry!\n" );
|
|
return;
|
|
}
|
|
m_bDispatching = true;
|
|
|
|
// pump event queue
|
|
for ( DWORD k = 0; k < m_dwCount; ++ k )
|
|
{
|
|
xevent_t *pEvent = &m_pQueue[ k ];
|
|
switch ( pEvent->event )
|
|
{
|
|
case XEV_REMOTECMD:
|
|
XBX_ProcessXCommand( *pEvent );
|
|
break;
|
|
|
|
case XEV_LISTENER_NOTIFICATION:
|
|
XBX_ProcessListenerNotification( *pEvent );
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_dwCount = 0;
|
|
if ( m_dwAllocated >= s_nQueueAbnormalSize )
|
|
{
|
|
m_dwAllocated = 0;
|
|
delete [] m_pQueue;
|
|
m_pQueue = NULL;
|
|
}
|
|
m_bDispatching = false;
|
|
}
|
|
|
|
bool CXbxEventQueue::IsDispatching() const
|
|
{
|
|
// No mutex lock in this case because if the thread
|
|
// is currently dispatching the queue, then it is currently
|
|
// owning the queue mutex and can check the bool directly.
|
|
// If the thread currently doesn't own the mutex, then the
|
|
// operation on the queue will attempt to acquire the mutex
|
|
// and it should be safe for the thread to stall anyway,
|
|
// so the out-of-date information about whether the queue is
|
|
// dispatching is not a concern.
|
|
return m_bDispatching;
|
|
}
|