|
|
//========= 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
|