mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-15 21:26:57 +00:00
1
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user