//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Xbox // //=====================================================================================// #include "pch_tier0.h" #include "xbox/xbox_console.h" #include "xbox/xbox_win32stubs.h" #include "xbox/xbox_launch.h" #include "tier0/memdbgon.h" #define XBX_MAX_EVENTS 32 xevent_t g_xbx_eventQueue[XBX_MAX_EVENTS]; int g_xbx_eventHead; int g_xbx_eventTail; DWORD g_iStorageDeviceId = XBX_INVALID_STORAGE_ID; DWORD g_iPrimaryUserId = XBX_INVALID_USER_ID; DWORD g_InvitedUserId = XBX_INVALID_USER_ID; HANDLE g_hListenHandle = INVALID_HANDLE_VALUE; ULONG64 g_ListenCategories = 0; XNKID g_InviteSessionId = { 0, 0, 0, 0, 0, 0, 0, 0 }; //----------------------------------------------------------------------------- // Convert an Xbox notification to a custom windows message //----------------------------------------------------------------------------- static int NotificationToWindowsMessage( DWORD id ) { 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; } } //----------------------------------------------------------------------------- // 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'; XBX_DebugString( XMAKECOLOR(255,0,0), message ); XBX_FlushDebugOutput(); DebugBreak(); static volatile int doReturn; while ( !doReturn ); } //----------------------------------------------------------------------------- // XBX_OutputDebugStringA // // Replaces 'OutputDebugString' to send through debugging channel //----------------------------------------------------------------------------- void XBX_OutputDebugStringA( LPCSTR lpOutputString ) { XBX_DebugString( XMAKECOLOR(0,0,0), lpOutputString ); } //----------------------------------------------------------------------------- // XBX_GetEvent // //----------------------------------------------------------------------------- static xevent_t* XBX_GetEvent(void) { xevent_t* evPtr; if ( g_xbx_eventHead == g_xbx_eventTail ) { // empty return NULL; } evPtr = &g_xbx_eventQueue[g_xbx_eventHead & (XBX_MAX_EVENTS-1)]; // advance to next event g_xbx_eventHead++; return evPtr; } //----------------------------------------------------------------------------- // XBX_FlushEvents // //----------------------------------------------------------------------------- static void XBX_FlushEvents(void) { g_xbx_eventHead = 0; g_xbx_eventTail = 0; } //----------------------------------------------------------------------------- // XBX_ProcessXCommand // //----------------------------------------------------------------------------- static void XBX_ProcessXCommand( const char *pCommand ) { // 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 ); } } //----------------------------------------------------------------------------- // XBX_ProcessListenerNotification // //----------------------------------------------------------------------------- static void XBX_ProcessListenerNotification( int notification, int parameter ) { // pass it game via windows message HWND hWnd = GetFocus(); WNDPROC windowProc = ( WNDPROC)GetWindowLong( hWnd, GWL_WNDPROC ); if ( windowProc ) { windowProc( hWnd, notification, 0, (LPARAM)parameter ); } } //----------------------------------------------------------------------------- // XBX_QueueEvent // //----------------------------------------------------------------------------- void XBX_QueueEvent(xevent_e event, int arg1, int arg2, int arg3) { xevent_t* evPtr; evPtr = &g_xbx_eventQueue[g_xbx_eventTail & (XBX_MAX_EVENTS-1)]; evPtr->event = event; evPtr->arg1 = arg1; evPtr->arg2 = arg2; evPtr->arg3 = arg3; // next slot, queue never fills just overwrite older events g_xbx_eventTail++; } //----------------------------------------------------------------------------- // XBX_ProcessEvents // // Assumed one per frame only! //----------------------------------------------------------------------------- void XBX_ProcessEvents(void) { xevent_t *evPtr; DWORD id; ULONG parameter; while ( XNotifyGetNext( g_hListenHandle, 0, &id, ¶meter ) ) { // Special handling switch( id ) { case XN_SYS_STORAGEDEVICESCHANGED: { // Have we selected a storage device? DWORD storageID = XBX_GetStorageDeviceId(); if ( storageID == XBX_INVALID_STORAGE_ID || storageID == XBX_STORAGE_DECLINED ) break; // Validate the selected storage device XDEVICE_DATA deviceData; DWORD ret = XContentGetDeviceData( storageID, &deviceData ); if ( ret != ERROR_SUCCESS ) { // Device was removed XBX_SetStorageDeviceId( XBX_INVALID_STORAGE_ID ); XBX_QueueEvent( XEV_LISTENER_NOTIFICATION, NotificationToWindowsMessage( id ), 0, 0 ); } break; } default: XBX_QueueEvent( XEV_LISTENER_NOTIFICATION, NotificationToWindowsMessage( id ), parameter, 0 ); break; } } // pump event queue while ( 1 ) { evPtr = XBX_GetEvent(); if ( !evPtr ) break; switch ( evPtr->event ) { case XEV_REMOTECMD: XBX_ProcessXCommand( (char *)evPtr->arg1 ); // clear to mark as absorbed ((char *)evPtr->arg1)[0] = '\0'; break; case XEV_LISTENER_NOTIFICATION: XBX_ProcessListenerNotification( evPtr->arg1, evPtr->arg2 ); break; } } } //----------------------------------------------------------------------------- // XBX_NotifyCreateListener // // Add notification categories to the listener object //----------------------------------------------------------------------------- bool XBX_NotifyCreateListener( ULONG64 categories ) { if ( categories != 0 ) { categories |= g_ListenCategories; } g_hListenHandle = XNotifyCreateListener( categories ); if ( g_hListenHandle == NULL || g_hListenHandle == INVALID_HANDLE_VALUE ) { return false; } g_ListenCategories = categories; return true; } //----------------------------------------------------------------------------- // XBX_GetLanguageString // // Returns the xbox language setting as a string //----------------------------------------------------------------------------- const char* XBX_GetLanguageString( void ) { switch( XGetLanguage() ) { case XC_LANGUAGE_FRENCH: return "french"; case XC_LANGUAGE_GERMAN: return "german"; } return "english"; } bool XBX_IsLocalized( void ) { switch( XGetLanguage() ) { case XC_LANGUAGE_FRENCH: case XC_LANGUAGE_GERMAN: return true; } return false; } //----------------------------------------------------------------------------- // XBX_GetStorageDeviceId // // Returns the xbox storage device ID //----------------------------------------------------------------------------- DWORD XBX_GetStorageDeviceId( void ) { return g_iStorageDeviceId; } //----------------------------------------------------------------------------- // XBX_SetStorageDeviceId // // Sets the xbox storage device ID //----------------------------------------------------------------------------- void XBX_SetStorageDeviceId( DWORD id ) { g_iStorageDeviceId = id; } //----------------------------------------------------------------------------- // XBX_GetPrimaryUserId // // Returns the active user ID //----------------------------------------------------------------------------- DWORD XBX_GetPrimaryUserId( void ) { return g_iPrimaryUserId; } //----------------------------------------------------------------------------- // XBX_SetPrimaryUserId // // Sets the active user ID //----------------------------------------------------------------------------- void XBX_SetPrimaryUserId( DWORD idx ) { g_iPrimaryUserId = idx; } //----------------------------------------------------------------------------- // 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 ) { return g_InvitedUserId; } //----------------------------------------------------------------------------- // Purpose: Set the Id of the user who received an invite //----------------------------------------------------------------------------- void XBX_SetInvitedUserId( DWORD nUserId ) { g_InvitedUserId = nUserId; } static CXboxLaunch g_XBoxLaunch; CXboxLaunch *XboxLaunch() { return &g_XBoxLaunch; }