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.
295 lines
7.8 KiB
295 lines
7.8 KiB
//========= 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
|
|
|