summaryrefslogtreecommitdiff
path: root/common/xbox/xbox_launch.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/xbox/xbox_launch.h')
-rw-r--r--common/xbox/xbox_launch.h295
1 files changed, 295 insertions, 0 deletions
diff --git a/common/xbox/xbox_launch.h b/common/xbox/xbox_launch.h
new file mode 100644
index 0000000..a0a9e66
--- /dev/null
+++ b/common/xbox/xbox_launch.h
@@ -0,0 +1,295 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Xbox Launch Routines.
+//
+//=====================================================================================//
+
+#ifndef _XBOX_LAUNCH_H_
+#define _XBOX_LAUNCH_H_
+
+#pragma once
+
+#ifndef _CERT
+#pragma comment( lib, "xbdm.lib" )
+#endif
+
+// id and version are used to tag the data blob, currently only need a singe hardcoded id
+// when the version and id don't match, the data blob is not ours
+#define VALVE_LAUNCH_ID (('V'<<24)|('A'<<16)|('L'<<8)|('V'<<0))
+#define VALVE_LAUNCH_VERSION 1
+
+// launch flags
+#define LF_ISDEBUGGING 0x80000000 // set if session was active prior to launch
+#define LF_INTERNALLAUNCH 0x00000001 // set if launch was internal (as opposed to dashboard)
+#define LF_EXITFROMINSTALLER 0x00000002 // set if exit was from an installer
+#define LF_EXITFROMGAME 0x00000004 // set if exit was from a game
+#define LF_EXITFROMCHOOSER 0x00000008 // set if exit was from the chooser
+#define LF_GAMERESTART 0x00000010 // set if game wants to restart self (skips appchooser)
+#define LF_INVITERESTART 0x00000020 // set if game was invited from another app (launches TF and fires off session connect)
+
+#pragma pack(1)
+struct launchHeader_t
+{
+ unsigned int id;
+ unsigned int version;
+ unsigned int flags;
+
+ int nStorageID;
+ int nUserID;
+ int bForceEnglish;
+ XNKID nInviteSessionID;
+
+ // for caller defined data, occurs after this header
+ // limited to slightly less than MAX_LAUNCH_DATA_SIZE
+ unsigned int nDataSize;
+};
+#pragma pack()
+
+// per docs, no larger than MAX_LAUNCH_DATA_SIZE
+union xboxLaunchData_t
+{
+ launchHeader_t header;
+ char data[MAX_LAUNCH_DATA_SIZE];
+};
+
+//--------------------------------------------------------------------------------------
+// Simple class to wrap the peristsent launch payload.
+//
+// Can be used by an application that does not use tier0 (i.e. the launcher).
+// Primarily designed to be anchored in tier0, so multiple systems can easily query and
+// set the persistent payload.
+//--------------------------------------------------------------------------------------
+class CXboxLaunch
+{
+public:
+ CXboxLaunch()
+ {
+ ResetLaunchData();
+ }
+
+ void ResetLaunchData()
+ {
+ // invalid until established
+ // nonzero identifies a valid payload
+ m_LaunchDataSize = 0;
+
+ m_Launch.header.id = 0;
+ m_Launch.header.version = 0;
+ m_Launch.header.flags = 0;
+
+ m_Launch.header.nStorageID = XBX_INVALID_STORAGE_ID;
+ m_Launch.header.nUserID = XBX_INVALID_USER_ID;
+ m_Launch.header.bForceEnglish = false;
+
+ memset( &m_Launch.header.nInviteSessionID, 0, sizeof( m_Launch.header.nInviteSessionID ) );
+
+ m_Launch.header.nDataSize = 0;
+ }
+
+ // Returns how much space can be used by caller
+ int MaxPayloadSize()
+ {
+ return sizeof( xboxLaunchData_t ) - sizeof( launchHeader_t );
+ }
+
+ bool SetLaunchData( void *pData, int dataSize, int flags = 0 )
+ {
+ if ( pData && dataSize && dataSize > MaxPayloadSize() )
+ {
+ // not enough room
+ return false;
+ }
+
+ if ( pData && dataSize && dataSize <= MaxPayloadSize() )
+ {
+ memcpy( m_Launch.data + sizeof( launchHeader_t ), pData, dataSize );
+ m_Launch.header.nDataSize = dataSize;
+ }
+ else
+ {
+ m_Launch.header.nDataSize = 0;
+ }
+
+ flags |= LF_INTERNALLAUNCH;
+#if !defined( _CERT )
+ if ( DmIsDebuggerPresent() )
+ {
+ flags |= LF_ISDEBUGGING;
+ }
+#endif
+ m_Launch.header.id = VALVE_LAUNCH_ID;
+ m_Launch.header.version = VALVE_LAUNCH_VERSION;
+ m_Launch.header.flags = flags;
+
+ XSetLaunchData( &m_Launch, MAX_LAUNCH_DATA_SIZE );
+
+ // assume successful, mark as valid
+ m_LaunchDataSize = MAX_LAUNCH_DATA_SIZE;
+
+ return true;
+ }
+
+ //--------------------------------------------------------------------------------------
+ // Returns TRUE if the launch data blob is available. FALSE otherwise.
+ // Caller is expected to validate and interpret contents based on ID.
+ //--------------------------------------------------------------------------------------
+ bool GetLaunchData( unsigned int *pID, void **pData, int *pDataSize )
+ {
+ if ( !m_LaunchDataSize )
+ {
+ // purposely not doing this in the constructor (unstable as used by tier0), but on first fetch
+ bool bValid = false;
+ DWORD dwLaunchDataSize;
+ DWORD dwStatus = XGetLaunchDataSize( &dwLaunchDataSize );
+ if ( dwStatus == ERROR_SUCCESS && dwLaunchDataSize <= MAX_LAUNCH_DATA_SIZE )
+ {
+ dwStatus = XGetLaunchData( (void*)&m_Launch, dwLaunchDataSize );
+ if ( dwStatus == ERROR_SUCCESS )
+ {
+ bValid = true;
+ m_LaunchDataSize = dwLaunchDataSize;
+ }
+ }
+
+ if ( !bValid )
+ {
+ ResetLaunchData();
+ }
+ }
+
+ // a valid launch payload could be ours (re-launch) or from an alternate booter (demo launcher)
+ if ( m_LaunchDataSize == MAX_LAUNCH_DATA_SIZE && m_Launch.header.id == VALVE_LAUNCH_ID && m_Launch.header.version == VALVE_LAUNCH_VERSION )
+ {
+ // internal recognized format
+ if ( pID )
+ {
+ *pID = m_Launch.header.id;
+ }
+ if ( pData )
+ {
+ *pData = m_Launch.data + sizeof( launchHeader_t );
+ }
+ if ( pDataSize )
+ {
+ *pDataSize = m_Launch.header.nDataSize;
+ }
+ }
+ else if ( m_LaunchDataSize )
+ {
+ // not ours, unknown format, caller interprets
+ if ( pID )
+ {
+ // assume payload was packaged with an initial ID
+ *pID = *(unsigned int *)m_Launch.data;
+ }
+ if ( pData )
+ {
+ *pData = m_Launch.data;
+ }
+ if ( pDataSize )
+ {
+ *pDataSize = m_LaunchDataSize;
+ }
+ }
+
+ // valid when data is available (not necessarily valve's tag)
+ return m_LaunchDataSize != 0;
+ }
+
+ //--------------------------------------------------------------------------------------
+ // Returns TRUE if the launch data blob is available. FALSE otherwise.
+ // Data blob could be ours or not.
+ //--------------------------------------------------------------------------------------
+ bool RestoreLaunchData()
+ {
+ return GetLaunchData( NULL, NULL, NULL );
+ }
+
+ //--------------------------------------------------------------------------------------
+ // Restores the data blob. If the data blob is not ours, resets it.
+ //--------------------------------------------------------------------------------------
+ void RestoreOrResetLaunchData()
+ {
+ RestoreLaunchData();
+ if ( m_Launch.header.id != VALVE_LAUNCH_ID || m_Launch.header.version != VALVE_LAUNCH_VERSION )
+ {
+ // not interested in somebody else's data
+ ResetLaunchData();
+ }
+ }
+
+ //--------------------------------------------------------------------------------------
+ // Returns OUR internal launch flags.
+ //--------------------------------------------------------------------------------------
+ int GetLaunchFlags()
+ {
+ // establish the data
+ RestoreOrResetLaunchData();
+ return m_Launch.header.flags;
+ }
+
+ int GetStorageID( void )
+ {
+ RestoreOrResetLaunchData();
+ return m_Launch.header.nStorageID;
+ }
+ void SetStorageID( int storageID )
+ {
+ RestoreOrResetLaunchData();
+ m_Launch.header.nStorageID = storageID;
+ }
+
+ int GetUserID( void )
+ {
+ RestoreOrResetLaunchData();
+ return m_Launch.header.nUserID;
+ }
+ void SetUserID( int userID )
+ {
+ RestoreOrResetLaunchData();
+ m_Launch.header.nUserID = userID;
+ }
+
+ bool GetForceEnglish( void )
+ {
+ RestoreOrResetLaunchData();
+ return m_Launch.header.bForceEnglish ? true : false;
+ }
+ void SetForceEnglish( bool bForceEnglish )
+ {
+ RestoreOrResetLaunchData();
+ m_Launch.header.bForceEnglish = bForceEnglish;
+ }
+
+ void GetInviteSessionID( XNKID *pSessionID )
+ {
+ RestoreOrResetLaunchData();
+ *pSessionID = m_Launch.header.nInviteSessionID;
+ }
+ void SetInviteSessionID( XNKID *pSessionID )
+ {
+ RestoreOrResetLaunchData();
+ m_Launch.header.nInviteSessionID = *pSessionID;
+ }
+
+ void Launch( const char *pNewImageName = NULL )
+ {
+ if ( !pNewImageName )
+ {
+ pNewImageName = "default.xex";
+ }
+
+ XLaunchNewImage( pNewImageName, 0 );
+ }
+
+private:
+ xboxLaunchData_t m_Launch;
+ DWORD m_LaunchDataSize;
+};
+
+#if defined( PLATFORM_H )
+// For applications that use tier0.dll
+PLATFORM_INTERFACE CXboxLaunch *XboxLaunch();
+#endif
+
+#endif