Counter Strike : Global Offensive Source Code
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.
 
 
 
 
 
 

451 lines
11 KiB

//========= Copyright © 1996-2005, 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_WARMRESTART 0x00000010 // set if game wants to restart self (skips intro movies)
#define LF_INSTALLEDTOCACHE 0x00000040 // set if installer populated or validated cache partition
#define LF_UNKNOWNDATA 0x00000080
#pragma pack(1)
struct launchHeader_t
{
unsigned int id;
unsigned int version;
unsigned int flags;
int nUserID;
int nCtrlr2Storage[4];
char nSlot2Ctrlr[4];
char nSlot2Guest[4];
int numGameUsers;
int bForceEnglish;
// increments at each engine re-launch
DWORD nAttractID;
// 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.nUserID = XBX_INVALID_USER_ID;
m_Launch.header.bForceEnglish = false;
m_Launch.header.nCtrlr2Storage[0] = XBX_INVALID_STORAGE_ID;
m_Launch.header.nCtrlr2Storage[1] = XBX_INVALID_STORAGE_ID;
m_Launch.header.nCtrlr2Storage[2] = XBX_INVALID_STORAGE_ID;
m_Launch.header.nCtrlr2Storage[3] = XBX_INVALID_STORAGE_ID;
m_Launch.header.nSlot2Ctrlr[0] = 0;
m_Launch.header.nSlot2Ctrlr[1] = 1;
m_Launch.header.nSlot2Ctrlr[2] = 2;
m_Launch.header.nSlot2Ctrlr[3] = 3;
m_Launch.header.nSlot2Guest[0] = 0;
m_Launch.header.nSlot2Guest[1] = 0;
m_Launch.header.nSlot2Guest[2] = 0;
m_Launch.header.nSlot2Guest[3] = 0;
m_Launch.header.numGameUsers = 0;
m_Launch.header.nAttractID = 0;
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 defined( _DEMO )
if ( pData && ( flags & LF_UNKNOWNDATA ) )
{
// not ours, put the demo structure back as-is
XSetLaunchData( pData, dataSize );
m_LaunchDataSize = dataSize;
return true;
}
#endif
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;
}
}
else if ( !m_LaunchDataSize )
{
// mark for caller as all invalid
if ( pID )
{
*pID = 0;
}
if ( pData )
{
*pData = NULL;
}
if ( pDataSize )
{
*pDataSize = 0;
}
}
// valid when any 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 !defined( _DEMO )
if ( m_Launch.header.id != VALVE_LAUNCH_ID || m_Launch.header.version != VALVE_LAUNCH_VERSION )
{
// not interested in somebody else's data
ResetLaunchData();
}
#endif
}
//--------------------------------------------------------------------------------------
// Returns OUR internal launch flags.
//--------------------------------------------------------------------------------------
int GetLaunchFlags()
{
// establish the data
RestoreOrResetLaunchData();
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return 0;
}
#endif
return m_Launch.header.flags;
}
void SetLaunchFlags( unsigned int ufNewFlags )
{
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return;
}
#endif
m_Launch.header.flags = ufNewFlags;
}
void GetStorageID( int storageID[4] )
{
RestoreOrResetLaunchData();
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
storageID[0] = XBX_INVALID_STORAGE_ID;
storageID[1] = XBX_INVALID_STORAGE_ID;
storageID[2] = XBX_INVALID_STORAGE_ID;
storageID[3] = XBX_INVALID_STORAGE_ID;
return;
}
#endif
memcpy( storageID, m_Launch.header.nCtrlr2Storage, sizeof( m_Launch.header.nCtrlr2Storage ) );
}
void SetStorageID( int const storageID[4] )
{
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return;
}
#endif
memcpy( m_Launch.header.nCtrlr2Storage, storageID, sizeof( m_Launch.header.nCtrlr2Storage ) );
}
void GetSlotUsers( int &numGameUsers, char nSlot2Ctrlr[4], char nSlot2Guest[4] )
{
RestoreOrResetLaunchData();
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
numGameUsers = 0;
nSlot2Ctrlr[0] = 0;
nSlot2Ctrlr[1] = 1;
nSlot2Ctrlr[2] = 2;
nSlot2Ctrlr[3] = 3;
nSlot2Guest[0] = 0;
nSlot2Guest[1] = 0;
nSlot2Guest[2] = 0;
nSlot2Guest[3] = 0;
return;
}
#endif
numGameUsers = m_Launch.header.numGameUsers;
memcpy( nSlot2Ctrlr, m_Launch.header.nSlot2Ctrlr, sizeof( m_Launch.header.nSlot2Ctrlr ) );
memcpy( nSlot2Guest, m_Launch.header.nSlot2Guest, sizeof( m_Launch.header.nSlot2Guest ) );
}
void SetSlotUsers( int numGameUsers, char const nSlot2Ctrlr[4], char const nSlot2Guest[4] )
{
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return;
}
#endif
m_Launch.header.numGameUsers = numGameUsers;
memcpy( m_Launch.header.nSlot2Ctrlr, nSlot2Ctrlr, sizeof( m_Launch.header.nSlot2Ctrlr ) );
memcpy( m_Launch.header.nSlot2Guest, nSlot2Guest, sizeof( m_Launch.header.nSlot2Guest ) );
}
int GetUserID( void )
{
RestoreOrResetLaunchData();
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return XBX_INVALID_USER_ID;
}
#endif
return m_Launch.header.nUserID;
}
void SetUserID( int userID )
{
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return;
}
#endif
m_Launch.header.nUserID = userID;
}
bool GetForceEnglish( void )
{
RestoreOrResetLaunchData();
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return false;
}
#endif
return m_Launch.header.bForceEnglish ? true : false;
}
void SetForceEnglish( bool bForceEnglish )
{
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return;
}
#endif
m_Launch.header.bForceEnglish = bForceEnglish;
}
DWORD GetAttractID( void )
{
RestoreOrResetLaunchData();
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return 0;
}
#endif
return m_Launch.header.nAttractID;
}
void SetAttractID( DWORD nAttractID )
{
#if defined( _DEMO )
if ( m_Launch.header.id && m_Launch.header.id != VALVE_LAUNCH_ID )
{
return;
}
#endif
m_Launch.header.nAttractID = nAttractID;
}
void Launch( const char *pNewImageName = NULL )
{
if ( !pNewImageName )
{
#if defined( _DEMO )
pNewImageName = XLAUNCH_KEYWORD_DEFAULT_APP;
#else
pNewImageName = "default.xex";
#endif
}
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